From ba8c4c5c0b192441125afcf7c3c55174b8f71cdf Mon Sep 17 00:00:00 2001 From: dushek Date: Thu, 27 Mar 2025 10:52:37 +0100 Subject: [PATCH 1/2] New walidation on create --- kmip/pie/client.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kmip/pie/client.py b/kmip/pie/client.py index d27ad4b1..1e7629ca 100644 --- a/kmip/pie/client.py +++ b/kmip/pie/client.py @@ -194,8 +194,7 @@ def close(self): raise @is_connected - def create(self, algorithm, length, operation_policy_name=None, name=None, - cryptographic_usage_mask=None): + def create(self, algorithm, length, operation_policy_name=None, name=None, cryptographic_usage_mask=None): """ Create a symmetric key on a KMIP appliance. @@ -218,10 +217,24 @@ def create(self, algorithm, length, operation_policy_name=None, name=None, KmipOperationFailure: if the operation result is a failure TypeError: if the input arguments are invalid """ + + # Check inputs - if not isinstance(algorithm, enums.CryptographicAlgorithm): + # TODO (peter-hamilton) Add better input validation checks. + from kmip.core.enums import CryptographicAlgorithm as CoreAlgorithm + + if not ( + isinstance(algorithm, enums.CryptographicAlgorithm) or isinstance(algorithm, CoreAlgorithm) + ): raise TypeError( - "algorithm must be a CryptographicAlgorithm enumeration") + f"algorithm must be a CryptographicAlgorithm enumeration, got {type(algorithm)}" + ) + + + #if not isinstance(algorithm, enums.CryptographicAlgorithm): + # raise TypeError( + # "algorithm must be a CryptographicAlgorithm enumeration") + elif not isinstance(length, six.integer_types) or length <= 0: raise TypeError("length must be a positive integer") if cryptographic_usage_mask is not None: From 22709b0ee53b70dbfa0ed69935285f43c003b771 Mon Sep 17 00:00:00 2001 From: dushek Date: Fri, 6 Feb 2026 10:29:30 +0100 Subject: [PATCH 2/2] New python and extended unit test --- ._coverage_api.json | 3177 +++++++++++++++++ ._coverage_focus.json | 429 +++ ._coverage_missing.txt | 257 ++ ._coverage_missing_clean.md | 257 ++ ._coverage_missing_ready.md | 72 + ._coverage_report.json | 1297 +++++++ ._coverage_table.json | 1260 +++++++ ._coverage_table.md | 83 + ._coverage_table_clean.md | 83 + ._coverage_table_ready.md | 83 + .github/workflows/tox.yml | 9 +- .travis.yml | 267 +- docs/source/development.rst | 12 +- kmip/__init__.py | 1 - kmip/core/attributes.py | 45 +- kmip/core/config_helper.py | 5 +- kmip/core/enums.py | 85 +- kmip/core/exceptions.py | 28 - kmip/core/factories/attribute_values.py | 1 - kmip/core/factories/attributes.py | 1 - kmip/core/factories/credentials.py | 1 - kmip/core/factories/payloads/__init__.py | 1 - kmip/core/factories/payloads/request.py | 1 - kmip/core/factories/payloads/response.py | 1 - kmip/core/factories/secrets.py | 1 - kmip/core/messages/contents.py | 24 +- kmip/core/messages/messages.py | 10 +- kmip/core/messages/payloads/__init__.py | 1 - kmip/core/messages/payloads/activate.py | 2 - kmip/core/messages/payloads/archive.py | 8 +- kmip/core/messages/payloads/base.py | 2 - kmip/core/messages/payloads/cancel.py | 8 +- kmip/core/messages/payloads/check.py | 20 +- kmip/core/messages/payloads/create.py | 6 +- .../core/messages/payloads/create_key_pair.py | 8 +- kmip/core/messages/payloads/decrypt.py | 82 +- .../messages/payloads/delete_attribute.py | 12 +- kmip/core/messages/payloads/derive_key.py | 8 +- kmip/core/messages/payloads/destroy.py | 61 +- .../messages/payloads/discover_versions.py | 8 +- kmip/core/messages/payloads/encrypt.py | 86 +- kmip/core/messages/payloads/get.py | 8 +- .../messages/payloads/get_attribute_list.py | 10 +- kmip/core/messages/payloads/get_attributes.py | 10 +- .../messages/payloads/get_usage_allocation.py | 10 +- kmip/core/messages/payloads/locate.py | 14 +- kmip/core/messages/payloads/mac.py | 2 - .../messages/payloads/modify_attribute.py | 8 +- kmip/core/messages/payloads/obtain_lease.py | 12 +- kmip/core/messages/payloads/poll.py | 5 +- kmip/core/messages/payloads/query.py | 10 +- kmip/core/messages/payloads/recover.py | 8 +- kmip/core/messages/payloads/register.py | 6 +- kmip/core/messages/payloads/rekey.py | 10 +- kmip/core/messages/payloads/rekey_key_pair.py | 2 - kmip/core/messages/payloads/revoke.py | 2 - kmip/core/messages/payloads/set_attribute.py | 8 +- kmip/core/messages/payloads/sign.py | 12 +- .../messages/payloads/signature_verify.py | 20 +- kmip/core/misc.py | 6 - kmip/core/objects.py | 118 +- kmip/core/policy.py | 12 +- kmip/core/primitives.py | 39 +- kmip/core/secrets.py | 19 +- kmip/core/utils.py | 7 - kmip/demos/pie/create.py | 1 - kmip/demos/pie/create_key_pair.py | 1 - kmip/demos/pie/decrypt.py | 1 - kmip/demos/pie/delete_attribute.py | 1 - kmip/demos/pie/derive_key.py | 1 - kmip/demos/pie/destroy.py | 1 - kmip/demos/pie/encrypt.py | 1 - kmip/demos/pie/get.py | 1 - kmip/demos/pie/get_attribute_list.py | 1 - kmip/demos/pie/get_attributes.py | 1 - kmip/demos/pie/locate.py | 1 - kmip/demos/pie/mac.py | 1 - kmip/demos/pie/modify_attribute.py | 1 - kmip/demos/pie/register_certificate.py | 1 - kmip/demos/pie/register_opaque_object.py | 1 - kmip/demos/pie/register_private_key.py | 1 - kmip/demos/pie/register_public_key.py | 1 - kmip/demos/pie/register_secret_data.py | 2 - kmip/demos/pie/register_split_key.py | 1 - kmip/demos/pie/register_symmetric_key.py | 1 - kmip/demos/pie/revoke.py | 1 - kmip/demos/pie/set_attribute.py | 1 - kmip/demos/pie/sign.py | 1 - kmip/demos/pie/signature_verify.py | 1 - kmip/demos/units/activate.py | 1 - kmip/demos/units/create.py | 1 - kmip/demos/units/create_key_pair.py | 1 - kmip/demos/units/destroy.py | 1 - kmip/demos/units/discover_versions.py | 1 - kmip/demos/units/get.py | 1 - kmip/demos/units/locate.py | 1 - kmip/demos/units/query.py | 11 +- kmip/demos/units/register.py | 1 - kmip/demos/units/revoke.py | 1 - kmip/demos/utils.py | 19 - kmip/pie/__init__.py | 1 - kmip/pie/client.py | 70 +- kmip/pie/exceptions.py | 3 - kmip/pie/factory.py | 1 - kmip/pie/objects.py | 55 +- kmip/pie/sqltypes.py | 5 - kmip/services/auth.py | 8 +- kmip/services/kmip_client.py | 54 +- kmip/services/kmip_protocol.py | 3 - kmip/services/results.py | 15 - kmip/services/server/__init__.py | 1 - kmip/services/server/auth/__init__.py | 1 - kmip/services/server/auth/api.py | 5 +- kmip/services/server/auth/slugs.py | 4 +- kmip/services/server/auth/utils.py | 4 - kmip/services/server/config.py | 25 +- kmip/services/server/crypto/api.py | 6 +- kmip/services/server/crypto/engine.py | 1 - kmip/services/server/engine.py | 64 +- kmip/services/server/monitor.py | 2 - kmip/services/server/policy.py | 2 - kmip/services/server/server.py | 46 +- kmip/services/server/session.py | 1 - kmip/tests/functional/conftest.py | 2 - .../services/test_authentication.py | 9 +- kmip/tests/integration/conftest.py | 3 - .../integration/services/test_integration.py | 1 - .../integration/services/test_kmip_client.py | 1 - .../services/test_proxykmipclient.py | 26 +- .../test_application_specific_information.py | 1 - .../unit/core/attributes/test_attributes.py | 43 +- .../tests/unit/core/attributes/test_digest.py | 1 - .../core/factories/payloads/test_payload.py | 1 - .../core/factories/payloads/test_request.py | 1 - .../core/factories/payloads/test_response.py | 1 - .../unit/core/factories/test_attribute.py | 1 - .../core/factories/test_attribute_values.py | 1 - .../messages/contents/test_authentication.py | 1 - .../contents/test_protocol_version.py | 2 - .../core/messages/payloads/test_activate.py | 170 +- .../core/messages/payloads/test_archive.py | 2 - .../core/messages/payloads/test_cancel.py | 2 - .../unit/core/messages/payloads/test_check.py | 209 +- .../core/messages/payloads/test_create.py | 207 +- .../messages/payloads/test_create_key_pair.py | 268 +- .../core/messages/payloads/test_decrypt.py | 156 +- .../payloads/test_delete_attribute.py | 181 +- .../core/messages/payloads/test_derive_key.py | 207 +- .../core/messages/payloads/test_destroy.py | 288 ++ .../payloads/test_discover_versions.py | 104 +- .../core/messages/payloads/test_encrypt.py | 156 +- .../unit/core/messages/payloads/test_get.py | 151 +- .../payloads/test_get_attribute_list.py | 110 +- .../messages/payloads/test_get_attributes.py | 109 +- .../payloads/test_get_usage_allocation.py | 219 +- .../core/messages/payloads/test_locate.py | 193 +- .../unit/core/messages/payloads/test_mac.py | 81 +- .../payloads/test_modify_attribute.py | 183 +- .../messages/payloads/test_obtain_lease.py | 219 +- .../unit/core/messages/payloads/test_poll.py | 1 - .../unit/core/messages/payloads/test_query.py | 160 +- .../core/messages/payloads/test_recover.py | 2 - .../core/messages/payloads/test_register.py | 190 +- .../unit/core/messages/payloads/test_rekey.py | 2 - .../messages/payloads/test_rekey_key_pair.py | 2 - .../core/messages/payloads/test_revoke.py | 170 +- .../messages/payloads/test_set_attribute.py | 162 +- .../unit/core/messages/payloads/test_sign.py | 154 +- .../payloads/test_signature_verify.py | 163 +- .../tests/unit/core/messages/test_messages.py | 13 +- kmip/tests/unit/core/misc/test_misc.py | 11 +- .../unit/core/misc/test_server_information.py | 6 +- .../tests/unit/core/objects/test_attribute.py | 1 - .../unit/core/objects/test_credentials.py | 5 - .../core/objects/test_current_attribute.py | 1 - .../objects/test_extension_information.py | 1 - .../unit/core/objects/test_new_attribute.py | 1 - kmip/tests/unit/core/objects/test_objects.py | 22 +- kmip/tests/unit/core/primitives/test_base.py | 1 - .../unit/core/primitives/test_big_integer.py | 1 - .../unit/core/primitives/test_boolean.py | 1 - .../unit/core/primitives/test_byte_string.py | 1 - .../unit/core/primitives/test_date_time.py | 1 - .../unit/core/primitives/test_enumeration.py | 2 - .../unit/core/primitives/test_integer.py | 1 - .../unit/core/primitives/test_interval.py | 1 - .../unit/core/primitives/test_long_integer.py | 1 - .../unit/core/primitives/test_text_string.py | 4 +- .../unit/core/secrets/test_certificate.py | 1 - .../tests/unit/core/secrets/test_split_key.py | 1 - kmip/tests/unit/core/test_config_helper.py | 1 - .../unit/core/test_config_helper_extended.py | 112 + kmip/tests/unit/core/test_enums.py | 19 +- .../unit/core/test_exceptions_extended.py | 131 + kmip/tests/unit/core/test_policy.py | 6 +- kmip/tests/unit/core/test_policy_extended.py | 98 + .../unit/core/test_primitives_extended.py | 1667 +++++++++ kmip/tests/unit/core/test_utils.py | 2 - kmip/tests/unit/core/test_utils_extended.py | 69 + .../test_application_specific_information.py | 1 - .../unit/pie/objects/test_certificate.py | 2 - .../pie/objects/test_cryptographic_object.py | 3 - kmip/tests/unit/pie/objects/test_key.py | 3 - .../unit/pie/objects/test_managed_object.py | 2 - .../unit/pie/objects/test_object_group.py | 1 - .../unit/pie/objects/test_opaque_object.py | 1 - .../unit/pie/objects/test_private_key.py | 1 - .../tests/unit/pie/objects/test_public_key.py | 1 - .../unit/pie/objects/test_secret_data.py | 1 - kmip/tests/unit/pie/objects/test_split_key.py | 1 - kmip/tests/unit/pie/objects/test_sqltypes.py | 1 - .../pie/objects/test_sqltypes_extended.py | 50 + .../unit/pie/objects/test_symmetric_key.py | 1 - .../unit/pie/objects/test_x509_certificate.py | 1 - kmip/tests/unit/pie/test_client.py | 293 +- kmip/tests/unit/pie/test_client_extended.py | 1224 +++++++ kmip/tests/unit/pie/test_exceptions.py | 3 - kmip/tests/unit/pie/test_factory.py | 1 - .../unit/services/server/auth/test_slugs.py | 1 - .../unit/services/server/auth/test_utils.py | 1 - .../services/server/crypto/test_engine.py | 21 - .../server/crypto/test_engine_extended.py | 773 ++++ .../tests/unit/services/server/test_config.py | 35 +- .../tests/unit/services/server/test_engine.py | 381 +- .../services/server/test_engine_extended.py | 1884 ++++++++++ .../unit/services/server/test_monitor.py | 7 - .../tests/unit/services/server/test_policy.py | 1 - .../tests/unit/services/server/test_server.py | 1 - .../services/server/test_server_extended.py | 565 +++ .../unit/services/server/test_session.py | 69 +- kmip/tests/unit/services/test_auth.py | 2 - kmip/tests/unit/services/test_kmip_client.py | 5 +- .../tests/unit/services/test_kmip_protocol.py | 1 - kmip/tests/unit/test_integration_inmemory.py | 800 +++++ kmip/tests/unit/test_kmip.py | 1 - requirements.txt | 2 - setup.py | 11 +- tox.ini | 2 +- 238 files changed, 19743 insertions(+), 1511 deletions(-) create mode 100644 ._coverage_api.json create mode 100644 ._coverage_focus.json create mode 100644 ._coverage_missing.txt create mode 100644 ._coverage_missing_clean.md create mode 100644 ._coverage_missing_ready.md create mode 100644 ._coverage_report.json create mode 100644 ._coverage_table.json create mode 100644 ._coverage_table.md create mode 100644 ._coverage_table_clean.md create mode 100644 ._coverage_table_ready.md create mode 100644 kmip/tests/unit/core/test_config_helper_extended.py create mode 100644 kmip/tests/unit/core/test_exceptions_extended.py create mode 100644 kmip/tests/unit/core/test_policy_extended.py create mode 100644 kmip/tests/unit/core/test_primitives_extended.py create mode 100644 kmip/tests/unit/core/test_utils_extended.py create mode 100644 kmip/tests/unit/pie/objects/test_sqltypes_extended.py create mode 100644 kmip/tests/unit/pie/test_client_extended.py create mode 100644 kmip/tests/unit/services/server/crypto/test_engine_extended.py create mode 100644 kmip/tests/unit/services/server/test_engine_extended.py create mode 100644 kmip/tests/unit/services/server/test_server_extended.py create mode 100644 kmip/tests/unit/test_integration_inmemory.py diff --git a/._coverage_api.json b/._coverage_api.json new file mode 100644 index 00000000..b153924e --- /dev/null +++ b/._coverage_api.json @@ -0,0 +1,3177 @@ +[ + { + "source": "kmip/version.py", + "module": "kmip.version", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/__init__.py", + "module": "kmip.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/attributes.py", + "module": "kmip.core.attributes", + "tests": [ + "kmip/tests/unit/core/test_enums.py", + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_attribute.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "UniqueIdentifier": [], + "PrivateKeyUniqueIdentifier": [], + "PublicKeyUniqueIdentifier": [], + "Name": [ + "read", + "write", + "validate", + "create" + ], + "ObjectType": [], + "CryptographicAlgorithm": [], + "CryptographicLength": [], + "HashingAlgorithm": [], + "CryptographicParameters": [ + "block_cipher_mode", + "block_cipher_mode", + "padding_method", + "padding_method", + "hashing_algorithm", + "hashing_algorithm", + "key_role_type", + "key_role_type", + "digital_signature_algorithm", + "digital_signature_algorithm", + "cryptographic_algorithm", + "cryptographic_algorithm", + "random_iv", + "random_iv", + "iv_length", + "iv_length", + "tag_length", + "tag_length", + "fixed_field_length", + "fixed_field_length", + "invocation_field_length", + "invocation_field_length", + "counter_length", + "counter_length", + "initial_counter_value", + "initial_counter_value", + "read", + "write" + ], + "CertificateType": [], + "DigestValue": [], + "Digest": [ + "read", + "write", + "validate", + "create" + ], + "OperationPolicyName": [], + "CryptographicUsageMask": [], + "State": [], + "ApplicationSpecificInformation": [ + "application_namespace", + "application_namespace", + "application_data", + "application_data", + "read", + "write" + ], + "ContactInformation": [], + "CustomAttribute": [], + "DerivationParameters": [ + "cryptographic_parameters", + "cryptographic_parameters", + "initialization_vector", + "initialization_vector", + "derivation_data", + "derivation_data", + "salt", + "salt", + "iteration_count", + "iteration_count", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/config_helper.py", + "module": "kmip.core.config_helper", + "tests": [ + "kmip/tests/unit/core/test_config_helper.py" + ], + "public_classes": { + "ConfigHelper": [ + "get_valid_value" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/enums.py", + "module": "kmip.core.enums", + "tests": [ + "kmip/tests/unit/core/test_enums.py", + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/factories/payloads/test_payload.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_sqltypes.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "OrderedEnum": [], + "AdjustmentType": [], + "AlternativeNameType": [], + "AsynchronousIndicator": [], + "AttestationType": [], + "AttributeType": [], + "AuthenticationSuite": [], + "BatchErrorContinuationOption": [], + "BlockCipherMode": [], + "CancellationResult": [], + "CertificateRequestType": [], + "CertificateType": [], + "ClientRegistrationMethod": [], + "ConformanceClause": [], + "CredentialType": [], + "CryptographicAlgorithm": [], + "CryptographicUsageMask": [], + "Data": [], + "DerivationMethod": [], + "DestroyAction": [], + "DigitalSignatureAlgorithm": [], + "DRBGAlgorithm": [], + "EncodingOption": [], + "EndpointRole": [], + "FIPS186Variation": [], + "HashingAlgorithm": [], + "InteropFunction": [], + "ItemType": [], + "KeyCompressionType": [], + "KeyFormatType": [], + "KeyRoleType": [], + "KeyValueLocationType": [], + "KeyWrapType": [], + "KMIPVersion": [], + "LinkType": [], + "MaskGenerator": [], + "NameType": [], + "NISTKeyType": [], + "ObjectGroupMember": [], + "ObjectType": [], + "OpaqueDataType": [], + "Operation": [], + "PaddingMethod": [], + "PKCS11Function": [], + "PKCS11ReturnCode": [], + "Policy": [], + "ProfileName": [], + "ProtectionLevel": [], + "ProtectionStorageMask": [], + "PutFunction": [], + "QueryFunction": [], + "RecommendedCurve": [], + "ResultReason": [], + "ResultStatus": [], + "RevocationReasonCode": [], + "RNGAlgorithm": [], + "RNGMode": [], + "SecretDataType": [], + "ShreddingAlgorithm": [], + "SplitKeyMethod": [], + "State": [], + "StorageStatusMask": [], + "Tags": [], + "TicketType": [], + "Types": [], + "UniqueIdentifier": [], + "UnwrapMode": [], + "UsageLimitsUnit": [], + "ValidationAuthorityType": [], + "ValidationType": [], + "ValidityIndicator": [], + "WrappingMethod": [] + }, + "public_functions": [ + "convert_attribute_name_to_tag", + "convert_attribute_tag_to_name", + "get_bit_mask_from_enumerations", + "get_enumerations_from_bit_mask", + "is_bit_mask", + "is_enum_value", + "is_attribute" + ], + "missing_classes": [ + "OrderedEnum", + "AdjustmentType", + "AlternativeNameType", + "CertificateRequestType", + "EndpointRole", + "InteropFunction", + "ItemType", + "KeyValueLocationType", + "KeyWrapType", + "LinkType", + "MaskGenerator", + "NISTKeyType", + "PKCS11Function", + "PKCS11ReturnCode", + "ProtectionLevel", + "PutFunction", + "TicketType", + "UsageLimitsUnit" + ], + "missing_methods": { + "OrderedEnum": [], + "AdjustmentType": [], + "AlternativeNameType": [], + "CertificateRequestType": [], + "EndpointRole": [], + "InteropFunction": [], + "ItemType": [], + "KeyValueLocationType": [], + "KeyWrapType": [], + "LinkType": [], + "MaskGenerator": [], + "NISTKeyType": [], + "PKCS11Function": [], + "PKCS11ReturnCode": [], + "ProtectionLevel": [], + "PutFunction": [], + "TicketType": [], + "UsageLimitsUnit": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/exceptions.py", + "module": "kmip.core.exceptions", + "tests": [ + "kmip/tests/unit/core/test_utils.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/services/server/test_config.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "KmipError": [], + "CryptographicFailure": [], + "EncodingOptionError": [], + "IllegalOperation": [], + "IndexOutOfBounds": [], + "InvalidField": [], + "InvalidMessage": [], + "ItemNotFound": [], + "KeyCompressionTypeNotSupported": [], + "KeyFormatTypeNotSupported": [], + "OperationFailure": [], + "OperationNotSupported": [], + "PermissionDenied": [], + "AttributeNotSupported": [], + "ConfigurationError": [], + "ConnectionClosed": [], + "NetworkingError": [], + "InvalidKmipEncoding": [], + "InvalidPaddingBytes": [], + "InvalidPrimitiveLength": [], + "ShutdownError": [], + "VersionNotSupported": [], + "StreamNotEmptyError": [], + "ReadValueError": [], + "WriteOverflowError": [], + "KMIPServerZombieError": [], + "KMIPServerSuicideError": [], + "ErrorStrings": [] + }, + "public_functions": [], + "missing_classes": [ + "WriteOverflowError", + "KMIPServerZombieError", + "KMIPServerSuicideError" + ], + "missing_methods": { + "WriteOverflowError": [], + "KMIPServerZombieError": [], + "KMIPServerSuicideError": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/misc.py", + "module": "kmip.core.misc", + "tests": [ + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "CertificateValue": [], + "Offset": [], + "QueryFunction": [], + "VendorIdentification": [], + "ServerInformation": [ + "read", + "write", + "validate" + ], + "KeyFormatType": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "ServerInformation": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/objects.py", + "module": "kmip.core.objects", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_attribute.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "Attribute": [ + "read", + "write" + ], + "CurrentAttribute": [ + "attribute", + "attribute", + "read", + "write" + ], + "NewAttribute": [ + "attribute", + "attribute", + "read", + "write" + ], + "AttributeReference": [ + "vendor_identification", + "vendor_identification", + "attribute_name", + "attribute_name", + "read", + "write" + ], + "Attributes": [ + "attributes", + "attributes", + "read", + "write" + ], + "Nonce": [ + "nonce_id", + "nonce_id", + "nonce_value", + "nonce_value", + "read", + "write" + ], + "CredentialValue": [], + "UsernamePasswordCredential": [ + "username", + "username", + "password", + "password", + "read", + "write" + ], + "DeviceCredential": [ + "device_serial_number", + "device_serial_number", + "password", + "password", + "device_identifier", + "device_identifier", + "network_identifier", + "network_identifier", + "machine_identifier", + "machine_identifier", + "media_identifier", + "media_identifier", + "read", + "write" + ], + "AttestationCredential": [ + "nonce", + "nonce", + "attestation_type", + "attestation_type", + "attestation_measurement", + "attestation_measurement", + "attestation_assertion", + "attestation_assertion", + "read", + "write" + ], + "Credential": [ + "credential_type", + "credential_type", + "credential_value", + "credential_value", + "read", + "write" + ], + "KeyBlock": [ + "read", + "write", + "validate" + ], + "KeyMaterial": [], + "KeyMaterialStruct": [ + "read", + "write", + "validate" + ], + "KeyValue": [ + "read", + "write", + "validate" + ], + "EncryptionKeyInformation": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "read", + "write" + ], + "MACSignatureKeyInformation": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "read", + "write" + ], + "KeyWrappingData": [ + "wrapping_method", + "wrapping_method", + "encryption_key_information", + "encryption_key_information", + "mac_signature_key_information", + "mac_signature_key_information", + "mac_signature", + "mac_signature", + "iv_counter_nonce", + "iv_counter_nonce", + "encoding_option", + "encoding_option", + "read", + "write" + ], + "KeyWrappingSpecification": [ + "wrapping_method", + "wrapping_method", + "encryption_key_information", + "encryption_key_information", + "mac_signature_key_information", + "mac_signature_key_information", + "attribute_names", + "attribute_names", + "encoding_option", + "encoding_option", + "read", + "write" + ], + "TemplateAttribute": [ + "read", + "write", + "validate" + ], + "CommonTemplateAttribute": [], + "PrivateKeyTemplateAttribute": [], + "PublicKeyTemplateAttribute": [], + "ExtensionName": [], + "ExtensionTag": [], + "ExtensionType": [], + "ExtensionInformation": [ + "read", + "write", + "validate", + "create" + ], + "Data": [], + "MACData": [], + "RevocationReasonCode": [], + "RevocationReason": [ + "read", + "write", + "validate" + ], + "ObjectDefaults": [ + "object_type", + "object_type", + "attributes", + "attributes", + "read", + "write" + ], + "DefaultsInformation": [ + "object_defaults", + "object_defaults", + "read", + "write" + ], + "RNGParameters": [ + "rng_algorithm", + "rng_algorithm", + "cryptographic_algorithm", + "cryptographic_algorithm", + "cryptographic_length", + "cryptographic_length", + "hashing_algorithm", + "hashing_algorithm", + "drbg_algorithm", + "drbg_algorithm", + "recommended_curve", + "recommended_curve", + "fips186_variation", + "fips186_variation", + "prediction_resistance", + "prediction_resistance", + "read", + "write" + ], + "ProfileInformation": [ + "profile_name", + "profile_name", + "server_uri", + "server_uri", + "server_port", + "server_port", + "read", + "write" + ], + "ValidationInformation": [ + "validation_authority_type", + "validation_authority_type", + "validation_authority_country", + "validation_authority_country", + "validation_authority_uri", + "validation_authority_uri", + "validation_version_major", + "validation_version_major", + "validation_version_minor", + "validation_version_minor", + "validation_type", + "validation_type", + "validation_level", + "validation_level", + "validation_certificate_identifier", + "validation_certificate_identifier", + "validation_certificate_uri", + "validation_certificate_uri", + "validation_vendor_uri", + "validation_vendor_uri", + "validation_profiles", + "validation_profiles", + "read", + "write" + ], + "CapabilityInformation": [ + "streaming_capability", + "streaming_capability", + "asynchronous_capability", + "asynchronous_capability", + "attestation_capability", + "attestation_capability", + "batch_undo_capability", + "batch_undo_capability", + "batch_continue_capability", + "batch_continue_capability", + "unwrap_mode", + "unwrap_mode", + "destroy_action", + "destroy_action", + "shredding_algorithm", + "shredding_algorithm", + "rng_mode", + "rng_mode", + "read", + "write" + ], + "ProtectionStorageMasks": [ + "protection_storage_masks", + "protection_storage_masks", + "read", + "write" + ] + }, + "public_functions": [ + "convert_template_attribute_to_attributes", + "convert_attributes_to_template_attribute" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/policy.py", + "module": "kmip.core.policy", + "tests": [ + "kmip/tests/unit/core/test_policy.py" + ], + "public_classes": {}, + "public_functions": [ + "parse_policy", + "read_policy_from_file" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/primitives.py", + "module": "kmip.core.primitives", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_boolean.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_date_time.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "Base": [ + "is_oversized", + "read_tag", + "read_type", + "read_length", + "read_value", + "read", + "write_tag", + "write_type", + "write_length", + "write_value", + "write", + "validate", + "is_tag_next", + "is_type_next" + ], + "Struct": [], + "Integer": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "LongInteger": [ + "read", + "write", + "validate" + ], + "BigInteger": [ + "read", + "write", + "validate" + ], + "Enumeration": [ + "read", + "write", + "validate" + ], + "Boolean": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "TextString": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "ByteString": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "DateTime": [], + "Interval": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "Base": [ + "is_type_next" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/secrets.py", + "module": "kmip.core.secrets", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py" + ], + "public_classes": { + "Certificate": [ + "read", + "write" + ], + "KeyBlockKey": [ + "read", + "write", + "validate" + ], + "SymmetricKey": [ + "validate" + ], + "PublicKey": [ + "validate" + ], + "PrivateKey": [ + "validate" + ], + "SplitKey": [ + "split_key_parts", + "split_key_parts", + "key_part_identifier", + "key_part_identifier", + "split_key_threshold", + "split_key_threshold", + "split_key_method", + "split_key_method", + "prime_field_size", + "prime_field_size", + "key_block", + "key_block", + "read", + "write" + ], + "Template": [ + "read", + "write", + "validate" + ], + "SecretData": [ + "read", + "write", + "validate" + ], + "OpaqueObject": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [ + "KeyBlockKey" + ], + "missing_methods": { + "KeyBlockKey": [ + "read", + "write", + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/utils.py", + "module": "kmip.core.utils", + "tests": [ + "kmip/tests/unit/core/test_utils.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_boolean.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_date_time.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_archive.py", + "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "kmip/tests/unit/core/messages/payloads/test_check.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py", + "kmip/tests/unit/core/messages/payloads/test_poll.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_recover.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "BytearrayStream": [ + "read", + "readall", + "readinto", + "peek", + "write", + "length" + ] + }, + "public_functions": [ + "bit_length", + "count_bytes", + "print_bytearray", + "hexlify_bytearray", + "is_stream_empty", + "build_er_error" + ], + "missing_classes": [], + "missing_methods": { + "BytearrayStream": [ + "readall", + "readinto", + "peek" + ] + }, + "missing_functions": [ + "bit_length", + "print_bytearray", + "is_stream_empty", + "build_er_error" + ] + }, + { + "source": "kmip/core/__init__.py", + "module": "kmip.core.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/pie/client.py", + "module": "kmip.pie.client", + "tests": [ + "kmip/tests/unit/pie/test_client.py" + ], + "public_classes": { + "ProxyKmipClient": [ + "kmip_version", + "kmip_version", + "open", + "close", + "create", + "create_key_pair", + "delete_attribute", + "set_attribute", + "modify_attribute", + "register", + "rekey", + "derive_key", + "locate", + "check", + "get", + "get_attributes", + "get_attribute_list", + "activate", + "revoke", + "destroy", + "encrypt", + "decrypt", + "signature_verify", + "sign", + "mac" + ] + }, + "public_functions": [ + "is_connected" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [ + "is_connected" + ] + }, + { + "source": "kmip/pie/exceptions.py", + "module": "kmip.pie.exceptions", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "public_classes": { + "ClientConnectionFailure": [], + "ClientConnectionNotOpen": [], + "KmipOperationFailure": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/pie/factory.py", + "module": "kmip.pie.factory", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py" + ], + "public_classes": { + "ObjectFactory": [ + "convert" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/pie/objects.py", + "module": "kmip.pie.objects", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_cryptographic_object.py", + "kmip/tests/unit/pie/objects/test_key.py", + "kmip/tests/unit/pie/objects/test_managed_object.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "ManagedObject": [ + "object_type", + "object_type", + "validate" + ], + "CryptographicObject": [], + "Key": [ + "key_wrapping_data", + "key_wrapping_data" + ], + "SymmetricKey": [ + "validate" + ], + "PublicKey": [ + "validate" + ], + "PrivateKey": [ + "validate" + ], + "SplitKey": [ + "split_key_parts", + "split_key_parts", + "key_part_identifier", + "key_part_identifier", + "split_key_threshold", + "split_key_threshold", + "split_key_method", + "split_key_method", + "prime_field_size", + "prime_field_size" + ], + "Certificate": [ + "validate" + ], + "X509Certificate": [], + "SecretData": [ + "validate" + ], + "OpaqueObject": [ + "validate" + ], + "ApplicationSpecificInformation": [ + "application_namespace", + "application_namespace", + "application_data", + "application_data" + ], + "ObjectGroup": [ + "object_group", + "object_group" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/pie/sqltypes.py", + "module": "kmip.pie.sqltypes", + "tests": [ + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_sqltypes.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "UsageMaskType": [ + "process_bind_param", + "process_result_value" + ], + "EnumType": [ + "process_bind_param", + "process_result_value" + ], + "ManagedObjectName": [] + }, + "public_functions": [ + "attribute_append_factory" + ], + "missing_classes": [ + "UsageMaskType", + "EnumType" + ], + "missing_methods": { + "UsageMaskType": [ + "process_bind_param", + "process_result_value" + ], + "EnumType": [ + "process_bind_param", + "process_result_value" + ] + }, + "missing_functions": [ + "attribute_append_factory" + ] + }, + { + "source": "kmip/pie/__init__.py", + "module": "kmip.pie.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/auth.py", + "module": "kmip.services.auth", + "tests": [ + "kmip/tests/unit/services/test_auth.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/services/server/test_server.py" + ], + "public_classes": { + "AuthenticationSuite": [ + "protocol", + "ciphers" + ], + "BasicAuthenticationSuite": [], + "TLS12AuthenticationSuite": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/kmip_client.py", + "module": "kmip.services.kmip_client", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "public_classes": { + "KMIPProxy": [ + "kmip_version", + "kmip_version", + "get_supported_conformance_clauses", + "get_supported_authentication_suites", + "is_conformance_clause_supported", + "is_authentication_suite_supported", + "is_profile_supported", + "open", + "close", + "send_request_payload", + "create", + "create_key_pair", + "activate", + "rekey", + "derive_key", + "check", + "get", + "get_attributes", + "get_attribute_list", + "revoke", + "destroy", + "register", + "rekey_key_pair", + "locate", + "query", + "discover_versions", + "encrypt", + "decrypt", + "signature_verify", + "sign", + "mac" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "KMIPProxy": [ + "rekey_key_pair", + "query", + "discover_versions" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/kmip_protocol.py", + "module": "kmip.services.kmip_protocol", + "tests": [ + "kmip/tests/unit/services/test_kmip_protocol.py" + ], + "public_classes": { + "KMIPProtocol": [ + "write", + "read" + ], + "KMIPProtocolFactory": [ + "getProtocol" + ], + "RequestLengthMismatch": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/results.py", + "module": "kmip.services.results", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "public_classes": { + "OperationResult": [], + "CreateResult": [], + "CreateKeyPairResult": [], + "ActivateResult": [], + "RegisterResult": [], + "RekeyKeyPairResult": [], + "GetResult": [], + "GetAttributesResult": [], + "GetAttributeListResult": [], + "DestroyResult": [], + "LocateResult": [], + "QueryResult": [], + "DiscoverVersionsResult": [], + "RevokeResult": [], + "MACResult": [] + }, + "public_functions": [], + "missing_classes": [ + "ActivateResult", + "DestroyResult", + "RevokeResult" + ], + "missing_methods": { + "ActivateResult": [], + "DestroyResult": [], + "RevokeResult": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/__init__.py", + "module": "kmip.services.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/attributes.py", + "module": "kmip.core.factories.attributes", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "AttributeFactory": [ + "create_attribute" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/attribute_values.py", + "module": "kmip.core.factories.attribute_values", + "tests": [ + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "public_classes": { + "AttributeValueFactory": [ + "create_attribute_value", + "create_attribute_value_by_enum" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/credentials.py", + "module": "kmip.core.factories.credentials", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "public_classes": { + "CredentialFactory": [ + "create_credential", + "create_username_password_credential", + "create_device_credential" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "CredentialFactory": [ + "create_credential", + "create_username_password_credential", + "create_device_credential" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/secrets.py", + "module": "kmip.core.factories.secrets", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "public_classes": { + "SecretFactory": [ + "create" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/__init__.py", + "module": "kmip.core.factories.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/contents.py", + "module": "kmip.core.messages.contents", + "tests": [ + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/factories/payloads/test_payload.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "ProtocolVersion": [ + "major", + "major", + "minor", + "minor", + "read", + "write" + ], + "Operation": [], + "MaximumResponseSize": [], + "UniqueBatchItemID": [], + "TimeStamp": [], + "Authentication": [ + "credentials", + "credentials", + "read", + "write" + ], + "AsynchronousIndicator": [], + "AsynchronousCorrelationValue": [], + "ResultStatus": [], + "ResultReason": [], + "ResultMessage": [], + "BatchOrderOption": [], + "BatchErrorContinuationOption": [], + "BatchCount": [], + "MessageExtension": [], + "ServerCorrelationValue": [], + "KeyCompressionType": [] + }, + "public_functions": [ + "protocol_version_to_kmip_version" + ], + "missing_classes": [ + "AsynchronousCorrelationValue", + "MessageExtension", + "ServerCorrelationValue" + ], + "missing_methods": { + "AsynchronousCorrelationValue": [], + "MessageExtension": [], + "ServerCorrelationValue": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/messages.py", + "module": "kmip.core.messages.messages", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "RequestHeader": [ + "read", + "write" + ], + "ResponseHeader": [ + "server_hashed_password", + "server_hashed_password", + "read", + "write", + "validate" + ], + "RequestBatchItem": [ + "ephemeral", + "ephemeral", + "read", + "write" + ], + "ResponseBatchItem": [ + "read", + "write", + "validate" + ], + "RequestMessage": [ + "read", + "write" + ], + "ResponseMessage": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "ResponseHeader": [ + "validate" + ], + "ResponseBatchItem": [ + "validate" + ], + "ResponseMessage": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/__init__.py", + "module": "kmip.core.messages.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/payloads/request.py", + "module": "kmip.core.factories.payloads.request", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py" + ], + "public_classes": { + "RequestPayloadFactory": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/payloads/response.py", + "module": "kmip.core.factories.payloads.response", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_response.py" + ], + "public_classes": { + "ResponsePayloadFactory": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/factories/payloads/__init__.py", + "module": "kmip.core.factories.payloads.__init__", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_payload.py" + ], + "public_classes": { + "PayloadFactory": [ + "create" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/activate.py", + "module": "kmip.core.messages.payloads.activate", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "ActivateRequestPayload": [ + "read", + "write", + "validate" + ], + "ActivateResponsePayload": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "ActivateRequestPayload": [ + "validate" + ], + "ActivateResponsePayload": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/archive.py", + "module": "kmip.core.messages.payloads.archive", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_archive.py" + ], + "public_classes": { + "ArchiveRequestPayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ], + "ArchiveResponsePayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/base.py", + "module": "kmip.core.messages.payloads.base", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "public_classes": { + "RequestPayload": [], + "ResponsePayload": [] + }, + "public_functions": [], + "missing_classes": [ + "ResponsePayload" + ], + "missing_methods": { + "ResponsePayload": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/cancel.py", + "module": "kmip.core.messages.payloads.cancel", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_cancel.py" + ], + "public_classes": { + "CancelRequestPayload": [ + "asynchronous_correlation_value", + "asynchronous_correlation_value", + "read", + "write" + ], + "CancelResponsePayload": [ + "asynchronous_correlation_value", + "asynchronous_correlation_value", + "cancellation_result", + "cancellation_result", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/check.py", + "module": "kmip.core.messages.payloads.check", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_check.py" + ], + "public_classes": { + "CheckRequestPayload": [ + "unique_identifier", + "unique_identifier", + "usage_limits_count", + "usage_limits_count", + "cryptographic_usage_mask", + "cryptographic_usage_mask", + "lease_time", + "lease_time", + "read", + "write" + ], + "CheckResponsePayload": [ + "unique_identifier", + "unique_identifier", + "usage_limits_count", + "usage_limits_count", + "cryptographic_usage_mask", + "cryptographic_usage_mask", + "lease_time", + "lease_time", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/create.py", + "module": "kmip.core.messages.payloads.create", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "CreateRequestPayload": [ + "object_type", + "object_type", + "template_attribute", + "template_attribute", + "protection_storage_masks", + "protection_storage_masks", + "read", + "write" + ], + "CreateResponsePayload": [ + "object_type", + "object_type", + "unique_identifier", + "unique_identifier", + "template_attribute", + "template_attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/create_key_pair.py", + "module": "kmip.core.messages.payloads.create_key_pair", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "CreateKeyPairRequestPayload": [ + "common_template_attribute", + "common_template_attribute", + "private_key_template_attribute", + "private_key_template_attribute", + "public_key_template_attribute", + "public_key_template_attribute", + "common_protection_storage_masks", + "common_protection_storage_masks", + "private_protection_storage_masks", + "private_protection_storage_masks", + "public_protection_storage_masks", + "public_protection_storage_masks", + "read", + "write" + ], + "CreateKeyPairResponsePayload": [ + "private_key_unique_identifier", + "private_key_unique_identifier", + "public_key_unique_identifier", + "public_key_unique_identifier", + "private_key_template_attribute", + "private_key_template_attribute", + "public_key_template_attribute", + "public_key_template_attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/decrypt.py", + "module": "kmip.core.messages.payloads.decrypt", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "DecryptRequestPayload": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "data", + "data", + "iv_counter_nonce", + "iv_counter_nonce", + "auth_additional_data", + "auth_additional_data", + "auth_tag", + "auth_tag", + "read", + "write" + ], + "DecryptResponsePayload": [ + "unique_identifier", + "unique_identifier", + "data", + "data", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/delete_attribute.py", + "module": "kmip.core.messages.payloads.delete_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "DeleteAttributeRequestPayload": [ + "unique_identifier", + "unique_identifier", + "attribute_name", + "attribute_name", + "attribute_index", + "attribute_index", + "current_attribute", + "current_attribute", + "attribute_reference", + "attribute_reference", + "read", + "write" + ], + "DeleteAttributeResponsePayload": [ + "unique_identifier", + "unique_identifier", + "attribute", + "attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/derive_key.py", + "module": "kmip.core.messages.payloads.derive_key", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "DeriveKeyRequestPayload": [ + "object_type", + "object_type", + "unique_identifiers", + "unique_identifiers", + "derivation_method", + "derivation_method", + "derivation_parameters", + "derivation_parameters", + "template_attribute", + "template_attribute", + "read", + "write" + ], + "DeriveKeyResponsePayload": [ + "unique_identifier", + "unique_identifier", + "template_attribute", + "template_attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/destroy.py", + "module": "kmip.core.messages.payloads.destroy", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "DestroyRequestPayload": [ + "read", + "write", + "validate" + ], + "DestroyResponsePayload": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "DestroyRequestPayload": [ + "validate" + ], + "DestroyResponsePayload": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/discover_versions.py", + "module": "kmip.core.messages.payloads.discover_versions", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "DiscoverVersionsRequestPayload": [ + "read", + "write", + "validate" + ], + "DiscoverVersionsResponsePayload": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "DiscoverVersionsRequestPayload": [ + "validate" + ], + "DiscoverVersionsResponsePayload": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/encrypt.py", + "module": "kmip.core.messages.payloads.encrypt", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "EncryptRequestPayload": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "data", + "data", + "iv_counter_nonce", + "iv_counter_nonce", + "auth_additional_data", + "auth_additional_data", + "read", + "write" + ], + "EncryptResponsePayload": [ + "unique_identifier", + "unique_identifier", + "data", + "data", + "iv_counter_nonce", + "iv_counter_nonce", + "auth_tag", + "auth_tag", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/get.py", + "module": "kmip.core.messages.payloads.get", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "GetRequestPayload": [ + "unique_identifier", + "unique_identifier", + "key_format_type", + "key_format_type", + "key_compression_type", + "key_compression_type", + "key_wrapping_specification", + "key_wrapping_specification", + "read", + "write" + ], + "GetResponsePayload": [ + "object_type", + "object_type", + "unique_identifier", + "unique_identifier", + "secret", + "secret", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/get_attributes.py", + "module": "kmip.core.messages.payloads.get_attributes", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "GetAttributesRequestPayload": [ + "unique_identifier", + "unique_identifier", + "attribute_names", + "attribute_names", + "read", + "write" + ], + "GetAttributesResponsePayload": [ + "unique_identifier", + "unique_identifier", + "attributes", + "attributes", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/get_attribute_list.py", + "module": "kmip.core.messages.payloads.get_attribute_list", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "GetAttributeListRequestPayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ], + "GetAttributeListResponsePayload": [ + "unique_identifier", + "unique_identifier", + "attribute_names", + "attribute_names", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/get_usage_allocation.py", + "module": "kmip.core.messages.payloads.get_usage_allocation", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py" + ], + "public_classes": { + "GetUsageAllocationRequestPayload": [ + "unique_identifier", + "unique_identifier", + "usage_limits_count", + "usage_limits_count", + "read", + "write" + ], + "GetUsageAllocationResponsePayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/locate.py", + "module": "kmip.core.messages.payloads.locate", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "LocateRequestPayload": [ + "maximum_items", + "maximum_items", + "offset_items", + "offset_items", + "storage_status_mask", + "storage_status_mask", + "object_group_member", + "object_group_member", + "attributes", + "attributes", + "read", + "write" + ], + "LocateResponsePayload": [ + "located_items", + "located_items", + "unique_identifiers", + "unique_identifiers", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/mac.py", + "module": "kmip.core.messages.payloads.mac", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "MACRequestPayload": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "data", + "data", + "read", + "write" + ], + "MACResponsePayload": [ + "unique_identifier", + "unique_identifier", + "mac_data", + "mac_data", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/modify_attribute.py", + "module": "kmip.core.messages.payloads.modify_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "ModifyAttributeRequestPayload": [ + "unique_identifier", + "unique_identifier", + "attribute", + "attribute", + "current_attribute", + "current_attribute", + "new_attribute", + "new_attribute", + "read", + "write" + ], + "ModifyAttributeResponsePayload": [ + "unique_identifier", + "unique_identifier", + "attribute", + "attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/obtain_lease.py", + "module": "kmip.core.messages.payloads.obtain_lease", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py" + ], + "public_classes": { + "ObtainLeaseRequestPayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ], + "ObtainLeaseResponsePayload": [ + "unique_identifier", + "unique_identifier", + "lease_time", + "lease_time", + "last_change_date", + "last_change_date", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/poll.py", + "module": "kmip.core.messages.payloads.poll", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_poll.py" + ], + "public_classes": { + "PollRequestPayload": [ + "asynchronous_correlation_value", + "asynchronous_correlation_value", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/query.py", + "module": "kmip.core.messages.payloads.query", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "QueryRequestPayload": [ + "query_functions", + "query_functions", + "read", + "write" + ], + "QueryResponsePayload": [ + "operations", + "operations", + "object_types", + "object_types", + "vendor_identification", + "vendor_identification", + "server_information", + "server_information", + "application_namespaces", + "application_namespaces", + "extension_information", + "extension_information", + "attestation_types", + "attestation_types", + "rng_parameters", + "rng_parameters", + "profile_information", + "profile_information", + "validation_information", + "validation_information", + "capability_information", + "capability_information", + "client_registration_methods", + "client_registration_methods", + "defaults_information", + "defaults_information", + "protection_storage_masks", + "protection_storage_masks", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/recover.py", + "module": "kmip.core.messages.payloads.recover", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_recover.py" + ], + "public_classes": { + "RecoverRequestPayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ], + "RecoverResponsePayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/register.py", + "module": "kmip.core.messages.payloads.register", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "RegisterRequestPayload": [ + "object_type", + "object_type", + "template_attribute", + "template_attribute", + "managed_object", + "managed_object", + "protection_storage_masks", + "protection_storage_masks", + "read", + "write" + ], + "RegisterResponsePayload": [ + "unique_identifier", + "unique_identifier", + "template_attribute", + "template_attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/rekey.py", + "module": "kmip.core.messages.payloads.rekey", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py" + ], + "public_classes": { + "RekeyRequestPayload": [ + "unique_identifier", + "unique_identifier", + "offset", + "offset", + "template_attribute", + "template_attribute", + "read", + "write" + ], + "RekeyResponsePayload": [ + "unique_identifier", + "unique_identifier", + "template_attribute", + "template_attribute", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/rekey_key_pair.py", + "module": "kmip.core.messages.payloads.rekey_key_pair", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py" + ], + "public_classes": { + "RekeyKeyPairRequestPayload": [ + "read", + "write", + "validate" + ], + "RekeyKeyPairResponsePayload": [] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "RekeyKeyPairRequestPayload": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/revoke.py", + "module": "kmip.core.messages.payloads.revoke", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "RevokeRequestPayload": [ + "read", + "write", + "validate" + ], + "RevokeResponsePayload": [ + "read", + "write", + "validate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": { + "RevokeRequestPayload": [ + "validate" + ], + "RevokeResponsePayload": [ + "validate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/set_attribute.py", + "module": "kmip.core.messages.payloads.set_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "SetAttributeRequestPayload": [ + "unique_identifier", + "unique_identifier", + "new_attribute", + "new_attribute", + "read", + "write" + ], + "SetAttributeResponsePayload": [ + "unique_identifier", + "unique_identifier", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/sign.py", + "module": "kmip.core.messages.payloads.sign", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "SignRequestPayload": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "data", + "data", + "read", + "write" + ], + "SignResponsePayload": [ + "unique_identifier", + "unique_identifier", + "signature_data", + "signature_data", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/signature_verify.py", + "module": "kmip.core.messages.payloads.signature_verify", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "public_classes": { + "SignatureVerifyRequestPayload": [ + "unique_identifier", + "unique_identifier", + "cryptographic_parameters", + "cryptographic_parameters", + "data", + "data", + "digested_data", + "digested_data", + "signature_data", + "signature_data", + "correlation_value", + "correlation_value", + "init_indicator", + "init_indicator", + "final_indicator", + "final_indicator", + "read", + "write" + ], + "SignatureVerifyResponsePayload": [ + "unique_identifier", + "unique_identifier", + "validity_indicator", + "validity_indicator", + "data", + "data", + "correlation_value", + "correlation_value", + "read", + "write" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/core/messages/payloads/__init__.py", + "module": "kmip.core.messages.payloads.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/config.py", + "module": "kmip.services.server.config", + "tests": [ + "kmip/tests/unit/services/server/test_config.py" + ], + "public_classes": { + "KmipServerConfig": [ + "set_setting", + "load_settings", + "parse_auth_settings" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/engine.py", + "module": "kmip.services.server.engine", + "tests": [ + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "KmipEngine": [ + "process_request", + "build_error_response", + "get_relevant_policy_section", + "is_allowed" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/monitor.py", + "module": "kmip.services.server.monitor", + "tests": [ + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_server.py" + ], + "public_classes": { + "PolicyDirectoryMonitor": [ + "stop", + "scan_policies", + "run", + "initialize_tracking_structures", + "disassociate_policy_and_file", + "restore_or_delete_policy" + ] + }, + "public_functions": [ + "get_json_files" + ], + "missing_classes": [], + "missing_methods": { + "PolicyDirectoryMonitor": [ + "scan_policies" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/server/policy.py", + "module": "kmip.services.server.policy", + "tests": [ + "kmip/tests/unit/services/server/test_policy.py" + ], + "public_classes": { + "AttributeRuleSet": [], + "AttributePolicy": [ + "is_attribute_supported", + "is_attribute_deprecated", + "is_attribute_deletable_by_client", + "is_attribute_modifiable_by_client", + "is_attribute_applicable_to_object_type", + "is_attribute_multivalued", + "get_all_attribute_names" + ] + }, + "public_functions": [], + "missing_classes": [ + "AttributeRuleSet" + ], + "missing_methods": { + "AttributeRuleSet": [] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/server/server.py", + "module": "kmip.services.server.server", + "tests": [ + "kmip/tests/unit/services/server/test_server.py" + ], + "public_classes": { + "KmipServer": [ + "start", + "stop", + "serve" + ] + }, + "public_functions": [ + "build_argument_parser", + "main" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [ + "build_argument_parser", + "main" + ] + }, + { + "source": "kmip/services/server/session.py", + "module": "kmip.services.server.session", + "tests": [ + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "public_classes": { + "KmipSession": [ + "run", + "authenticate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/__init__.py", + "module": "kmip.services.server.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/auth/api.py", + "module": "kmip.services.server.auth.api", + "tests": [], + "public_classes": { + "AuthAPI": [ + "authenticate" + ] + }, + "public_functions": [], + "missing_classes": [ + "AuthAPI" + ], + "missing_methods": { + "AuthAPI": [ + "authenticate" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/server/auth/slugs.py", + "module": "kmip.services.server.auth.slugs", + "tests": [ + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py" + ], + "public_classes": { + "SLUGSConnector": [ + "url", + "url", + "authenticate" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/auth/utils.py", + "module": "kmip.services.server.auth.utils", + "tests": [ + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py", + "kmip/tests/unit/services/server/auth/test_utils.py" + ], + "public_classes": {}, + "public_functions": [ + "get_certificate_from_connection", + "get_extended_key_usage_from_certificate", + "get_common_names_from_certificate", + "get_client_identity_from_certificate" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/auth/__init__.py", + "module": "kmip.services.server.auth.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/crypto/api.py", + "module": "kmip.services.server.crypto.api", + "tests": [], + "public_classes": { + "CryptographicEngine": [ + "create_symmetric_key", + "create_asymmetric_key_pair", + "mac", + "encrypt", + "decrypt", + "sign" + ] + }, + "public_functions": [], + "missing_classes": [ + "CryptographicEngine" + ], + "missing_methods": { + "CryptographicEngine": [ + "create_symmetric_key", + "create_asymmetric_key_pair", + "mac", + "encrypt", + "decrypt", + "sign" + ] + }, + "missing_functions": [] + }, + { + "source": "kmip/services/server/crypto/engine.py", + "module": "kmip.services.server.crypto.engine", + "tests": [ + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "public_classes": { + "CryptographyEngine": [ + "create_symmetric_key", + "create_asymmetric_key_pair", + "mac", + "encrypt", + "decrypt", + "derive_key", + "wrap_key", + "sign", + "verify_signature" + ] + }, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + { + "source": "kmip/services/server/crypto/__init__.py", + "module": "kmip.services.server.crypto.__init__", + "tests": [], + "public_classes": {}, + "public_functions": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + } +] \ No newline at end of file diff --git a/._coverage_focus.json b/._coverage_focus.json new file mode 100644 index 00000000..3b77151e --- /dev/null +++ b/._coverage_focus.json @@ -0,0 +1,429 @@ +{ + "kmip/core/primitives.py": { + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "missing_classes": [ + "Base", + "Struct", + "Integer", + "LongInteger", + "BigInteger", + "ByteString", + "Interval" + ], + "missing_methods": { + "Base": [ + "is_oversized", + "read_tag", + "read_type", + "read_length", + "read_value", + "read", + "write_tag", + "write_type", + "write_length", + "write_value", + "write", + "validate", + "is_tag_next", + "is_type_next" + ], + "Struct": [], + "Integer": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "LongInteger": [ + "read", + "write", + "validate" + ], + "BigInteger": [ + "read", + "write", + "validate" + ], + "Enumeration": [ + "validate" + ], + "Boolean": [ + "read_value", + "write_value", + "validate" + ], + "TextString": [ + "read_value", + "write_value", + "validate" + ], + "ByteString": [ + "read_value", + "read", + "write_value", + "write", + "validate" + ], + "Interval": [ + "read", + "write", + "validate" + ] + }, + "missing_functions": [] + }, + "kmip/core/policy.py": { + "tests": [], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [ + "parse_policy", + "read_policy_from_file" + ] + }, + "kmip/core/factories/attribute_values.py": { + "tests": [], + "missing_classes": [ + "AttributeValueFactory" + ], + "missing_methods": { + "AttributeValueFactory": [ + "create_attribute_value", + "create_attribute_value_by_enum" + ] + }, + "missing_functions": [] + }, + "kmip/core/factories/attributes.py": { + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + "kmip/core/factories/credentials.py": { + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing_classes": [], + "missing_methods": { + "CredentialFactory": [ + "create_credential", + "create_username_password_credential", + "create_device_credential" + ] + }, + "missing_functions": [] + }, + "kmip/core/factories/payloads/__init__.py": { + "tests": [], + "missing_classes": [ + "PayloadFactory" + ], + "missing_methods": { + "PayloadFactory": [ + "create" + ] + }, + "missing_functions": [] + }, + "kmip/core/factories/payloads/request.py": { + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + "kmip/core/factories/payloads/response.py": { + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_response.py" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + "kmip/core/factories/secrets.py": { + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + "kmip/services/server/engine.py": { + "tests": [], + "missing_classes": [ + "KmipEngine" + ], + "missing_methods": { + "KmipEngine": [ + "process_request", + "build_error_response", + "get_relevant_policy_section", + "is_allowed" + ] + }, + "missing_functions": [] + }, + "kmip/services/server/server.py": { + "tests": [], + "missing_classes": [ + "KmipServer" + ], + "missing_methods": { + "KmipServer": [ + "start", + "stop", + "serve" + ] + }, + "missing_functions": [ + "build_argument_parser", + "main" + ] + }, + "kmip/services/server/monitor.py": { + "tests": [], + "missing_classes": [ + "PolicyDirectoryMonitor" + ], + "missing_methods": { + "PolicyDirectoryMonitor": [ + "stop", + "scan_policies", + "run", + "initialize_tracking_structures", + "disassociate_policy_and_file", + "restore_or_delete_policy" + ] + }, + "missing_functions": [ + "get_json_files" + ] + }, + "kmip/services/kmip_client.py": { + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing_classes": [], + "missing_methods": { + "KMIPProxy": [ + "rekey_key_pair", + "query", + "discover_versions" + ] + }, + "missing_functions": [] + }, + "kmip/services/server/crypto/engine.py": { + "tests": [], + "missing_classes": [ + "CryptographyEngine" + ], + "missing_methods": { + "CryptographyEngine": [ + "create_symmetric_key", + "create_asymmetric_key_pair", + "mac", + "encrypt", + "decrypt", + "derive_key", + "wrap_key", + "sign", + "verify_signature" + ] + }, + "missing_functions": [] + }, + "kmip/services/auth.py": { + "tests": [], + "missing_classes": [ + "AuthenticationSuite", + "BasicAuthenticationSuite", + "TLS12AuthenticationSuite" + ], + "missing_methods": { + "AuthenticationSuite": [ + "protocol", + "ciphers" + ], + "BasicAuthenticationSuite": [], + "TLS12AuthenticationSuite": [] + }, + "missing_functions": [] + }, + "kmip/core/config_helper.py": { + "tests": [ + "kmip/tests/unit/core/test_config_helper.py" + ], + "missing_classes": [], + "missing_methods": {}, + "missing_functions": [] + }, + "kmip/core/exceptions.py": { + "tests": [], + "missing_classes": [ + "KmipError", + "CryptographicFailure", + "EncodingOptionError", + "IllegalOperation", + "IndexOutOfBounds", + "InvalidField", + "InvalidMessage", + "ItemNotFound", + "KeyCompressionTypeNotSupported", + "KeyFormatTypeNotSupported", + "OperationFailure", + "OperationNotSupported", + "PermissionDenied", + "AttributeNotSupported", + "ConfigurationError", + "ConnectionClosed", + "NetworkingError", + "InvalidKmipEncoding", + "InvalidPaddingBytes", + "InvalidPrimitiveLength", + "ShutdownError", + "VersionNotSupported", + "StreamNotEmptyError", + "ReadValueError", + "WriteOverflowError", + "KMIPServerZombieError", + "KMIPServerSuicideError", + "ErrorStrings" + ], + "missing_methods": { + "KmipError": [], + "CryptographicFailure": [], + "EncodingOptionError": [], + "IllegalOperation": [], + "IndexOutOfBounds": [], + "InvalidField": [], + "InvalidMessage": [], + "ItemNotFound": [], + "KeyCompressionTypeNotSupported": [], + "KeyFormatTypeNotSupported": [], + "OperationFailure": [], + "OperationNotSupported": [], + "PermissionDenied": [], + "AttributeNotSupported": [], + "ConfigurationError": [], + "ConnectionClosed": [], + "NetworkingError": [], + "InvalidKmipEncoding": [], + "InvalidPaddingBytes": [], + "InvalidPrimitiveLength": [], + "ShutdownError": [], + "VersionNotSupported": [], + "StreamNotEmptyError": [], + "ReadValueError": [], + "WriteOverflowError": [], + "KMIPServerZombieError": [], + "KMIPServerSuicideError": [], + "ErrorStrings": [] + }, + "missing_functions": [] + }, + "kmip/core/utils.py": { + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py" + ], + "missing_classes": [], + "missing_methods": { + "BytearrayStream": [ + "readall", + "readinto", + "peek" + ] + }, + "missing_functions": [ + "bit_length", + "count_bytes", + "print_bytearray", + "is_stream_empty", + "build_er_error" + ] + }, + "kmip/pie/objects.py": { + "tests": [ + "kmip/tests/unit/pie/objects/test_cryptographic_object.py", + "kmip/tests/unit/pie/objects/test_key.py", + "kmip/tests/unit/pie/objects/test_managed_object.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py" + ], + "missing_classes": [ + "SplitKey", + "ApplicationSpecificInformation", + "ObjectGroup" + ], + "missing_methods": { + "SplitKey": [ + "split_key_parts", + "split_key_parts", + "key_part_identifier", + "key_part_identifier", + "split_key_threshold", + "split_key_threshold", + "split_key_method", + "split_key_method", + "prime_field_size", + "prime_field_size" + ], + "ApplicationSpecificInformation": [ + "application_namespace", + "application_namespace", + "application_data", + "application_data" + ], + "ObjectGroup": [ + "object_group", + "object_group" + ] + }, + "missing_functions": [] + }, + "kmip/pie/sqltypes.py": { + "tests": [ + "kmip/tests/unit/pie/objects/test_sqltypes.py" + ], + "missing_classes": [ + "UsageMaskType", + "EnumType" + ], + "missing_methods": { + "UsageMaskType": [ + "process_bind_param", + "process_result_value" + ], + "EnumType": [ + "process_bind_param", + "process_result_value" + ] + }, + "missing_functions": [ + "attribute_append_factory" + ] + } +} \ No newline at end of file diff --git a/._coverage_missing.txt b/._coverage_missing.txt new file mode 100644 index 00000000..4672e340 --- /dev/null +++ b/._coverage_missing.txt @@ -0,0 +1,257 @@ +kmip/__init__.py +kmip/core/__init__.py +kmip/core/attributes.py + classes_missing: PublicKeyUniqueIdentifier, State, CustomAttribute +kmip/core/enums.py + classes_missing: OrderedEnum, AdjustmentType, AlternativeNameType, AsynchronousIndicator, AttestationType, BatchErrorContinuationOption, CancellationResult, CertificateRequestType, ClientRegistrationMethod, EndpointRole, InteropFunction, ItemType, KeyCompressionType, KeyValueLocationType, KeyWrapType, LinkType, MaskGenerator, NISTKeyType, ObjectGroupMember, OpaqueDataType, PKCS11Function, PKCS11ReturnCode, ProtectionLevel, PutFunction, RevocationReasonCode, SecretDataType, SplitKeyMethod, StorageStatusMask, TicketType, Types, UsageLimitsUnit + functions_missing: convert_attribute_name_to_tag, convert_attribute_tag_to_name, get_bit_mask_from_enumerations, get_enumerations_from_bit_mask, is_bit_mask, is_enum_value, is_attribute +kmip/core/exceptions.py + classes_missing: KmipError, CryptographicFailure, EncodingOptionError, IllegalOperation, IndexOutOfBounds, InvalidField, InvalidMessage, ItemNotFound, KeyCompressionTypeNotSupported, KeyFormatTypeNotSupported, OperationFailure, OperationNotSupported, PermissionDenied, AttributeNotSupported, ConfigurationError, ConnectionClosed, NetworkingError, InvalidKmipEncoding, InvalidPaddingBytes, InvalidPrimitiveLength, ShutdownError, VersionNotSupported, StreamNotEmptyError, ReadValueError, WriteOverflowError, KMIPServerZombieError, KMIPServerSuicideError, ErrorStrings +kmip/core/factories/__init__.py +kmip/core/factories/attribute_values.py + classes_missing: AttributeValueFactory + methods_missing AttributeValueFactory: create_attribute_value, create_attribute_value_by_enum +kmip/core/factories/attributes.py +kmip/core/factories/credentials.py + methods_missing CredentialFactory: create_credential, create_username_password_credential, create_device_credential +kmip/core/factories/payloads/__init__.py + classes_missing: PayloadFactory + methods_missing PayloadFactory: create +kmip/core/factories/secrets.py +kmip/core/messages/__init__.py +kmip/core/messages/contents.py + classes_missing: MaximumResponseSize, UniqueBatchItemID, TimeStamp, Authentication, AsynchronousIndicator, AsynchronousCorrelationValue, BatchOrderOption, BatchErrorContinuationOption, BatchCount, MessageExtension, ServerCorrelationValue, KeyCompressionType + functions_missing: protocol_version_to_kmip_version + methods_missing ProtocolVersion: major, major, minor, minor + methods_missing Authentication: credentials, credentials, read, write +kmip/core/messages/messages.py + classes_missing: RequestHeader, ResponseHeader, RequestMessage + methods_missing RequestHeader: read, write + methods_missing ResponseHeader: server_hashed_password, server_hashed_password, read, write, validate + methods_missing RequestBatchItem: ephemeral, ephemeral, read + methods_missing ResponseBatchItem: read, validate + methods_missing RequestMessage: read, write + methods_missing ResponseMessage: read, validate +kmip/core/messages/payloads/__init__.py +kmip/core/messages/payloads/activate.py + classes_missing: ActivateRequestPayload, ActivateResponsePayload + methods_missing ActivateRequestPayload: read, write, validate + methods_missing ActivateResponsePayload: read, write, validate +kmip/core/messages/payloads/archive.py + classes_missing: ArchiveRequestPayload, ArchiveResponsePayload + methods_missing ArchiveRequestPayload: unique_identifier, unique_identifier, read, write + methods_missing ArchiveResponsePayload: unique_identifier, unique_identifier, read, write +kmip/core/messages/payloads/base.py + classes_missing: RequestPayload, ResponsePayload +kmip/core/messages/payloads/cancel.py + classes_missing: CancelRequestPayload, CancelResponsePayload + methods_missing CancelRequestPayload: asynchronous_correlation_value, asynchronous_correlation_value, read, write + methods_missing CancelResponsePayload: asynchronous_correlation_value, asynchronous_correlation_value, cancellation_result, cancellation_result, read, write +kmip/core/messages/payloads/check.py + classes_missing: CheckRequestPayload, CheckResponsePayload + methods_missing CheckRequestPayload: unique_identifier, unique_identifier, usage_limits_count, usage_limits_count, cryptographic_usage_mask, cryptographic_usage_mask, lease_time, lease_time, read, write + methods_missing CheckResponsePayload: unique_identifier, unique_identifier, usage_limits_count, usage_limits_count, cryptographic_usage_mask, cryptographic_usage_mask, lease_time, lease_time, read, write +kmip/core/messages/payloads/create.py + classes_missing: CreateRequestPayload, CreateResponsePayload + methods_missing CreateRequestPayload: object_type, object_type, template_attribute, template_attribute, protection_storage_masks, protection_storage_masks, read, write + methods_missing CreateResponsePayload: object_type, object_type, unique_identifier, unique_identifier, template_attribute, template_attribute, read, write +kmip/core/messages/payloads/create_key_pair.py + classes_missing: CreateKeyPairRequestPayload, CreateKeyPairResponsePayload + methods_missing CreateKeyPairRequestPayload: common_template_attribute, common_template_attribute, private_key_template_attribute, private_key_template_attribute, public_key_template_attribute, public_key_template_attribute, common_protection_storage_masks, common_protection_storage_masks, private_protection_storage_masks, private_protection_storage_masks, public_protection_storage_masks, public_protection_storage_masks, read, write + methods_missing CreateKeyPairResponsePayload: private_key_unique_identifier, private_key_unique_identifier, public_key_unique_identifier, public_key_unique_identifier, private_key_template_attribute, private_key_template_attribute, public_key_template_attribute, public_key_template_attribute, read, write +kmip/core/messages/payloads/decrypt.py + classes_missing: DecryptRequestPayload, DecryptResponsePayload + methods_missing DecryptRequestPayload: unique_identifier, unique_identifier, cryptographic_parameters, cryptographic_parameters, data, data, iv_counter_nonce, iv_counter_nonce, auth_additional_data, auth_additional_data, auth_tag, auth_tag, read, write + methods_missing DecryptResponsePayload: unique_identifier, unique_identifier, data, data, read, write +kmip/core/messages/payloads/delete_attribute.py + classes_missing: DeleteAttributeRequestPayload, DeleteAttributeResponsePayload + methods_missing DeleteAttributeRequestPayload: unique_identifier, unique_identifier, attribute_name, attribute_name, attribute_index, attribute_index, current_attribute, current_attribute, attribute_reference, attribute_reference, read, write + methods_missing DeleteAttributeResponsePayload: unique_identifier, unique_identifier, attribute, attribute, read, write +kmip/core/messages/payloads/derive_key.py + classes_missing: DeriveKeyRequestPayload, DeriveKeyResponsePayload + methods_missing DeriveKeyRequestPayload: object_type, object_type, unique_identifiers, unique_identifiers, derivation_method, derivation_method, derivation_parameters, derivation_parameters, template_attribute, template_attribute, read, write + methods_missing DeriveKeyResponsePayload: unique_identifier, unique_identifier, template_attribute, template_attribute, read, write +kmip/core/messages/payloads/destroy.py + classes_missing: DestroyRequestPayload, DestroyResponsePayload + methods_missing DestroyRequestPayload: read, write, validate + methods_missing DestroyResponsePayload: read, write, validate +kmip/core/messages/payloads/discover_versions.py + classes_missing: DiscoverVersionsRequestPayload, DiscoverVersionsResponsePayload + methods_missing DiscoverVersionsRequestPayload: read, write, validate + methods_missing DiscoverVersionsResponsePayload: read, write, validate +kmip/core/messages/payloads/encrypt.py + classes_missing: EncryptRequestPayload, EncryptResponsePayload + methods_missing EncryptRequestPayload: unique_identifier, unique_identifier, cryptographic_parameters, cryptographic_parameters, data, data, iv_counter_nonce, iv_counter_nonce, auth_additional_data, auth_additional_data, read, write + methods_missing EncryptResponsePayload: unique_identifier, unique_identifier, data, data, iv_counter_nonce, iv_counter_nonce, auth_tag, auth_tag, read, write +kmip/core/messages/payloads/get.py + classes_missing: GetRequestPayload, GetResponsePayload + methods_missing GetRequestPayload: unique_identifier, unique_identifier, key_format_type, key_format_type, key_compression_type, key_compression_type, key_wrapping_specification, key_wrapping_specification, read, write + methods_missing GetResponsePayload: object_type, object_type, unique_identifier, unique_identifier, secret, secret, read, write +kmip/core/messages/payloads/get_attribute_list.py + classes_missing: GetAttributeListRequestPayload, GetAttributeListResponsePayload + methods_missing GetAttributeListRequestPayload: unique_identifier, unique_identifier, read, write + methods_missing GetAttributeListResponsePayload: unique_identifier, unique_identifier, attribute_names, attribute_names, read, write +kmip/core/messages/payloads/get_attributes.py + classes_missing: GetAttributesRequestPayload, GetAttributesResponsePayload + methods_missing GetAttributesRequestPayload: unique_identifier, unique_identifier, attribute_names, attribute_names, read, write + methods_missing GetAttributesResponsePayload: unique_identifier, unique_identifier, attributes, attributes, read, write +kmip/core/messages/payloads/get_usage_allocation.py + classes_missing: GetUsageAllocationRequestPayload, GetUsageAllocationResponsePayload + methods_missing GetUsageAllocationRequestPayload: unique_identifier, unique_identifier, usage_limits_count, usage_limits_count, read, write + methods_missing GetUsageAllocationResponsePayload: unique_identifier, unique_identifier, read, write +kmip/core/messages/payloads/locate.py + classes_missing: LocateRequestPayload, LocateResponsePayload + methods_missing LocateRequestPayload: maximum_items, maximum_items, offset_items, offset_items, storage_status_mask, storage_status_mask, object_group_member, object_group_member, attributes, attributes, read, write + methods_missing LocateResponsePayload: located_items, located_items, unique_identifiers, unique_identifiers, read, write +kmip/core/messages/payloads/mac.py + classes_missing: MACRequestPayload, MACResponsePayload + methods_missing MACRequestPayload: unique_identifier, unique_identifier, cryptographic_parameters, cryptographic_parameters, data, data, read, write + methods_missing MACResponsePayload: unique_identifier, unique_identifier, mac_data, mac_data, read, write +kmip/core/messages/payloads/modify_attribute.py + classes_missing: ModifyAttributeRequestPayload, ModifyAttributeResponsePayload + methods_missing ModifyAttributeRequestPayload: unique_identifier, unique_identifier, attribute, attribute, current_attribute, current_attribute, new_attribute, new_attribute, read, write + methods_missing ModifyAttributeResponsePayload: unique_identifier, unique_identifier, attribute, attribute, read, write +kmip/core/messages/payloads/obtain_lease.py + classes_missing: ObtainLeaseRequestPayload, ObtainLeaseResponsePayload + methods_missing ObtainLeaseRequestPayload: unique_identifier, unique_identifier, read, write + methods_missing ObtainLeaseResponsePayload: unique_identifier, unique_identifier, lease_time, lease_time, last_change_date, last_change_date, read, write +kmip/core/messages/payloads/poll.py + classes_missing: PollRequestPayload + methods_missing PollRequestPayload: asynchronous_correlation_value, asynchronous_correlation_value, read, write +kmip/core/messages/payloads/query.py + classes_missing: QueryRequestPayload, QueryResponsePayload + methods_missing QueryRequestPayload: query_functions, query_functions, read, write + methods_missing QueryResponsePayload: operations, operations, object_types, object_types, vendor_identification, vendor_identification, server_information, server_information, application_namespaces, application_namespaces, extension_information, extension_information, attestation_types, attestation_types, rng_parameters, rng_parameters, profile_information, profile_information, validation_information, validation_information, capability_information, capability_information, client_registration_methods, client_registration_methods, defaults_information, defaults_information, protection_storage_masks, protection_storage_masks, read, write +kmip/core/messages/payloads/recover.py + classes_missing: RecoverRequestPayload, RecoverResponsePayload + methods_missing RecoverRequestPayload: unique_identifier, unique_identifier, read, write + methods_missing RecoverResponsePayload: unique_identifier, unique_identifier, read, write +kmip/core/messages/payloads/register.py + classes_missing: RegisterRequestPayload, RegisterResponsePayload + methods_missing RegisterRequestPayload: object_type, object_type, template_attribute, template_attribute, managed_object, managed_object, protection_storage_masks, protection_storage_masks, read, write + methods_missing RegisterResponsePayload: unique_identifier, unique_identifier, template_attribute, template_attribute, read, write +kmip/core/messages/payloads/rekey.py + classes_missing: RekeyRequestPayload, RekeyResponsePayload + methods_missing RekeyRequestPayload: unique_identifier, unique_identifier, offset, offset, template_attribute, template_attribute, read, write + methods_missing RekeyResponsePayload: unique_identifier, unique_identifier, template_attribute, template_attribute, read, write +kmip/core/messages/payloads/rekey_key_pair.py + classes_missing: RekeyKeyPairRequestPayload, RekeyKeyPairResponsePayload + methods_missing RekeyKeyPairRequestPayload: read, write, validate +kmip/core/messages/payloads/revoke.py + classes_missing: RevokeRequestPayload, RevokeResponsePayload + methods_missing RevokeRequestPayload: read, write, validate + methods_missing RevokeResponsePayload: read, write, validate +kmip/core/messages/payloads/set_attribute.py + classes_missing: SetAttributeRequestPayload, SetAttributeResponsePayload + methods_missing SetAttributeRequestPayload: unique_identifier, unique_identifier, new_attribute, new_attribute, read, write + methods_missing SetAttributeResponsePayload: unique_identifier, unique_identifier, read, write +kmip/core/messages/payloads/sign.py + classes_missing: SignRequestPayload, SignResponsePayload + methods_missing SignRequestPayload: unique_identifier, unique_identifier, cryptographic_parameters, cryptographic_parameters, data, data, read, write + methods_missing SignResponsePayload: unique_identifier, unique_identifier, signature_data, signature_data, read, write +kmip/core/messages/payloads/signature_verify.py + classes_missing: SignatureVerifyRequestPayload, SignatureVerifyResponsePayload + methods_missing SignatureVerifyRequestPayload: unique_identifier, unique_identifier, cryptographic_parameters, cryptographic_parameters, data, data, digested_data, digested_data, signature_data, signature_data, correlation_value, correlation_value, init_indicator, init_indicator, final_indicator, final_indicator, read, write + methods_missing SignatureVerifyResponsePayload: unique_identifier, unique_identifier, validity_indicator, validity_indicator, data, data, correlation_value, correlation_value, read, write +kmip/core/misc.py + methods_missing ServerInformation: validate +kmip/core/objects.py + classes_missing: CurrentAttribute, CredentialValue, UsernamePasswordCredential, DeviceCredential, AttestationCredential, Credential, KeyBlock, KeyMaterial, KeyValue, Data, MACData, RevocationReasonCode, RevocationReason + methods_missing CurrentAttribute: attribute, attribute, read, write + methods_missing Nonce: nonce_id, nonce_id, nonce_value, nonce_value + methods_missing UsernamePasswordCredential: username, username, password, password, read, write + methods_missing DeviceCredential: device_serial_number, device_serial_number, password, password, device_identifier, device_identifier, network_identifier, network_identifier, machine_identifier, machine_identifier, media_identifier, media_identifier, read, write + methods_missing AttestationCredential: nonce, nonce, attestation_type, attestation_type, attestation_measurement, attestation_measurement, attestation_assertion, attestation_assertion, read, write + methods_missing Credential: credential_type, credential_type, credential_value, credential_value, read, write + methods_missing KeyBlock: read, write, validate + methods_missing KeyMaterialStruct: validate + methods_missing KeyValue: read, write, validate + methods_missing TemplateAttribute: validate + methods_missing ExtensionInformation: validate + methods_missing RevocationReason: read, write, validate +kmip/core/policy.py + functions_missing: parse_policy, read_policy_from_file +kmip/core/primitives.py + classes_missing: Base, Struct, Integer, LongInteger, BigInteger, ByteString, Interval + methods_missing Base: is_oversized, read_tag, read_type, read_length, read_value, read, write_tag, write_type, write_length, write_value, write, validate, is_tag_next, is_type_next + methods_missing Integer: read_value, read, write_value, write, validate + methods_missing LongInteger: read, write, validate + methods_missing BigInteger: read, write, validate + methods_missing Enumeration: validate + methods_missing Boolean: read_value, write_value, validate + methods_missing TextString: read_value, write_value, validate + methods_missing ByteString: read_value, read, write_value, write, validate + methods_missing Interval: read, write, validate +kmip/core/secrets.py + classes_missing: KeyBlockKey, PublicKey, PrivateKey, SplitKey, SecretData, OpaqueObject + methods_missing KeyBlockKey: read, write, validate + methods_missing SymmetricKey: validate + methods_missing PublicKey: validate + methods_missing PrivateKey: validate + methods_missing SplitKey: split_key_parts, split_key_parts, key_part_identifier, key_part_identifier, split_key_threshold, split_key_threshold, split_key_method, split_key_method, prime_field_size, prime_field_size, key_block, key_block, read, write + methods_missing Template: validate + methods_missing SecretData: read, write, validate + methods_missing OpaqueObject: read, write, validate +kmip/core/utils.py + functions_missing: bit_length, count_bytes, print_bytearray, is_stream_empty, build_er_error + methods_missing BytearrayStream: readall, readinto, peek +kmip/pie/__init__.py +kmip/pie/client.py + functions_missing: is_connected +kmip/pie/factory.py + classes_missing: ObjectFactory + methods_missing ObjectFactory: convert +kmip/pie/objects.py + classes_missing: SplitKey, ApplicationSpecificInformation, ObjectGroup + methods_missing SplitKey: split_key_parts, split_key_parts, key_part_identifier, key_part_identifier, split_key_threshold, split_key_threshold, split_key_method, split_key_method, prime_field_size, prime_field_size + methods_missing ApplicationSpecificInformation: application_namespace, application_namespace, application_data, application_data + methods_missing ObjectGroup: object_group, object_group +kmip/pie/sqltypes.py + classes_missing: UsageMaskType, EnumType + functions_missing: attribute_append_factory + methods_missing UsageMaskType: process_bind_param, process_result_value + methods_missing EnumType: process_bind_param, process_result_value +kmip/services/__init__.py +kmip/services/auth.py + classes_missing: AuthenticationSuite, BasicAuthenticationSuite, TLS12AuthenticationSuite + methods_missing AuthenticationSuite: protocol, ciphers +kmip/services/results.py + classes_missing: CreateResult, ActivateResult, RegisterResult, GetResult, DestroyResult, LocateResult, RevokeResult, MACResult +kmip/services/server/__init__.py +kmip/services/server/auth/__init__.py +kmip/services/server/auth/api.py + classes_missing: AuthAPI + methods_missing AuthAPI: authenticate +kmip/services/server/auth/slugs.py + classes_missing: SLUGSConnector + methods_missing SLUGSConnector: url, url, authenticate +kmip/services/server/auth/utils.py + functions_missing: get_certificate_from_connection, get_extended_key_usage_from_certificate, get_common_names_from_certificate, get_client_identity_from_certificate +kmip/services/server/config.py + classes_missing: KmipServerConfig + methods_missing KmipServerConfig: set_setting, load_settings, parse_auth_settings +kmip/services/server/crypto/__init__.py +kmip/services/server/crypto/api.py + classes_missing: CryptographicEngine + methods_missing CryptographicEngine: create_symmetric_key, create_asymmetric_key_pair, mac, encrypt, decrypt, sign +kmip/services/server/crypto/engine.py + classes_missing: CryptographyEngine + methods_missing CryptographyEngine: create_symmetric_key, create_asymmetric_key_pair, mac, encrypt, decrypt, derive_key, wrap_key, sign, verify_signature +kmip/services/server/engine.py + classes_missing: KmipEngine + methods_missing KmipEngine: process_request, build_error_response, get_relevant_policy_section, is_allowed +kmip/services/server/monitor.py + classes_missing: PolicyDirectoryMonitor + functions_missing: get_json_files + methods_missing PolicyDirectoryMonitor: stop, scan_policies, run, initialize_tracking_structures, disassociate_policy_and_file, restore_or_delete_policy +kmip/services/server/policy.py + classes_missing: AttributeRuleSet, AttributePolicy + methods_missing AttributePolicy: is_attribute_supported, is_attribute_deprecated, is_attribute_deletable_by_client, is_attribute_modifiable_by_client, is_attribute_applicable_to_object_type, is_attribute_multivalued, get_all_attribute_names +kmip/services/server/server.py + classes_missing: KmipServer + functions_missing: build_argument_parser, main + methods_missing KmipServer: start, stop, serve +kmip/services/server/session.py + classes_missing: KmipSession + methods_missing KmipSession: run, authenticate +kmip/version.py \ No newline at end of file diff --git a/._coverage_missing_clean.md b/._coverage_missing_clean.md new file mode 100644 index 00000000..83bc9014 --- /dev/null +++ b/._coverage_missing_clean.md @@ -0,0 +1,257 @@ +- kmip/__init__.py +- kmip/core/__init__.py +- kmip/core/attributes.py + classes_missing: PublicKeyUniqueIdentifier, State, CustomAttribute +- kmip/core/enums.py + classes_missing: OrderedEnum, AdjustmentType, AlternativeNameType, AsynchronousIndicator, AttestationType, BatchErrorContinuationOption, CancellationResult, CertificateRequestType, ClientRegistrationMethod, EndpointRole, InteropFunction, ItemType, KeyCompressionType, KeyValueLocationType, KeyWrapType, LinkType, MaskGenerator, NISTKeyType, ObjectGroupMember, OpaqueDataType, PKCS11Function, PKCS11ReturnCode, ProtectionLevel, PutFunction, RevocationReasonCode, SecretDataType, SplitKeyMethod, StorageStatusMask, TicketType, Types, UsageLimitsUnit + functions_missing: convert_attribute_name_to_tag, convert_attribute_tag_to_name, get_bit_mask_from_enumerations, get_enumerations_from_bit_mask, is_bit_mask, is_enum_value, is_attribute +- kmip/core/exceptions.py + classes_missing: KmipError, CryptographicFailure, EncodingOptionError, IllegalOperation, IndexOutOfBounds, InvalidField, InvalidMessage, ItemNotFound, KeyCompressionTypeNotSupported, KeyFormatTypeNotSupported, OperationFailure, OperationNotSupported, PermissionDenied, AttributeNotSupported, ConfigurationError, ConnectionClosed, NetworkingError, InvalidKmipEncoding, InvalidPaddingBytes, InvalidPrimitiveLength, ShutdownError, VersionNotSupported, StreamNotEmptyError, ReadValueError, WriteOverflowError, KMIPServerZombieError, KMIPServerSuicideError, ErrorStrings +- kmip/core/factories/__init__.py +- kmip/core/factories/attribute_values.py + classes_missing: AttributeValueFactory + methods_missing AttributeValueFactory: create_attribute_value, create_attribute_value_by_enum +- kmip/core/factories/attributes.py +- kmip/core/factories/credentials.py + methods_missing CredentialFactory: create_credential, create_username_password_credential, create_device_credential +- kmip/core/factories/payloads/__init__.py + classes_missing: PayloadFactory + methods_missing PayloadFactory: create +- kmip/core/factories/secrets.py +- kmip/core/messages/__init__.py +- kmip/core/messages/contents.py + classes_missing: MaximumResponseSize, UniqueBatchItemID, TimeStamp, Authentication, AsynchronousIndicator, AsynchronousCorrelationValue, BatchOrderOption, BatchErrorContinuationOption, BatchCount, MessageExtension, ServerCorrelationValue, KeyCompressionType + functions_missing: protocol_version_to_kmip_version + methods_missing Authentication: credentials, read, write + methods_missing ProtocolVersion: major, minor +- kmip/core/messages/messages.py + classes_missing: RequestHeader, ResponseHeader, RequestMessage + methods_missing RequestBatchItem: ephemeral, read + methods_missing RequestHeader: read, write + methods_missing RequestMessage: read, write + methods_missing ResponseBatchItem: read, validate + methods_missing ResponseHeader: server_hashed_password, read, write, validate + methods_missing ResponseMessage: read, validate +- kmip/core/messages/payloads/__init__.py +- kmip/core/messages/payloads/activate.py + classes_missing: ActivateRequestPayload, ActivateResponsePayload + methods_missing ActivateRequestPayload: read, write, validate + methods_missing ActivateResponsePayload: read, write, validate +- kmip/core/messages/payloads/archive.py + classes_missing: ArchiveRequestPayload, ArchiveResponsePayload + methods_missing ArchiveRequestPayload: unique_identifier, read, write + methods_missing ArchiveResponsePayload: unique_identifier, read, write +- kmip/core/messages/payloads/base.py + classes_missing: RequestPayload, ResponsePayload +- kmip/core/messages/payloads/cancel.py + classes_missing: CancelRequestPayload, CancelResponsePayload + methods_missing CancelRequestPayload: asynchronous_correlation_value, read, write + methods_missing CancelResponsePayload: asynchronous_correlation_value, cancellation_result, read, write +- kmip/core/messages/payloads/check.py + classes_missing: CheckRequestPayload, CheckResponsePayload + methods_missing CheckRequestPayload: unique_identifier, usage_limits_count, cryptographic_usage_mask, lease_time, read, write + methods_missing CheckResponsePayload: unique_identifier, usage_limits_count, cryptographic_usage_mask, lease_time, read, write +- kmip/core/messages/payloads/create.py + classes_missing: CreateRequestPayload, CreateResponsePayload + methods_missing CreateRequestPayload: object_type, template_attribute, protection_storage_masks, read, write + methods_missing CreateResponsePayload: object_type, unique_identifier, template_attribute, read, write +- kmip/core/messages/payloads/create_key_pair.py + classes_missing: CreateKeyPairRequestPayload, CreateKeyPairResponsePayload + methods_missing CreateKeyPairRequestPayload: common_template_attribute, private_key_template_attribute, public_key_template_attribute, common_protection_storage_masks, private_protection_storage_masks, public_protection_storage_masks, read, write + methods_missing CreateKeyPairResponsePayload: private_key_unique_identifier, public_key_unique_identifier, private_key_template_attribute, public_key_template_attribute, read, write +- kmip/core/messages/payloads/decrypt.py + classes_missing: DecryptRequestPayload, DecryptResponsePayload + methods_missing DecryptRequestPayload: unique_identifier, cryptographic_parameters, data, iv_counter_nonce, auth_additional_data, auth_tag, read, write + methods_missing DecryptResponsePayload: unique_identifier, data, read, write +- kmip/core/messages/payloads/delete_attribute.py + classes_missing: DeleteAttributeRequestPayload, DeleteAttributeResponsePayload + methods_missing DeleteAttributeRequestPayload: unique_identifier, attribute_name, attribute_index, current_attribute, attribute_reference, read, write + methods_missing DeleteAttributeResponsePayload: unique_identifier, attribute, read, write +- kmip/core/messages/payloads/derive_key.py + classes_missing: DeriveKeyRequestPayload, DeriveKeyResponsePayload + methods_missing DeriveKeyRequestPayload: object_type, unique_identifiers, derivation_method, derivation_parameters, template_attribute, read, write + methods_missing DeriveKeyResponsePayload: unique_identifier, template_attribute, read, write +- kmip/core/messages/payloads/destroy.py + classes_missing: DestroyRequestPayload, DestroyResponsePayload + methods_missing DestroyRequestPayload: read, write, validate + methods_missing DestroyResponsePayload: read, write, validate +- kmip/core/messages/payloads/discover_versions.py + classes_missing: DiscoverVersionsRequestPayload, DiscoverVersionsResponsePayload + methods_missing DiscoverVersionsRequestPayload: read, write, validate + methods_missing DiscoverVersionsResponsePayload: read, write, validate +- kmip/core/messages/payloads/encrypt.py + classes_missing: EncryptRequestPayload, EncryptResponsePayload + methods_missing EncryptRequestPayload: unique_identifier, cryptographic_parameters, data, iv_counter_nonce, auth_additional_data, read, write + methods_missing EncryptResponsePayload: unique_identifier, data, iv_counter_nonce, auth_tag, read, write +- kmip/core/messages/payloads/get.py + classes_missing: GetRequestPayload, GetResponsePayload + methods_missing GetRequestPayload: unique_identifier, key_format_type, key_compression_type, key_wrapping_specification, read, write + methods_missing GetResponsePayload: object_type, unique_identifier, secret, read, write +- kmip/core/messages/payloads/get_attribute_list.py + classes_missing: GetAttributeListRequestPayload, GetAttributeListResponsePayload + methods_missing GetAttributeListRequestPayload: unique_identifier, read, write + methods_missing GetAttributeListResponsePayload: unique_identifier, attribute_names, read, write +- kmip/core/messages/payloads/get_attributes.py + classes_missing: GetAttributesRequestPayload, GetAttributesResponsePayload + methods_missing GetAttributesRequestPayload: unique_identifier, attribute_names, read, write + methods_missing GetAttributesResponsePayload: unique_identifier, attributes, read, write +- kmip/core/messages/payloads/get_usage_allocation.py + classes_missing: GetUsageAllocationRequestPayload, GetUsageAllocationResponsePayload + methods_missing GetUsageAllocationRequestPayload: unique_identifier, usage_limits_count, read, write + methods_missing GetUsageAllocationResponsePayload: unique_identifier, read, write +- kmip/core/messages/payloads/locate.py + classes_missing: LocateRequestPayload, LocateResponsePayload + methods_missing LocateRequestPayload: maximum_items, offset_items, storage_status_mask, object_group_member, attributes, read, write + methods_missing LocateResponsePayload: located_items, unique_identifiers, read, write +- kmip/core/messages/payloads/mac.py + classes_missing: MACRequestPayload, MACResponsePayload + methods_missing MACRequestPayload: unique_identifier, cryptographic_parameters, data, read, write + methods_missing MACResponsePayload: unique_identifier, mac_data, read, write +- kmip/core/messages/payloads/modify_attribute.py + classes_missing: ModifyAttributeRequestPayload, ModifyAttributeResponsePayload + methods_missing ModifyAttributeRequestPayload: unique_identifier, attribute, current_attribute, new_attribute, read, write + methods_missing ModifyAttributeResponsePayload: unique_identifier, attribute, read, write +- kmip/core/messages/payloads/obtain_lease.py + classes_missing: ObtainLeaseRequestPayload, ObtainLeaseResponsePayload + methods_missing ObtainLeaseRequestPayload: unique_identifier, read, write + methods_missing ObtainLeaseResponsePayload: unique_identifier, lease_time, last_change_date, read, write +- kmip/core/messages/payloads/poll.py + classes_missing: PollRequestPayload + methods_missing PollRequestPayload: asynchronous_correlation_value, read, write +- kmip/core/messages/payloads/query.py + classes_missing: QueryRequestPayload, QueryResponsePayload + methods_missing QueryRequestPayload: query_functions, read, write + methods_missing QueryResponsePayload: operations, object_types, vendor_identification, server_information, application_namespaces, extension_information, attestation_types, rng_parameters, profile_information, validation_information, capability_information, client_registration_methods, defaults_information, protection_storage_masks, read, write +- kmip/core/messages/payloads/recover.py + classes_missing: RecoverRequestPayload, RecoverResponsePayload + methods_missing RecoverRequestPayload: unique_identifier, read, write + methods_missing RecoverResponsePayload: unique_identifier, read, write +- kmip/core/messages/payloads/register.py + classes_missing: RegisterRequestPayload, RegisterResponsePayload + methods_missing RegisterRequestPayload: object_type, template_attribute, managed_object, protection_storage_masks, read, write + methods_missing RegisterResponsePayload: unique_identifier, template_attribute, read, write +- kmip/core/messages/payloads/rekey.py + classes_missing: RekeyRequestPayload, RekeyResponsePayload + methods_missing RekeyRequestPayload: unique_identifier, offset, template_attribute, read, write + methods_missing RekeyResponsePayload: unique_identifier, template_attribute, read, write +- kmip/core/messages/payloads/rekey_key_pair.py + classes_missing: RekeyKeyPairRequestPayload, RekeyKeyPairResponsePayload + methods_missing RekeyKeyPairRequestPayload: read, write, validate +- kmip/core/messages/payloads/revoke.py + classes_missing: RevokeRequestPayload, RevokeResponsePayload + methods_missing RevokeRequestPayload: read, write, validate + methods_missing RevokeResponsePayload: read, write, validate +- kmip/core/messages/payloads/set_attribute.py + classes_missing: SetAttributeRequestPayload, SetAttributeResponsePayload + methods_missing SetAttributeRequestPayload: unique_identifier, new_attribute, read, write + methods_missing SetAttributeResponsePayload: unique_identifier, read, write +- kmip/core/messages/payloads/sign.py + classes_missing: SignRequestPayload, SignResponsePayload + methods_missing SignRequestPayload: unique_identifier, cryptographic_parameters, data, read, write + methods_missing SignResponsePayload: unique_identifier, signature_data, read, write +- kmip/core/messages/payloads/signature_verify.py + classes_missing: SignatureVerifyRequestPayload, SignatureVerifyResponsePayload + methods_missing SignatureVerifyRequestPayload: unique_identifier, cryptographic_parameters, data, digested_data, signature_data, correlation_value, init_indicator, final_indicator, read, write + methods_missing SignatureVerifyResponsePayload: unique_identifier, validity_indicator, data, correlation_value, read, write +- kmip/core/misc.py + methods_missing ServerInformation: validate +- kmip/core/objects.py + classes_missing: CurrentAttribute, CredentialValue, UsernamePasswordCredential, DeviceCredential, AttestationCredential, Credential, KeyBlock, KeyMaterial, KeyValue, Data, MACData, RevocationReasonCode, RevocationReason + methods_missing AttestationCredential: nonce, attestation_type, attestation_measurement, attestation_assertion, read, write + methods_missing Credential: credential_type, credential_value, read, write + methods_missing CurrentAttribute: attribute, read, write + methods_missing DeviceCredential: device_serial_number, password, device_identifier, network_identifier, machine_identifier, media_identifier, read, write + methods_missing ExtensionInformation: validate + methods_missing KeyBlock: read, write, validate + methods_missing KeyMaterialStruct: validate + methods_missing KeyValue: read, write, validate + methods_missing Nonce: nonce_id, nonce_value + methods_missing RevocationReason: read, write, validate + methods_missing TemplateAttribute: validate + methods_missing UsernamePasswordCredential: username, password, read, write +- kmip/core/policy.py + functions_missing: parse_policy, read_policy_from_file +- kmip/core/primitives.py + classes_missing: Base, Struct, Integer, LongInteger, BigInteger, ByteString, Interval + methods_missing Base: is_oversized, read_tag, read_type, read_length, read_value, read, write_tag, write_type, write_length, write_value, write, validate, is_tag_next, is_type_next + methods_missing BigInteger: read, write, validate + methods_missing Boolean: read_value, write_value, validate + methods_missing ByteString: read_value, read, write_value, write, validate + methods_missing Enumeration: validate + methods_missing Integer: read_value, read, write_value, write, validate + methods_missing Interval: read, write, validate + methods_missing LongInteger: read, write, validate + methods_missing TextString: read_value, write_value, validate +- kmip/core/secrets.py + classes_missing: KeyBlockKey, PublicKey, PrivateKey, SplitKey, SecretData, OpaqueObject + methods_missing KeyBlockKey: read, write, validate + methods_missing OpaqueObject: read, write, validate + methods_missing PrivateKey: validate + methods_missing PublicKey: validate + methods_missing SecretData: read, write, validate + methods_missing SplitKey: split_key_parts, key_part_identifier, split_key_threshold, split_key_method, prime_field_size, key_block, read, write + methods_missing SymmetricKey: validate + methods_missing Template: validate +- kmip/core/utils.py + functions_missing: bit_length, count_bytes, print_bytearray, is_stream_empty, build_er_error + methods_missing BytearrayStream: readall, readinto, peek +- kmip/pie/__init__.py +- kmip/pie/client.py + functions_missing: is_connected +- kmip/pie/factory.py + classes_missing: ObjectFactory + methods_missing ObjectFactory: convert +- kmip/pie/objects.py + classes_missing: SplitKey, ApplicationSpecificInformation, ObjectGroup + methods_missing ApplicationSpecificInformation: application_namespace, application_data + methods_missing ObjectGroup: object_group + methods_missing SplitKey: split_key_parts, key_part_identifier, split_key_threshold, split_key_method, prime_field_size +- kmip/pie/sqltypes.py + classes_missing: UsageMaskType, EnumType + functions_missing: attribute_append_factory + methods_missing EnumType: process_bind_param, process_result_value + methods_missing UsageMaskType: process_bind_param, process_result_value +- kmip/services/__init__.py +- kmip/services/auth.py + classes_missing: AuthenticationSuite, BasicAuthenticationSuite, TLS12AuthenticationSuite + methods_missing AuthenticationSuite: protocol, ciphers +- kmip/services/results.py + classes_missing: CreateResult, ActivateResult, RegisterResult, GetResult, DestroyResult, LocateResult, RevokeResult, MACResult +- kmip/services/server/__init__.py +- kmip/services/server/auth/__init__.py +- kmip/services/server/auth/api.py + classes_missing: AuthAPI + methods_missing AuthAPI: authenticate +- kmip/services/server/auth/slugs.py + classes_missing: SLUGSConnector + methods_missing SLUGSConnector: url, authenticate +- kmip/services/server/auth/utils.py + functions_missing: get_certificate_from_connection, get_extended_key_usage_from_certificate, get_common_names_from_certificate, get_client_identity_from_certificate +- kmip/services/server/config.py + classes_missing: KmipServerConfig + methods_missing KmipServerConfig: set_setting, load_settings, parse_auth_settings +- kmip/services/server/crypto/__init__.py +- kmip/services/server/crypto/api.py + classes_missing: CryptographicEngine + methods_missing CryptographicEngine: create_symmetric_key, create_asymmetric_key_pair, mac, encrypt, decrypt, sign +- kmip/services/server/crypto/engine.py + classes_missing: CryptographyEngine + methods_missing CryptographyEngine: create_symmetric_key, create_asymmetric_key_pair, mac, encrypt, decrypt, derive_key, wrap_key, sign, verify_signature +- kmip/services/server/engine.py + classes_missing: KmipEngine + methods_missing KmipEngine: process_request, build_error_response, get_relevant_policy_section, is_allowed +- kmip/services/server/monitor.py + classes_missing: PolicyDirectoryMonitor + functions_missing: get_json_files + methods_missing PolicyDirectoryMonitor: stop, scan_policies, run, initialize_tracking_structures, disassociate_policy_and_file, restore_or_delete_policy +- kmip/services/server/policy.py + classes_missing: AttributeRuleSet, AttributePolicy + methods_missing AttributePolicy: is_attribute_supported, is_attribute_deprecated, is_attribute_deletable_by_client, is_attribute_modifiable_by_client, is_attribute_applicable_to_object_type, is_attribute_multivalued, get_all_attribute_names +- kmip/services/server/server.py + classes_missing: KmipServer + functions_missing: build_argument_parser, main + methods_missing KmipServer: start, stop, serve +- kmip/services/server/session.py + classes_missing: KmipSession + methods_missing KmipSession: run, authenticate +- kmip/version.py \ No newline at end of file diff --git a/._coverage_missing_ready.md b/._coverage_missing_ready.md new file mode 100644 index 00000000..12d4f123 --- /dev/null +++ b/._coverage_missing_ready.md @@ -0,0 +1,72 @@ +- `kmip/__init__.py` +- `kmip/core/__init__.py` +- `kmip/core/enums.py` + classes_missing: OrderedEnum, AdjustmentType, AlternativeNameType, CertificateRequestType, EndpointRole, InteropFunction, ItemType, KeyValueLocationType, KeyWrapType, LinkType, MaskGenerator, NISTKeyType, PKCS11Function, PKCS11ReturnCode, ProtectionLevel, PutFunction, TicketType, UsageLimitsUnit +- `kmip/core/exceptions.py` + classes_missing: WriteOverflowError, KMIPServerZombieError, KMIPServerSuicideError +- `kmip/core/factories/__init__.py` +- `kmip/core/factories/credentials.py` + methods_missing CredentialFactory: create_credential, create_username_password_credential, create_device_credential +- `kmip/core/messages/__init__.py` +- `kmip/core/messages/contents.py` + classes_missing: AsynchronousCorrelationValue, MessageExtension, ServerCorrelationValue +- `kmip/core/messages/messages.py` + methods_missing ResponseBatchItem: validate + methods_missing ResponseHeader: validate + methods_missing ResponseMessage: validate +- `kmip/core/messages/payloads/__init__.py` +- `kmip/core/messages/payloads/activate.py` + methods_missing ActivateRequestPayload: validate + methods_missing ActivateResponsePayload: validate +- `kmip/core/messages/payloads/base.py` + classes_missing: ResponsePayload +- `kmip/core/messages/payloads/destroy.py` + methods_missing DestroyRequestPayload: validate + methods_missing DestroyResponsePayload: validate +- `kmip/core/messages/payloads/discover_versions.py` + methods_missing DiscoverVersionsRequestPayload: validate + methods_missing DiscoverVersionsResponsePayload: validate +- `kmip/core/messages/payloads/rekey_key_pair.py` + methods_missing RekeyKeyPairRequestPayload: validate +- `kmip/core/messages/payloads/revoke.py` + methods_missing RevokeRequestPayload: validate + methods_missing RevokeResponsePayload: validate +- `kmip/core/misc.py` + methods_missing ServerInformation: validate +- `kmip/core/primitives.py` + methods_missing Base: is_type_next +- `kmip/core/secrets.py` + classes_missing: KeyBlockKey + methods_missing KeyBlockKey: read, write, validate +- `kmip/core/utils.py` + functions_missing: bit_length, print_bytearray, is_stream_empty, build_er_error + methods_missing BytearrayStream: readall, readinto, peek +- `kmip/pie/__init__.py` +- `kmip/pie/client.py` + functions_missing: is_connected +- `kmip/pie/sqltypes.py` + classes_missing: UsageMaskType, EnumType + functions_missing: attribute_append_factory + methods_missing EnumType: process_bind_param, process_result_value + methods_missing UsageMaskType: process_bind_param, process_result_value +- `kmip/services/__init__.py` +- `kmip/services/kmip_client.py` + methods_missing KMIPProxy: rekey_key_pair, query, discover_versions +- `kmip/services/results.py` + classes_missing: ActivateResult, DestroyResult, RevokeResult +- `kmip/services/server/__init__.py` +- `kmip/services/server/auth/__init__.py` +- `kmip/services/server/auth/api.py` + classes_missing: AuthAPI + methods_missing AuthAPI: authenticate +- `kmip/services/server/crypto/__init__.py` +- `kmip/services/server/crypto/api.py` + classes_missing: CryptographicEngine + methods_missing CryptographicEngine: create_symmetric_key, create_asymmetric_key_pair, mac, encrypt, decrypt, sign +- `kmip/services/server/monitor.py` + methods_missing PolicyDirectoryMonitor: scan_policies +- `kmip/services/server/policy.py` + classes_missing: AttributeRuleSet +- `kmip/services/server/server.py` + functions_missing: build_argument_parser, main +- `kmip/version.py` \ No newline at end of file diff --git a/._coverage_report.json b/._coverage_report.json new file mode 100644 index 00000000..527c2575 --- /dev/null +++ b/._coverage_report.json @@ -0,0 +1,1297 @@ +[ + { + "source": "kmip/version.py", + "module": "kmip.version", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/test_version.py", + "expected_exists": false + }, + { + "source": "kmip/__init__.py", + "module": "kmip.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/core/attributes.py", + "module": "kmip.core.attributes", + "tests": [ + "kmip/tests/unit/core/test_enums.py", + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_attribute.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/test_attributes.py", + "expected_exists": false + }, + { + "source": "kmip/core/config_helper.py", + "module": "kmip.core.config_helper", + "tests": [ + "kmip/tests/unit/core/test_config_helper.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/test_config_helper.py", + "expected_exists": true + }, + { + "source": "kmip/core/enums.py", + "module": "kmip.core.enums", + "tests": [ + "kmip/tests/unit/core/test_enums.py", + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/factories/payloads/test_payload.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_sqltypes.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_enums.py", + "expected_exists": true + }, + { + "source": "kmip/core/exceptions.py", + "module": "kmip.core.exceptions", + "tests": [ + "kmip/tests/unit/core/test_utils.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/services/server/test_config.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_exceptions.py", + "expected_exists": false + }, + { + "source": "kmip/core/misc.py", + "module": "kmip.core.misc", + "tests": [ + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_misc.py", + "expected_exists": false + }, + { + "source": "kmip/core/objects.py", + "module": "kmip.core.objects", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_attribute.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/test_objects.py", + "expected_exists": false + }, + { + "source": "kmip/core/policy.py", + "module": "kmip.core.policy", + "tests": [ + "kmip/tests/unit/core/test_policy.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/test_policy.py", + "expected_exists": true + }, + { + "source": "kmip/core/primitives.py", + "module": "kmip.core.primitives", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_boolean.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_date_time.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_primitives.py", + "expected_exists": false + }, + { + "source": "kmip/core/secrets.py", + "module": "kmip.core.secrets", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_secrets.py", + "expected_exists": false + }, + { + "source": "kmip/core/utils.py", + "module": "kmip.core.utils", + "tests": [ + "kmip/tests/unit/core/test_utils.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_credentials.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/primitives/test_base.py", + "kmip/tests/unit/core/primitives/test_big_integer.py", + "kmip/tests/unit/core/primitives/test_boolean.py", + "kmip/tests/unit/core/primitives/test_byte_string.py", + "kmip/tests/unit/core/primitives/test_date_time.py", + "kmip/tests/unit/core/primitives/test_enumeration.py", + "kmip/tests/unit/core/primitives/test_integer.py", + "kmip/tests/unit/core/primitives/test_interval.py", + "kmip/tests/unit/core/primitives/test_long_integer.py", + "kmip/tests/unit/core/primitives/test_text_string.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/core/messages/payloads/test_archive.py", + "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "kmip/tests/unit/core/messages/payloads/test_check.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py", + "kmip/tests/unit/core/messages/payloads/test_poll.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_recover.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/test_utils.py", + "expected_exists": true + }, + { + "source": "kmip/core/__init__.py", + "module": "kmip.core.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/core/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/pie/client.py", + "module": "kmip.pie.client", + "tests": [ + "kmip/tests/unit/pie/test_client.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/pie/test_client.py", + "expected_exists": true + }, + { + "source": "kmip/pie/exceptions.py", + "module": "kmip.pie.exceptions", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/pie/test_exceptions.py", + "expected_exists": true + }, + { + "source": "kmip/pie/factory.py", + "module": "kmip.pie.factory", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/pie/test_factory.py", + "expected_exists": true + }, + { + "source": "kmip/pie/objects.py", + "module": "kmip.pie.objects", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_factory.py", + "kmip/tests/unit/core/attributes/test_application_specific_information.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py", + "kmip/tests/unit/core/secrets/test_split_key.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_certificate.py", + "kmip/tests/unit/pie/objects/test_cryptographic_object.py", + "kmip/tests/unit/pie/objects/test_key.py", + "kmip/tests/unit/pie/objects/test_managed_object.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_utils.py", + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/pie/test_objects.py", + "expected_exists": false + }, + { + "source": "kmip/pie/sqltypes.py", + "module": "kmip.pie.sqltypes", + "tests": [ + "kmip/tests/unit/pie/objects/test_application_specific_information.py", + "kmip/tests/unit/pie/objects/test_object_group.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_split_key.py", + "kmip/tests/unit/pie/objects/test_sqltypes.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/pie/test_sqltypes.py", + "expected_exists": false + }, + { + "source": "kmip/pie/__init__.py", + "module": "kmip.pie.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/pie/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/services/auth.py", + "module": "kmip.services.auth", + "tests": [ + "kmip/tests/unit/services/test_auth.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/services/server/test_server.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/test_auth.py", + "expected_exists": true + }, + { + "source": "kmip/services/kmip_client.py", + "module": "kmip.services.kmip_client", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/services/test_kmip_client.py", + "expected_exists": true + }, + { + "source": "kmip/services/kmip_protocol.py", + "module": "kmip.services.kmip_protocol", + "tests": [ + "kmip/tests/unit/services/test_kmip_protocol.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/test_kmip_protocol.py", + "expected_exists": true + }, + { + "source": "kmip/services/results.py", + "module": "kmip.services.results", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/services/test_results.py", + "expected_exists": false + }, + { + "source": "kmip/services/__init__.py", + "module": "kmip.services.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/core/factories/attributes.py", + "module": "kmip.core.factories.attributes", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/test_attribute.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/test_attributes.py", + "expected_exists": false + }, + { + "source": "kmip/core/factories/attribute_values.py", + "module": "kmip.core.factories.attribute_values", + "tests": [ + "kmip/tests/unit/core/factories/test_attribute_values.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/test_attribute_values.py", + "expected_exists": true + }, + { + "source": "kmip/core/factories/credentials.py", + "module": "kmip.core.factories.credentials", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/factories/test_credentials.py", + "expected_exists": false + }, + { + "source": "kmip/core/factories/secrets.py", + "module": "kmip.core.factories.secrets", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/test_secrets.py", + "expected_exists": false + }, + { + "source": "kmip/core/factories/__init__.py", + "module": "kmip.core.factories.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/core/factories/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/core/messages/contents.py", + "module": "kmip.core.messages.contents", + "tests": [ + "kmip/tests/unit/core/test_policy.py", + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_current_attribute.py", + "kmip/tests/unit/core/objects/test_new_attribute.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/factories/payloads/test_payload.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/contents/test_authentication.py", + "kmip/tests/unit/core/messages/contents/test_protocol_version.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_policy.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/test_contents.py", + "expected_exists": false + }, + { + "source": "kmip/core/messages/messages.py", + "module": "kmip.core.messages.messages", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/test_messages.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/__init__.py", + "module": "kmip.core.messages.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/core/messages/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/core/factories/payloads/request.py", + "module": "kmip.core.factories.payloads.request", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/payloads/test_request.py", + "expected_exists": true + }, + { + "source": "kmip/core/factories/payloads/response.py", + "module": "kmip.core.factories.payloads.response", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_response.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/payloads/test_response.py", + "expected_exists": true + }, + { + "source": "kmip/core/factories/payloads/__init__.py", + "module": "kmip.core.factories.payloads.__init__", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_payload.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/factories/payloads/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/core/messages/payloads/activate.py", + "module": "kmip.core.messages.payloads.activate", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_activate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_activate.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/archive.py", + "module": "kmip.core.messages.payloads.archive", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_archive.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_archive.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/base.py", + "module": "kmip.core.messages.payloads.base", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_base.py", + "expected_exists": false + }, + { + "source": "kmip/core/messages/payloads/cancel.py", + "module": "kmip.core.messages.payloads.cancel", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_cancel.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/check.py", + "module": "kmip.core.messages.payloads.check", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_check.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_check.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/create.py", + "module": "kmip.core.messages.payloads.create", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_create.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_create.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/create_key_pair.py", + "module": "kmip.core.messages.payloads.create_key_pair", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/decrypt.py", + "module": "kmip.core.messages.payloads.decrypt", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/delete_attribute.py", + "module": "kmip.core.messages.payloads.delete_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/derive_key.py", + "module": "kmip.core.messages.payloads.derive_key", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/destroy.py", + "module": "kmip.core.messages.payloads.destroy", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_destroy.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/discover_versions.py", + "module": "kmip.core.messages.payloads.discover_versions", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/encrypt.py", + "module": "kmip.core.messages.payloads.encrypt", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/get.py", + "module": "kmip.core.messages.payloads.get", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_get.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/get_attributes.py", + "module": "kmip.core.messages.payloads.get_attributes", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/get_attribute_list.py", + "module": "kmip.core.messages.payloads.get_attribute_list", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/get_usage_allocation.py", + "module": "kmip.core.messages.payloads.get_usage_allocation", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/locate.py", + "module": "kmip.core.messages.payloads.locate", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_locate.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_locate.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/mac.py", + "module": "kmip.core.messages.payloads.mac", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_mac.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_mac.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/modify_attribute.py", + "module": "kmip.core.messages.payloads.modify_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/obtain_lease.py", + "module": "kmip.core.messages.payloads.obtain_lease", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/poll.py", + "module": "kmip.core.messages.payloads.poll", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_poll.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_poll.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/query.py", + "module": "kmip.core.messages.payloads.query", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_query.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_query.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/recover.py", + "module": "kmip.core.messages.payloads.recover", + "tests": [ + "kmip/tests/unit/core/messages/payloads/test_recover.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_recover.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/register.py", + "module": "kmip.core.messages.payloads.register", + "tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_register.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_register.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/rekey.py", + "module": "kmip.core.messages.payloads.rekey", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_rekey.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/rekey_key_pair.py", + "module": "kmip.core.messages.payloads.rekey_key_pair", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/revoke.py", + "module": "kmip.core.messages.payloads.revoke", + "tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/set_attribute.py", + "module": "kmip.core.messages.payloads.set_attribute", + "tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/sign.py", + "module": "kmip.core.messages.payloads.sign", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_sign.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_sign.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/signature_verify.py", + "module": "kmip.core.messages.payloads.signature_verify", + "tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/factories/payloads/test_request.py", + "kmip/tests/unit/core/factories/payloads/test_response.py", + "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "kmip/tests/unit/services/server/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "expected_exists": true + }, + { + "source": "kmip/core/messages/payloads/__init__.py", + "module": "kmip.core.messages.payloads.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/core/messages/payloads/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/services/server/config.py", + "module": "kmip.services.server.config", + "tests": [ + "kmip/tests/unit/services/server/test_config.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/test_config.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/engine.py", + "module": "kmip.services.server.engine", + "tests": [ + "kmip/tests/unit/services/server/test_engine.py", + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/test_engine.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/monitor.py", + "module": "kmip.services.server.monitor", + "tests": [ + "kmip/tests/unit/services/server/test_monitor.py", + "kmip/tests/unit/services/server/test_server.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/services/server/test_monitor.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/policy.py", + "module": "kmip.services.server.policy", + "tests": [ + "kmip/tests/unit/services/server/test_policy.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/services/server/test_policy.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/server.py", + "module": "kmip.services.server.server", + "tests": [ + "kmip/tests/unit/services/server/test_server.py" + ], + "status": "PARTIAL", + "expected_test": "kmip/tests/unit/services/server/test_server.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/session.py", + "module": "kmip.services.server.session", + "tests": [ + "kmip/tests/unit/services/server/test_server.py", + "kmip/tests/unit/services/server/test_session.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/test_session.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/__init__.py", + "module": "kmip.services.server.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/server/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/services/server/auth/api.py", + "module": "kmip.services.server.auth.api", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/server/auth/test_api.py", + "expected_exists": false + }, + { + "source": "kmip/services/server/auth/slugs.py", + "module": "kmip.services.server.auth.slugs", + "tests": [ + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/auth/test_slugs.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/auth/utils.py", + "module": "kmip.services.server.auth.utils", + "tests": [ + "kmip/tests/unit/services/server/test_session.py", + "kmip/tests/unit/services/server/auth/test_slugs.py", + "kmip/tests/unit/services/server/auth/test_utils.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/auth/test_utils.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/auth/__init__.py", + "module": "kmip.services.server.auth.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/server/auth/test___init__.py", + "expected_exists": false + }, + { + "source": "kmip/services/server/crypto/api.py", + "module": "kmip.services.server.crypto.api", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/server/crypto/test_api.py", + "expected_exists": false + }, + { + "source": "kmip/services/server/crypto/engine.py", + "module": "kmip.services.server.crypto.engine", + "tests": [ + "kmip/tests/unit/services/server/crypto/test_engine.py" + ], + "status": "EXISTS", + "expected_test": "kmip/tests/unit/services/server/crypto/test_engine.py", + "expected_exists": true + }, + { + "source": "kmip/services/server/crypto/__init__.py", + "module": "kmip.services.server.crypto.__init__", + "tests": [], + "status": "MISSING", + "expected_test": "kmip/tests/unit/services/server/crypto/test___init__.py", + "expected_exists": false + } +] \ No newline at end of file diff --git a/._coverage_table.json b/._coverage_table.json new file mode 100644 index 00000000..a7540fc3 --- /dev/null +++ b/._coverage_table.json @@ -0,0 +1,1260 @@ +[ + { + "source": "kmip/__init__.py", + "test": "kmip/tests/unit/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/__init__.py", + "test": "kmip/tests/unit/core/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/attributes.py", + "test": "kmip/tests/unit/core/test_attributes.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/secrets/test_certificate.py" + ], + "missing": { + "classes": [ + "PublicKeyUniqueIdentifier", + "State", + "CustomAttribute" + ], + "functions": [] + } + }, + { + "source": "kmip/core/config_helper.py", + "test": "kmip/tests/unit/core/test_config_helper.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/core/test_config_helper.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/enums.py", + "test": "kmip/tests/unit/core/test_enums.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/pie/test_exceptions.py", + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "missing": { + "classes": [ + "OrderedEnum", + "AdjustmentType", + "AlternativeNameType", + "AsynchronousIndicator", + "AttestationType", + "BatchErrorContinuationOption", + "CancellationResult", + "CertificateRequestType", + "ClientRegistrationMethod", + "EndpointRole", + "InteropFunction", + "ItemType", + "KeyCompressionType", + "KeyValueLocationType", + "KeyWrapType", + "LinkType", + "MaskGenerator", + "NISTKeyType", + "ObjectGroupMember", + "OpaqueDataType", + "PKCS11Function", + "PKCS11ReturnCode", + "ProtectionLevel", + "PutFunction", + "RevocationReasonCode", + "SecretDataType", + "SplitKeyMethod", + "StorageStatusMask", + "TicketType", + "Types", + "UsageLimitsUnit" + ], + "functions": [ + "convert_attribute_name_to_tag", + "convert_attribute_tag_to_name", + "get_bit_mask_from_enumerations", + "get_enumerations_from_bit_mask", + "is_bit_mask", + "is_enum_value", + "is_attribute" + ] + } + }, + { + "source": "kmip/core/exceptions.py", + "test": "kmip/tests/unit/core/test_exceptions.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [ + "KmipError", + "CryptographicFailure", + "EncodingOptionError", + "IllegalOperation", + "IndexOutOfBounds", + "InvalidField", + "InvalidMessage", + "ItemNotFound", + "KeyCompressionTypeNotSupported", + "KeyFormatTypeNotSupported", + "OperationFailure", + "OperationNotSupported", + "PermissionDenied", + "AttributeNotSupported", + "ConfigurationError", + "ConnectionClosed", + "NetworkingError", + "InvalidKmipEncoding", + "InvalidPaddingBytes", + "InvalidPrimitiveLength", + "ShutdownError", + "VersionNotSupported", + "StreamNotEmptyError", + "ReadValueError", + "WriteOverflowError", + "KMIPServerZombieError", + "KMIPServerSuicideError", + "ErrorStrings" + ], + "functions": [] + } + }, + { + "source": "kmip/core/factories/__init__.py", + "test": "kmip/tests/unit/core/factories/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/factories/attribute_values.py", + "test": "kmip/tests/unit/core/factories/test_attribute_values.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "AttributeValueFactory" + ], + "functions": [] + } + }, + { + "source": "kmip/core/factories/attributes.py", + "test": "kmip/tests/unit/core/factories/test_attributes.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/factories/credentials.py", + "test": "kmip/tests/unit/core/factories/test_credentials.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/factories/payloads/__init__.py", + "test": "kmip/tests/unit/core/factories/payloads/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [ + "PayloadFactory" + ], + "functions": [] + } + }, + { + "source": "kmip/core/factories/payloads/request.py", + "test": "kmip/tests/unit/core/factories/payloads/test_request.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/core/factories/payloads/test_request.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/factories/payloads/response.py", + "test": "kmip/tests/unit/core/factories/payloads/test_response.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/core/factories/payloads/test_response.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/factories/secrets.py", + "test": "kmip/tests/unit/core/factories/test_secrets.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/messages/__init__.py", + "test": "kmip/tests/unit/core/messages/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/messages/contents.py", + "test": "kmip/tests/unit/core/messages/test_contents.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/payloads/test_discover_versions.py" + ], + "missing": { + "classes": [ + "MaximumResponseSize", + "UniqueBatchItemID", + "TimeStamp", + "Authentication", + "AsynchronousIndicator", + "AsynchronousCorrelationValue", + "BatchOrderOption", + "BatchErrorContinuationOption", + "BatchCount", + "MessageExtension", + "ServerCorrelationValue", + "KeyCompressionType" + ], + "functions": [ + "protocol_version_to_kmip_version" + ] + } + }, + { + "source": "kmip/core/messages/messages.py", + "test": "kmip/tests/unit/core/messages/test_messages.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing": { + "classes": [ + "RequestHeader", + "ResponseHeader", + "RequestMessage" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/__init__.py", + "test": "kmip/tests/unit/core/messages/payloads/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/activate.py", + "test": "kmip/tests/unit/core/messages/payloads/test_activate.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "ActivateRequestPayload", + "ActivateResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/archive.py", + "test": "kmip/tests/unit/core/messages/payloads/test_archive.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "ArchiveRequestPayload", + "ArchiveResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/base.py", + "test": "kmip/tests/unit/core/messages/payloads/test_base.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [ + "RequestPayload", + "ResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/cancel.py", + "test": "kmip/tests/unit/core/messages/payloads/test_cancel.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "CancelRequestPayload", + "CancelResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/check.py", + "test": "kmip/tests/unit/core/messages/payloads/test_check.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "CheckRequestPayload", + "CheckResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/create.py", + "test": "kmip/tests/unit/core/messages/payloads/test_create.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "CreateRequestPayload", + "CreateResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/create_key_pair.py", + "test": "kmip/tests/unit/core/messages/payloads/test_create_key_pair.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "CreateKeyPairRequestPayload", + "CreateKeyPairResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/decrypt.py", + "test": "kmip/tests/unit/core/messages/payloads/test_decrypt.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "DecryptRequestPayload", + "DecryptResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/delete_attribute.py", + "test": "kmip/tests/unit/core/messages/payloads/test_delete_attribute.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "DeleteAttributeRequestPayload", + "DeleteAttributeResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/derive_key.py", + "test": "kmip/tests/unit/core/messages/payloads/test_derive_key.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "DeriveKeyRequestPayload", + "DeriveKeyResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/destroy.py", + "test": "kmip/tests/unit/core/messages/payloads/test_destroy.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "DestroyRequestPayload", + "DestroyResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/discover_versions.py", + "test": "kmip/tests/unit/core/messages/payloads/test_discover_versions.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "DiscoverVersionsRequestPayload", + "DiscoverVersionsResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/encrypt.py", + "test": "kmip/tests/unit/core/messages/payloads/test_encrypt.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "EncryptRequestPayload", + "EncryptResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/get.py", + "test": "kmip/tests/unit/core/messages/payloads/test_get.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "GetRequestPayload", + "GetResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/get_attribute_list.py", + "test": "kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "GetAttributeListRequestPayload", + "GetAttributeListResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/get_attributes.py", + "test": "kmip/tests/unit/core/messages/payloads/test_get_attributes.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "GetAttributesRequestPayload", + "GetAttributesResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/get_usage_allocation.py", + "test": "kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "GetUsageAllocationRequestPayload", + "GetUsageAllocationResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/locate.py", + "test": "kmip/tests/unit/core/messages/payloads/test_locate.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "LocateRequestPayload", + "LocateResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/mac.py", + "test": "kmip/tests/unit/core/messages/payloads/test_mac.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "MACRequestPayload", + "MACResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/modify_attribute.py", + "test": "kmip/tests/unit/core/messages/payloads/test_modify_attribute.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "ModifyAttributeRequestPayload", + "ModifyAttributeResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/obtain_lease.py", + "test": "kmip/tests/unit/core/messages/payloads/test_obtain_lease.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "ObtainLeaseRequestPayload", + "ObtainLeaseResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/poll.py", + "test": "kmip/tests/unit/core/messages/payloads/test_poll.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "PollRequestPayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/query.py", + "test": "kmip/tests/unit/core/messages/payloads/test_query.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "QueryRequestPayload", + "QueryResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/recover.py", + "test": "kmip/tests/unit/core/messages/payloads/test_recover.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "RecoverRequestPayload", + "RecoverResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/register.py", + "test": "kmip/tests/unit/core/messages/payloads/test_register.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "RegisterRequestPayload", + "RegisterResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/rekey.py", + "test": "kmip/tests/unit/core/messages/payloads/test_rekey.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "RekeyRequestPayload", + "RekeyResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/rekey_key_pair.py", + "test": "kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "RekeyKeyPairRequestPayload", + "RekeyKeyPairResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/revoke.py", + "test": "kmip/tests/unit/core/messages/payloads/test_revoke.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "RevokeRequestPayload", + "RevokeResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/set_attribute.py", + "test": "kmip/tests/unit/core/messages/payloads/test_set_attribute.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "SetAttributeRequestPayload", + "SetAttributeResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/sign.py", + "test": "kmip/tests/unit/core/messages/payloads/test_sign.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "SignRequestPayload", + "SignResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/messages/payloads/signature_verify.py", + "test": "kmip/tests/unit/core/messages/payloads/test_signature_verify.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "SignatureVerifyRequestPayload", + "SignatureVerifyResponsePayload" + ], + "functions": [] + } + }, + { + "source": "kmip/core/misc.py", + "test": "kmip/tests/unit/core/test_misc.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_misc.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/secrets/test_certificate.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/core/objects.py", + "test": "kmip/tests/unit/core/test_objects.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_objects.py" + ], + "missing": { + "classes": [ + "CurrentAttribute", + "CredentialValue", + "UsernamePasswordCredential", + "DeviceCredential", + "AttestationCredential", + "Credential", + "KeyBlock", + "KeyMaterial", + "KeyValue", + "Data", + "MACData", + "RevocationReasonCode", + "RevocationReason" + ], + "functions": [] + } + }, + { + "source": "kmip/core/policy.py", + "test": "kmip/tests/unit/core/test_policy.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [], + "functions": [ + "parse_policy", + "read_policy_from_file" + ] + } + }, + { + "source": "kmip/core/primitives.py", + "test": "kmip/tests/unit/core/test_primitives.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/core/messages/test_messages.py" + ], + "missing": { + "classes": [ + "Base", + "Struct", + "Integer", + "LongInteger", + "BigInteger", + "ByteString", + "Interval" + ], + "functions": [] + } + }, + { + "source": "kmip/core/secrets.py", + "test": "kmip/tests/unit/core/test_secrets.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/secrets/test_certificate.py" + ], + "missing": { + "classes": [ + "KeyBlockKey", + "PublicKey", + "PrivateKey", + "SplitKey", + "SecretData", + "OpaqueObject" + ], + "functions": [] + } + }, + { + "source": "kmip/core/utils.py", + "test": "kmip/tests/unit/core/test_utils.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py", + "kmip/tests/unit/core/attributes/test_attributes.py", + "kmip/tests/unit/core/attributes/test_digest.py", + "kmip/tests/unit/core/messages/test_messages.py", + "kmip/tests/unit/core/misc/test_server_information.py", + "kmip/tests/unit/core/objects/test_extension_information.py", + "kmip/tests/unit/core/objects/test_objects.py", + "kmip/tests/unit/core/secrets/test_certificate.py" + ], + "missing": { + "classes": [], + "functions": [ + "bit_length", + "count_bytes", + "print_bytearray", + "is_stream_empty", + "build_er_error" + ] + } + }, + { + "source": "kmip/pie/__init__.py", + "test": "kmip/tests/unit/pie/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/pie/client.py", + "test": "kmip/tests/unit/pie/test_client.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/pie/test_client.py" + ], + "missing": { + "classes": [], + "functions": [ + "is_connected" + ] + } + }, + { + "source": "kmip/pie/exceptions.py", + "test": "kmip/tests/unit/pie/test_exceptions.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/pie/test_exceptions.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/pie/factory.py", + "test": "kmip/tests/unit/pie/test_factory.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "ObjectFactory" + ], + "functions": [] + } + }, + { + "source": "kmip/pie/objects.py", + "test": "kmip/tests/unit/pie/test_objects.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/pie/objects/test_cryptographic_object.py", + "kmip/tests/unit/pie/objects/test_key.py", + "kmip/tests/unit/pie/objects/test_managed_object.py", + "kmip/tests/unit/pie/objects/test_opaque_object.py", + "kmip/tests/unit/pie/objects/test_private_key.py", + "kmip/tests/unit/pie/objects/test_public_key.py", + "kmip/tests/unit/pie/objects/test_secret_data.py", + "kmip/tests/unit/pie/objects/test_symmetric_key.py", + "kmip/tests/unit/pie/objects/test_x509_certificate.py" + ], + "missing": { + "classes": [ + "SplitKey", + "ApplicationSpecificInformation", + "ObjectGroup" + ], + "functions": [] + } + }, + { + "source": "kmip/pie/sqltypes.py", + "test": "kmip/tests/unit/pie/test_sqltypes.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/pie/objects/test_sqltypes.py" + ], + "missing": { + "classes": [ + "UsageMaskType", + "EnumType" + ], + "functions": [ + "attribute_append_factory" + ] + } + }, + { + "source": "kmip/services/__init__.py", + "test": "kmip/tests/unit/services/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/auth.py", + "test": "kmip/tests/unit/services/test_auth.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "AuthenticationSuite", + "BasicAuthenticationSuite", + "TLS12AuthenticationSuite" + ], + "functions": [] + } + }, + { + "source": "kmip/services/kmip_client.py", + "test": "kmip/tests/unit/services/test_kmip_client.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/pie/test_client.py", + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/kmip_protocol.py", + "test": "kmip/tests/unit/services/test_kmip_protocol.py", + "status": "EXISTS", + "has_expected_test": true, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_protocol.py" + ], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/results.py", + "test": "kmip/tests/unit/services/test_results.py", + "status": "PARTIAL", + "has_expected_test": false, + "import_tests": [ + "kmip/tests/unit/services/test_kmip_client.py" + ], + "missing": { + "classes": [ + "CreateResult", + "ActivateResult", + "RegisterResult", + "GetResult", + "DestroyResult", + "LocateResult", + "RevokeResult", + "MACResult" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/__init__.py", + "test": "kmip/tests/unit/services/server/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/server/auth/__init__.py", + "test": "kmip/tests/unit/services/server/auth/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/server/auth/api.py", + "test": "kmip/tests/unit/services/server/auth/test_api.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [ + "AuthAPI" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/auth/slugs.py", + "test": "kmip/tests/unit/services/server/auth/test_slugs.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "SLUGSConnector" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/auth/utils.py", + "test": "kmip/tests/unit/services/server/auth/test_utils.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [], + "functions": [ + "get_certificate_from_connection", + "get_extended_key_usage_from_certificate", + "get_common_names_from_certificate", + "get_client_identity_from_certificate" + ] + } + }, + { + "source": "kmip/services/server/config.py", + "test": "kmip/tests/unit/services/server/test_config.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "KmipServerConfig" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/crypto/__init__.py", + "test": "kmip/tests/unit/services/server/crypto/test___init__.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + }, + { + "source": "kmip/services/server/crypto/api.py", + "test": "kmip/tests/unit/services/server/crypto/test_api.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [ + "CryptographicEngine" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/crypto/engine.py", + "test": "kmip/tests/unit/services/server/crypto/test_engine.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "CryptographyEngine" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/engine.py", + "test": "kmip/tests/unit/services/server/test_engine.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "KmipEngine" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/monitor.py", + "test": "kmip/tests/unit/services/server/test_monitor.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "PolicyDirectoryMonitor" + ], + "functions": [ + "get_json_files" + ] + } + }, + { + "source": "kmip/services/server/policy.py", + "test": "kmip/tests/unit/services/server/test_policy.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "AttributeRuleSet", + "AttributePolicy" + ], + "functions": [] + } + }, + { + "source": "kmip/services/server/server.py", + "test": "kmip/tests/unit/services/server/test_server.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "KmipServer" + ], + "functions": [ + "build_argument_parser", + "main" + ] + } + }, + { + "source": "kmip/services/server/session.py", + "test": "kmip/tests/unit/services/server/test_session.py", + "status": "PARTIAL", + "has_expected_test": true, + "import_tests": [], + "missing": { + "classes": [ + "KmipSession" + ], + "functions": [] + } + }, + { + "source": "kmip/version.py", + "test": "kmip/tests/unit/test_version.py", + "status": "MISSING", + "has_expected_test": false, + "import_tests": [], + "missing": { + "classes": [], + "functions": [] + } + } +] \ No newline at end of file diff --git a/._coverage_table.md b/._coverage_table.md new file mode 100644 index 00000000..dd157595 --- /dev/null +++ b/._coverage_table.md @@ -0,0 +1,83 @@ +| Modu? ?r?d?owy | Plik testowy | Status | +|---|---|---| +| kmip/__init__.py | kmip/tests/unit/test___init__.py | ? MISSING | +| kmip/core/__init__.py | kmip/tests/unit/core/test___init__.py | ? MISSING | +| kmip/core/attributes.py | kmip/tests/unit/core/test_attributes.py | ?? PARTIAL | +| kmip/core/config_helper.py | kmip/tests/unit/core/test_config_helper.py | ? EXISTS | +| kmip/core/enums.py | kmip/tests/unit/core/test_enums.py | ?? PARTIAL | +| kmip/core/exceptions.py | kmip/tests/unit/core/test_exceptions.py | ? MISSING | +| kmip/core/factories/__init__.py | kmip/tests/unit/core/factories/test___init__.py | ? MISSING | +| kmip/core/factories/attribute_values.py | kmip/tests/unit/core/factories/test_attribute_values.py | ?? PARTIAL | +| kmip/core/factories/attributes.py | kmip/tests/unit/core/factories/test_attributes.py | ?? PARTIAL | +| kmip/core/factories/credentials.py | kmip/tests/unit/core/factories/test_credentials.py | ?? PARTIAL | +| kmip/core/factories/payloads/__init__.py | kmip/tests/unit/core/factories/payloads/test___init__.py | ? MISSING | +| kmip/core/factories/payloads/request.py | kmip/tests/unit/core/factories/payloads/test_request.py | ? EXISTS | +| kmip/core/factories/payloads/response.py | kmip/tests/unit/core/factories/payloads/test_response.py | ? EXISTS | +| kmip/core/factories/secrets.py | kmip/tests/unit/core/factories/test_secrets.py | ?? PARTIAL | +| kmip/core/messages/__init__.py | kmip/tests/unit/core/messages/test___init__.py | ? MISSING | +| kmip/core/messages/contents.py | kmip/tests/unit/core/messages/test_contents.py | ?? PARTIAL | +| kmip/core/messages/messages.py | kmip/tests/unit/core/messages/test_messages.py | ?? PARTIAL | +| kmip/core/messages/payloads/__init__.py | kmip/tests/unit/core/messages/payloads/test___init__.py | ? MISSING | +| kmip/core/messages/payloads/activate.py | kmip/tests/unit/core/messages/payloads/test_activate.py | ?? PARTIAL | +| kmip/core/messages/payloads/archive.py | kmip/tests/unit/core/messages/payloads/test_archive.py | ?? PARTIAL | +| kmip/core/messages/payloads/base.py | kmip/tests/unit/core/messages/payloads/test_base.py | ? MISSING | +| kmip/core/messages/payloads/cancel.py | kmip/tests/unit/core/messages/payloads/test_cancel.py | ?? PARTIAL | +| kmip/core/messages/payloads/check.py | kmip/tests/unit/core/messages/payloads/test_check.py | ?? PARTIAL | +| kmip/core/messages/payloads/create.py | kmip/tests/unit/core/messages/payloads/test_create.py | ?? PARTIAL | +| kmip/core/messages/payloads/create_key_pair.py | kmip/tests/unit/core/messages/payloads/test_create_key_pair.py | ?? PARTIAL | +| kmip/core/messages/payloads/decrypt.py | kmip/tests/unit/core/messages/payloads/test_decrypt.py | ?? PARTIAL | +| kmip/core/messages/payloads/delete_attribute.py | kmip/tests/unit/core/messages/payloads/test_delete_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/derive_key.py | kmip/tests/unit/core/messages/payloads/test_derive_key.py | ?? PARTIAL | +| kmip/core/messages/payloads/destroy.py | kmip/tests/unit/core/messages/payloads/test_destroy.py | ?? PARTIAL | +| kmip/core/messages/payloads/discover_versions.py | kmip/tests/unit/core/messages/payloads/test_discover_versions.py | ?? PARTIAL | +| kmip/core/messages/payloads/encrypt.py | kmip/tests/unit/core/messages/payloads/test_encrypt.py | ?? PARTIAL | +| kmip/core/messages/payloads/get.py | kmip/tests/unit/core/messages/payloads/test_get.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_attribute_list.py | kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_attributes.py | kmip/tests/unit/core/messages/payloads/test_get_attributes.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_usage_allocation.py | kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py | ?? PARTIAL | +| kmip/core/messages/payloads/locate.py | kmip/tests/unit/core/messages/payloads/test_locate.py | ?? PARTIAL | +| kmip/core/messages/payloads/mac.py | kmip/tests/unit/core/messages/payloads/test_mac.py | ?? PARTIAL | +| kmip/core/messages/payloads/modify_attribute.py | kmip/tests/unit/core/messages/payloads/test_modify_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/obtain_lease.py | kmip/tests/unit/core/messages/payloads/test_obtain_lease.py | ?? PARTIAL | +| kmip/core/messages/payloads/poll.py | kmip/tests/unit/core/messages/payloads/test_poll.py | ?? PARTIAL | +| kmip/core/messages/payloads/query.py | kmip/tests/unit/core/messages/payloads/test_query.py | ?? PARTIAL | +| kmip/core/messages/payloads/recover.py | kmip/tests/unit/core/messages/payloads/test_recover.py | ?? PARTIAL | +| kmip/core/messages/payloads/register.py | kmip/tests/unit/core/messages/payloads/test_register.py | ?? PARTIAL | +| kmip/core/messages/payloads/rekey.py | kmip/tests/unit/core/messages/payloads/test_rekey.py | ?? PARTIAL | +| kmip/core/messages/payloads/rekey_key_pair.py | kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py | ?? PARTIAL | +| kmip/core/messages/payloads/revoke.py | kmip/tests/unit/core/messages/payloads/test_revoke.py | ?? PARTIAL | +| kmip/core/messages/payloads/set_attribute.py | kmip/tests/unit/core/messages/payloads/test_set_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/sign.py | kmip/tests/unit/core/messages/payloads/test_sign.py | ?? PARTIAL | +| kmip/core/messages/payloads/signature_verify.py | kmip/tests/unit/core/messages/payloads/test_signature_verify.py | ?? PARTIAL | +| kmip/core/misc.py | kmip/tests/unit/core/test_misc.py | ?? PARTIAL | +| kmip/core/objects.py | kmip/tests/unit/core/test_objects.py | ?? PARTIAL | +| kmip/core/policy.py | kmip/tests/unit/core/test_policy.py | ?? PARTIAL | +| kmip/core/primitives.py | kmip/tests/unit/core/test_primitives.py | ?? PARTIAL | +| kmip/core/secrets.py | kmip/tests/unit/core/test_secrets.py | ?? PARTIAL | +| kmip/core/utils.py | kmip/tests/unit/core/test_utils.py | ?? PARTIAL | +| kmip/pie/__init__.py | kmip/tests/unit/pie/test___init__.py | ? MISSING | +| kmip/pie/client.py | kmip/tests/unit/pie/test_client.py | ?? PARTIAL | +| kmip/pie/exceptions.py | kmip/tests/unit/pie/test_exceptions.py | ? EXISTS | +| kmip/pie/factory.py | kmip/tests/unit/pie/test_factory.py | ?? PARTIAL | +| kmip/pie/objects.py | kmip/tests/unit/pie/test_objects.py | ?? PARTIAL | +| kmip/pie/sqltypes.py | kmip/tests/unit/pie/test_sqltypes.py | ?? PARTIAL | +| kmip/services/__init__.py | kmip/tests/unit/services/test___init__.py | ? MISSING | +| kmip/services/auth.py | kmip/tests/unit/services/test_auth.py | ?? PARTIAL | +| kmip/services/kmip_client.py | kmip/tests/unit/services/test_kmip_client.py | ? EXISTS | +| kmip/services/kmip_protocol.py | kmip/tests/unit/services/test_kmip_protocol.py | ? EXISTS | +| kmip/services/results.py | kmip/tests/unit/services/test_results.py | ?? PARTIAL | +| kmip/services/server/__init__.py | kmip/tests/unit/services/server/test___init__.py | ? MISSING | +| kmip/services/server/auth/__init__.py | kmip/tests/unit/services/server/auth/test___init__.py | ? MISSING | +| kmip/services/server/auth/api.py | kmip/tests/unit/services/server/auth/test_api.py | ? MISSING | +| kmip/services/server/auth/slugs.py | kmip/tests/unit/services/server/auth/test_slugs.py | ?? PARTIAL | +| kmip/services/server/auth/utils.py | kmip/tests/unit/services/server/auth/test_utils.py | ?? PARTIAL | +| kmip/services/server/config.py | kmip/tests/unit/services/server/test_config.py | ?? PARTIAL | +| kmip/services/server/crypto/__init__.py | kmip/tests/unit/services/server/crypto/test___init__.py | ? MISSING | +| kmip/services/server/crypto/api.py | kmip/tests/unit/services/server/crypto/test_api.py | ? MISSING | +| kmip/services/server/crypto/engine.py | kmip/tests/unit/services/server/crypto/test_engine.py | ?? PARTIAL | +| kmip/services/server/engine.py | kmip/tests/unit/services/server/test_engine.py | ?? PARTIAL | +| kmip/services/server/monitor.py | kmip/tests/unit/services/server/test_monitor.py | ?? PARTIAL | +| kmip/services/server/policy.py | kmip/tests/unit/services/server/test_policy.py | ?? PARTIAL | +| kmip/services/server/server.py | kmip/tests/unit/services/server/test_server.py | ?? PARTIAL | +| kmip/services/server/session.py | kmip/tests/unit/services/server/test_session.py | ?? PARTIAL | +| kmip/version.py | kmip/tests/unit/test_version.py | ? MISSING | \ No newline at end of file diff --git a/._coverage_table_clean.md b/._coverage_table_clean.md new file mode 100644 index 00000000..dd157595 --- /dev/null +++ b/._coverage_table_clean.md @@ -0,0 +1,83 @@ +| Modu? ?r?d?owy | Plik testowy | Status | +|---|---|---| +| kmip/__init__.py | kmip/tests/unit/test___init__.py | ? MISSING | +| kmip/core/__init__.py | kmip/tests/unit/core/test___init__.py | ? MISSING | +| kmip/core/attributes.py | kmip/tests/unit/core/test_attributes.py | ?? PARTIAL | +| kmip/core/config_helper.py | kmip/tests/unit/core/test_config_helper.py | ? EXISTS | +| kmip/core/enums.py | kmip/tests/unit/core/test_enums.py | ?? PARTIAL | +| kmip/core/exceptions.py | kmip/tests/unit/core/test_exceptions.py | ? MISSING | +| kmip/core/factories/__init__.py | kmip/tests/unit/core/factories/test___init__.py | ? MISSING | +| kmip/core/factories/attribute_values.py | kmip/tests/unit/core/factories/test_attribute_values.py | ?? PARTIAL | +| kmip/core/factories/attributes.py | kmip/tests/unit/core/factories/test_attributes.py | ?? PARTIAL | +| kmip/core/factories/credentials.py | kmip/tests/unit/core/factories/test_credentials.py | ?? PARTIAL | +| kmip/core/factories/payloads/__init__.py | kmip/tests/unit/core/factories/payloads/test___init__.py | ? MISSING | +| kmip/core/factories/payloads/request.py | kmip/tests/unit/core/factories/payloads/test_request.py | ? EXISTS | +| kmip/core/factories/payloads/response.py | kmip/tests/unit/core/factories/payloads/test_response.py | ? EXISTS | +| kmip/core/factories/secrets.py | kmip/tests/unit/core/factories/test_secrets.py | ?? PARTIAL | +| kmip/core/messages/__init__.py | kmip/tests/unit/core/messages/test___init__.py | ? MISSING | +| kmip/core/messages/contents.py | kmip/tests/unit/core/messages/test_contents.py | ?? PARTIAL | +| kmip/core/messages/messages.py | kmip/tests/unit/core/messages/test_messages.py | ?? PARTIAL | +| kmip/core/messages/payloads/__init__.py | kmip/tests/unit/core/messages/payloads/test___init__.py | ? MISSING | +| kmip/core/messages/payloads/activate.py | kmip/tests/unit/core/messages/payloads/test_activate.py | ?? PARTIAL | +| kmip/core/messages/payloads/archive.py | kmip/tests/unit/core/messages/payloads/test_archive.py | ?? PARTIAL | +| kmip/core/messages/payloads/base.py | kmip/tests/unit/core/messages/payloads/test_base.py | ? MISSING | +| kmip/core/messages/payloads/cancel.py | kmip/tests/unit/core/messages/payloads/test_cancel.py | ?? PARTIAL | +| kmip/core/messages/payloads/check.py | kmip/tests/unit/core/messages/payloads/test_check.py | ?? PARTIAL | +| kmip/core/messages/payloads/create.py | kmip/tests/unit/core/messages/payloads/test_create.py | ?? PARTIAL | +| kmip/core/messages/payloads/create_key_pair.py | kmip/tests/unit/core/messages/payloads/test_create_key_pair.py | ?? PARTIAL | +| kmip/core/messages/payloads/decrypt.py | kmip/tests/unit/core/messages/payloads/test_decrypt.py | ?? PARTIAL | +| kmip/core/messages/payloads/delete_attribute.py | kmip/tests/unit/core/messages/payloads/test_delete_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/derive_key.py | kmip/tests/unit/core/messages/payloads/test_derive_key.py | ?? PARTIAL | +| kmip/core/messages/payloads/destroy.py | kmip/tests/unit/core/messages/payloads/test_destroy.py | ?? PARTIAL | +| kmip/core/messages/payloads/discover_versions.py | kmip/tests/unit/core/messages/payloads/test_discover_versions.py | ?? PARTIAL | +| kmip/core/messages/payloads/encrypt.py | kmip/tests/unit/core/messages/payloads/test_encrypt.py | ?? PARTIAL | +| kmip/core/messages/payloads/get.py | kmip/tests/unit/core/messages/payloads/test_get.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_attribute_list.py | kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_attributes.py | kmip/tests/unit/core/messages/payloads/test_get_attributes.py | ?? PARTIAL | +| kmip/core/messages/payloads/get_usage_allocation.py | kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py | ?? PARTIAL | +| kmip/core/messages/payloads/locate.py | kmip/tests/unit/core/messages/payloads/test_locate.py | ?? PARTIAL | +| kmip/core/messages/payloads/mac.py | kmip/tests/unit/core/messages/payloads/test_mac.py | ?? PARTIAL | +| kmip/core/messages/payloads/modify_attribute.py | kmip/tests/unit/core/messages/payloads/test_modify_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/obtain_lease.py | kmip/tests/unit/core/messages/payloads/test_obtain_lease.py | ?? PARTIAL | +| kmip/core/messages/payloads/poll.py | kmip/tests/unit/core/messages/payloads/test_poll.py | ?? PARTIAL | +| kmip/core/messages/payloads/query.py | kmip/tests/unit/core/messages/payloads/test_query.py | ?? PARTIAL | +| kmip/core/messages/payloads/recover.py | kmip/tests/unit/core/messages/payloads/test_recover.py | ?? PARTIAL | +| kmip/core/messages/payloads/register.py | kmip/tests/unit/core/messages/payloads/test_register.py | ?? PARTIAL | +| kmip/core/messages/payloads/rekey.py | kmip/tests/unit/core/messages/payloads/test_rekey.py | ?? PARTIAL | +| kmip/core/messages/payloads/rekey_key_pair.py | kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py | ?? PARTIAL | +| kmip/core/messages/payloads/revoke.py | kmip/tests/unit/core/messages/payloads/test_revoke.py | ?? PARTIAL | +| kmip/core/messages/payloads/set_attribute.py | kmip/tests/unit/core/messages/payloads/test_set_attribute.py | ?? PARTIAL | +| kmip/core/messages/payloads/sign.py | kmip/tests/unit/core/messages/payloads/test_sign.py | ?? PARTIAL | +| kmip/core/messages/payloads/signature_verify.py | kmip/tests/unit/core/messages/payloads/test_signature_verify.py | ?? PARTIAL | +| kmip/core/misc.py | kmip/tests/unit/core/test_misc.py | ?? PARTIAL | +| kmip/core/objects.py | kmip/tests/unit/core/test_objects.py | ?? PARTIAL | +| kmip/core/policy.py | kmip/tests/unit/core/test_policy.py | ?? PARTIAL | +| kmip/core/primitives.py | kmip/tests/unit/core/test_primitives.py | ?? PARTIAL | +| kmip/core/secrets.py | kmip/tests/unit/core/test_secrets.py | ?? PARTIAL | +| kmip/core/utils.py | kmip/tests/unit/core/test_utils.py | ?? PARTIAL | +| kmip/pie/__init__.py | kmip/tests/unit/pie/test___init__.py | ? MISSING | +| kmip/pie/client.py | kmip/tests/unit/pie/test_client.py | ?? PARTIAL | +| kmip/pie/exceptions.py | kmip/tests/unit/pie/test_exceptions.py | ? EXISTS | +| kmip/pie/factory.py | kmip/tests/unit/pie/test_factory.py | ?? PARTIAL | +| kmip/pie/objects.py | kmip/tests/unit/pie/test_objects.py | ?? PARTIAL | +| kmip/pie/sqltypes.py | kmip/tests/unit/pie/test_sqltypes.py | ?? PARTIAL | +| kmip/services/__init__.py | kmip/tests/unit/services/test___init__.py | ? MISSING | +| kmip/services/auth.py | kmip/tests/unit/services/test_auth.py | ?? PARTIAL | +| kmip/services/kmip_client.py | kmip/tests/unit/services/test_kmip_client.py | ? EXISTS | +| kmip/services/kmip_protocol.py | kmip/tests/unit/services/test_kmip_protocol.py | ? EXISTS | +| kmip/services/results.py | kmip/tests/unit/services/test_results.py | ?? PARTIAL | +| kmip/services/server/__init__.py | kmip/tests/unit/services/server/test___init__.py | ? MISSING | +| kmip/services/server/auth/__init__.py | kmip/tests/unit/services/server/auth/test___init__.py | ? MISSING | +| kmip/services/server/auth/api.py | kmip/tests/unit/services/server/auth/test_api.py | ? MISSING | +| kmip/services/server/auth/slugs.py | kmip/tests/unit/services/server/auth/test_slugs.py | ?? PARTIAL | +| kmip/services/server/auth/utils.py | kmip/tests/unit/services/server/auth/test_utils.py | ?? PARTIAL | +| kmip/services/server/config.py | kmip/tests/unit/services/server/test_config.py | ?? PARTIAL | +| kmip/services/server/crypto/__init__.py | kmip/tests/unit/services/server/crypto/test___init__.py | ? MISSING | +| kmip/services/server/crypto/api.py | kmip/tests/unit/services/server/crypto/test_api.py | ? MISSING | +| kmip/services/server/crypto/engine.py | kmip/tests/unit/services/server/crypto/test_engine.py | ?? PARTIAL | +| kmip/services/server/engine.py | kmip/tests/unit/services/server/test_engine.py | ?? PARTIAL | +| kmip/services/server/monitor.py | kmip/tests/unit/services/server/test_monitor.py | ?? PARTIAL | +| kmip/services/server/policy.py | kmip/tests/unit/services/server/test_policy.py | ?? PARTIAL | +| kmip/services/server/server.py | kmip/tests/unit/services/server/test_server.py | ?? PARTIAL | +| kmip/services/server/session.py | kmip/tests/unit/services/server/test_session.py | ?? PARTIAL | +| kmip/version.py | kmip/tests/unit/test_version.py | ? MISSING | \ No newline at end of file diff --git a/._coverage_table_ready.md b/._coverage_table_ready.md new file mode 100644 index 00000000..0ef06dd0 --- /dev/null +++ b/._coverage_table_ready.md @@ -0,0 +1,83 @@ +| Modu? ?r?d?owy | Plik testowy | Status | +|---|---|---| +| `kmip/__init__.py` | `kmip/tests/unit/test___init__.py` | ? MISSING | +| `kmip/core/__init__.py` | `kmip/tests/unit/core/test___init__.py` | ? MISSING | +| `kmip/core/attributes.py` | `kmip/tests/unit/core/test_attributes.py` | ? EXISTS | +| `kmip/core/config_helper.py` | `kmip/tests/unit/core/test_config_helper.py` | ? EXISTS | +| `kmip/core/enums.py` | `kmip/tests/unit/core/test_enums.py` | ?? PARTIAL | +| `kmip/core/exceptions.py` | `kmip/tests/unit/core/test_exceptions.py` | ?? PARTIAL | +| `kmip/core/factories/__init__.py` | `kmip/tests/unit/core/factories/test___init__.py` | ? MISSING | +| `kmip/core/factories/attribute_values.py` | `kmip/tests/unit/core/factories/test_attribute_values.py` | ? EXISTS | +| `kmip/core/factories/attributes.py` | `kmip/tests/unit/core/factories/test_attributes.py` | ? EXISTS | +| `kmip/core/factories/credentials.py` | `kmip/tests/unit/core/factories/test_credentials.py` | ?? PARTIAL | +| `kmip/core/factories/payloads/__init__.py` | `kmip/tests/unit/core/factories/payloads/test___init__.py` | ? EXISTS | +| `kmip/core/factories/payloads/request.py` | `kmip/tests/unit/core/factories/payloads/test_request.py` | ? EXISTS | +| `kmip/core/factories/payloads/response.py` | `kmip/tests/unit/core/factories/payloads/test_response.py` | ? EXISTS | +| `kmip/core/factories/secrets.py` | `kmip/tests/unit/core/factories/test_secrets.py` | ? EXISTS | +| `kmip/core/messages/__init__.py` | `kmip/tests/unit/core/messages/test___init__.py` | ? MISSING | +| `kmip/core/messages/contents.py` | `kmip/tests/unit/core/messages/test_contents.py` | ?? PARTIAL | +| `kmip/core/messages/messages.py` | `kmip/tests/unit/core/messages/test_messages.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/__init__.py` | `kmip/tests/unit/core/messages/payloads/test___init__.py` | ? MISSING | +| `kmip/core/messages/payloads/activate.py` | `kmip/tests/unit/core/messages/payloads/test_activate.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/archive.py` | `kmip/tests/unit/core/messages/payloads/test_archive.py` | ? EXISTS | +| `kmip/core/messages/payloads/base.py` | `kmip/tests/unit/core/messages/payloads/test_base.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/cancel.py` | `kmip/tests/unit/core/messages/payloads/test_cancel.py` | ? EXISTS | +| `kmip/core/messages/payloads/check.py` | `kmip/tests/unit/core/messages/payloads/test_check.py` | ? EXISTS | +| `kmip/core/messages/payloads/create.py` | `kmip/tests/unit/core/messages/payloads/test_create.py` | ? EXISTS | +| `kmip/core/messages/payloads/create_key_pair.py` | `kmip/tests/unit/core/messages/payloads/test_create_key_pair.py` | ? EXISTS | +| `kmip/core/messages/payloads/decrypt.py` | `kmip/tests/unit/core/messages/payloads/test_decrypt.py` | ? EXISTS | +| `kmip/core/messages/payloads/delete_attribute.py` | `kmip/tests/unit/core/messages/payloads/test_delete_attribute.py` | ? EXISTS | +| `kmip/core/messages/payloads/derive_key.py` | `kmip/tests/unit/core/messages/payloads/test_derive_key.py` | ? EXISTS | +| `kmip/core/messages/payloads/destroy.py` | `kmip/tests/unit/core/messages/payloads/test_destroy.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/discover_versions.py` | `kmip/tests/unit/core/messages/payloads/test_discover_versions.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/encrypt.py` | `kmip/tests/unit/core/messages/payloads/test_encrypt.py` | ? EXISTS | +| `kmip/core/messages/payloads/get.py` | `kmip/tests/unit/core/messages/payloads/test_get.py` | ? EXISTS | +| `kmip/core/messages/payloads/get_attribute_list.py` | `kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py` | ? EXISTS | +| `kmip/core/messages/payloads/get_attributes.py` | `kmip/tests/unit/core/messages/payloads/test_get_attributes.py` | ? EXISTS | +| `kmip/core/messages/payloads/get_usage_allocation.py` | `kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py` | ? EXISTS | +| `kmip/core/messages/payloads/locate.py` | `kmip/tests/unit/core/messages/payloads/test_locate.py` | ? EXISTS | +| `kmip/core/messages/payloads/mac.py` | `kmip/tests/unit/core/messages/payloads/test_mac.py` | ? EXISTS | +| `kmip/core/messages/payloads/modify_attribute.py` | `kmip/tests/unit/core/messages/payloads/test_modify_attribute.py` | ? EXISTS | +| `kmip/core/messages/payloads/obtain_lease.py` | `kmip/tests/unit/core/messages/payloads/test_obtain_lease.py` | ? EXISTS | +| `kmip/core/messages/payloads/poll.py` | `kmip/tests/unit/core/messages/payloads/test_poll.py` | ? EXISTS | +| `kmip/core/messages/payloads/query.py` | `kmip/tests/unit/core/messages/payloads/test_query.py` | ? EXISTS | +| `kmip/core/messages/payloads/recover.py` | `kmip/tests/unit/core/messages/payloads/test_recover.py` | ? EXISTS | +| `kmip/core/messages/payloads/register.py` | `kmip/tests/unit/core/messages/payloads/test_register.py` | ? EXISTS | +| `kmip/core/messages/payloads/rekey.py` | `kmip/tests/unit/core/messages/payloads/test_rekey.py` | ? EXISTS | +| `kmip/core/messages/payloads/rekey_key_pair.py` | `kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/revoke.py` | `kmip/tests/unit/core/messages/payloads/test_revoke.py` | ?? PARTIAL | +| `kmip/core/messages/payloads/set_attribute.py` | `kmip/tests/unit/core/messages/payloads/test_set_attribute.py` | ? EXISTS | +| `kmip/core/messages/payloads/sign.py` | `kmip/tests/unit/core/messages/payloads/test_sign.py` | ? EXISTS | +| `kmip/core/messages/payloads/signature_verify.py` | `kmip/tests/unit/core/messages/payloads/test_signature_verify.py` | ? EXISTS | +| `kmip/core/misc.py` | `kmip/tests/unit/core/test_misc.py` | ?? PARTIAL | +| `kmip/core/objects.py` | `kmip/tests/unit/core/test_objects.py` | ? EXISTS | +| `kmip/core/policy.py` | `kmip/tests/unit/core/test_policy.py` | ? EXISTS | +| `kmip/core/primitives.py` | `kmip/tests/unit/core/test_primitives.py` | ?? PARTIAL | +| `kmip/core/secrets.py` | `kmip/tests/unit/core/test_secrets.py` | ?? PARTIAL | +| `kmip/core/utils.py` | `kmip/tests/unit/core/test_utils.py` | ?? PARTIAL | +| `kmip/pie/__init__.py` | `kmip/tests/unit/pie/test___init__.py` | ? MISSING | +| `kmip/pie/client.py` | `kmip/tests/unit/pie/test_client.py` | ?? PARTIAL | +| `kmip/pie/exceptions.py` | `kmip/tests/unit/pie/test_exceptions.py` | ? EXISTS | +| `kmip/pie/factory.py` | `kmip/tests/unit/pie/test_factory.py` | ? EXISTS | +| `kmip/pie/objects.py` | `kmip/tests/unit/pie/test_objects.py` | ? EXISTS | +| `kmip/pie/sqltypes.py` | `kmip/tests/unit/pie/test_sqltypes.py` | ?? PARTIAL | +| `kmip/services/__init__.py` | `kmip/tests/unit/services/test___init__.py` | ? MISSING | +| `kmip/services/auth.py` | `kmip/tests/unit/services/test_auth.py` | ? EXISTS | +| `kmip/services/kmip_client.py` | `kmip/tests/unit/services/test_kmip_client.py` | ?? PARTIAL | +| `kmip/services/kmip_protocol.py` | `kmip/tests/unit/services/test_kmip_protocol.py` | ? EXISTS | +| `kmip/services/results.py` | `kmip/tests/unit/services/test_results.py` | ?? PARTIAL | +| `kmip/services/server/__init__.py` | `kmip/tests/unit/services/server/test___init__.py` | ? MISSING | +| `kmip/services/server/auth/__init__.py` | `kmip/tests/unit/services/server/auth/test___init__.py` | ? MISSING | +| `kmip/services/server/auth/api.py` | `kmip/tests/unit/services/server/auth/test_api.py` | ? MISSING | +| `kmip/services/server/auth/slugs.py` | `kmip/tests/unit/services/server/auth/test_slugs.py` | ? EXISTS | +| `kmip/services/server/auth/utils.py` | `kmip/tests/unit/services/server/auth/test_utils.py` | ? EXISTS | +| `kmip/services/server/config.py` | `kmip/tests/unit/services/server/test_config.py` | ? EXISTS | +| `kmip/services/server/crypto/__init__.py` | `kmip/tests/unit/services/server/crypto/test___init__.py` | ? MISSING | +| `kmip/services/server/crypto/api.py` | `kmip/tests/unit/services/server/crypto/test_api.py` | ? MISSING | +| `kmip/services/server/crypto/engine.py` | `kmip/tests/unit/services/server/crypto/test_engine.py` | ? EXISTS | +| `kmip/services/server/engine.py` | `kmip/tests/unit/services/server/test_engine.py` | ? EXISTS | +| `kmip/services/server/monitor.py` | `kmip/tests/unit/services/server/test_monitor.py` | ?? PARTIAL | +| `kmip/services/server/policy.py` | `kmip/tests/unit/services/server/test_policy.py` | ?? PARTIAL | +| `kmip/services/server/server.py` | `kmip/tests/unit/services/server/test_server.py` | ?? PARTIAL | +| `kmip/services/server/session.py` | `kmip/tests/unit/services/server/test_session.py` | ? EXISTS | +| `kmip/version.py` | `kmip/tests/unit/test_version.py` | ? MISSING | \ No newline at end of file diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 6f1c5e95..9b81e7d8 100755 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -11,10 +11,9 @@ jobs: matrix: os: [ubuntu-latest] python: - - {version: '3.8', env: py38} - - {version: '3.9', env: py39} - - {version: '3.10', env: py310} - - {version: '3.11', env: py311} + - {version: '3.12', env: py312} + - {version: '3.13', env: py313} + - {version: '3.14', env: py314} test_mode: [0, 1] runs-on: ${{ matrix.os }} env: @@ -35,7 +34,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python: ['3.8', '3.9', '3.10', '3.11'] + python: ['3.12', '3.13', '3.14'] test: [pep8, bandit, docs] runs-on: ${{ matrix.os }} env: diff --git a/.travis.yml b/.travis.yml index 80bb9643..0e91df89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,249 +1,46 @@ sudo: true language: python -matrix: - include: - - python: 2.7 - os: linux - dist: precise - env: TOXENV=py27 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=py27 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=py27 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: precise - env: TOXENV=py27 RUN_INTEGRATION_TESTS=1 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=py27 RUN_INTEGRATION_TESTS=1 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=py27 RUN_INTEGRATION_TESTS=1 - - python: 2.7 - os: linux - dist: precise - env: TOXENV=py27 RUN_INTEGRATION_TESTS=2 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=py27 RUN_INTEGRATION_TESTS=2 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=py27 RUN_INTEGRATION_TESTS=2 - - python: 3.4 - os: linux - dist: precise - env: TOXENV=py34 RUN_INTEGRATION_TESTS=0 - - python: 3.4 - os: linux - dist: trusty - env: TOXENV=py34 RUN_INTEGRATION_TESTS=0 - - python: 3.4 - os: linux - dist: xenial - env: TOXENV=py34 RUN_INTEGRATION_TESTS=0 - - python: 3.4 - os: linux - dist: precise - env: TOXENV=py34 RUN_INTEGRATION_TESTS=1 - - python: 3.4 - os: linux - dist: trusty - env: TOXENV=py34 RUN_INTEGRATION_TESTS=1 - - python: 3.4 - os: linux - dist: xenial - env: TOXENV=py34 RUN_INTEGRATION_TESTS=1 - - python: 3.4 - os: linux - dist: precise - env: TOXENV=py34 RUN_INTEGRATION_TESTS=2 - - python: 3.4 - os: linux - dist: trusty - env: TOXENV=py34 RUN_INTEGRATION_TESTS=2 - - python: 3.4 - os: linux - dist: xenial - env: TOXENV=py34 RUN_INTEGRATION_TESTS=2 - - python: 3.5 - os: linux - dist: precise - env: TOXENV=py35 RUN_INTEGRATION_TESTS=0 - - python: 3.5 - os: linux - dist: trusty - env: TOXENV=py35 RUN_INTEGRATION_TESTS=0 - - python: 3.5 - os: linux - dist: xenial - env: TOXENV=py35 RUN_INTEGRATION_TESTS=0 - - python: 3.5 - os: linux - dist: precise - env: TOXENV=py35 RUN_INTEGRATION_TESTS=1 - - python: 3.5 - os: linux - dist: trusty - env: TOXENV=py35 RUN_INTEGRATION_TESTS=1 - - python: 3.5 - os: linux - dist: xenial - env: TOXENV=py35 RUN_INTEGRATION_TESTS=1 - - python: 3.5 - os: linux - dist: precise - env: TOXENV=py35 RUN_INTEGRATION_TESTS=2 - - python: 3.5 - os: linux - dist: trusty - env: TOXENV=py35 RUN_INTEGRATION_TESTS=2 - - python: 3.5 - os: linux - dist: xenial - env: TOXENV=py35 RUN_INTEGRATION_TESTS=2 - - python: 3.6 - os: linux - dist: precise - env: TOXENV=py36 RUN_INTEGRATION_TESTS=0 - - python: 3.6 - os: linux - dist: trusty - env: TOXENV=py36 RUN_INTEGRATION_TESTS=0 - - python: 3.6 - os: linux - dist: xenial - env: TOXENV=py36 RUN_INTEGRATION_TESTS=0 - - python: 3.6 - os: linux - dist: precise - env: TOXENV=py36 RUN_INTEGRATION_TESTS=1 - - python: 3.6 - os: linux - dist: trusty - env: TOXENV=py36 RUN_INTEGRATION_TESTS=1 - - python: 3.6 - os: linux - dist: xenial - env: TOXENV=py36 RUN_INTEGRATION_TESTS=1 - - python: 3.6 - os: linux - dist: precise - env: TOXENV=py36 RUN_INTEGRATION_TESTS=2 - - python: 3.6 - os: linux - dist: trusty - env: TOXENV=py36 RUN_INTEGRATION_TESTS=2 - - python: 3.6 - os: linux - dist: xenial - env: TOXENV=py36 RUN_INTEGRATION_TESTS=2 -# - python: 3.7 -# os: linux -# dist: precise -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=0 -# - python: 3.7 -# os: linux -# dist: trusty -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=0 - - python: 3.7 - os: linux - dist: xenial - env: TOXENV=py37 RUN_INTEGRATION_TESTS=0 -# - python: 3.7 -# os: linux -# dist: precise -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=1 -# - python: 3.7 -# os: linux -# dist: trusty -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=1 - - python: 3.7 - os: linux - dist: xenial - env: TOXENV=py36 RUN_INTEGRATION_TESTS=1 -# - python: 3.7 -# os: linux -# dist: precise -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=2 -# - python: 3.7 -# os: linux -# dist: trusty -# env: TOXENV=py37 RUN_INTEGRATION_TESTS=2 - - python: 3.7 - os: linux - dist: xenial - env: TOXENV=py37 RUN_INTEGRATION_TESTS=2 - - python: 2.7 - os: linux - dist: precise - env: TOXENV=pep8 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=pep8 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=pep8 RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: precise - env: TOXENV=bandit RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=bandit RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=bandit RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: precise - env: TOXENV=docs RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: trusty - env: TOXENV=docs RUN_INTEGRATION_TESTS=0 - - python: 2.7 - os: linux - dist: xenial - env: TOXENV=docs RUN_INTEGRATION_TESTS=0 + +jobs: + include: + - python: "3.12" + env: TOXENV=py312 RUN_INTEGRATION_TESTS=0 + - python: "3.12" + env: TOXENV=py312 RUN_INTEGRATION_TESTS=1 + - python: "3.12" + env: TOXENV=py312 RUN_INTEGRATION_TESTS=2 + - python: "3.13" + env: TOXENV=py313 RUN_INTEGRATION_TESTS=0 + - python: "3.13" + env: TOXENV=py313 RUN_INTEGRATION_TESTS=1 + - python: "3.13" + env: TOXENV=py313 RUN_INTEGRATION_TESTS=2 + - python: "3.14" + env: TOXENV=py314 RUN_INTEGRATION_TESTS=0 + - python: "3.14" + env: TOXENV=py314 RUN_INTEGRATION_TESTS=1 + - python: "3.14" + env: TOXENV=py314 RUN_INTEGRATION_TESTS=2 + - python: "3.12" + env: TOXENV=pep8 RUN_INTEGRATION_TESTS=0 + - python: "3.12" + env: TOXENV=bandit RUN_INTEGRATION_TESTS=0 + - python: "3.12" + env: TOXENV=docs RUN_INTEGRATION_TESTS=0 + install: - # Pin six to >= 1.11.0 to avoid setuptools/pip race condition - # For more info, see: https://github.com/OpenKMIP/PyKMIP/issues/435 - - pip uninstall -y six - - pip install six>=1.11.0 - # Pin more_itertools to <= 7.2.0. Version 8.0.0+ drops support for - # Python 3.4. Once PyKMIP drops support for Python 3.4, remove this. - - pip install "more_itertools<=7.2.0" - # Pin tox to <= 3.14.1. Version 3.14.2+ moves to newer versions of - # the importlib_metadata package which breaks on Python 3.4. Future - # versions of tox will also drop support for Python 2.7 and 3.4. - # Once PyKMIP also drops support for Python 2.7 and 3.4, remove this. - - pip install "tox<=3.14.1" - # Pin PyYAML to <= 5.2. Version 5.3+ removes support for Python 3.4. - # PyYAML is installed as a bandit dependency, so while it doesn't - # break PyKMIP proper, it does break any of our test runs using - # Python 3.4. Once PyKMIP drops support for Python 3.4, remove this. - - pip install "PyYAML<=5.2" + - pip install tox - pip install bandit - pip install codecov - pip install slugs - python setup.py install + script: - ./.travis/run.sh + after_success: - codecov + after_failure: - if [ -f "/tmp/pykmip/server.log" ]; then cat /tmp/pykmip/server.log; fi - if [ -f "/tmp/slugs/access.log" ]; then cat /tmp/slugs/access.log; fi diff --git a/docs/source/development.rst b/docs/source/development.rst index c90ab4b3..80a268f1 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -106,7 +106,7 @@ Running Tests ------------- PyKMIP uses ``tox`` to manage testing across multiple Python versions. ``tox`` in turn uses ``pytest`` to run individual tests. Test infrastructure currently -supports Python 2.7, 3.4, 3.5, 3.6, and 3.7. Additional test environments are +supports Python 3.12, 3.13, and 3.14. Additional test environments are provided for security, style, and documentation checks. .. note:: @@ -149,19 +149,19 @@ base, verifying that each component works correctly in isolation. Ideal code coverage would include the entire code base. To facilitate improving coverage, test coverage results are included with each Python unit test environment. -To test against a specific Python version (e.g., Python 2.7), run: +To test against a specific Python version (e.g., Python 3.12), run: .. code-block:: console - $ tox -e py27 + $ tox -e py312 To run an individual test suite method or class, use the ``pytest`` ``-k`` flag to specify the name of the method or class to execute. For example, to -run the ``TestProxyKmipClient`` test suite class under Python 2.7, run: +run the ``TestProxyKmipClient`` test suite class under Python 3.12, run: .. code-block:: console - $ tox -e py27 -- -k TestProxyKmipClient + $ tox -e py312 -- -k TestProxyKmipClient For more information on the ``-k`` flag, see the `pytest`_ documentation. @@ -253,4 +253,4 @@ resources: .. _`flake8`: https://pypi.python.org/pypi/flake8 .. _`bandit`: https://pypi.python.org/pypi/bandit .. _`SLUGS`: https://github.com/OpenKMIP/SLUGS -.. _`pytest`: https://docs.pytest.org/en/latest/usage.html \ No newline at end of file +.. _`pytest`: https://docs.pytest.org/en/latest/usage.html diff --git a/kmip/__init__.py b/kmip/__init__.py index b809374e..3ef5ed98 100644 --- a/kmip/__init__.py +++ b/kmip/__init__.py @@ -34,7 +34,6 @@ ) __version__ = m.group(1) - __all__ = [ 'client', 'core', diff --git a/kmip/core/attributes.py b/kmip/core/attributes.py index d2788688..e025be27 100644 --- a/kmip/core/attributes.py +++ b/kmip/core/attributes.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core.enums import HashingAlgorithm as HashingAlgorithmEnum from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum @@ -37,28 +35,24 @@ from enum import Enum - # 3.1 class UniqueIdentifier(TextString): def __init__(self, value=None, tag=Tags.UNIQUE_IDENTIFIER): super(UniqueIdentifier, self).__init__(value, tag) - class PrivateKeyUniqueIdentifier(UniqueIdentifier): def __init__(self, value=None): super(PrivateKeyUniqueIdentifier, self).__init__( value, Tags.PRIVATE_KEY_UNIQUE_IDENTIFIER) - class PublicKeyUniqueIdentifier(UniqueIdentifier): def __init__(self, value=None): super(PublicKeyUniqueIdentifier, self).__init__( value, Tags.PUBLIC_KEY_UNIQUE_IDENTIFIER) - # 3.2 class Name(Struct): @@ -210,7 +204,6 @@ def __eq__(self, other): def __ne__(self, other): return not self.__eq__(other) - # 3.3 class ObjectType(Enumeration): @@ -218,7 +211,6 @@ def __init__(self, value=None): super(ObjectType, self).__init__( enums.ObjectType, value, Tags.OBJECT_TYPE) - # 3.4 class CryptographicAlgorithm(Enumeration): @@ -226,7 +218,6 @@ def __init__(self, value=None): super(CryptographicAlgorithm, self).__init__( enums.CryptographicAlgorithm, value, Tags.CRYPTOGRAPHIC_ALGORITHM) - # 3.5 class CryptographicLength(Integer): @@ -234,7 +225,6 @@ def __init__(self, value=None): super(CryptographicLength, self).__init__( value, Tags.CRYPTOGRAPHIC_LENGTH) - # 3.6 class HashingAlgorithm(Enumeration): """ @@ -257,7 +247,6 @@ def __init__(self, value=HashingAlgorithmEnum.SHA_256): super(HashingAlgorithm, self).__init__( enums.HashingAlgorithm, value, Tags.HASHING_ALGORITHM) - class CryptographicParameters(Struct): """ A set of values for cryptographic operations. @@ -476,7 +465,7 @@ def iv_length(self): def iv_length(self, value): if value is None: self._iv_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._iv_length = Integer( value=value, tag=Tags.IV_LENGTH @@ -495,7 +484,7 @@ def tag_length(self): def tag_length(self, value): if value is None: self._tag_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._tag_length = Integer( value=value, tag=Tags.TAG_LENGTH @@ -514,7 +503,7 @@ def fixed_field_length(self): def fixed_field_length(self, value): if value is None: self._fixed_field_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._fixed_field_length = Integer( value=value, tag=Tags.FIXED_FIELD_LENGTH @@ -533,7 +522,7 @@ def invocation_field_length(self): def invocation_field_length(self, value): if value is None: self._invocation_field_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._invocation_field_length = Integer( value=value, tag=Tags.INVOCATION_FIELD_LENGTH @@ -552,7 +541,7 @@ def counter_length(self): def counter_length(self, value): if value is None: self._counter_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._counter_length = Integer( value=value, tag=Tags.COUNTER_LENGTH @@ -571,7 +560,7 @@ def initial_counter_value(self): def initial_counter_value(self, value): if value is None: self._initial_counter_value = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._initial_counter_value = Integer( value=value, tag=Tags.INITIAL_COUNTER_VALUE @@ -802,7 +791,6 @@ def __str__(self): 'initial_counter_value': self.initial_counter_value }) - class CertificateType(Enumeration): """ An encodeable wrapper for the CertificateType enumeration. @@ -824,7 +812,6 @@ def __init__(self, value=enums.CertificateType.X_509): super(CertificateType, self).__init__( enums.CertificateType, value, Tags.CERTIFICATE_TYPE) - class DigestValue(ByteString): """ A byte string representing the hash value of a Digest. @@ -848,7 +835,6 @@ def __init__(self, value=b''): """ super(DigestValue, self).__init__(value, Tags.DIGEST_VALUE) - class Digest(Struct): """ A structure storing a hash digest of a Managed Object. @@ -1041,7 +1027,6 @@ def create(cls, digest_value=value, key_format_type=format_type) - # 3.18 class OperationPolicyName(TextString): @@ -1049,7 +1034,6 @@ def __init__(self, value=None): super(OperationPolicyName, self).__init__( value, Tags.OPERATION_POLICY_NAME) - # 3.19 class CryptographicUsageMask(Integer): @@ -1059,13 +1043,11 @@ def __init__(self, value=None): super(CryptographicUsageMask, self).__init__( value, Tags.CRYPTOGRAPHIC_USAGE_MASK) - class State(Enumeration): def __init__(self, value=None): super(State, self).__init__(enums.State, value, Tags.STATE) - class ApplicationSpecificInformation(primitives.Struct): """ A structure used to store data specific to the applications that use a @@ -1112,7 +1094,7 @@ def application_namespace(self): def application_namespace(self, value): if value is None: self._application_namespace = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._application_namespace = primitives.TextString( value=value, tag=enums.Tags.APPLICATION_NAMESPACE @@ -1130,7 +1112,7 @@ def application_data(self): def application_data(self, value): if value is None: self._application_data = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._application_data = primitives.TextString( value=value, tag=enums.Tags.APPLICATION_DATA @@ -1265,7 +1247,6 @@ def __ne__(self, other): else: return NotImplemented - # 3.37 class ContactInformation(TextString): @@ -1273,7 +1254,6 @@ def __init__(self, value=None): super(ContactInformation, self).__init__( value, Tags.CONTACT_INFORMATION) - # 3.39 # TODO (peter-hamilton) A CustomAttribute TextString is not sufficient to # TODO (peter-hamilton) cover all potential custom attributes. This is a @@ -1283,7 +1263,6 @@ class CustomAttribute(TextString): def __init__(self, value=None): super(CustomAttribute, self).__init__(value, Tags.ATTRIBUTE_VALUE) - class DerivationParameters(Struct): """ A set of values needed for key or secret derivation. @@ -1361,7 +1340,7 @@ def initialization_vector(self): def initialization_vector(self, value): if value is None: self._initialization_vector = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._initialization_vector = ByteString( value=value, tag=enums.Tags.INITIALIZATION_VECTOR @@ -1380,7 +1359,7 @@ def derivation_data(self): def derivation_data(self, value): if value is None: self._derivation_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._derivation_data = ByteString( value=value, tag=enums.Tags.DERIVATION_DATA @@ -1399,7 +1378,7 @@ def salt(self): def salt(self, value): if value is None: self._salt = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._salt = ByteString( value=value, tag=enums.Tags.SALT @@ -1418,7 +1397,7 @@ def iteration_count(self): def iteration_count(self, value): if value is None: self._iteration_count = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._iteration_count = Integer( value=value, tag=Tags.ITERATION_COUNT diff --git a/kmip/core/config_helper.py b/kmip/core/config_helper.py index a204666d..d2989b94 100644 --- a/kmip/core/config_helper.py +++ b/kmip/core/config_helper.py @@ -15,9 +15,7 @@ import logging import os - -from six.moves.configparser import ConfigParser - +from configparser import ConfigParser FILE_PATH = os.path.dirname(os.path.abspath(__file__)) # TODO (peter-hamilton): Remove support for kmipconfig.ini on future release. @@ -27,7 +25,6 @@ os.path.normpath(os.path.join(FILE_PATH, '../pykmip.conf')), os.path.normpath(os.path.join(FILE_PATH, '../kmipconfig.ini'))] - class ConfigHelper(object): NONE_VALUE = 'None' DEFAULT_HOST = "127.0.0.1" diff --git a/kmip/core/enums.py b/kmip/core/enums.py index 5118d3ad..576b0b32 100644 --- a/kmip/core/enums.py +++ b/kmip/core/enums.py @@ -19,8 +19,6 @@ import copy import enum import functools -import six - class OrderedEnum(enum.Enum): """ @@ -49,14 +47,12 @@ def __lt__(self, other): return self.value < other.value return NotImplemented - class AdjustmentType(enum.Enum): # KMIP 2.0 INCREMENT = 0x00000001 DECREMENT = 0x00000002 NEGATE = 0x00000003 - class AlternativeNameType(enum.Enum): # KMIP 1.2 UNINTERPRETED_TEXT_STRING = 0x00000001 @@ -67,21 +63,18 @@ class AlternativeNameType(enum.Enum): X500_DISTINGUISHED_NAME = 0x00000006 IP_ADDRESS = 0x00000007 - class AsynchronousIndicator(enum.Enum): # KMIP 2.0 MANDATORY = 0x00000001 OPTIONAL = 0x00000002 PROHIBITED = 0x00000003 - class AttestationType(enum.Enum): # KMIP 1.2 TPM_QUOTE = 0x00000001 TCG_INTEGRITY_REPORT = 0x00000002 SAML_ASSERTION = 0x00000003 - class AttributeType(enum.Enum): UNIQUE_IDENTIFIER = 'Unique Identifier' NAME = 'Name' @@ -131,7 +124,6 @@ class AttributeType(enum.Enum): EXTRACTABLE = 'Extractable' NEVER_EXTRACTABLE = 'Never Extractable' - class AuthenticationSuite(enum.Enum): """ The type of authentication suite used by KMIP clients and servers. @@ -145,14 +137,12 @@ class AuthenticationSuite(enum.Enum): BASIC = 1 TLS12 = 2 - class BatchErrorContinuationOption(enum.Enum): # KMIP 1.0 CONTINUE = 0x00000001 STOP = 0x00000002 UNDO = 0x00000003 - class BlockCipherMode(enum.Enum): # KMIP 1.0 CBC = 0x00000001 @@ -175,7 +165,6 @@ class BlockCipherMode(enum.Enum): # KMIP 1.4 AEAD = 0x00000012 - class CancellationResult(enum.Enum): # KMIP 1.0 CANCELED = 0x00000001 @@ -184,7 +173,6 @@ class CancellationResult(enum.Enum): FAILED = 0x00000004 UNAVAILABLE = 0x00000005 - class CertificateRequestType(enum.Enum): # KMIP 1.0 CRMF = 0x00000001 @@ -192,13 +180,11 @@ class CertificateRequestType(enum.Enum): PEM = 0x00000003 PGP = 0x00000004 # Deprecated, designated '(Reserved)' in KMIP 2.0 - class CertificateType(enum.Enum): # KMIP 1.0 X_509 = 0x00000001 PGP = 0x00000002 # Deprecated as of KMIP 1.2, not deprecated in KMIP 2.0 - class ClientRegistrationMethod(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -207,7 +193,6 @@ class ClientRegistrationMethod(enum.Enum): CLIENT_GENERATED = 0x00000004 CLIENT_REGISTERED = 0x00000005 - class ConformanceClause(enum.Enum): DISCOVER_VERSIONS = 1 BASELINE = 2 @@ -221,7 +206,6 @@ class ConformanceClause(enum.Enum): ASYMMETRIC_KEY_FOUNDRY_AND_CERTIFICATE = 10 STORAGE = 11 - class CredentialType(enum.Enum): # KMIP 1.0 USERNAME_AND_PASSWORD = 0x00000001 @@ -234,7 +218,6 @@ class CredentialType(enum.Enum): HASHED_PASSWORD = 0x00000005 TICKET = 0x00000006 - class CryptographicAlgorithm(enum.Enum): # KMIP 1.0 DES = 0x00000001 @@ -298,7 +281,6 @@ class CryptographicAlgorithm(enum.Enum): ED25519 = 0x00000037 ED448 = 0x00000038 - class CryptographicUsageMask(enum.Enum): # KMIP 1.0 SIGN = 0x00000001 @@ -327,7 +309,6 @@ class CryptographicUsageMask(enum.Enum): FPE_ENCRYPT = 0x00400000 FPE_DECRYPT = 0x00800000 - class Data(enum.Enum): # KMIP 2.0 DECRYPT = 0x00000001 @@ -338,7 +319,6 @@ class Data(enum.Enum): SIGN_SIGNATURE_DATA = 0x00000006 SIGNATURE_VERIFY = 0x00000007 - class DerivationMethod(enum.Enum): # KMIP 1.0 PBKDF2 = 0x00000001 @@ -354,7 +334,6 @@ class DerivationMethod(enum.Enum): AWS_SIGNATURE_VERSION_4 = 0x00000009 HKDF = 0x0000000A - class DestroyAction(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -365,7 +344,6 @@ class DestroyAction(enum.Enum): DELETED = 0x00000006 SHREDDED = 0x00000007 - class DigitalSignatureAlgorithm(enum.Enum): # KMIP 1.1 MD2_WITH_RSA_ENCRYPTION = 0x00000001 @@ -389,7 +367,6 @@ class DigitalSignatureAlgorithm(enum.Enum): SHA3_384_WITH_RSA_ENCRYPTION = 0x00000012 SHA3_512_WITH_RSA_ENCRYPTION = 0x00000013 - class DRBGAlgorithm(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -398,18 +375,15 @@ class DRBGAlgorithm(enum.Enum): HMAC = 0x00000004 CTR = 0x00000005 - class EncodingOption(enum.Enum): # KMIP 1.1 NO_ENCODING = 0x00000001 TTLV_ENCODING = 0x00000002 - class EndpointRole(enum.Enum): CLIENT = 0x00000001 SERVER = 0x00000002 - class FIPS186Variation(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -420,7 +394,6 @@ class FIPS186Variation(enum.Enum): K_ORIGINAL = 0x00000006 K_CHANGE_NOTICE = 0x00000007 - class HashingAlgorithm(enum.Enum): # KMIP 1.0 MD2 = 0x00000001 @@ -443,14 +416,12 @@ class HashingAlgorithm(enum.Enum): SHA3_384 = 0x00000010 SHA3_512 = 0x00000011 - class InteropFunction(enum.Enum): # KMIP 2.0 BEGIN = 0x00000001 END = 0x00000002 RESET = 0x00000003 - class ItemType(enum.Enum): # KMIP 2.0 STRUCTURE = 0x00000001 @@ -465,7 +436,6 @@ class ItemType(enum.Enum): INTERVAL = 0x0000000A DATE_TIME_EXTENDED = 0x0000000B - class KeyCompressionType(enum.Enum): # KMIP 1.0 EC_PUBLIC_KEY_TYPE_UNCOMPRESSED = 0x00000001 @@ -473,7 +443,6 @@ class KeyCompressionType(enum.Enum): EC_PUBLIC_KEY_TYPE_X9_62_COMPRESSED_CHAR2 = 0x00000003 EC_PUBLIC_KEY_TYPE_X9_62_HYBRID = 0x00000004 - class KeyFormatType(enum.Enum): # KMIP 1.0 RAW = 0x00000001 @@ -501,7 +470,6 @@ class KeyFormatType(enum.Enum): # KMIP 1.4 PKCS_12 = 0x00000016 - class KeyRoleType(enum.Enum): # KMIP 1.0 BDK = 0x00000001 @@ -530,18 +498,15 @@ class KeyRoleType(enum.Enum): IV = 0x00000017 TRKBK = 0x00000018 - class KeyValueLocationType(enum.Enum): # KMIP 1.2 UNINTERPRETED_TEXT_STRING = 0x00000001 URI = 0x00000002 - class KeyWrapType(enum.Enum): NOT_WRAPPED = 0x00000001 AS_REGISTERED = 0x00000002 - class KMIPVersion(OrderedEnum): KMIP_1_0 = 1.0 KMIP_1_1 = 1.1 @@ -550,7 +515,6 @@ class KMIPVersion(OrderedEnum): KMIP_1_4 = 1.4 KMIP_2_0 = 2.0 - class LinkType(enum.Enum): # KMIP 1.0 CERTIFICATE_LINK = 0x00000101 @@ -571,18 +535,15 @@ class LinkType(enum.Enum): # KMIP 2.0 WRAPPING_KEY_LINK = 0x0000010E - class MaskGenerator(enum.Enum): # KMIP 1.4 MGF1 = 0x00000001 - class NameType(enum.Enum): # KMIP 1.0 UNINTERPRETED_TEXT_STRING = 0x00000001 URI = 0x00000002 - class NISTKeyType(enum.Enum): # KMIP 2.0 PRIVATE_SIGNATURE_KEY = 0x00000001 @@ -605,13 +566,11 @@ class NISTKeyType(enum.Enum): PRIVATE_AUTHORIZATION_KEY = 0x00000012 PUBLIC_AUTHORIZATION_KEY = 0x00000013 - class ObjectGroupMember(enum.Enum): # KMIP 1.1 GROUP_MEMBER_FRESH = 0x00000001 GROUP_MEMBER_DEFAULT = 0x00000002 - class ObjectType(enum.Enum): # KMIP 1.0 CERTIFICATE = 0x00000001 @@ -627,13 +586,11 @@ class ObjectType(enum.Enum): # KMIP 2.0 CERTIFICATE_REQUEST = 0x0000000A - class OpaqueDataType(enum.Enum): NONE = 0x80000000 # Not defined by the standard, but we need something. # The standard does say that values starting 0x8xxxxxx # are considered extensions - class Operation(enum.Enum): # KMIP 1.0 CREATE = 0x00000001 @@ -694,7 +651,6 @@ class Operation(enum.Enum): INTEROP = 0x00000034 REPROVISION = 0x00000035 - class PaddingMethod(enum.Enum): # KMIP 1.0 NONE = 0x00000001 @@ -708,7 +664,6 @@ class PaddingMethod(enum.Enum): X931 = 0x00000009 PSS = 0x0000000A - class PKCS11Function(enum.Enum): # KMIP 2.0 # @@ -721,7 +676,6 @@ class PKCS11Function(enum.Enum): # be filled in in a future update. PLACEHOLDER = 'Do not use this.' - class PKCS11ReturnCode(enum.Enum): # KMIP 2.0 # @@ -733,13 +687,11 @@ class PKCS11ReturnCode(enum.Enum): # be filled in in a future update. PLACEHOLDER = 'Do not use this.' - class Policy(enum.Enum): ALLOW_ALL = "Allow All" ALLOW_OWNER = "Allow Owner" DISALLOW_ALL = "Disallow All" - class ProfileName(enum.Enum): # KMIP 1.3 BASELINE_SERVER_BASIC_KMIPv12 = 0x00000001 @@ -942,13 +894,11 @@ class ProfileName(enum.Enum): BASELINE_SERVER = 0x0000012B COMPLETE_SERVER = 0x0000012C - class ProtectionLevel(enum.Enum): # KMIP 2.0 HIGH = 0x00000001 LOW = 0x00000002 - class ProtectionStorageMask(enum.Enum): # KMIP 2.0 SOFTWARE = 0x00000001 @@ -966,13 +916,11 @@ class ProtectionStorageMask(enum.Enum): VALIDATED = 0x00001000 SAME_JURISDICTION = 0x00002000 - class PutFunction(enum.Enum): # KMIP 1.0 NEW = 0x00000001 REPLACE = 0x00000002 - class QueryFunction(enum.Enum): # KMIP 1.0 QUERY_OPERATIONS = 0x00000001 @@ -994,7 +942,6 @@ class QueryFunction(enum.Enum): QUERY_DEFAULTS_INFORMATION = 0x0000000D QUERY_STORAGE_PROTECTION_MASKS = 0x0000000E - class RecommendedCurve(enum.Enum): # KMIP 1.0 P_192 = 0x00000001 @@ -1070,7 +1017,6 @@ class RecommendedCurve(enum.Enum): CURVE25519 = 0x00000045 CURVE448 = 0x00000046 - class ResultReason(enum.Enum): # KMIP 1.0 ITEM_NOT_FOUND = 0x00000001 @@ -1147,7 +1093,6 @@ class ResultReason(enum.Enum): PKCS11_INVALID_FUNCTION = 0x00000046 PKCS11_INVALID_INTERFACE = 0x00000047 - class ResultStatus(enum.Enum): # KMIP 1.0 SUCCESS = 0x00000000 @@ -1155,7 +1100,6 @@ class ResultStatus(enum.Enum): OPERATION_PENDING = 0x00000002 OPERATION_UNDONE = 0x00000003 - class RevocationReasonCode(enum.Enum): # KMIP 1.0 UNSPECIFIED = 0x00000001 @@ -1166,7 +1110,6 @@ class RevocationReasonCode(enum.Enum): CESSATION_OF_OPERATION = 0x00000006 PRIVILEGE_WITHDRAWN = 0x00000007 - class RNGAlgorithm(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -1176,27 +1119,23 @@ class RNGAlgorithm(enum.Enum): ANSI_X931 = 0x00000005 ANSI_X962 = 0x00000006 - class RNGMode(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 SHARED_INSTANTIATION = 0x00000002 NON_SHARED_INSTANTIATION = 0x00000003 - class SecretDataType(enum.Enum): # KMIP 1.0 PASSWORD = 0x00000001 SEED = 0x00000002 - class ShreddingAlgorithm(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 CRYPTOGRAPHIC = 0x00000002 UNSUPPORTED = 0x00000003 - class SplitKeyMethod(enum.Enum): # KMIP 1.0 XOR = 0x00000001 @@ -1205,7 +1144,6 @@ class SplitKeyMethod(enum.Enum): # KMIP 1.2 POLYNOMIAL_SHARING_GF_2_8 = 0x00000004 - class State(enum.Enum): # KMIP 1.0 PRE_ACTIVE = 0x00000001 @@ -1215,7 +1153,6 @@ class State(enum.Enum): DESTROYED = 0x00000005 DESTROYED_COMPROMISED = 0x00000006 - class StorageStatusMask(enum.Enum): # KMIP 1.0 ONLINE_STORAGE = 0x00000001 @@ -1223,7 +1160,6 @@ class StorageStatusMask(enum.Enum): # KMIP 2.0 DESTROYED_STORAGE = 0x00000004 - class Tags(enum.Enum): DEFAULT = 0x420000 # Custom PyKMIP tag used as the global default # KMIP 1.0 @@ -1592,12 +1528,10 @@ class Tags(enum.Enum): PRIVATE_PROTECTION_STORAGE_MASKS = 0x420164 PUBLIC_PROTECTION_STORAGE_MASKS = 0x420165 - class TicketType(enum.Enum): # KMIP 2.0 LOGIN = 0x00000001 - class Types(enum.Enum): DEFAULT = 0x00 STRUCTURE = 0x01 @@ -1611,7 +1545,6 @@ class Types(enum.Enum): DATE_TIME = 0x09 INTERVAL = 0x0A - class UniqueIdentifier(enum.Enum): # KMIP 2.0 ID_PLACEHOLDER = 0x00000001 @@ -1632,27 +1565,23 @@ class UniqueIdentifier(enum.Enum): REKEY_KEY_PAIR_PRIVATE_KEY = 0x00000010 REKEY_KEY_PAIR_PUBLIC_KEY = 0x00000011 - class UnwrapMode(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 PROCESSED = 0x00000002 NOT_PROCESSED = 0x00000003 - class UsageLimitsUnit(enum.Enum): # KMIP 1.0 BYTE = 0x00000001 OBJECT = 0x00000002 - class ValidationAuthorityType(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 NIST_CMVP = 0x00000002 COMMON_CRITERIA = 0x00000003 - class ValidationType(enum.Enum): # KMIP 1.3 UNSPECIFIED = 0x00000001 @@ -1661,14 +1590,12 @@ class ValidationType(enum.Enum): FIRMWARE = 0x00000004 HYBRID = 0x00000005 - class ValidityIndicator(enum.Enum): # KMIP 1.0 VALID = 0x00000001 INVALID = 0x00000002 UNKNOWN = 0x00000003 - class WrappingMethod(enum.Enum): # KMIP 1.0 ENCRYPT = 0x00000001 @@ -1677,7 +1604,6 @@ class WrappingMethod(enum.Enum): MAC_SIGN_THEN_ENCRYPT = 0x00000004 TR_31 = 0x00000005 - attribute_name_tag_table = [ ("Activation Date", Tags.ACTIVATION_DATE), ("Alternative Name", Tags.ALTERNATIVE_NAME), @@ -1765,7 +1691,6 @@ class WrappingMethod(enum.Enum): ("X.509 Certificate Subject", Tags.X_509_CERTIFICATE_SUBJECT) ] - def convert_attribute_name_to_tag(value): """ A utility function that converts an attribute name string into the @@ -1784,7 +1709,7 @@ def convert_attribute_name_to_tag(value): ValueError: if the attribute name string is not a string or if it is an unrecognized attribute name """ - if not isinstance(value, six.string_types): + if not isinstance(value, str): raise ValueError("The attribute name must be a string.") for entry in attribute_name_tag_table: @@ -1793,7 +1718,6 @@ def convert_attribute_name_to_tag(value): raise ValueError("Unrecognized attribute name: '{}'".format(value)) - def convert_attribute_tag_to_name(value): """ A utility function that converts an attribute tag into the corresponding @@ -1821,7 +1745,6 @@ def convert_attribute_tag_to_name(value): raise ValueError("Unrecognized attribute tag: {}".format(value)) - def get_bit_mask_from_enumerations(enumerations): """ A utility function that computes a bit mask from a collection of @@ -1838,7 +1761,6 @@ def get_bit_mask_from_enumerations(enumerations): lambda x, y: x | y, [z.value for z in enumerations] ) - def get_enumerations_from_bit_mask(enumeration, mask): """ A utility function that creates a list of enumeration values from a bit @@ -1854,7 +1776,6 @@ def get_enumerations_from_bit_mask(enumeration, mask): """ return [x for x in enumeration if (x.value & mask) == x.value] - def is_bit_mask(enumeration, potential_mask): """ A utility function that checks if the provided value is a composite bit @@ -1873,7 +1794,7 @@ def is_bit_mask(enumeration, potential_mask): True: if the potential mask is a valid bit mask of the mask enumeration False: otherwise """ - if not isinstance(potential_mask, six.integer_types): + if not isinstance(potential_mask, int): return False mask_enumerations = ( @@ -1894,7 +1815,6 @@ def is_bit_mask(enumeration, potential_mask): return True - def is_enum_value(enumeration, potential_value): """ A utility function that checks if the enumeration class contains the @@ -1916,7 +1836,6 @@ def is_enum_value(enumeration, potential_value): return True - def is_attribute(tag, kmip_version=None): """ A utility function that checks if the tag is a valid attribute tag. diff --git a/kmip/core/exceptions.py b/kmip/core/exceptions.py index 6636a382..5c7b8a37 100644 --- a/kmip/core/exceptions.py +++ b/kmip/core/exceptions.py @@ -15,7 +15,6 @@ from kmip.core import enums - class KmipError(Exception): """ A generic KMIP error that is the base for the KMIP error hierarchy. @@ -57,7 +56,6 @@ def __ne__(self, other): else: return NotImplemented - class CryptographicFailure(KmipError): """ An error generated when problems occur with cryptographic operations. @@ -75,7 +73,6 @@ def __init__(self, message): message=message ) - class EncodingOptionError(KmipError): """ An encoding error generated during key wrapping. @@ -97,7 +94,6 @@ def __init__(self, message): message=message ) - class IllegalOperation(KmipError): """ An error generated when an improper operation is attempted. The operation @@ -117,7 +113,6 @@ def __init__(self, message): message=message ) - class IndexOutOfBounds(KmipError): """ An error generated when exceeding the attribute instance limit. @@ -135,7 +130,6 @@ def __init__(self, message): message=message ) - class InvalidField(KmipError): """ An error generated when an invalid field value is processed. @@ -153,7 +147,6 @@ def __init__(self, message): message=message ) - class InvalidMessage(KmipError): """ An error generated when an invalid message is processed. @@ -171,7 +164,6 @@ def __init__(self, message): message=message ) - class ItemNotFound(KmipError): """ An error generated when a request item cannot be located. @@ -189,7 +181,6 @@ def __init__(self, message): message=message ) - class KeyCompressionTypeNotSupported(KmipError): """ An error generated when dealing with unsupported key compression types @@ -208,7 +199,6 @@ def __init__(self, message): message=message ) - class KeyFormatTypeNotSupported(KmipError): """ An error generated when dealing with unsupported key formats @@ -227,7 +217,6 @@ def __init__(self, message): message=message ) - class OperationFailure(KmipError): """ An exception raised upon the failure of a KMIP appliance operation. @@ -244,7 +233,6 @@ def __init__(self, status, reason, message): """ super(OperationFailure, self).__init__(status, reason, message) - class OperationNotSupported(KmipError): """ An error generated when an unsupported operation is invoked. @@ -262,7 +250,6 @@ def __init__(self, message): message=message ) - class PermissionDenied(KmipError): """ An error generated when permission constraints are violated. @@ -280,14 +267,12 @@ def __init__(self, message): message=message ) - class AttributeNotSupported(Exception): """ An error generated when an unsupported attribute is processed. """ pass - class ConfigurationError(Exception): """ An error generated when a problem occurs with a client or server @@ -295,7 +280,6 @@ class ConfigurationError(Exception): """ pass - class ConnectionClosed(Exception): """ An exception generated when attempting to use a connection that has been @@ -303,7 +287,6 @@ class ConnectionClosed(Exception): """ pass - class NetworkingError(Exception): """ An error generated when a problem occurs with client or server networking @@ -311,14 +294,12 @@ class NetworkingError(Exception): """ pass - class InvalidKmipEncoding(Exception): """ An exception raised when processing invalid KMIP message encodings. """ pass - class InvalidPaddingBytes(Exception): """ An exception raised for errors when processing the padding bytes of @@ -326,7 +307,6 @@ class InvalidPaddingBytes(Exception): """ pass - class InvalidPrimitiveLength(Exception): """ An exception raised for errors when processing primitives with invalid @@ -334,19 +314,16 @@ class InvalidPrimitiveLength(Exception): """ pass - class ShutdownError(Exception): """ An error generated when a problem occurs with shutting down the server. """ - class VersionNotSupported(Exception): """ An error generated when an unsupported KMIP version is referenced. """ - class StreamNotEmptyError(Exception): def __init__(self, cls, extra): super(StreamNotEmptyError, self).__init__() @@ -358,7 +335,6 @@ def __str__(self): msg = "Invalid length used to read {0}, bytes remaining: {1}" return msg.format(self.cls, self.extra) - class ReadValueError(Exception): def __init__(self, cls, attr, exp, recv): super(ReadValueError, self).__init__() @@ -372,7 +348,6 @@ def __str__(self): msg = "Tried to read {0}.{1}: expected {2}, received {3}" return msg.format(self.cls, self.attr, self.exp, self.recv) - class WriteOverflowError(Exception): def __init__(self, cls, attr, exp, recv): super(WriteOverflowError, self).__init__() @@ -387,7 +362,6 @@ def __str__(self): msg += "expected {2}, received {3}" return msg.format(self.cls, self.attr, self.exp, self.recv) - class KMIPServerZombieError(Exception): """KMIP server error for hung and persistent live KMIP servers.""" def __init__(self, pid): @@ -400,7 +374,6 @@ def __init__(self, pid): def __str__(self): return self.message - class KMIPServerSuicideError(Exception): """KMIP server error for prematurely dead KMIP servers.""" def __init__(self, pid): @@ -411,7 +384,6 @@ def __init__(self, pid): def __str__(self): return self.message - class ErrorStrings: BAD_EXP_RECV = "Bad {0} {1}: expected {2}, received {3}" BAD_ENCODING = "Bad {0} {1}: encoding mismatch" diff --git a/kmip/core/factories/attribute_values.py b/kmip/core/factories/attribute_values.py index 1bc1e208..1a278b53 100644 --- a/kmip/core/factories/attribute_values.py +++ b/kmip/core/factories/attribute_values.py @@ -18,7 +18,6 @@ from kmip.core import primitives from kmip.core import utils - class AttributeValueFactory(object): def create_attribute_value(self, name, value): diff --git a/kmip/core/factories/attributes.py b/kmip/core/factories/attributes.py index 48ddddb2..c186d8da 100644 --- a/kmip/core/factories/attributes.py +++ b/kmip/core/factories/attributes.py @@ -21,7 +21,6 @@ from kmip.core import utils - class AttributeFactory(object): def __init__(self): diff --git a/kmip/core/factories/credentials.py b/kmip/core/factories/credentials.py index 81d7a865..8ac9cbb7 100644 --- a/kmip/core/factories/credentials.py +++ b/kmip/core/factories/credentials.py @@ -16,7 +16,6 @@ from kmip.core import enums from kmip.core import objects - class CredentialFactory(object): def create_credential(self, credential_type, credential_value): diff --git a/kmip/core/factories/payloads/__init__.py b/kmip/core/factories/payloads/__init__.py index c0048e8c..2ee17939 100644 --- a/kmip/core/factories/payloads/__init__.py +++ b/kmip/core/factories/payloads/__init__.py @@ -15,7 +15,6 @@ from kmip.core import enums - class PayloadFactory(): def create(self, operation): diff --git a/kmip/core/factories/payloads/request.py b/kmip/core/factories/payloads/request.py index 52767bf4..29d5a057 100644 --- a/kmip/core/factories/payloads/request.py +++ b/kmip/core/factories/payloads/request.py @@ -16,7 +16,6 @@ from kmip.core.factories.payloads import PayloadFactory from kmip.core.messages import payloads - class RequestPayloadFactory(PayloadFactory): # TODO (peterhamilton) Alphabetize these diff --git a/kmip/core/factories/payloads/response.py b/kmip/core/factories/payloads/response.py index edf702e7..67cd1af8 100644 --- a/kmip/core/factories/payloads/response.py +++ b/kmip/core/factories/payloads/response.py @@ -16,7 +16,6 @@ from kmip.core.factories.payloads import PayloadFactory from kmip.core.messages import payloads - class ResponsePayloadFactory(PayloadFactory): # TODO (peterhamilton) Alphabetize these diff --git a/kmip/core/factories/secrets.py b/kmip/core/factories/secrets.py index 2880631c..60beb550 100644 --- a/kmip/core/factories/secrets.py +++ b/kmip/core/factories/secrets.py @@ -38,7 +38,6 @@ from kmip.core import utils from kmip.core import exceptions - class SecretFactory(object): def __init__(self): diff --git a/kmip/core/messages/contents.py b/kmip/core/messages/contents.py index 470c4318..646d9b28 100644 --- a/kmip/core/messages/contents.py +++ b/kmip/core/messages/contents.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import objects from kmip.core import utils @@ -28,7 +26,6 @@ from kmip.core.primitives import ByteString from kmip.core.primitives import DateTime - class ProtocolVersion(primitives.Struct): """ A struct representing a ProtocolVersion number. @@ -67,7 +64,7 @@ def major(self): def major(self, value): if value is None: self._major = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._major = primitives.Integer( value=value, tag=enums.Tags.PROTOCOL_VERSION_MAJOR @@ -88,7 +85,7 @@ def minor(self): def minor(self, value): if value is None: self._minor = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._minor = primitives.Integer( value=value, tag=enums.Tags.PROTOCOL_VERSION_MINOR @@ -248,7 +245,6 @@ def __repr__(self): def __str__(self): return "{}.{}".format(self.major, self.minor) - def protocol_version_to_kmip_version(value): """ Convert a ProtocolVersion struct to its KMIPVersion enumeration equivalent. @@ -285,7 +281,6 @@ def protocol_version_to_kmip_version(value): else: return None - # 6.2 class Operation(Enumeration): @@ -293,27 +288,23 @@ def __init__(self, value=None): super(Operation, self).__init__( enums.Operation, value, enums.Tags.OPERATION) - # 6.3 class MaximumResponseSize(Integer): def __init__(self, value=None): super(MaximumResponseSize, self).\ __init__(value, enums.Tags.MAXIMUM_RESPONSE_SIZE) - # 6.4 class UniqueBatchItemID(ByteString): def __init__(self, value=None): super(UniqueBatchItemID, self)\ .__init__(value, enums.Tags.UNIQUE_BATCH_ITEM_ID) - # 6.5 class TimeStamp(DateTime): def __init__(self, value=None): super(TimeStamp, self).__init__(value, enums.Tags.TIME_STAMP) - class Authentication(Struct): """ A struct representing an Authentication bundle. @@ -441,21 +432,18 @@ def __str__(self): credentials = ", ".join([str(x) for x in self.credentials]) return "{'credentials': [" + credentials + "]}" - # 6.7 class AsynchronousIndicator(Boolean): def __init__(self, value=None): super(AsynchronousIndicator, self).\ __init__(value, enums.Tags.ASYNCHRONOUS_INDICATOR) - # 6.8 class AsynchronousCorrelationValue(ByteString): def __init__(self, value=None): super(AsynchronousCorrelationValue, self).\ __init__(value, enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE) - # 6.9 class ResultStatus(Enumeration): @@ -463,7 +451,6 @@ def __init__(self, value=None): super(ResultStatus, self).__init__( enums.ResultStatus, value, enums.Tags.RESULT_STATUS) - # 6.10 class ResultReason(Enumeration): @@ -471,20 +458,17 @@ def __init__(self, value=None): super(ResultReason, self).__init__( enums.ResultReason, value, enums.Tags.RESULT_REASON) - # 6.11 class ResultMessage(TextString): def __init__(self, value=None): super(ResultMessage, self).__init__(value, enums.Tags.RESULT_MESSAGE) - # 6.12 class BatchOrderOption(Boolean): def __init__(self, value=None): super(BatchOrderOption, self).\ __init__(value, enums.Tags.BATCH_ORDER_OPTION) - # 6.13 class BatchErrorContinuationOption(Enumeration): @@ -493,26 +477,22 @@ def __init__(self, value=None): enums.BatchErrorContinuationOption, value, enums.Tags.BATCH_ERROR_CONTINUATION_OPTION) - # 6.14 class BatchCount(Integer): def __init__(self, value=None): super(BatchCount, self).__init__(value, enums.Tags.BATCH_COUNT) - # 6.16 class MessageExtension(Struct): def __init__(self): super(MessageExtension, self).__init__(enums.Tags.MESSAGE_EXTENSION) - # 6.19 class ServerCorrelationValue(TextString): def __init__(self, value=None): super(ServerCorrelationValue, self).__init__( value, enums.Tags.SERVER_CORRELATION_VALUE) - # 9.1.3.2.2 class KeyCompressionType(Enumeration): diff --git a/kmip/core/messages/messages.py b/kmip/core/messages/messages.py index c1b4c6bc..82083e67 100644 --- a/kmip/core/messages/messages.py +++ b/kmip/core/messages/messages.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core.enums import Tags @@ -30,7 +28,6 @@ from kmip.core.utils import BytearrayStream - class RequestHeader(Struct): def __init__(self, @@ -143,7 +140,6 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): ) ostream.write(tstream.buffer) - class ResponseHeader(Struct): def __init__(self, @@ -171,7 +167,7 @@ def server_hashed_password(self): def server_hashed_password(self, value): if value is None: self._server_hashed_password = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._server_hashed_password = primitives.ByteString( value=value, tag=enums.Tags.SERVER_HASHED_PASSWORD @@ -248,7 +244,6 @@ def validate(self): # TODO (peter-hamilton) conduct type check self.batch_count.validate() - class RequestBatchItem(Struct): def __init__(self, @@ -347,7 +342,6 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): ) ostream.write(tstream.buffer) - class ResponseBatchItem(Struct): def __init__(self, @@ -464,7 +458,6 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): def validate(self): pass - class RequestMessage(Struct): def __init__(self, request_header=None, batch_items=None,): @@ -507,7 +500,6 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): ) ostream.write(tstream.buffer) - class ResponseMessage(Struct): def __init__(self, response_header=None, batch_items=None,): diff --git a/kmip/core/messages/payloads/__init__.py b/kmip/core/messages/payloads/__init__.py index cea8b429..3fe60c35 100644 --- a/kmip/core/messages/payloads/__init__.py +++ b/kmip/core/messages/payloads/__init__.py @@ -140,7 +140,6 @@ SignatureVerifyResponsePayload ) - __all__ = [ "ActivateRequestPayload", "ActivateResponsePayload", diff --git a/kmip/core/messages/payloads/activate.py b/kmip/core/messages/payloads/activate.py index a91452d7..b5e91774 100644 --- a/kmip/core/messages/payloads/activate.py +++ b/kmip/core/messages/payloads/activate.py @@ -18,7 +18,6 @@ from kmip.core.utils import BytearrayStream from kmip.core.messages.payloads import base - class ActivateRequestPayload(base.RequestPayload): """ A request payload for the Activate operation. @@ -99,7 +98,6 @@ def validate(self): msg = "invalid unique identifier" raise TypeError(msg) - class ActivateResponsePayload(base.ResponsePayload): """ A response payload for the Activate operation. diff --git a/kmip/core/messages/payloads/archive.py b/kmip/core/messages/payloads/archive.py index 100de943..7c9fe2da 100644 --- a/kmip/core/messages/payloads/archive.py +++ b/kmip/core/messages/payloads/archive.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class ArchiveRequestPayload(base.RequestPayload): """ A request payload for the Archive operation. @@ -53,7 +50,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -149,7 +146,6 @@ def __str__(self): 'unique_identifier': self.unique_identifier }) - class ArchiveResponsePayload(base.ResponsePayload): """ A response payload for the Archive operation. @@ -182,7 +178,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/base.py b/kmip/core/messages/payloads/base.py index cbfda03f..f490158f 100644 --- a/kmip/core/messages/payloads/base.py +++ b/kmip/core/messages/payloads/base.py @@ -16,7 +16,6 @@ from kmip.core import enums from kmip.core import primitives - class RequestPayload(primitives.Struct): """ An abstract base class for KMIP request payloads. @@ -24,7 +23,6 @@ class RequestPayload(primitives.Struct): def __init__(self): super(RequestPayload, self).__init__(enums.Tags.REQUEST_PAYLOAD) - class ResponsePayload(primitives.Struct): """ An abstract base class for KMIP response payloads. diff --git a/kmip/core/messages/payloads/cancel.py b/kmip/core/messages/payloads/cancel.py index 383d5b96..9f744832 100644 --- a/kmip/core/messages/payloads/cancel.py +++ b/kmip/core/messages/payloads/cancel.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class CancelRequestPayload(base.RequestPayload): """ A request payload for the Cancel operation. @@ -54,7 +51,7 @@ def asynchronous_correlation_value(self): def asynchronous_correlation_value(self, value): if value is None: self._asynchronous_correlation_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._asynchronous_correlation_value = primitives.ByteString( value=value, tag=enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE @@ -157,7 +154,6 @@ def __str__(self): self.asynchronous_correlation_value }) - class CancelResponsePayload(base.ResponsePayload): """ A response payload for the Cancel operation. @@ -201,7 +197,7 @@ def asynchronous_correlation_value(self): def asynchronous_correlation_value(self, value): if value is None: self._asynchronous_correlation_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._asynchronous_correlation_value = primitives.ByteString( value=value, tag=enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE diff --git a/kmip/core/messages/payloads/check.py b/kmip/core/messages/payloads/check.py index e4d0da51..6814e13f 100644 --- a/kmip/core/messages/payloads/check.py +++ b/kmip/core/messages/payloads/check.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class CheckRequestPayload(base.RequestPayload): """ A request payload for the Check operation. @@ -79,7 +76,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -98,7 +95,7 @@ def usage_limits_count(self): def usage_limits_count(self, value): if value is None: self._usage_limits_count = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._usage_limits_count = primitives.LongInteger( value=value, tag=enums.Tags.USAGE_LIMITS_COUNT @@ -117,7 +114,7 @@ def cryptographic_usage_mask(self): def cryptographic_usage_mask(self, value): if value is None: self._cryptographic_usage_mask = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._cryptographic_usage_mask = primitives.Integer( value=value, tag=enums.Tags.CRYPTOGRAPHIC_USAGE_MASK @@ -136,7 +133,7 @@ def lease_time(self): def lease_time(self, value): if value is None: self._lease_time = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._lease_time = primitives.Interval( value=value, tag=enums.Tags.LEASE_TIME @@ -285,7 +282,6 @@ def __str__(self): 'lease_time': self.lease_time }) - class CheckResponsePayload(base.ResponsePayload): """ A response payload for the Check operation. @@ -344,7 +340,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -363,7 +359,7 @@ def usage_limits_count(self): def usage_limits_count(self, value): if value is None: self._usage_limits_count = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._usage_limits_count = primitives.LongInteger( value=value, tag=enums.Tags.USAGE_LIMITS_COUNT @@ -382,7 +378,7 @@ def cryptographic_usage_mask(self): def cryptographic_usage_mask(self, value): if value is None: self._cryptographic_usage_mask = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._cryptographic_usage_mask = primitives.Integer( value=value, tag=enums.Tags.CRYPTOGRAPHIC_USAGE_MASK @@ -401,7 +397,7 @@ def lease_time(self): def lease_time(self, value): if value is None: self._lease_time = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._lease_time = primitives.Interval( value=value, tag=enums.Tags.LEASE_TIME diff --git a/kmip/core/messages/payloads/create.py b/kmip/core/messages/payloads/create.py index d212d7f2..a7d1bc5d 100644 --- a/kmip/core/messages/payloads/create.py +++ b/kmip/core/messages/payloads/create.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class CreateRequestPayload(base.RequestPayload): """ A request payload for the Create operation. @@ -314,7 +311,6 @@ def __str__(self): ) return '{' + value + '}' - class CreateResponsePayload(base.ResponsePayload): """ A response payload for the Create operation. @@ -386,7 +382,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/create_key_pair.py b/kmip/core/messages/payloads/create_key_pair.py index 29fc4329..11dd52e7 100644 --- a/kmip/core/messages/payloads/create_key_pair.py +++ b/kmip/core/messages/payloads/create_key_pair.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class CreateKeyPairRequestPayload(base.RequestPayload): """ A request payload for the CreateKeyPair operation. @@ -516,7 +513,6 @@ def __str__(self): ) return '{' + value + '}' - class CreateKeyPairResponsePayload(base.ResponsePayload): """ A response payload for the CreateKeyPair operation. @@ -578,7 +574,7 @@ def private_key_unique_identifier(self): def private_key_unique_identifier(self, value): if value is None: self._private_key_unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._private_key_unique_identifier = primitives.TextString( value=value, tag=enums.Tags.PRIVATE_KEY_UNIQUE_IDENTIFIER @@ -597,7 +593,7 @@ def public_key_unique_identifier(self): def public_key_unique_identifier(self, value): if value is None: self._public_key_unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._public_key_unique_identifier = primitives.TextString( value=value, tag=enums.Tags.PUBLIC_KEY_UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/decrypt.py b/kmip/core/messages/payloads/decrypt.py index cc12cf1f..f0f65dbb 100644 --- a/kmip/core/messages/payloads/decrypt.py +++ b/kmip/core/messages/payloads/decrypt.py @@ -13,15 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import attributes from kmip.core import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class DecryptRequestPayload(base.RequestPayload): """ A request payload for the Decrypt operation. @@ -102,7 +99,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -137,7 +134,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -156,7 +153,7 @@ def iv_counter_nonce(self): def iv_counter_nonce(self, value): if value is None: self._iv_counter_nonce = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._iv_counter_nonce = primitives.ByteString( value=value, tag=enums.Tags.IV_COUNTER_NONCE @@ -175,7 +172,7 @@ def auth_additional_data(self): def auth_additional_data(self, value): if value is None: self._auth_additional_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._auth_additional_data = primitives.ByteString( value=value, tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA @@ -194,7 +191,7 @@ def auth_tag(self): def auth_tag(self, value): if value is None: self._auth_tag = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._auth_tag = primitives.ByteString( value=value, tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG @@ -260,28 +257,27 @@ def read(self, input_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self.is_tag_next( - enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, - local_stream - ): - self._auth_additional_data = primitives.ByteString( - tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA - ) - self._auth_additional_data.read( - local_stream, - kmip_version=kmip_version - ) - if self.is_tag_next( - enums.Tags.AUTHENTICATED_ENCRYPTION_TAG, local_stream - ): - self._auth_tag = primitives.ByteString( - tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG - ) - self._auth_tag.read( - local_stream, - kmip_version=kmip_version - ) + if self.is_tag_next( + enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, + local_stream + ): + self._auth_additional_data = primitives.ByteString( + tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA + ) + self._auth_additional_data.read( + local_stream, + kmip_version=kmip_version + ) + if self.is_tag_next( + enums.Tags.AUTHENTICATED_ENCRYPTION_TAG, local_stream + ): + self._auth_tag = primitives.ByteString( + tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG + ) + self._auth_tag.read( + local_stream, + kmip_version=kmip_version + ) self.is_oversized(local_stream) @@ -324,17 +320,16 @@ def write(self, output_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self._auth_additional_data: - self._auth_additional_data.write( - local_stream, - kmip_version=kmip_version - ) - if self._auth_tag: - self._auth_tag.write( - local_stream, - kmip_version=kmip_version - ) + if self._auth_additional_data: + self._auth_additional_data.write( + local_stream, + kmip_version=kmip_version + ) + if self._auth_tag: + self._auth_tag.write( + local_stream, + kmip_version=kmip_version + ) self.length = local_stream.length() super(DecryptRequestPayload, self).write( @@ -392,7 +387,6 @@ def __str__(self): 'auth_tag': self.auth_tag }) - class DecryptResponsePayload(base.ResponsePayload): """ A response payload for the Decrypt operation. @@ -435,7 +429,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -454,7 +448,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA diff --git a/kmip/core/messages/payloads/delete_attribute.py b/kmip/core/messages/payloads/delete_attribute.py index 758e4451..7a95b5a1 100644 --- a/kmip/core/messages/payloads/delete_attribute.py +++ b/kmip/core/messages/payloads/delete_attribute.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class DeleteAttributeRequestPayload(base.RequestPayload): """ A request payload for the DeleteAttribute operation. @@ -90,7 +87,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -108,7 +105,7 @@ def attribute_name(self): def attribute_name(self, value): if value is None: self._attribute_name = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._attribute_name = primitives.TextString( value=value, tag=enums.Tags.ATTRIBUTE_NAME @@ -126,7 +123,7 @@ def attribute_index(self): def attribute_index(self, value): if value is None: self._attribute_index = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._attribute_index = primitives.Integer( value=value, tag=enums.Tags.ATTRIBUTE_INDEX @@ -372,7 +369,6 @@ def __ne__(self, other): else: return NotImplemented - class DeleteAttributeResponsePayload(base.ResponsePayload): """ A response payload for the DeleteAttribute operation. @@ -414,7 +410,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/derive_key.py b/kmip/core/messages/payloads/derive_key.py index 06f09f4b..813e77c6 100644 --- a/kmip/core/messages/payloads/derive_key.py +++ b/kmip/core/messages/payloads/derive_key.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import attributes from kmip.core import enums from kmip.core import exceptions @@ -23,7 +21,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class DeriveKeyRequestPayload(base.RequestPayload): """ A request payload for the DeriveKey operation. @@ -120,7 +117,7 @@ def unique_identifiers(self, value): elif isinstance(value, list): unique_identifiers = [] for i in value: - if isinstance(i, six.string_types): + if isinstance(i, str): unique_identifiers.append( primitives.TextString( value=i, @@ -432,7 +429,6 @@ def __str__(self): "template_attribute": self.template_attribute }) - class DeriveKeyResponsePayload(base.ResponsePayload): """ A response payload for the DeriveKey operation. @@ -479,7 +475,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/destroy.py b/kmip/core/messages/payloads/destroy.py index 2071c30c..d359127a 100644 --- a/kmip/core/messages/payloads/destroy.py +++ b/kmip/core/messages/payloads/destroy.py @@ -15,11 +15,11 @@ from kmip.core import attributes from kmip.core import enums +from kmip.core import exceptions from kmip.core.enums import Tags from kmip.core.messages.payloads import base from kmip.core.utils import BytearrayStream - # 4.21 class DestroyRequestPayload(base.RequestPayload): @@ -39,6 +39,11 @@ def read(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream): self.unique_identifier = attributes.UniqueIdentifier() self.unique_identifier.read(tstream, kmip_version=kmip_version) + else: + raise exceptions.InvalidKmipEncoding( + "The Destroy request payload encoding is missing the unique " + "identifier." + ) self.is_oversized(tstream) self.validate() @@ -48,6 +53,8 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): if self.unique_identifier is not None: self.unique_identifier.write(tstream, kmip_version=kmip_version) + else: + raise ValueError("Payload is missing the unique identifier field.") # Write the length and value of the request payload self.length = tstream.length() @@ -61,9 +68,22 @@ def validate(self): self.__validate() def __validate(self): - # TODO (peter-hamilton) Finish implementation. - pass - + if self.unique_identifier is not None: + if not isinstance( + self.unique_identifier, + attributes.UniqueIdentifier + ): + raise TypeError("invalid unique identifier") + + def __eq__(self, other): + if isinstance(other, DestroyRequestPayload): + return self.unique_identifier == other.unique_identifier + return NotImplemented + + def __ne__(self, other): + if isinstance(other, DestroyRequestPayload): + return not self.__eq__(other) + return NotImplemented class DestroyResponsePayload(base.ResponsePayload): @@ -80,8 +100,14 @@ def read(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): ) tstream = BytearrayStream(istream.read(self.length)) - self.unique_identifier = attributes.UniqueIdentifier() - self.unique_identifier.read(tstream, kmip_version=kmip_version) + if self.is_tag_next(Tags.UNIQUE_IDENTIFIER, tstream): + self.unique_identifier = attributes.UniqueIdentifier() + self.unique_identifier.read(tstream, kmip_version=kmip_version) + else: + raise exceptions.InvalidKmipEncoding( + "The Destroy response payload encoding is missing the unique " + "identifier." + ) self.is_oversized(tstream) self.validate() @@ -89,7 +115,10 @@ def read(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): tstream = BytearrayStream() - self.unique_identifier.write(tstream, kmip_version=kmip_version) + if self.unique_identifier is not None: + self.unique_identifier.write(tstream, kmip_version=kmip_version) + else: + raise ValueError("Payload is missing the unique identifier field.") # Write the length and value of the request payload self.length = tstream.length() @@ -103,5 +132,19 @@ def validate(self): self.__validate() def __validate(self): - # TODO (peter-hamilton) Finish implementation. - pass + if self.unique_identifier is not None: + if not isinstance( + self.unique_identifier, + attributes.UniqueIdentifier + ): + raise TypeError("invalid unique identifier") + + def __eq__(self, other): + if isinstance(other, DestroyResponsePayload): + return self.unique_identifier == other.unique_identifier + return NotImplemented + + def __ne__(self, other): + if isinstance(other, DestroyResponsePayload): + return not self.__eq__(other) + return NotImplemented diff --git a/kmip/core/messages/payloads/discover_versions.py b/kmip/core/messages/payloads/discover_versions.py index 92166d5e..95095ab6 100644 --- a/kmip/core/messages/payloads/discover_versions.py +++ b/kmip/core/messages/payloads/discover_versions.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from six.moves import xrange - from kmip.core import enums from kmip.core.messages.contents import ProtocolVersion from kmip.core.messages.payloads import base from kmip.core.utils import BytearrayStream - class DiscoverVersionsRequestPayload(base.RequestPayload): def __init__(self, protocol_versions=None): @@ -66,7 +63,7 @@ def validate(self): def __validate(self): if isinstance(self.protocol_versions, list): - for i in xrange(len(self.protocol_versions)): + for i in range(len(self.protocol_versions)): protocol_version = self.protocol_versions[i] if not isinstance(protocol_version, ProtocolVersion): msg = "invalid protocol version ({0} in list)".format(i) @@ -79,7 +76,6 @@ def __validate(self): list, self.protocol_versions) raise TypeError(msg) - class DiscoverVersionsResponsePayload(base.ResponsePayload): def __init__(self, protocol_versions=None): @@ -125,7 +121,7 @@ def validate(self): def __validate(self): if isinstance(self.protocol_versions, list): - for i in xrange(len(self.protocol_versions)): + for i in range(len(self.protocol_versions)): protocol_version = self.protocol_versions[i] if not isinstance(protocol_version, ProtocolVersion): msg = "invalid protocol version ({0} in list)".format(i) diff --git a/kmip/core/messages/payloads/encrypt.py b/kmip/core/messages/payloads/encrypt.py index f17d4f8e..96c6d1f5 100644 --- a/kmip/core/messages/payloads/encrypt.py +++ b/kmip/core/messages/payloads/encrypt.py @@ -13,15 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import attributes from kmip.core import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class EncryptRequestPayload(base.RequestPayload): """ A request payload for the Encrypt operation. @@ -89,7 +86,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -124,7 +121,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -143,7 +140,7 @@ def iv_counter_nonce(self): def iv_counter_nonce(self, value): if value is None: self._iv_counter_nonce = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._iv_counter_nonce = primitives.ByteString( value=value, tag=enums.Tags.IV_COUNTER_NONCE @@ -162,7 +159,7 @@ def auth_additional_data(self): def auth_additional_data(self, value): if value is None: self._auth_additional_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._auth_additional_data = primitives.ByteString( value=value, tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA @@ -228,18 +225,17 @@ def read(self, input_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self.is_tag_next( - enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, - local_stream - ): - self._auth_additional_data = primitives.ByteString( - tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA - ) - self._auth_additional_data.read( - local_stream, - kmip_version=kmip_version - ) + if self.is_tag_next( + enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, + local_stream + ): + self._auth_additional_data = primitives.ByteString( + tag=enums.Tags.AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA + ) + self._auth_additional_data.read( + local_stream, + kmip_version=kmip_version + ) self.is_oversized(local_stream) @@ -282,12 +278,11 @@ def write(self, output_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self._auth_additional_data: - self._auth_additional_data.write( - local_stream, - kmip_version=kmip_version - ) + if self._auth_additional_data: + self._auth_additional_data.write( + local_stream, + kmip_version=kmip_version + ) self.length = local_stream.length() super(EncryptRequestPayload, self).write( @@ -341,7 +336,6 @@ def __str__(self): 'auth_additional_data': self.auth_additional_data }) - class EncryptResponsePayload(base.ResponsePayload): """ A response payload for the Encrypt operation. @@ -406,7 +400,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -425,7 +419,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -444,7 +438,7 @@ def iv_counter_nonce(self): def iv_counter_nonce(self, value): if value is None: self._iv_counter_nonce = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._iv_counter_nonce = primitives.ByteString( value=value, tag=enums.Tags.IV_COUNTER_NONCE @@ -463,7 +457,7 @@ def auth_tag(self): def auth_tag(self, value): if value is None: self._auth_tag = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._auth_tag = primitives.ByteString( value=value, tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG @@ -525,17 +519,16 @@ def read(self, input_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self.is_tag_next( - enums.Tags.AUTHENTICATED_ENCRYPTION_TAG, local_stream - ): - self._auth_tag = primitives.ByteString( - tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG - ) - self._auth_tag.read( - local_stream, - kmip_version=kmip_version - ) + if self.is_tag_next( + enums.Tags.AUTHENTICATED_ENCRYPTION_TAG, local_stream + ): + self._auth_tag = primitives.ByteString( + tag=enums.Tags.AUTHENTICATED_ENCRYPTION_TAG + ) + self._auth_tag.read( + local_stream, + kmip_version=kmip_version + ) self.is_oversized(local_stream) @@ -578,12 +571,11 @@ def write(self, output_stream, kmip_version=enums.KMIPVersion.KMIP_1_0): kmip_version=kmip_version ) - if kmip_version >= enums.KMIPVersion.KMIP_1_4: - if self._auth_tag: - self._auth_tag.write( - local_stream, - kmip_version=kmip_version - ) + if self._auth_tag: + self._auth_tag.write( + local_stream, + kmip_version=kmip_version + ) self.length = local_stream.length() super(EncryptResponsePayload, self).write( diff --git a/kmip/core/messages/payloads/get.py b/kmip/core/messages/payloads/get.py index cf4d8071..2ac52ccd 100644 --- a/kmip/core/messages/payloads/get.py +++ b/kmip/core/messages/payloads/get.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import objects from kmip.core import primitives @@ -23,7 +21,6 @@ from kmip.core.factories import secrets as secret_factory from kmip.core.messages.payloads import base - class GetRequestPayload(base.RequestPayload): """ A request payload for the Get operation. @@ -85,7 +82,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -298,7 +295,6 @@ def __str__(self): 'key_wrapping_specification': self.key_wrapping_specification }) - class GetResponsePayload(base.ResponsePayload): """ A response payload for the Get operation. @@ -371,7 +367,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/get_attribute_list.py b/kmip/core/messages/payloads/get_attribute_list.py index e36f4289..880de7a2 100644 --- a/kmip/core/messages/payloads/get_attribute_list.py +++ b/kmip/core/messages/payloads/get_attribute_list.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class GetAttributeListRequestPayload(base.RequestPayload): """ A request payload for the GetAttributeList operation. @@ -62,7 +59,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -152,7 +149,6 @@ def __ne__(self, other): else: return NotImplemented - class GetAttributeListResponsePayload(base.ResponsePayload): """ A response payload for the GetAttributeList operation. @@ -201,7 +197,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -227,7 +223,7 @@ def attribute_names(self, value): names = list() for i in range(len(value)): name = value[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError( "Attribute names must be a list of strings; " "item {0} has type {1}".format(i + 1, type(name)) diff --git a/kmip/core/messages/payloads/get_attributes.py b/kmip/core/messages/payloads/get_attributes.py index db70ad34..5b13f3a7 100644 --- a/kmip/core/messages/payloads/get_attributes.py +++ b/kmip/core/messages/payloads/get_attributes.py @@ -10,8 +10,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -19,7 +17,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class GetAttributesRequestPayload(base.RequestPayload): """ A request payload for the GetAttributes operation. @@ -68,7 +65,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -94,7 +91,7 @@ def attribute_names(self, value): names = list() for i in range(len(value)): name = value[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): raise TypeError( "Attribute names must be a list of strings; " "item {0} has type {1}.".format(i + 1, type(name)) @@ -271,7 +268,6 @@ def __ne__(self, other): else: return NotImplemented - class GetAttributesResponsePayload(base.ResponsePayload): """ A response payload for the GetAttributes operation. @@ -316,7 +312,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/get_usage_allocation.py b/kmip/core/messages/payloads/get_usage_allocation.py index 9e98f84e..2f757fc0 100644 --- a/kmip/core/messages/payloads/get_usage_allocation.py +++ b/kmip/core/messages/payloads/get_usage_allocation.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class GetUsageAllocationRequestPayload(base.RequestPayload): """ A request payload for the GetUsageAllocation operation. @@ -62,7 +59,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -81,7 +78,7 @@ def usage_limits_count(self): def usage_limits_count(self, value): if value is None: self._usage_limits_count = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._usage_limits_count = primitives.LongInteger( value=value, tag=enums.Tags.USAGE_LIMITS_COUNT @@ -197,7 +194,6 @@ def __str__(self): 'usage_limits_count': self.usage_limits_count }) - class GetUsageAllocationResponsePayload(base.ResponsePayload): """ A response payload for the GetUsageAllocation operation. @@ -230,7 +226,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/locate.py b/kmip/core/messages/payloads/locate.py index a4307c49..1fa8f733 100644 --- a/kmip/core/messages/payloads/locate.py +++ b/kmip/core/messages/payloads/locate.py @@ -13,15 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import objects from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class LocateRequestPayload(base.RequestPayload): """ A request payload for the Locate operation. @@ -90,7 +87,7 @@ def maximum_items(self): def maximum_items(self, value): if value is None: self._maximum_items = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._maximum_items = primitives.Integer( value=value, tag=enums.Tags.MAXIMUM_ITEMS @@ -109,7 +106,7 @@ def offset_items(self): def offset_items(self, value): if value is None: self._offset_items = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._offset_items = primitives.Integer( value=value, tag=enums.Tags.OFFSET_ITEMS @@ -128,7 +125,7 @@ def storage_status_mask(self): def storage_status_mask(self, value): if value is None: self._storage_status_mask = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): if enums.is_bit_mask(enums.StorageStatusMask, value): self._storage_status_mask = primitives.Integer( value=value, @@ -368,7 +365,6 @@ def __str__(self): ) return '{' + value + '}' - class LocateResponsePayload(base.ResponsePayload): """ A response payload for the Locate operation. @@ -410,7 +406,7 @@ def located_items(self): def located_items(self, value): if value is None: self._located_items = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._located_items = primitives.Integer( value=value, tag=enums.Tags.LOCATED_ITEMS @@ -431,7 +427,7 @@ def unique_identifiers(self, value): elif isinstance(value, list): self._unique_identifiers = [] for v in value: - if not isinstance(v, six.string_types): + if not isinstance(v, str): self._unique_identifiers = [] raise TypeError( "Unique identifiers must be a list of strings." diff --git a/kmip/core/messages/payloads/mac.py b/kmip/core/messages/payloads/mac.py index 45552a8b..b3c9bb0d 100644 --- a/kmip/core/messages/payloads/mac.py +++ b/kmip/core/messages/payloads/mac.py @@ -20,7 +20,6 @@ from kmip.core.objects import Data, MACData from kmip.core.utils import BytearrayStream - # 4.33 class MACRequestPayload(base.RequestPayload): @@ -132,7 +131,6 @@ def write(self, ostream, kmip_version=enums.KMIPVersion.KMIP_1_0): ) ostream.write(tstream.buffer) - class MACResponsePayload(base.ResponsePayload): def __init__(self, diff --git a/kmip/core/messages/payloads/modify_attribute.py b/kmip/core/messages/payloads/modify_attribute.py index e94c08da..fa3d3ab6 100644 --- a/kmip/core/messages/payloads/modify_attribute.py +++ b/kmip/core/messages/payloads/modify_attribute.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class ModifyAttributeRequestPayload(base.RequestPayload): """ A request payload for the ModifyAttribute operation. @@ -84,7 +81,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -320,7 +317,6 @@ def __ne__(self, other): else: return NotImplemented - class ModifyAttributeResponsePayload(base.ResponsePayload): """ A response payload for the ModifyAttribute operation. @@ -361,7 +357,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/obtain_lease.py b/kmip/core/messages/payloads/obtain_lease.py index 178712dc..9633cc3e 100644 --- a/kmip/core/messages/payloads/obtain_lease.py +++ b/kmip/core/messages/payloads/obtain_lease.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class ObtainLeaseRequestPayload(base.RequestPayload): """ A request payload for the ObtainLease operation. @@ -54,7 +51,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -150,7 +147,6 @@ def __str__(self): 'unique_identifier': self.unique_identifier }) - class ObtainLeaseResponsePayload(base.ResponsePayload): """ A response payload for the ObtainLease operation. @@ -202,7 +198,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -221,7 +217,7 @@ def lease_time(self): def lease_time(self, value): if value is None: self._lease_time = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._lease_time = primitives.Interval( value=value, tag=enums.Tags.LEASE_TIME @@ -240,7 +236,7 @@ def last_change_date(self): def last_change_date(self, value): if value is None: self._last_change_date = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._last_change_date = primitives.DateTime( value=value, tag=enums.Tags.LAST_CHANGE_DATE diff --git a/kmip/core/messages/payloads/poll.py b/kmip/core/messages/payloads/poll.py index 948bdac6..b088e87b 100644 --- a/kmip/core/messages/payloads/poll.py +++ b/kmip/core/messages/payloads/poll.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class PollRequestPayload(base.RequestPayload): """ A request payload for the Poll operation. @@ -55,7 +52,7 @@ def asynchronous_correlation_value(self): def asynchronous_correlation_value(self, value): if value is None: self._asynchronous_correlation_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._asynchronous_correlation_value = primitives.ByteString( value=value, tag=enums.Tags.ASYNCHRONOUS_CORRELATION_VALUE diff --git a/kmip/core/messages/payloads/query.py b/kmip/core/messages/payloads/query.py index 8c65d2e2..e001109c 100644 --- a/kmip/core/messages/payloads/query.py +++ b/kmip/core/messages/payloads/query.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import misc @@ -23,7 +21,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class QueryRequestPayload(base.RequestPayload): """ A request payload for the Query operation. @@ -187,7 +184,6 @@ def __ne__(self, other): else: return NotImplemented - class QueryResponsePayload(base.ResponsePayload): """ A response payload for the Query operation. @@ -396,7 +392,7 @@ def vendor_identification(self): def vendor_identification(self, value): if value is None: self._vendor_identification = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._vendor_identification = primitives.TextString( value=value, tag=enums.Tags.VENDOR_IDENTIFICATION @@ -432,7 +428,7 @@ def application_namespaces(self, value): elif isinstance(value, list): application_namespaces = [] for i in value: - if isinstance(i, six.string_types): + if isinstance(i, str): application_namespaces.append( primitives.TextString( value=i, @@ -671,7 +667,7 @@ def protection_storage_masks(self, value): elif isinstance(value, list): protection_storage_masks = [] for i in value: - if isinstance(i, six.integer_types): + if isinstance(i, int): protection_storage_masks.append( primitives.Integer( value=i, diff --git a/kmip/core/messages/payloads/recover.py b/kmip/core/messages/payloads/recover.py index abbf3163..89d2711f 100644 --- a/kmip/core/messages/payloads/recover.py +++ b/kmip/core/messages/payloads/recover.py @@ -13,14 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class RecoverRequestPayload(base.RequestPayload): """ A request payload for the Recover operation. @@ -53,7 +50,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -149,7 +146,6 @@ def __str__(self): 'unique_identifier': self.unique_identifier }) - class RecoverResponsePayload(base.ResponsePayload): """ A response payload for the Recover operation. @@ -182,7 +178,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/register.py b/kmip/core/messages/payloads/register.py index 730f7faa..f8481d63 100644 --- a/kmip/core/messages/payloads/register.py +++ b/kmip/core/messages/payloads/register.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -24,7 +22,6 @@ from kmip.core.factories import secrets as secret_factory from kmip.core.messages.payloads import base - class RegisterRequestPayload(base.RequestPayload): """ A request payload for the Register operation. @@ -385,7 +382,6 @@ def __str__(self): ) return '{' + value + '}' - class RegisterResponsePayload(base.ResponsePayload): """ A response payload for the Register operation. @@ -428,7 +424,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/rekey.py b/kmip/core/messages/payloads/rekey.py index 0bd8f86e..6f477de7 100644 --- a/kmip/core/messages/payloads/rekey.py +++ b/kmip/core/messages/payloads/rekey.py @@ -10,15 +10,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import objects from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class RekeyRequestPayload(base.RequestPayload): """ A request payload for the Rekey operation. @@ -69,7 +66,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -88,7 +85,7 @@ def offset(self): def offset(self, value): if value is None: self._offset = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._offset = primitives.Interval( value=value, tag=enums.Tags.OFFSET @@ -225,7 +222,6 @@ def __str__(self): 'template_attribute': str(self.template_attribute) }) - class RekeyResponsePayload(base.ResponsePayload): """ A response payload for the Rekey operation. @@ -268,7 +264,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/rekey_key_pair.py b/kmip/core/messages/payloads/rekey_key_pair.py index f317dbd7..821125ff 100644 --- a/kmip/core/messages/payloads/rekey_key_pair.py +++ b/kmip/core/messages/payloads/rekey_key_pair.py @@ -23,7 +23,6 @@ CreateKeyPairResponsePayload from kmip.core.utils import BytearrayStream - class RekeyKeyPairRequestPayload(base.RequestPayload): def __init__(self, @@ -165,7 +164,6 @@ def __validate(self): self.public_key_template_attribute) raise TypeError(msg) - # TODO (ph) Remove the dependency on the CreateKeyPairResponsePayload class RekeyKeyPairResponsePayload(CreateKeyPairResponsePayload): diff --git a/kmip/core/messages/payloads/revoke.py b/kmip/core/messages/payloads/revoke.py index adcc0cd4..80808180 100644 --- a/kmip/core/messages/payloads/revoke.py +++ b/kmip/core/messages/payloads/revoke.py @@ -20,7 +20,6 @@ from kmip.core.messages.payloads import base from kmip.core.utils import BytearrayStream - class RevokeRequestPayload(base.RequestPayload): """ A request payload for the Revoke operation. @@ -141,7 +140,6 @@ def validate(self): msg = "invalid revocation reason" raise TypeError(msg) - class RevokeResponsePayload(base.ResponsePayload): """ A response payload for the Revoke operation. diff --git a/kmip/core/messages/payloads/set_attribute.py b/kmip/core/messages/payloads/set_attribute.py index e9288079..546e2ea7 100644 --- a/kmip/core/messages/payloads/set_attribute.py +++ b/kmip/core/messages/payloads/set_attribute.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import enums from kmip.core import exceptions from kmip.core import objects @@ -22,7 +20,6 @@ from kmip.core import utils from kmip.core.messages.payloads import base - class SetAttributeRequestPayload(base.RequestPayload): """ A request payload for the SetAttribute operation. @@ -65,7 +62,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -235,7 +232,6 @@ def __ne__(self, other): else: return NotImplemented - class SetAttributeResponsePayload(base.ResponsePayload): """ A response payload for the SetAttribute operation. @@ -270,7 +266,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER diff --git a/kmip/core/messages/payloads/sign.py b/kmip/core/messages/payloads/sign.py index 7035c8ee..aa35d5ed 100644 --- a/kmip/core/messages/payloads/sign.py +++ b/kmip/core/messages/payloads/sign.py @@ -13,15 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import attributes from kmip.core import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class SignRequestPayload(base.RequestPayload): """ A request payload for the Sign operation. @@ -73,7 +70,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -108,7 +105,7 @@ def data(self): def data(self, value): if value is None: self._data is None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -245,7 +242,6 @@ def __str__(self): 'data': self.data }) - class SignResponsePayload(base.ResponsePayload): """ A response payload for the Sign operation. @@ -278,7 +274,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -297,7 +293,7 @@ def signature_data(self): def signature_data(self, value): if value is None: self._signature_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._signature_data = primitives.ByteString( value=value, tag=enums.Tags.SIGNATURE_DATA diff --git a/kmip/core/messages/payloads/signature_verify.py b/kmip/core/messages/payloads/signature_verify.py index dc6f5066..e105ade0 100644 --- a/kmip/core/messages/payloads/signature_verify.py +++ b/kmip/core/messages/payloads/signature_verify.py @@ -13,15 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core import attributes from kmip.core import enums from kmip.core import primitives from kmip.core import utils from kmip.core.messages.payloads import base - class SignatureVerifyRequestPayload(base.RequestPayload): """ A request payload for the SignatureVerify operation. @@ -109,7 +106,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -144,7 +141,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -163,7 +160,7 @@ def digested_data(self): def digested_data(self, value): if value is None: self._digested_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._digested_data = primitives.ByteString( value=value, tag=enums.Tags.DIGESTED_DATA @@ -182,7 +179,7 @@ def signature_data(self): def signature_data(self, value): if value is None: self._signature_data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._signature_data = primitives.ByteString( value=value, tag=enums.Tags.SIGNATURE_DATA @@ -201,7 +198,7 @@ def correlation_value(self): def correlation_value(self, value): if value is None: self._correlation_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._correlation_value = primitives.ByteString( value=value, tag=enums.Tags.CORRELATION_VALUE @@ -436,7 +433,6 @@ def __str__(self): 'final_indicator': self.final_indicator }) - class SignatureVerifyResponsePayload(base.ResponsePayload): """ A response payload for the SignatureVerify operation. @@ -494,7 +490,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -535,7 +531,7 @@ def data(self): def data(self, value): if value is None: self._data = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._data = primitives.ByteString( value=value, tag=enums.Tags.DATA @@ -554,7 +550,7 @@ def correlation_value(self): def correlation_value(self, value): if value is None: self._correlation_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._correlation_value = primitives.ByteString( value=value, tag=enums.Tags.CORRELATION_VALUE diff --git a/kmip/core/misc.py b/kmip/core/misc.py index 2a5deb29..b3d98ca4 100644 --- a/kmip/core/misc.py +++ b/kmip/core/misc.py @@ -26,7 +26,6 @@ from kmip.core.utils import BytearrayStream - class CertificateValue(ByteString): """ The bytes of a DER-encoded X.509 public key certificate. @@ -47,7 +46,6 @@ def __init__(self, value=b''): """ super(CertificateValue, self).__init__(value, Tags.CERTIFICATE_VALUE) - class Offset(Interval): """ An integer representing a positive change in time. @@ -68,7 +66,6 @@ def __init__(self, value=None): """ super(Offset, self).__init__(value, Tags.OFFSET) - class QueryFunction(Enumeration): """ An encodeable wrapper for the QueryFunction enumeration. @@ -90,7 +87,6 @@ def __init__(self, value=None): super(QueryFunction, self).__init__( QueryFunctionEnum, value, Tags.QUERY_FUNCTION) - class VendorIdentification(TextString): """ A text string uniquely identifying a KMIP vendor. @@ -111,7 +107,6 @@ def __init__(self, value=None): super(VendorIdentification, self).__init__( value, Tags.VENDOR_IDENTIFICATION) - class ServerInformation(Struct): """ A structure containing vendor-specific fields and/or substructures. @@ -216,7 +211,6 @@ def __repr__(self): def __str__(self): return str(self.data) - class KeyFormatType(Enumeration): """ An encodeable wrapper for the KeyFormatType enumeration. diff --git a/kmip/core/objects.py b/kmip/core/objects.py index fb49555f..3621d9bd 100644 --- a/kmip/core/objects.py +++ b/kmip/core/objects.py @@ -14,8 +14,7 @@ # under the License. import abc -import six -from six.moves import xrange + import struct from kmip.core import attributes @@ -41,7 +40,6 @@ from kmip.core import utils from kmip.core.utils import BytearrayStream - # 2.1 # 2.1.1 class Attribute(Struct): @@ -174,7 +172,6 @@ def __ne__(self, other): else: return NotImplemented - class CurrentAttribute(primitives.Struct): """ A structure containing a single attribute. @@ -355,7 +352,6 @@ def __ne__(self, other): else: return NotImplemented - class NewAttribute(primitives.Struct): """ A structure containing a single attribute. @@ -536,7 +532,6 @@ def __ne__(self, other): else: return NotImplemented - class AttributeReference(primitives.Struct): """ A structure containing reference information for an attribute. @@ -581,7 +576,7 @@ def vendor_identification(self): def vendor_identification(self, value): if value is None: self._vendor_identification = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._vendor_identification = primitives.TextString( value, tag=enums.Tags.VENDOR_IDENTIFICATION @@ -600,7 +595,7 @@ def attribute_name(self): def attribute_name(self, value): if value is None: self._attribute_name = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._attribute_name = primitives.TextString( value, tag=enums.Tags.ATTRIBUTE_NAME @@ -766,7 +761,6 @@ def __ne__(self, other): else: return NotImplemented - class Attributes(primitives.Struct): """ A collection of KMIP attributes. @@ -946,7 +940,7 @@ def __eq__(self, other): # TODO (ph) Allow order independence? - for i in six.moves.range(len(self.attributes)): + for i in range(len(self.attributes)): a = self.attributes[i] b = other.attributes[i] @@ -961,7 +955,6 @@ def __ne__(self, other): else: return NotImplemented - class Nonce(primitives.Struct): """ A struct representing a Nonce object. @@ -1002,7 +995,7 @@ def nonce_id(self): def nonce_id(self, value): if value is None: self._nonce_id = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._nonce_id = primitives.ByteString( value=value, tag=enums.Tags.NONCE_ID @@ -1021,7 +1014,7 @@ def nonce_value(self): def nonce_value(self, value): if value is None: self._nonce_value = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._nonce_value = primitives.ByteString( value=value, tag=enums.Tags.NONCE_VALUE @@ -1133,15 +1126,12 @@ def __str__(self): ]) return "{" + body + "}" - -@six.add_metaclass(abc.ABCMeta) -class CredentialValue(primitives.Struct): +class CredentialValue(primitives.Struct, metaclass=abc.ABCMeta): """ An empty, abstract base class to be used by Credential objects to easily group and type-check credential values. """ - class UsernamePasswordCredential(CredentialValue): """ A struct representing a UsernamePasswordCredential object. @@ -1182,7 +1172,7 @@ def username(self): def username(self, value): if value is None: self._username = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._username = primitives.TextString( value=value, tag=enums.Tags.USERNAME @@ -1201,7 +1191,7 @@ def password(self): def password(self, value): if value is None: self._password = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._password = primitives.TextString( value=value, tag=enums.Tags.PASSWORD @@ -1314,7 +1304,6 @@ def __str__(self): "password": self.password }) - class DeviceCredential(CredentialValue): """ A struct representing a DeviceCredential object. @@ -1379,7 +1368,7 @@ def device_serial_number(self): def device_serial_number(self, value): if value is None: self._device_serial_number = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._device_serial_number = primitives.TextString( value=value, tag=enums.Tags.DEVICE_SERIAL_NUMBER @@ -1398,7 +1387,7 @@ def password(self): def password(self, value): if value is None: self._password = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._password = primitives.TextString( value=value, tag=enums.Tags.PASSWORD @@ -1417,7 +1406,7 @@ def device_identifier(self): def device_identifier(self, value): if value is None: self._device_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._device_identifier = primitives.TextString( value=value, tag=enums.Tags.DEVICE_IDENTIFIER @@ -1436,7 +1425,7 @@ def network_identifier(self): def network_identifier(self, value): if value is None: self._network_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._network_identifier = primitives.TextString( value=value, tag=enums.Tags.NETWORK_IDENTIFIER @@ -1455,7 +1444,7 @@ def machine_identifier(self): def machine_identifier(self, value): if value is None: self._machine_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._machine_identifier = primitives.TextString( value=value, tag=enums.Tags.MACHINE_IDENTIFIER @@ -1474,7 +1463,7 @@ def media_identifier(self): def media_identifier(self, value): if value is None: self._media_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._media_identifier = primitives.TextString( value=value, tag=enums.Tags.MEDIA_IDENTIFIER @@ -1651,7 +1640,6 @@ def __str__(self): "media_identifier": self.media_identifier }) - class AttestationCredential(CredentialValue): """ A struct representing an AttestationCredential object. @@ -1743,7 +1731,7 @@ def attestation_measurement(self): def attestation_measurement(self, value): if value is None: self._attestation_measurement = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._attestation_measurement = primitives.ByteString( value=value, tag=enums.Tags.ATTESTATION_MEASUREMENT @@ -1762,7 +1750,7 @@ def attestation_assertion(self): def attestation_assertion(self, value): if value is None: self._attestation_assertion = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._attestation_assertion = primitives.ByteString( value=value, tag=enums.Tags.ATTESTATION_ASSERTION @@ -1949,7 +1937,6 @@ def __str__(self): "'attestation_assertion': " + \ str(self.attestation_assertion) + "}" - class Credential(primitives.Struct): """ A struct representing a Credential object. @@ -2146,7 +2133,6 @@ def __str__(self): "credential_value": str(self.credential_value) }) - class KeyBlock(Struct): class KeyCompressionType(Enumeration): @@ -2254,14 +2240,12 @@ def __validate(self): ) raise TypeError(msg) - # 2.1.4 class KeyMaterial(ByteString): def __init__(self, value=None): super(KeyMaterial, self).__init__(value, Tags.KEY_MATERIAL) - # TODO (peter-hamilton) Get rid of this and replace with a KeyMaterial factory. class KeyMaterialStruct(Struct): @@ -2299,7 +2283,6 @@ def __validate(self): # NOTE (peter-hamilton): Intentional pass, no way to validate data. pass - class KeyValue(Struct): def __init__(self, @@ -2363,7 +2346,7 @@ def __validate(self): raise TypeError(msg) if isinstance(self.attributes, list): - for i in xrange(len(self.attributes)): + for i in range(len(self.attributes)): attribute = self.attributes[i] if not isinstance(attribute, Attribute): msg = "invalid attribute ({0} in list)".format(i) @@ -2376,7 +2359,6 @@ def __validate(self): list, self.attributes) raise TypeError(msg) - class EncryptionKeyInformation(Struct): """ A set of values detailing how an encrypted value was encrypted. @@ -2419,7 +2401,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -2558,7 +2540,6 @@ def __str__(self): 'cryptographic_parameters': self.cryptographic_parameters }) - class MACSignatureKeyInformation(primitives.Struct): """ A set of values detailing how an MAC/signed value was MAC/signed. @@ -2601,7 +2582,7 @@ def unique_identifier(self): def unique_identifier(self, value): if value is None: self._unique_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._unique_identifier = primitives.TextString( value=value, tag=enums.Tags.UNIQUE_IDENTIFIER @@ -2740,7 +2721,6 @@ def __str__(self): 'cryptographic_parameters': self.cryptographic_parameters }) - class KeyWrappingData(Struct): """ A set of key block values needed for key wrapping functionality @@ -2864,7 +2844,7 @@ def mac_signature(self): def mac_signature(self, value): if value is None: self._mac_signature = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._mac_signature = primitives.ByteString( value=value, tag=enums.Tags.MAC_SIGNATURE @@ -2883,7 +2863,7 @@ def iv_counter_nonce(self): def iv_counter_nonce(self, value): if value is None: self._iv_counter_nonce = None - elif isinstance(value, six.binary_type): + elif isinstance(value, bytes): self._iv_counter_nonce = primitives.ByteString( value=value, tag=enums.Tags.IV_COUNTER_NONCE @@ -3103,7 +3083,6 @@ def __str__(self): 'encoding_option': self.encoding_option }) - class KeyWrappingSpecification(primitives.Struct): """ A set of values needed for key wrapping functionality. @@ -3224,7 +3203,7 @@ def attribute_names(self, value): elif isinstance(value, list): attribute_names = [] for i in value: - if isinstance(i, six.string_types): + if isinstance(i, str): attribute_names.append( primitives.TextString( value=i, @@ -3435,7 +3414,6 @@ def __str__(self): 'encoding_option': self.encoding_option }) - class TemplateAttribute(Struct): def __init__(self, @@ -3514,14 +3492,14 @@ def __eq__(self, other): # TODO (peter-hamilton) Allow order independence? - for i in xrange(len(self.names)): + for i in range(len(self.names)): a = self.names[i] b = other.names[i] if a != b: return False - for i in xrange(len(self.attributes)): + for i in range(len(self.attributes)): a = self.attributes[i] b = other.attributes[i] @@ -3538,7 +3516,6 @@ def __ne__(self, other): else: return NotImplemented - class CommonTemplateAttribute(TemplateAttribute): def __init__(self, @@ -3547,7 +3524,6 @@ def __init__(self, super(CommonTemplateAttribute, self).__init__( names, attributes, Tags.COMMON_TEMPLATE_ATTRIBUTE) - class PrivateKeyTemplateAttribute(TemplateAttribute): def __init__(self, @@ -3556,7 +3532,6 @@ def __init__(self, super(PrivateKeyTemplateAttribute, self).__init__( names, attributes, Tags.PRIVATE_KEY_TEMPLATE_ATTRIBUTE) - class PublicKeyTemplateAttribute(TemplateAttribute): def __init__(self, @@ -3565,7 +3540,6 @@ def __init__(self, super(PublicKeyTemplateAttribute, self).__init__( names, attributes, Tags.PUBLIC_KEY_TEMPLATE_ATTRIBUTE) - def convert_template_attribute_to_attributes(value): if not isinstance(value, TemplateAttribute): raise TypeError("Input must be a TemplateAttribute structure.") @@ -3589,7 +3563,6 @@ def convert_template_attribute_to_attributes(value): return Attributes(attributes=attribute_values, tag=tag) - def convert_attributes_to_template_attribute(value): if not isinstance(value, Attributes): raise TypeError("Input must be an Attributes structure.") @@ -3619,7 +3592,6 @@ def convert_attributes_to_template_attribute(value): tag=template_tag ) - # 2.1.9 class ExtensionName(TextString): """ @@ -3642,7 +3614,6 @@ def __init__(self, value=''): """ super(ExtensionName, self).__init__(value, Tags.EXTENSION_NAME) - class ExtensionTag(Integer): """ The tag of an extended Object. @@ -3663,7 +3634,6 @@ def __init__(self, value=0): """ super(ExtensionTag, self).__init__(value, Tags.EXTENSION_TAG) - class ExtensionType(Integer): """ The type of an extended Object. @@ -3686,7 +3656,6 @@ def __init__(self, value=None): """ super(ExtensionType, self).__init__(value, Tags.EXTENSION_TYPE) - class ExtensionInformation(Struct): """ A structure describing Objects defined in KMIP specification extensions. @@ -3872,21 +3841,18 @@ def create(cls, extension_name=None, extension_tag=None, extension_tag=extension_tag, extension_type=extension_type) - # 2.1.10 class Data(ByteString): def __init__(self, value=None): super(Data, self).__init__(value, Tags.DATA) - # 2.1.13 class MACData(ByteString): def __init__(self, value=None): super(MACData, self).__init__(value, Tags.MAC_DATA) - # 3.31, 9.1.3.2.19 class RevocationReasonCode(Enumeration): @@ -3895,7 +3861,6 @@ def __init__(self, value=enums.RevocationReasonCode.UNSPECIFIED): enums.RevocationReasonCode, value=value, tag=Tags.REVOCATION_REASON_CODE) - # 3.31 class RevocationReason(Struct): """ @@ -3991,7 +3956,6 @@ def validate(self): msg = "TextString expect" raise TypeError(msg) - class ObjectDefaults(primitives.Struct): """ A structure containing default object values used by the server. @@ -4202,7 +4166,6 @@ def __ne__(self, other): else: return NotImplemented - class DefaultsInformation(primitives.Struct): """ """ @@ -4364,7 +4327,6 @@ def __ne__(self, other): else: return NotImplemented - class RNGParameters(primitives.Struct): """ A structure containing parameters for a random number generator. @@ -4500,7 +4462,7 @@ def cryptographic_length(self): def cryptographic_length(self, value): if value is None: self._cryptographic_length = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._cryptographic_length = primitives.Integer( value=value, tag=enums.Tags.CRYPTOGRAPHIC_LENGTH @@ -4862,7 +4824,6 @@ def __ne__(self, other): else: return NotImplemented - class ProfileInformation(primitives.Struct): """ A structure containing details of supported KMIP profiles. @@ -4936,7 +4897,7 @@ def server_uri(self): def server_uri(self, value): if value is None: self._server_uri = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._server_uri = primitives.TextString( value=value, tag=enums.Tags.SERVER_URI @@ -4954,7 +4915,7 @@ def server_port(self): def server_port(self, value): if value is None: self._server_port = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._server_port = primitives.Integer( value=value, tag=enums.Tags.SERVER_PORT @@ -5103,7 +5064,6 @@ def __ne__(self, other): else: return NotImplemented - class ValidationInformation(primitives.Struct): """ A structure containing details of a formal validation. @@ -5251,7 +5211,7 @@ def validation_authority_country(self): def validation_authority_country(self, value): if value is None: self._validation_authority_country = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._validation_authority_country = primitives.TextString( value=value, tag=enums.Tags.VALIDATION_AUTHORITY_COUNTRY @@ -5271,7 +5231,7 @@ def validation_authority_uri(self): def validation_authority_uri(self, value): if value is None: self._validation_authority_uri = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._validation_authority_uri = primitives.TextString( value=value, tag=enums.Tags.VALIDATION_AUTHORITY_URI @@ -5289,7 +5249,7 @@ def validation_version_major(self): def validation_version_major(self, value): if value is None: self._validation_version_major = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._validation_version_major = primitives.Integer( value=value, tag=enums.Tags.VALIDATION_VERSION_MAJOR @@ -5307,7 +5267,7 @@ def validation_version_minor(self): def validation_version_minor(self, value): if value is None: self._validation_version_minor = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._validation_version_minor = primitives.Integer( value=value, tag=enums.Tags.VALIDATION_VERSION_MINOR @@ -5346,7 +5306,7 @@ def validation_level(self): def validation_level(self, value): if value is None: self._validation_level = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._validation_level = primitives.Integer( value=value, tag=enums.Tags.VALIDATION_LEVEL @@ -5364,7 +5324,7 @@ def validation_certificate_identifier(self): def validation_certificate_identifier(self, value): if value is None: self._validation_certificate_identifier = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._validation_certificate_identifier = primitives.TextString( value=value, tag=enums.Tags.VALIDATION_CERTIFICATE_IDENTIFIER @@ -5384,7 +5344,7 @@ def validation_certificate_uri(self): def validation_certificate_uri(self, value): if value is None: self._validation_certificate_uri = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._validation_certificate_uri = primitives.TextString( value=value, tag=enums.Tags.VALIDATION_CERTIFICATE_URI @@ -5402,7 +5362,7 @@ def validation_vendor_uri(self): def validation_vendor_uri(self, value): if value is None: self._validation_vendor_uri = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._validation_vendor_uri = primitives.TextString( value=value, tag=enums.Tags.VALIDATION_VENDOR_URI @@ -5423,7 +5383,7 @@ def validation_profiles(self, value): elif isinstance(value, list): validation_profiles = [] for v in value: - if isinstance(v, six.string_types): + if isinstance(v, str): validation_profiles.append( primitives.TextString( value=v, @@ -5861,7 +5821,6 @@ def __ne__(self, other): else: return NotImplemented - class CapabilityInformation(primitives.Struct): """ A structure containing details of supported server capabilities. @@ -6408,7 +6367,6 @@ def __ne__(self, other): else: return NotImplemented - class ProtectionStorageMasks(primitives.Struct): """ A structure containing a list of protection storage masks. @@ -6455,7 +6413,7 @@ def protection_storage_masks(self, value): elif isinstance(value, list): protection_storage_masks = [] for x in value: - if isinstance(x, six.integer_types): + if isinstance(x, int): if enums.is_bit_mask(enums.ProtectionStorageMask, x): protection_storage_masks.append( primitives.Integer( diff --git a/kmip/core/policy.py b/kmip/core/policy.py index 05d15c92..19351e16 100644 --- a/kmip/core/policy.py +++ b/kmip/core/policy.py @@ -14,18 +14,16 @@ # under the License. import json -import six from kmip.core import enums - def parse_policy(policy): result = {} - for object_type, operation_policies in six.iteritems(policy): + for object_type, operation_policies in policy.items(): processed_operation_policies = {} - for operation, permission in six.iteritems(operation_policies): + for operation, permission in operation_policies.items(): try: enum_operation = enums.Operation[operation] except Exception: @@ -58,7 +56,6 @@ def parse_policy(policy): return result - def read_policy_from_file(path): policy_blob = {} @@ -80,7 +77,7 @@ def read_policy_from_file(path): continue # Use subset checking to determine what type of policy we have - sections = set([s for s in six.iterkeys(object_policy)]) + sections = set([s for s in object_policy.keys()]) if sections <= policy_sections: parsed_policies = dict() @@ -91,7 +88,7 @@ def read_policy_from_file(path): group_policies = object_policy.get('groups') if group_policies: parsed_group_policies = dict() - for group_name, group_policy in six.iteritems(group_policies): + for group_name, group_policy in group_policies.items(): parsed_group_policies[group_name] = parse_policy( group_policy ) @@ -110,7 +107,6 @@ def read_policy_from_file(path): return result - policies = { 'default': { 'preset': { diff --git a/kmip/core/primitives.py b/kmip/core/primitives.py index b8cd9a75..f46699e2 100644 --- a/kmip/core/primitives.py +++ b/kmip/core/primitives.py @@ -15,7 +15,7 @@ import enum as enumeration import logging -import six + import struct import sys import time @@ -26,7 +26,6 @@ from kmip.core import exceptions from kmip.core import utils - class Base(object): TAG_SIZE = 3 TYPE_SIZE = 1 @@ -169,7 +168,6 @@ def is_type_next(kmip_type, stream): else: return False - class Struct(Base): def __init__(self, tag=enums.Tags.DEFAULT): @@ -179,7 +177,6 @@ def __init__(self, tag=enums.Tags.DEFAULT): def __repr__(self): return "Struct()" - class Integer(Base): LENGTH = 4 @@ -246,9 +243,9 @@ def validate(self): integer """ if self.value is not None: - if type(self.value) not in six.integer_types: + if type(self.value) is not int: raise TypeError('expected (one of): {0}, observed: {1}'.format( - six.integer_types, type(self.value))) + int, type(self.value))) else: if self.value > Integer.MAX: raise ValueError('integer value greater than accepted max') @@ -297,7 +294,6 @@ def __ge__(self, other): else: return NotImplemented - class LongInteger(Base): """ An encodeable object representing a long integer value. @@ -378,9 +374,9 @@ def validate(self): integer """ if self.value is not None: - if not isinstance(self.value, six.integer_types): + if not isinstance(self.value, int): raise TypeError('expected (one of): {0}, observed: {1}'.format( - six.integer_types, type(self.value))) + int, type(self.value))) else: if self.value > LongInteger.MAX: raise ValueError( @@ -410,7 +406,6 @@ def __ne__(self, other): else: return NotImplemented - class BigInteger(Base): """ An encodeable object representing a big integer value. @@ -520,9 +515,9 @@ def validate(self): TypeError: if the value is not of type int or long """ if self.value is not None: - if not isinstance(self.value, six.integer_types): + if not isinstance(self.value, int): raise TypeError('expected (one of): {0}, observed: {1}'.format( - six.integer_types, type(self.value))) + int, type(self.value))) def __repr__(self): return "BigInteger(value={0}, tag={1})".format(self.value, self.tag) @@ -545,7 +540,6 @@ def __ne__(self, other): else: return NotImplemented - class Enumeration(Base): """ An encodeable object representing an enumeration. @@ -558,7 +552,7 @@ class Enumeration(Base): # Bounds for unsigned 32-bit integers MIN = 0 - MAX = 4294967296 + MAX = 4294967295 def __init__(self, enum, value=None, tag=enums.Tags.DEFAULT): """ @@ -648,7 +642,7 @@ def validate(self): raise TypeError( 'enumeration {0} must be of type {1}'.format( self.value, self.enum)) - if type(self.value.value) not in six.integer_types: + if type(self.value.value) is not int: raise TypeError('enumeration value must be an int') else: if self.value.value > Enumeration.MAX: @@ -679,7 +673,6 @@ def __ne__(self, other): else: return NotImplemented - class Boolean(Base): """ An encodeable object representing a boolean value. @@ -813,7 +806,6 @@ def __ne__(self, other): else: return NotImplemented - class TextString(Base): PADDING_SIZE = 8 BYTE_FORMAT = '!c' @@ -850,6 +842,8 @@ def read_value(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): # Read padding and check content self.padding_length = self.PADDING_SIZE - (self.length % self.PADDING_SIZE) + if self.padding_length == self.PADDING_SIZE: + self.padding_length = 0 if self.padding_length < self.PADDING_SIZE: for _ in range(self.padding_length): pad = unpack('!B', istream.read(1))[0] @@ -884,7 +878,7 @@ def validate(self): def __validate(self): if self.value is not None: - if not isinstance(self.value, six.string_types): + if not isinstance(self.value, str): msg = exceptions.ErrorStrings.BAD_EXP_RECV raise TypeError(msg.format('TextString', 'value', str, type(self.value))) @@ -907,7 +901,6 @@ def __ne__(self, other): else: return NotImplemented - class ByteString(Base): PADDING_SIZE = 8 BYTE_FORMAT = '!B' @@ -1004,7 +997,6 @@ def __ne__(self, other): else: return NotImplemented - class DateTime(LongInteger): """ An encodeable object representing a date/time value. @@ -1037,7 +1029,6 @@ def __repr__(self): def __str__(self): return time.asctime(time.gmtime(self.value)) - class Interval(Base): """ An encodeable object representing an interval of time. @@ -1051,7 +1042,7 @@ class Interval(Base): # Bounds for unsigned 32-bit integers MIN = 0 - MAX = 4294967296 + MAX = 4294967295 def __init__(self, value=0, tag=enums.Tags.DEFAULT): super(Interval, self).__init__(tag, type=enums.Types.INTERVAL) @@ -1121,9 +1112,9 @@ def validate(self): 32-bit integer """ if self.value is not None: - if type(self.value) not in six.integer_types: + if type(self.value) is not int: raise TypeError('expected (one of): {0}, observed: {1}'.format( - six.integer_types, type(self.value))) + int, type(self.value))) else: if self.value > Interval.MAX: raise ValueError( diff --git a/kmip/core/secrets.py b/kmip/core/secrets.py index 1b0ceace..1195b65c 100644 --- a/kmip/core/secrets.py +++ b/kmip/core/secrets.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - from kmip.core.attributes import CertificateType from kmip.core import enums @@ -35,7 +33,6 @@ from kmip.core import utils from kmip.core.utils import BytearrayStream - # 2.2 # 2.2.1 class Certificate(Struct): @@ -142,7 +139,6 @@ def __repr__(self): def __str__(self): return "{0}".format(str(self.certificate_value)) - # 2.2.2 class KeyBlockKey(Struct): @@ -178,7 +174,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - class SymmetricKey(KeyBlockKey): def __init__(self, key_block=None): @@ -192,7 +187,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - # 2.2.3 class PublicKey(KeyBlockKey): @@ -207,7 +201,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - # 2.2.4 class PrivateKey(KeyBlockKey): @@ -222,7 +215,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - class SplitKey(primitives.Struct): """ A split key cryptographic object. @@ -301,7 +293,7 @@ def split_key_parts(self): def split_key_parts(self, value): if value is None: self._split_key_parts = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._split_key_parts = primitives.Integer( value=value, tag=enums.Tags.SPLIT_KEY_PARTS @@ -319,7 +311,7 @@ def key_part_identifier(self): def key_part_identifier(self, value): if value is None: self._key_part_identifier = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._key_part_identifier = primitives.Integer( value=value, tag=enums.Tags.KEY_PART_IDENTIFIER @@ -337,7 +329,7 @@ def split_key_threshold(self): def split_key_threshold(self, value): if value is None: self._split_key_threshold = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._split_key_threshold = primitives.Integer( value=value, tag=enums.Tags.SPLIT_KEY_THRESHOLD @@ -376,7 +368,7 @@ def prime_field_size(self): def prime_field_size(self, value): if value is None: self._prime_field_size = None - elif isinstance(value, six.integer_types): + elif isinstance(value, int): self._prime_field_size = primitives.BigInteger( value=value, tag=enums.Tags.PRIME_FIELD_SIZE @@ -619,7 +611,6 @@ def __ne__(self, other): else: return NotImplemented - # 2.2.6 class Template(Struct): @@ -664,7 +655,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - # 2.2.7 class SecretData(Struct): @@ -713,7 +703,6 @@ def __validate(self): # TODO (peter-hamilton) Finish implementation. pass - # 2.2.8 class OpaqueObject(Struct): diff --git a/kmip/core/utils.py b/kmip/core/utils.py index 8352580e..f7b28214 100644 --- a/kmip/core/utils.py +++ b/kmip/core/utils.py @@ -18,13 +18,11 @@ from kmip.core import exceptions - def bit_length(num): s = bin(num) s = s.lstrip('0b') return len(s) - def count_bytes(num): bits = bit_length(num) num_bytes = int(bits / 8) @@ -32,24 +30,20 @@ def count_bytes(num): num_bytes += 1 return num_bytes - def print_bytearray(array): sbuffer = hexlify_bytearray(array) print('buffer: {0}'.format(sbuffer)) - def hexlify_bytearray(array): sbuffer = bytes(array[0:]) return hexlify(sbuffer) - def is_stream_empty(stream): if len(stream.peek(1)) > 0: return False else: return True - def build_er_error(class_object, descriptor, expected, received, attribute=None): msg = exceptions.ErrorStrings.BAD_EXP_RECV @@ -61,7 +55,6 @@ def build_er_error(class_object, descriptor, expected, received, return msg.format(class_string, descriptor, expected, received) - class BytearrayStream(io.RawIOBase): def __init__(self, data=None): if data is None: diff --git a/kmip/demos/pie/create.py b/kmip/demos/pie/create.py index fdaea599..7c4e3b8f 100644 --- a/kmip/demos/pie/create.py +++ b/kmip/demos/pie/create.py @@ -21,7 +21,6 @@ from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/create_key_pair.py b/kmip/demos/pie/create_key_pair.py index d7e702a6..aea352c6 100644 --- a/kmip/demos/pie/create_key_pair.py +++ b/kmip/demos/pie/create_key_pair.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/decrypt.py b/kmip/demos/pie/decrypt.py index f1764e8b..83bd24d1 100644 --- a/kmip/demos/pie/decrypt.py +++ b/kmip/demos/pie/decrypt.py @@ -37,7 +37,6 @@ # INFO - Successfully decrypted the message. # INFO - Plain text: 'My test message.' - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/delete_attribute.py b/kmip/demos/pie/delete_attribute.py index 1a442a5e..c39c2172 100644 --- a/kmip/demos/pie/delete_attribute.py +++ b/kmip/demos/pie/delete_attribute.py @@ -21,7 +21,6 @@ from kmip.pie import client - # NOTE: This demo script shows how to delete the first Name attribute from # the user-specified object. The object *must* have at least one Name # attribute for attribute deletion to work. Otherwise, the client diff --git a/kmip/demos/pie/derive_key.py b/kmip/demos/pie/derive_key.py index f66e7e9e..837b5644 100644 --- a/kmip/demos/pie/derive_key.py +++ b/kmip/demos/pie/derive_key.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/destroy.py b/kmip/demos/pie/destroy.py index 03022821..b88b63c2 100644 --- a/kmip/demos/pie/destroy.py +++ b/kmip/demos/pie/destroy.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/encrypt.py b/kmip/demos/pie/encrypt.py index 4a84ffec..8a7f207c 100644 --- a/kmip/demos/pie/encrypt.py +++ b/kmip/demos/pie/encrypt.py @@ -37,7 +37,6 @@ # INFO - Successfully decrypted the message. # INFO - Plain text: 'My test message.' - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/get.py b/kmip/demos/pie/get.py index aaa89625..2ea725a8 100644 --- a/kmip/demos/pie/get.py +++ b/kmip/demos/pie/get.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/get_attribute_list.py b/kmip/demos/pie/get_attribute_list.py index 2c25c1b5..11291313 100644 --- a/kmip/demos/pie/get_attribute_list.py +++ b/kmip/demos/pie/get_attribute_list.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/get_attributes.py b/kmip/demos/pie/get_attributes.py index c45d79e5..3019ee1d 100644 --- a/kmip/demos/pie/get_attributes.py +++ b/kmip/demos/pie/get_attributes.py @@ -20,7 +20,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/locate.py b/kmip/demos/pie/locate.py index 7aedce11..e190dcd6 100644 --- a/kmip/demos/pie/locate.py +++ b/kmip/demos/pie/locate.py @@ -23,7 +23,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/mac.py b/kmip/demos/pie/mac.py index b5288edf..1f6a9b6a 100644 --- a/kmip/demos/pie/mac.py +++ b/kmip/demos/pie/mac.py @@ -21,7 +21,6 @@ from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/modify_attribute.py b/kmip/demos/pie/modify_attribute.py index c514db7c..8c4fb655 100644 --- a/kmip/demos/pie/modify_attribute.py +++ b/kmip/demos/pie/modify_attribute.py @@ -22,7 +22,6 @@ from kmip.pie import client - # NOTE: This demo script shows how to modify the first Name attribute on # the user-specified object. The object *must* have at least one Name # attribute for attribute modification to work. Otherwise, the client diff --git a/kmip/demos/pie/register_certificate.py b/kmip/demos/pie/register_certificate.py index 5f2aca73..9af7c61e 100644 --- a/kmip/demos/pie/register_certificate.py +++ b/kmip/demos/pie/register_certificate.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_opaque_object.py b/kmip/demos/pie/register_opaque_object.py index 48cf48cd..f31bd05e 100644 --- a/kmip/demos/pie/register_opaque_object.py +++ b/kmip/demos/pie/register_opaque_object.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_private_key.py b/kmip/demos/pie/register_private_key.py index e6f62b03..e4460f59 100644 --- a/kmip/demos/pie/register_private_key.py +++ b/kmip/demos/pie/register_private_key.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_public_key.py b/kmip/demos/pie/register_public_key.py index 17469a75..d1747fd3 100644 --- a/kmip/demos/pie/register_public_key.py +++ b/kmip/demos/pie/register_public_key.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_secret_data.py b/kmip/demos/pie/register_secret_data.py index 86d5f780..b8c26624 100644 --- a/kmip/demos/pie/register_secret_data.py +++ b/kmip/demos/pie/register_secret_data.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. - import logging import sys @@ -23,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_split_key.py b/kmip/demos/pie/register_split_key.py index 0ae6476f..8cfe8d7a 100644 --- a/kmip/demos/pie/register_split_key.py +++ b/kmip/demos/pie/register_split_key.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/register_symmetric_key.py b/kmip/demos/pie/register_symmetric_key.py index 5234e6d3..483e57c7 100644 --- a/kmip/demos/pie/register_symmetric_key.py +++ b/kmip/demos/pie/register_symmetric_key.py @@ -22,7 +22,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/revoke.py b/kmip/demos/pie/revoke.py index 2d418584..3fe8d403 100644 --- a/kmip/demos/pie/revoke.py +++ b/kmip/demos/pie/revoke.py @@ -21,7 +21,6 @@ from kmip.demos import utils from kmip.pie import client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/set_attribute.py b/kmip/demos/pie/set_attribute.py index 8267ddf8..7fb21bf6 100644 --- a/kmip/demos/pie/set_attribute.py +++ b/kmip/demos/pie/set_attribute.py @@ -22,7 +22,6 @@ from kmip.pie import client - # NOTE: This demo script shows how to set the Sensitive attribute on # the user-specified object. The server must support KMIP 2.0, since # the SetAttribute operation is KMIP 2.0+ only and the Sensitive diff --git a/kmip/demos/pie/sign.py b/kmip/demos/pie/sign.py index 291de5f0..ceb60d10 100644 --- a/kmip/demos/pie/sign.py +++ b/kmip/demos/pie/sign.py @@ -21,7 +21,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/pie/signature_verify.py b/kmip/demos/pie/signature_verify.py index 18010e77..bd5e5354 100644 --- a/kmip/demos/pie/signature_verify.py +++ b/kmip/demos/pie/signature_verify.py @@ -21,7 +21,6 @@ from kmip.pie import client from kmip.pie import objects - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/activate.py b/kmip/demos/units/activate.py index 27796e7a..c58b78fe 100644 --- a/kmip/demos/units/activate.py +++ b/kmip/demos/units/activate.py @@ -23,7 +23,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/create.py b/kmip/demos/units/create.py index bfd21095..95ac242c 100644 --- a/kmip/demos/units/create.py +++ b/kmip/demos/units/create.py @@ -38,7 +38,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/create_key_pair.py b/kmip/demos/units/create_key_pair.py index cb308de3..ca9a9db3 100644 --- a/kmip/demos/units/create_key_pair.py +++ b/kmip/demos/units/create_key_pair.py @@ -38,7 +38,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/destroy.py b/kmip/demos/units/destroy.py index bedaa00e..aaa6b1f6 100644 --- a/kmip/demos/units/destroy.py +++ b/kmip/demos/units/destroy.py @@ -27,7 +27,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/discover_versions.py b/kmip/demos/units/discover_versions.py index 4a63deed..9708e45d 100644 --- a/kmip/demos/units/discover_versions.py +++ b/kmip/demos/units/discover_versions.py @@ -26,7 +26,6 @@ import sys import re - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/get.py b/kmip/demos/units/get.py index 8db8c836..12be2eb3 100644 --- a/kmip/demos/units/get.py +++ b/kmip/demos/units/get.py @@ -30,7 +30,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/locate.py b/kmip/demos/units/locate.py index 92460e33..6c276e2a 100644 --- a/kmip/demos/units/locate.py +++ b/kmip/demos/units/locate.py @@ -24,7 +24,6 @@ from kmip.demos import utils from kmip.services import kmip_client - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/query.py b/kmip/demos/units/query.py index e6b5cb77..7f22f085 100644 --- a/kmip/demos/units/query.py +++ b/kmip/demos/units/query.py @@ -16,15 +16,12 @@ import logging import sys -from six.moves import xrange - from kmip.core import enums from kmip.demos import utils from kmip.services.kmip_client import KMIPProxy - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) @@ -69,12 +66,12 @@ logger.info('number of operations supported: {0}'.format( len(operations))) - for i in xrange(len(operations)): + for i in range(len(operations)): logger.info('operation supported: {0}'.format(operations[i])) logger.info('number of object types supported: {0}'.format( len(object_types))) - for i in xrange(len(object_types)): + for i in range(len(object_types)): logger.info('object type supported: {0}'.format(object_types[i])) logger.info('vendor identification: {0}'.format(vendor_identification)) @@ -82,13 +79,13 @@ logger.info('number of application namespaces supported: {0}'.format( len(application_namespaces))) - for i in xrange(len(application_namespaces)): + for i in range(len(application_namespaces)): logger.info('application namespace supported: {0}'.format( application_namespaces[i])) logger.info('number of extensions supported: {0}'.format( len(extension_information))) - for i in xrange(len(extension_information)): + for i in range(len(extension_information)): logger.info('extension supported: {0}'.format( extension_information[i])) diff --git a/kmip/demos/units/register.py b/kmip/demos/units/register.py index f5d11adf..f8873f27 100644 --- a/kmip/demos/units/register.py +++ b/kmip/demos/units/register.py @@ -29,7 +29,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/units/revoke.py b/kmip/demos/units/revoke.py index 5a6b7549..63950565 100644 --- a/kmip/demos/units/revoke.py +++ b/kmip/demos/units/revoke.py @@ -24,7 +24,6 @@ import logging import sys - if __name__ == '__main__': logger = utils.build_console_logger(logging.INFO) diff --git a/kmip/demos/utils.py b/kmip/demos/utils.py index 18211d34..62f00cd9 100644 --- a/kmip/demos/utils.py +++ b/kmip/demos/utils.py @@ -43,7 +43,6 @@ from kmip.core.secrets import SymmetricKey from kmip.core.secrets import SecretData - def build_console_logger(level): logger = logging.getLogger('demo') logger.setLevel(level) @@ -55,7 +54,6 @@ def build_console_logger(level): logger.addHandler(handler) return logger - def build_cli_parser(operation): # Build the argument parser and setup expected options parser = optparse.OptionParser( @@ -458,7 +456,6 @@ def build_cli_parser(operation): ) return parser - def build_cryptographic_usage_mask(logger, object_type): if object_type == ObjectType.CERTIFICATE: flags = [CryptographicUsageMask.ENCRYPT, @@ -482,7 +479,6 @@ def build_cryptographic_usage_mask(logger, object_type): return usage_mask - def build_object(logger, object_type, key_format_type): if object_type == ObjectType.CERTIFICATE: @@ -493,7 +489,6 @@ def build_object(logger, object_type, key_format_type): else: return build_key(logger, object_type, key_format_type) - def build_key(logger, object_type, key_format_type): key_value = build_secret_value(logger, object_type) @@ -521,7 +516,6 @@ def build_key(logger, object_type, key_format_type): logger.error("Unrecognized object type, could not build key") sys.exit() - def build_cryptographic_length(logger, object_type): if (object_type == ObjectType.SYMMETRIC_KEY or object_type == ObjectType.SECRET_DATA): @@ -535,7 +529,6 @@ def build_cryptographic_length(logger, object_type): "length") sys.exit() - def build_cryptographic_algorithm(logger, object_type): if (object_type == ObjectType.SYMMETRIC_KEY or object_type == ObjectType.SECRET_DATA): @@ -549,7 +542,6 @@ def build_cryptographic_algorithm(logger, object_type): "algorithm") sys.exit() - def build_secret_value(logger, object_type): if object_type == ObjectType.CERTIFICATE: # Encoding from Section 13.2 of the KMIP 1.1 Test Cases document. @@ -675,7 +667,6 @@ def build_secret_value(logger, object_type): logger.error("Unrecognized object type, could not build secret value") sys.exit() - def build_key_block(key_format_type, key_value, cryptographic_algorithm, cryptographic_length): key_material = KeyMaterial(key_value) @@ -689,7 +680,6 @@ def build_key_block(key_format_type, key_value, cryptographic_algorithm, cryptographic_length=cryptographic_length, key_wrapping_data=None) - def log_template_attribute(logger, template_attribute): names = template_attribute.names attributes = template_attribute.attributes @@ -701,7 +691,6 @@ def log_template_attribute(logger, template_attribute): log_attribute_list(logger, attributes) - def log_attribute_list(logger, attributes): logger.info('number of attributes: {0}'.format(len(attributes))) for i in range(len(attributes)): @@ -716,7 +705,6 @@ def log_attribute_list(logger, attributes): logger.info(' attribute_value: {0}'.format( repr(attribute_value))) - def log_secret(logger, secret_type, secret_value): if secret_type is ObjectType.CERTIFICATE: log_certificate(logger, secret_value) @@ -731,7 +719,6 @@ def log_secret(logger, secret_type, secret_value): else: logger.info('generic secret: {0}'.format(secret_value)) - def log_certificate(logger, certificate): logger.info('certificate:') logger.info('* certificate type: {0}'.format( @@ -739,25 +726,21 @@ def log_certificate(logger, certificate): logger.info('* certificate value: {0}'.format( binascii.hexlify(certificate.certificate_value.value))) - def log_public_key(logger, public_key): key_block = public_key.key_block log_key_block(logger, key_block) - def log_private_key(logger, private_key): key_block = private_key.key_block log_key_block(logger, key_block) - def log_symmetric_key(logger, skey): key_block = skey.key_block log_key_block(logger, key_block) - def log_split_key(logger, split_key): logger.info("Split Key:") logger.info("* Split Key Parts: {}".format(split_key.split_key_parts)) @@ -771,7 +754,6 @@ def log_split_key(logger, split_key): logger.info("* Prime Field Size: {}".format(split_key.prime_field_size)) log_key_block(logger, split_key.key_block) - def log_key_block(logger, key_block): if key_block is not None: logger.info("* Key Block:") @@ -796,7 +778,6 @@ def log_key_block(logger, key_block): else: logger.info("* Key Block: {}".format(key_block)) - def log_key_value(logger, key_value): if key_value is not None: logger.info(" * Key Value:") diff --git a/kmip/pie/__init__.py b/kmip/pie/__init__.py index f3e3d0b0..2817cd9b 100644 --- a/kmip/pie/__init__.py +++ b/kmip/pie/__init__.py @@ -15,7 +15,6 @@ from kmip.pie.client import ProxyKmipClient - __all__ = [ "ProxyKmipClient" ] diff --git a/kmip/pie/client.py b/kmip/pie/client.py index 1e7629ca..45343c3c 100644 --- a/kmip/pie/client.py +++ b/kmip/pie/client.py @@ -14,7 +14,6 @@ # under the License. import logging -import six from kmip.core import enums from kmip.core import primitives @@ -33,7 +32,6 @@ from kmip.services.kmip_client import KMIPProxy - def is_connected(function): def wrapper(self, *args, **kwargs): if not self._is_open: @@ -41,7 +39,6 @@ def wrapper(self, *args, **kwargs): return function(self, *args, **kwargs) return wrapper - class ProxyKmipClient(object): """ A simplified KMIP client for conducting KMIP operations. @@ -218,7 +215,6 @@ def create(self, algorithm, length, operation_policy_name=None, name=None, crypt TypeError: if the input arguments are invalid """ - # Check inputs # TODO (peter-hamilton) Add better input validation checks. from kmip.core.enums import CryptographicAlgorithm as CoreAlgorithm @@ -235,7 +231,7 @@ def create(self, algorithm, length, operation_policy_name=None, name=None, crypt # raise TypeError( # "algorithm must be a CryptographicAlgorithm enumeration") - elif not isinstance(length, six.integer_types) or length <= 0: + elif not isinstance(length, int) or length <= 0: raise TypeError("length must be a positive integer") if cryptographic_usage_mask is not None: if not isinstance(cryptographic_usage_mask, list) or \ @@ -318,7 +314,7 @@ def create_key_pair(self, if not isinstance(algorithm, enums.CryptographicAlgorithm): raise TypeError( "algorithm must be a CryptographicAlgorithm enumeration") - elif not isinstance(length, six.integer_types) or length <= 0: + elif not isinstance(length, int) or length <= 0: raise TypeError("length must be a positive integer") # Create the common attributes that are shared @@ -624,10 +620,10 @@ def rekey(self, TypeError: if the input arguments are invalid """ if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("The unique identifier must be a string.") if offset is not None: - if not isinstance(offset, six.integer_types): + if not isinstance(offset, int): raise TypeError("The offset must be an integer.") # TODO (peter-hamilton) Unify attribute handling across operations @@ -748,7 +744,7 @@ def derive_key(self, raise TypeError("Unique identifiers must be a list of strings.") else: for unique_identifier in unique_identifiers: - if not isinstance(unique_identifier, six.string_types): + if not isinstance(unique_identifier, str): raise TypeError( "Unique identifiers must be a list of strings." ) @@ -846,13 +842,13 @@ def locate(self, maximum_items=None, storage_status_mask=None, """ # Check inputs if maximum_items is not None: - if not isinstance(maximum_items, six.integer_types): + if not isinstance(maximum_items, int): raise TypeError("maximum_items must be an integer") if offset_items is not None: - if not isinstance(offset_items, six.integer_types): + if not isinstance(offset_items, int): raise TypeError("offset items must be an integer") if storage_status_mask is not None: - if not isinstance(storage_status_mask, six.integer_types): + if not isinstance(storage_status_mask, int): raise TypeError("storage_status_mask must be an integer") if object_group_member is not None: if not isinstance(object_group_member, enums.ObjectGroupMember): @@ -904,10 +900,10 @@ def check(self, specified managed object. Optional, defaults to None. """ if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("The unique identifier must be a string.") if usage_limits_count is not None: - if not isinstance(usage_limits_count, six.integer_types): + if not isinstance(usage_limits_count, int): raise TypeError("The usage limits count must be an integer.") if cryptographic_usage_mask is not None: if not isinstance(cryptographic_usage_mask, list) or \ @@ -920,7 +916,7 @@ def check(self, "CryptographicUsageMask enumerations." ) if lease_time is not None: - if not isinstance(lease_time, six.integer_types): + if not isinstance(lease_time, int): raise TypeError("The lease time must be an integer.") result = self.proxy.check( @@ -986,7 +982,7 @@ def get(self, uid=None, key_wrapping_specification=None): """ # Check input if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if key_wrapping_specification is not None: if not isinstance(key_wrapping_specification, dict): @@ -1031,14 +1027,14 @@ def get_attributes(self, uid=None, attribute_names=None): """ # Check input if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if attribute_names is not None: if not isinstance(attribute_names, list): raise TypeError("attribute_names must be a list of strings") else: for attribute_name in attribute_names: - if not isinstance(attribute_name, six.string_types): + if not isinstance(attribute_name, str): raise TypeError( "attribute_names must be a list of strings" ) @@ -1069,7 +1065,7 @@ def get_attribute_list(self, uid=None): """ # Check input if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") # Get the list of attribute names for a managed object. @@ -1103,7 +1099,7 @@ def activate(self, uid=None): """ # Check input if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") # Activate the managed object and handle the results @@ -1148,13 +1144,13 @@ def revoke(self, revocation_reason, uid=None, revocation_message=None, raise TypeError( "revocation_reason must be a RevocationReasonCode enumeration") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if revocation_message is not None: - if not isinstance(revocation_message, six.string_types): + if not isinstance(revocation_message, str): raise TypeError("revocation_message must be a string") if compromise_occurrence_date is not None: - if not isinstance(compromise_occurrence_date, six.integer_types): + if not isinstance(compromise_occurrence_date, int): raise TypeError( "compromise_occurrence_date must be an integer") compromise_occurrence_date = primitives.DateTime( @@ -1191,7 +1187,7 @@ def destroy(self, uid=None): """ # Check input if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") # Destroy the managed object and handle the results @@ -1278,16 +1274,16 @@ def encrypt(self, data, uid=None, cryptographic_parameters=None, | mode (typically 1). """ # Check input - if not isinstance(data, six.binary_type): + if not isinstance(data, bytes): raise TypeError("data must be bytes") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if cryptographic_parameters is not None: if not isinstance(cryptographic_parameters, dict): raise TypeError("cryptographic_parameters must be a dict") if iv_counter_nonce is not None: - if not isinstance(iv_counter_nonce, six.binary_type): + if not isinstance(iv_counter_nonce, bytes): raise TypeError("iv_counter_nonce must be bytes") cryptographic_parameters = self._build_cryptographic_parameters( @@ -1383,16 +1379,16 @@ def decrypt(self, data, uid=None, cryptographic_parameters=None, | mode (typically 1). """ # Check input - if not isinstance(data, six.binary_type): + if not isinstance(data, bytes): raise TypeError("data must be bytes") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if cryptographic_parameters is not None: if not isinstance(cryptographic_parameters, dict): raise TypeError("cryptographic_parameters must be a dict") if iv_counter_nonce is not None: - if not isinstance(iv_counter_nonce, six.binary_type): + if not isinstance(iv_counter_nonce, bytes): raise TypeError("iv_counter_nonce must be bytes") cryptographic_parameters = self._build_cryptographic_parameters( @@ -1448,12 +1444,12 @@ def signature_verify(self, message, signature, uid=None, see the documentation for encrypt/decrypt. """ # Check input - if not isinstance(message, six.binary_type): + if not isinstance(message, bytes): raise TypeError("Message must be bytes.") - if not isinstance(signature, six.binary_type): + if not isinstance(signature, bytes): raise TypeError("Signature must be bytes.") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("Unique identifier must be a string.") if cryptographic_parameters is not None: if not isinstance(cryptographic_parameters, dict): @@ -1506,10 +1502,10 @@ def sign(self, data, uid=None, cryptographic_parameters=None): TypeError: if the input arguments are invalid """ # Check input - if not isinstance(data, six.binary_type): + if not isinstance(data, bytes): raise TypeError("Data to be signed must be bytes.") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("Unique identifier must be a string.") if cryptographic_parameters is not None: if not isinstance(cryptographic_parameters, dict): @@ -1561,10 +1557,10 @@ def mac(self, data, uid=None, algorithm=None): TypeError: if the input arguments are invalid """ # Check inputs - if not isinstance(data, six.binary_type): + if not isinstance(data, bytes): raise TypeError("data must be bytes") if uid is not None: - if not isinstance(uid, six.string_types): + if not isinstance(uid, str): raise TypeError("uid must be a string") if algorithm is not None: if not isinstance(algorithm, enums.CryptographicAlgorithm): diff --git a/kmip/pie/exceptions.py b/kmip/pie/exceptions.py index 27e845d6..7433e1b2 100644 --- a/kmip/pie/exceptions.py +++ b/kmip/pie/exceptions.py @@ -13,14 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. - class ClientConnectionFailure(Exception): """ An exception raised for errors with the client socket connection. """ pass - class ClientConnectionNotOpen(Exception): """ An exception raised when operations are issued to a closed connection. @@ -32,7 +30,6 @@ def __init__(self): super(ClientConnectionNotOpen, self).__init__( "client connection not open") - class KmipOperationFailure(Exception): """ An exception raised upon the failure of a KMIP appliance operation. diff --git a/kmip/pie/factory.py b/kmip/pie/factory.py index c9861938..4fd4b839 100644 --- a/kmip/pie/factory.py +++ b/kmip/pie/factory.py @@ -21,7 +21,6 @@ from kmip.pie import objects as pobjects - class ObjectFactory: """ A factory to convert between the Pie and core object hierarchies. diff --git a/kmip/pie/objects.py b/kmip/pie/objects.py index 4089ebbb..b68b3851 100644 --- a/kmip/pie/objects.py +++ b/kmip/pie/objects.py @@ -20,12 +20,10 @@ from sqlalchemy.ext.associationproxy import association_proxy import binascii -import six from kmip.core import enums from kmip.pie import sqltypes as sql - app_specific_info_map = sqlalchemy.Table( "app_specific_info_map", sql.Base.metadata, @@ -47,7 +45,6 @@ ) ) - object_group_map = sqlalchemy.Table( "object_group_map", sql.Base.metadata, @@ -69,7 +66,6 @@ ) ) - class ManagedObject(sql.Base): """ The abstract base class of the simplified KMIP object hierarchy. @@ -204,7 +200,6 @@ def __eq__(self, other): def __ne__(self, other): pass - class CryptographicObject(ManagedObject): """ The abstract base class of all ManagedObjects related to cryptography. @@ -261,7 +256,6 @@ def __init__(self): self._links = list() self._revocation_reason = None - class Key(CryptographicObject): """ The abstract base class of all ManagedObjects that are cryptographic keys. @@ -624,7 +618,6 @@ def key_wrapping_data(self, value): self._kdw_iv_counter_nonce = value.get('iv_counter_nonce') self._kdw_encoding_option = value.get('encoding_option') - class SymmetricKey(Key): """ The SymmetricKey class of the simplified KMIP object hierarchy. @@ -721,7 +714,7 @@ def validate(self): enums.CryptographicAlgorithm): raise TypeError("key algorithm must be a CryptographicAlgorithm " "enumeration") - elif not isinstance(self.cryptographic_length, six.integer_types): + elif not isinstance(self.cryptographic_length, int): raise TypeError("key length must be an integer") mask_count = len(self.cryptographic_usage_masks) @@ -736,7 +729,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("key name {0} must be a string".format( position)) @@ -789,11 +782,9 @@ def __ne__(self, other): else: 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. @@ -895,7 +886,7 @@ def validate(self): enums.CryptographicAlgorithm): raise TypeError("key algorithm must be a CryptographicAlgorithm " "enumeration") - elif not isinstance(self.cryptographic_length, six.integer_types): + elif not isinstance(self.cryptographic_length, int): raise TypeError("key length must be an integer") elif not isinstance(self.key_format_type, enums.KeyFormatType): raise TypeError("key format type must be a KeyFormatType " @@ -918,7 +909,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("key name {0} must be a string".format( position)) @@ -961,11 +952,9 @@ def __ne__(self, other): else: return NotImplemented - event.listen(PublicKey._names, 'append', sql.attribute_append_factory("name_index"), retval=False) - class PrivateKey(Key): """ The PrivateKey class of the simplified KMIP object hierarchy. @@ -1066,7 +1055,7 @@ def validate(self): enums.CryptographicAlgorithm): raise TypeError("key algorithm must be a CryptographicAlgorithm " "enumeration") - elif not isinstance(self.cryptographic_length, six.integer_types): + elif not isinstance(self.cryptographic_length, int): raise TypeError("key length must be an integer") elif not isinstance(self.key_format_type, enums.KeyFormatType): raise TypeError("key format type must be a KeyFormatType " @@ -1089,7 +1078,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("key name {0} must be a string".format( position)) @@ -1132,11 +1121,9 @@ def __ne__(self, other): else: return NotImplemented - event.listen(PrivateKey._names, 'append', sql.attribute_append_factory("name_index"), retval=False) - class SplitKey(Key): """ """ @@ -1249,7 +1236,7 @@ def split_key_parts(self): @split_key_parts.setter def split_key_parts(self, value): - if (value is None) or (isinstance(value, six.integer_types)): + if (value is None) or (isinstance(value, int)): self._split_key_parts = value else: raise TypeError("The split key parts must be an integer.") @@ -1260,7 +1247,7 @@ def key_part_identifier(self): @key_part_identifier.setter def key_part_identifier(self, value): - if (value is None) or (isinstance(value, six.integer_types)): + if (value is None) or (isinstance(value, int)): self._key_part_identifier = value else: raise TypeError("The key part identifier must be an integer.") @@ -1271,7 +1258,7 @@ def split_key_threshold(self): @split_key_threshold.setter def split_key_threshold(self, value): - if (value is None) or (isinstance(value, six.integer_types)): + if (value is None) or (isinstance(value, int)): self._split_key_threshold = value else: raise TypeError("The split key threshold must be an integer.") @@ -1295,7 +1282,7 @@ def prime_field_size(self): @prime_field_size.setter def prime_field_size(self, value): - if (value is None) or (isinstance(value, six.integer_types)): + if (value is None) or (isinstance(value, int)): self._prime_field_size = value else: raise TypeError("The prime field size must be an integer.") @@ -1386,7 +1373,6 @@ def __ne__(self, other): else: return NotImplemented - event.listen( SplitKey._names, "append", @@ -1394,7 +1380,6 @@ def __ne__(self, other): retval=False ) - class Certificate(CryptographicObject): """ The Certificate class of the simplified KMIP object hierarchy. @@ -1489,7 +1474,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("certificate name {0} must be a string".format( position)) @@ -1497,7 +1482,6 @@ def validate(self): def __str__(self): return str(binascii.hexlify(self.value)) - class X509Certificate(Certificate): """ The X509Certificate class of the simplified KMIP object hierarchy. @@ -1570,11 +1554,9 @@ def __ne__(self, other): else: return NotImplemented - event.listen(X509Certificate._names, 'append', sql.attribute_append_factory("name_index"), retval=False) - class SecretData(CryptographicObject): """ The SecretData class of the simplified KMIP object hierarchy. @@ -1664,7 +1646,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("secret data name {0} must be a string".format( position)) @@ -1695,11 +1677,9 @@ def __ne__(self, other): else: return NotImplemented - event.listen(SecretData._names, 'append', sql.attribute_append_factory("name_index"), retval=False) - class OpaqueObject(ManagedObject): """ The OpaqueObject class of the simplified KMIP object hierarchy. @@ -1771,7 +1751,7 @@ def validate(self): name_count = len(self.names) for i in range(name_count): name = self.names[i] - if not isinstance(name, six.string_types): + if not isinstance(name, str): position = "({0} in list)".format(i) raise TypeError("opaque data name {0} must be a string".format( position)) @@ -1802,11 +1782,9 @@ def __ne__(self, other): else: return NotImplemented - event.listen(OpaqueObject._names, 'append', sql.attribute_append_factory("name_index"), retval=False) - class ApplicationSpecificInformation(sql.Base): __tablename__ = "app_specific_info" id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) @@ -1847,7 +1825,7 @@ def application_namespace(self): @application_namespace.setter def application_namespace(self, value): - if (value is None) or (isinstance(value, six.string_types)): + if (value is None) or (isinstance(value, str)): self._application_namespace = value else: raise TypeError("The application namespace must be a string.") @@ -1858,7 +1836,7 @@ def application_data(self): @application_data.setter def application_data(self, value): - if (value is None) or (isinstance(value, six.string_types)): + if (value is None) or (isinstance(value, str)): self._application_data = value else: raise TypeError("The application data must be a string.") @@ -1905,7 +1883,6 @@ def __ne__(self, other): else: return NotImplemented - class ObjectGroup(sql.Base): __tablename__ = "object_groups" id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) @@ -1937,7 +1914,7 @@ def object_group(self): @object_group.setter def object_group(self, value): - if (value is None) or (isinstance(value, six.string_types)): + if (value is None) or (isinstance(value, str)): self._object_group = value else: raise TypeError("The object group must be a string.") diff --git a/kmip/pie/sqltypes.py b/kmip/pie/sqltypes.py index 6b27616a..6d2bee60 100644 --- a/kmip/pie/sqltypes.py +++ b/kmip/pie/sqltypes.py @@ -20,10 +20,8 @@ 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) @@ -32,7 +30,6 @@ def attribute_append(list_container, list_attribute, initiator): return list_attribute return attribute_append - class UsageMaskType(types.TypeDecorator): """ Converts a list of enums.CryptographicUsageMask Enums in an integer @@ -75,7 +72,6 @@ def process_result_value(self, value, dialect): masks.append(e) return masks - class EnumType(types.TypeDecorator): """ Converts a Python enum to an integer before storing it in the database. @@ -127,7 +123,6 @@ def process_result_value(self, value, dialect): return None return self._cls(value) - class ManagedObjectName(Base): __tablename__ = 'managed_object_names' diff --git a/kmip/services/auth.py b/kmip/services/auth.py index a53af297..1f643220 100644 --- a/kmip/services/auth.py +++ b/kmip/services/auth.py @@ -14,12 +14,10 @@ # under the License. import abc -import six -import ssl +import ssl -@six.add_metaclass(abc.ABCMeta) -class AuthenticationSuite(object): +class AuthenticationSuite(metaclass=abc.ABCMeta): """ An authentication suite used to establish secure network connections. @@ -150,7 +148,6 @@ def ciphers(self): """ return self._cipher_suites - class BasicAuthenticationSuite(AuthenticationSuite): """ An authentication suite used to establish secure network connections. @@ -186,7 +183,6 @@ def __init__(self, cipher_suites=None): super(BasicAuthenticationSuite, self).__init__(cipher_suites) self._protocol = ssl.PROTOCOL_TLSv1 - class TLS12AuthenticationSuite(AuthenticationSuite): """ An authentication suite used to establish secure network connections. diff --git a/kmip/services/kmip_client.py b/kmip/services/kmip_client.py index 7f72adf7..27fc1950 100644 --- a/kmip/services/kmip_client.py +++ b/kmip/services/kmip_client.py @@ -64,7 +64,7 @@ import logging import logging.config import os -import six + import socket import ssl import sys @@ -72,7 +72,6 @@ FILE_PATH = os.path.dirname(os.path.abspath(__file__)) CONFIG_FILE = os.path.normpath(os.path.join(FILE_PATH, '../kmipconfig.ini')) - class KMIPProxy(object): def __init__(self, host=None, port=None, keyfile=None, @@ -98,11 +97,17 @@ def __init__(self, host=None, port=None, keyfile=None, self.kmip_version = enums.KMIPVersion.KMIP_1_2 if config_file: - if not isinstance(config_file, six.string_types): + if not isinstance(config_file, str): raise ValueError( "The client configuration file argument must be a string." ) - if not os.path.exists(config_file): + normalized_path = os.path.normcase(os.path.normpath(config_file)) + devnull_paths = { + os.path.normcase(os.path.normpath(os.devnull)), + os.path.normcase(os.path.normpath('/dev/null')) + } + if normalized_path not in devnull_paths and not os.path.exists( + config_file): raise ValueError( "The client configuration file '{}' does not " "exist.".format(config_file) @@ -282,18 +287,39 @@ def open(self): self.socket = None if last_error: - six.reraise(*last_error) + exc = last_error[1] + tb = last_error[2] + if exc is None: + raise last_error[0] + raise exc.with_traceback(tb) def _create_socket(self, sock): - self.socket = ssl.wrap_socket( - sock, - keyfile=self.keyfile, - certfile=self.certfile, - cert_reqs=self.cert_reqs, - ssl_version=self.ssl_version, - ca_certs=self.ca_certs, - do_handshake_on_connect=self.do_handshake_on_connect, - suppress_ragged_eofs=self.suppress_ragged_eofs) + if hasattr(ssl, "wrap_socket"): + self.socket = ssl.wrap_socket( + sock, + keyfile=self.keyfile, + certfile=self.certfile, + cert_reqs=self.cert_reqs, + ssl_version=self.ssl_version, + ca_certs=self.ca_certs, + do_handshake_on_connect=self.do_handshake_on_connect, + suppress_ragged_eofs=self.suppress_ragged_eofs) + else: + context = ssl.SSLContext(self.ssl_version) + context.check_hostname = False + context.verify_mode = self.cert_reqs + if self.ca_certs: + context.load_verify_locations(self.ca_certs) + if self.certfile or self.keyfile: + context.load_cert_chain( + certfile=self.certfile, + keyfile=self.keyfile + ) + self.socket = context.wrap_socket( + sock, + do_handshake_on_connect=self.do_handshake_on_connect, + suppress_ragged_eofs=self.suppress_ragged_eofs + ) self.socket.settimeout(self.timeout) def __del__(self): diff --git a/kmip/services/kmip_protocol.py b/kmip/services/kmip_protocol.py index f0c57f35..05427ce0 100644 --- a/kmip/services/kmip_protocol.py +++ b/kmip/services/kmip_protocol.py @@ -20,7 +20,6 @@ from kmip.core.utils import BytearrayStream - class KMIPProtocol(object): HEADER_SIZE = 8 @@ -71,13 +70,11 @@ def _recv_all(self, total_bytes_to_be_read): return total_msg - class KMIPProtocolFactory(object): def getProtocol(self, socket): return KMIPProtocol(socket) - class RequestLengthMismatch(Exception): """ This exception raised when the request read from stream has unexpected diff --git a/kmip/services/results.py b/kmip/services/results.py index 96622d59..8647cc1f 100644 --- a/kmip/services/results.py +++ b/kmip/services/results.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. - class OperationResult(object): def __init__(self, @@ -32,7 +31,6 @@ def __init__(self, else: self.result_message = None - class CreateResult(OperationResult): def __init__(self, @@ -59,7 +57,6 @@ def __init__(self, else: self.template_attribute = None - class CreateKeyPairResult(OperationResult): def __init__(self, @@ -77,7 +74,6 @@ def __init__(self, self.private_key_template_attribute = private_key_template_attribute self.public_key_template_attribute = public_key_template_attribute - class ActivateResult(OperationResult): def __init__(self, @@ -93,7 +89,6 @@ def __init__(self, else: self.uuid = None - class RegisterResult(OperationResult): def __init__(self, @@ -114,7 +109,6 @@ def __init__(self, else: self.template_attribute = None - class RekeyKeyPairResult(CreateKeyPairResult): def __init__(self, @@ -130,7 +124,6 @@ def __init__(self, public_key_uuid, private_key_template_attribute, public_key_template_attribute) - class GetResult(OperationResult): def __init__(self, @@ -157,7 +150,6 @@ def __init__(self, else: self.secret = None - class GetAttributesResult(OperationResult): def __init__( @@ -176,7 +168,6 @@ def __init__( self.uuid = uuid self.attributes = attributes - class GetAttributeListResult(OperationResult): def __init__( @@ -191,7 +182,6 @@ def __init__( self.uid = uid self.names = names - class DestroyResult(OperationResult): def __init__(self, @@ -206,7 +196,6 @@ def __init__(self, else: self.uuid = None - class LocateResult(OperationResult): def __init__(self, @@ -218,7 +207,6 @@ def __init__(self, result_status, result_reason, result_message) self.uuids = uuids - class QueryResult(OperationResult): """ A container for the results of a Query operation. @@ -272,7 +260,6 @@ def __init__(self, else: self.extension_information = extension_information - class DiscoverVersionsResult(OperationResult): def __init__(self, @@ -284,7 +271,6 @@ def __init__(self, result_status, result_reason, result_message) self.protocol_versions = protocol_versions - class RevokeResult(OperationResult): def __init__(self, @@ -296,7 +282,6 @@ def __init__(self, result_status, result_reason, result_message) self.unique_identifier = unique_identifier - class MACResult(OperationResult): def __init__(self, diff --git a/kmip/services/server/__init__.py b/kmip/services/server/__init__.py index 30225d35..f53468b2 100644 --- a/kmip/services/server/__init__.py +++ b/kmip/services/server/__init__.py @@ -15,7 +15,6 @@ from kmip.services.server.server import KmipServer - __all__ = [ "KmipServer" ] diff --git a/kmip/services/server/auth/__init__.py b/kmip/services/server/auth/__init__.py index c4141a53..3dabcaab 100644 --- a/kmip/services/server/auth/__init__.py +++ b/kmip/services/server/auth/__init__.py @@ -23,7 +23,6 @@ from kmip.services.server.auth.utils import \ get_extended_key_usage_from_certificate - __all__ = [ 'AuthAPI', 'SLUGSConnector', diff --git a/kmip/services/server/auth/api.py b/kmip/services/server/auth/api.py index 536c8669..57c71e56 100644 --- a/kmip/services/server/auth/api.py +++ b/kmip/services/server/auth/api.py @@ -14,11 +14,8 @@ # under the License. import abc -import six - -@six.add_metaclass(abc.ABCMeta) -class AuthAPI: +class AuthAPI(metaclass=abc.ABCMeta): """ The base class for an authentication API connector. """ diff --git a/kmip/services/server/auth/slugs.py b/kmip/services/server/auth/slugs.py index 5046313a..88bb5b85 100644 --- a/kmip/services/server/auth/slugs.py +++ b/kmip/services/server/auth/slugs.py @@ -14,13 +14,11 @@ # under the License. import requests -import six from kmip.core import exceptions from kmip.services.server.auth import api from kmip.services.server.auth import utils - class SLUGSConnector(api.AuthAPI): """ An authentication API connector for a SLUGS service. @@ -50,7 +48,7 @@ def url(self, value): self._url = None self.users_url = None self.groups_url = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self._url = value if not self._url.endswith("/"): self._url += "/" diff --git a/kmip/services/server/auth/utils.py b/kmip/services/server/auth/utils.py index 072eb6d2..dc4f95a7 100644 --- a/kmip/services/server/auth/utils.py +++ b/kmip/services/server/auth/utils.py @@ -18,7 +18,6 @@ from kmip.core import exceptions - def get_certificate_from_connection(connection): """ Extract an X.509 certificate from a socket connection. @@ -31,7 +30,6 @@ def get_certificate_from_connection(connection): ) return None - def get_extended_key_usage_from_certificate(certificate): """ Given an X.509 certificate, extract and return the extendedKeyUsage @@ -44,7 +42,6 @@ def get_extended_key_usage_from_certificate(certificate): except x509.ExtensionNotFound: return None - def get_common_names_from_certificate(certificate): """ Given an X.509 certificate, extract and return all common names. @@ -55,7 +52,6 @@ def get_common_names_from_certificate(certificate): ) return [common_name.value for common_name in common_names] - def get_client_identity_from_certificate(certificate): """ Given an X.509 certificate, extract and return the client identity. diff --git a/kmip/services/server/config.py b/kmip/services/server/config.py index 912d980d..bc3c0d63 100644 --- a/kmip/services/server/config.py +++ b/kmip/services/server/config.py @@ -15,13 +15,10 @@ import logging import os -import six - -from six.moves import configparser +import configparser from kmip.core import exceptions - class KmipServerConfig(object): """ A configuration management tool for the KmipServer. @@ -186,7 +183,7 @@ def _parse_settings(self, parser): self._set_database_path(parser.get('server', 'database_path')) def _set_hostname(self, value): - if isinstance(value, six.string_types): + if isinstance(value, str): self.settings['hostname'] = value else: raise exceptions.ConfigurationError( @@ -194,7 +191,7 @@ def _set_hostname(self, value): ) def _set_port(self, value): - if isinstance(value, six.integer_types): + if isinstance(value, int): if 0 < value < 65535: self.settings['port'] = value else: @@ -209,7 +206,7 @@ def _set_port(self, value): def _set_certificate_path(self, value): if value is None: self.settings['certificate_path'] = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): if os.path.exists(value): self.settings['certificate_path'] = value else: @@ -226,7 +223,7 @@ def _set_certificate_path(self, value): def _set_key_path(self, value): if value is None: self.settings['key_path'] = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): if os.path.exists(value): self.settings['key_path'] = value else: @@ -243,7 +240,7 @@ def _set_key_path(self, value): def _set_ca_path(self, value): if value is None: self.settings['ca_path'] = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): if os.path.exists(value): self.settings['ca_path'] = value else: @@ -271,7 +268,7 @@ def _set_auth_suite(self, value): def _set_policy_path(self, value): if not value: self.settings['policy_path'] = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self.settings['policy_path'] = value else: raise exceptions.ConfigurationError( @@ -294,12 +291,12 @@ def _set_tls_cipher_suites(self, value): if not value: self.settings['tls_cipher_suites'] = [] return - if isinstance(value, six.string_types): + if isinstance(value, str): value = value.split() if isinstance(value, list): for entry in value: - if not isinstance(entry, six.string_types): + if not isinstance(entry, str): raise exceptions.ConfigurationError( "The TLS cipher suites must be a set of strings " "representing cipher suite names." @@ -325,7 +322,7 @@ def _set_logging_level(self, value): } if value in logging_levels.values(): self.settings['logging_level'] = value - elif isinstance(value, six.string_types): + elif isinstance(value, str): level = logging_levels.get(value.upper()) if level: self.settings['logging_level'] = level @@ -343,7 +340,7 @@ def _set_logging_level(self, value): def _set_database_path(self, value): if not value: self.settings['database_path'] = None - elif isinstance(value, six.string_types): + elif isinstance(value, str): self.settings['database_path'] = value else: raise exceptions.ConfigurationError( diff --git a/kmip/services/server/crypto/api.py b/kmip/services/server/crypto/api.py index b06e2bd9..c24dcec1 100644 --- a/kmip/services/server/crypto/api.py +++ b/kmip/services/server/crypto/api.py @@ -16,11 +16,7 @@ from abc import ABCMeta from abc import abstractmethod -import six - - -@six.add_metaclass(ABCMeta) -class CryptographicEngine(object): +class CryptographicEngine(metaclass=ABCMeta): """ The abstract base class of the cryptographic engine hierarchy. diff --git a/kmip/services/server/crypto/engine.py b/kmip/services/server/crypto/engine.py index 5b7cacaa..9a54323e 100644 --- a/kmip/services/server/crypto/engine.py +++ b/kmip/services/server/crypto/engine.py @@ -33,7 +33,6 @@ from kmip.core import exceptions from kmip.services.server.crypto import api - class CryptographyEngine(api.CryptographicEngine): """ A cryptographic engine that uses pyca/cryptography to generate diff --git a/kmip/services/server/engine.py b/kmip/services/server/engine.py index 43fdbe93..18a741ff 100644 --- a/kmip/services/server/engine.py +++ b/kmip/services/server/engine.py @@ -15,7 +15,9 @@ import copy import logging -import six +import os +import tempfile + import sqlalchemy from sqlalchemy.orm import exc @@ -29,7 +31,7 @@ from kmip.core import enums from kmip.core import exceptions -from kmip.core.objects import MACData, KeyWrappingData +from kmip.core.objects import KeyMaterial, KeyWrappingData, MACData from kmip.core.factories import attributes as attribute_factory from kmip.core.factories import secrets @@ -46,7 +48,6 @@ from kmip.services.server import policy from kmip.services.server.crypto import engine - class KmipEngine(object): """ A KMIP request processor that acts as the core of the KmipServer. @@ -88,9 +89,27 @@ def __init__(self, policies=None, database_path=None): self._cryptography_engine = engine.CryptographyEngine() - self.database_path = 'sqlite:///{}'.format(database_path) - if not database_path: - self.database_path = 'sqlite:////tmp/pykmip.database' + if database_path: + if database_path.startswith('sqlite:'): + self.database_path = database_path + elif database_path == ':memory:': + self.database_path = 'sqlite:///:memory:' + else: + db_path = os.path.abspath(database_path) + db_dir = os.path.dirname(db_path) + if db_dir: + os.makedirs(db_dir, exist_ok=True) + self.database_path = 'sqlite:///{}'.format( + db_path.replace('\\', '/') + ) + else: + db_path = os.path.join(tempfile.gettempdir(), 'pykmip.database') + db_dir = os.path.dirname(db_path) + if db_dir: + os.makedirs(db_dir, exist_ok=True) + self.database_path = 'sqlite:///{}'.format( + db_path.replace('\\', '/') + ) self._data_store = sqlalchemy.create_engine( self.database_path, @@ -847,7 +866,7 @@ def _set_attributes_on_managed_object(self, managed_object, attributes): Given a kmip.pie object and a dictionary of attributes, attempt to set the attribute values on the object. """ - for attribute_name, attribute_value in six.iteritems(attributes): + for attribute_name, attribute_value in attributes.items(): object_type = managed_object._object_type if self._attribute_policy.is_attribute_applicable_to_object_type( attribute_name, @@ -1446,7 +1465,7 @@ def _process_create_key_pair(self, payload): # Propagate common attributes if not overridden by the public/private # attribute sets - for key, value in six.iteritems(common_attributes): + for key, value in common_attributes.items(): if key not in public_key_attributes.keys(): public_key_attributes.update([(key, value)]) if key not in private_key_attributes.keys(): @@ -2436,11 +2455,20 @@ def _process_locate(self, payload): managed_objects = managed_objects_filtered - # Sort the matching results by their creation date. + # Sort by creation date (newest first) with a deterministic tie-breaker + # for equal timestamps. + def _locate_sort_key(obj): + initial_date = obj.initial_date or 0 + uid = obj.unique_identifier + try: + uid_key = (0, int(uid)) + except (TypeError, ValueError): + uid_key = (1, str(uid)) + return (-initial_date, uid_key) + managed_objects = sorted( managed_objects, - key=lambda x: x.initial_date, - reverse=True + key=_locate_sort_key ) # Skip the requested offset items and keep the requested maximum items @@ -2592,15 +2620,21 @@ def _process_get(self, payload): encryption_key=key.value ) - wrapped_object = copy.deepcopy(managed_object) - wrapped_object.value = result - - core_secret = self._build_core_object(wrapped_object) + core_secret = self._build_core_object(managed_object) key_wrapping_data = KeyWrappingData( wrapping_method=wrapping_method, encryption_key_information=key_info, encoding_option=encoding_option ) + if not hasattr(core_secret, 'key_block') or \ + core_secret.key_block is None or \ + core_secret.key_block.key_value is None: + raise exceptions.InvalidField( + "The requested object type does not support key " + "wrapping." + ) + core_secret.key_block.key_value.key_material = \ + KeyMaterial(result) core_secret.key_block.key_wrapping_data = key_wrapping_data elif key_wrapping_spec.mac_signature_key_information: diff --git a/kmip/services/server/monitor.py b/kmip/services/server/monitor.py index a3cd6b48..0a82d190 100644 --- a/kmip/services/server/monitor.py +++ b/kmip/services/server/monitor.py @@ -21,7 +21,6 @@ from kmip.core import policy as operation_policy - def get_json_files(p): """ Scan the provided policy directory for all JSON policy files. @@ -29,7 +28,6 @@ def get_json_files(p): f = [os.path.join(p, x) for x in os.listdir(p) if x.endswith(".json")] return sorted(f) - class PolicyDirectoryMonitor(multiprocessing.Process): """ A file monitor that tracks modifications made within the policy directory. diff --git a/kmip/services/server/policy.py b/kmip/services/server/policy.py index 400ffdfd..fa0786c6 100644 --- a/kmip/services/server/policy.py +++ b/kmip/services/server/policy.py @@ -16,7 +16,6 @@ from kmip.core import enums from kmip.core.messages import contents - class AttributeRuleSet(object): """ A set of flags and indicators defining how an attribute may be used. @@ -100,7 +99,6 @@ def __init__(self, self.version_added = version_added self.version_deprecated = version_deprecated - class AttributePolicy(object): """ A collection of attribute rules and methods to query those rules. diff --git a/kmip/services/server/server.py b/kmip/services/server/server.py index 534ab61d..419b004a 100644 --- a/kmip/services/server/server.py +++ b/kmip/services/server/server.py @@ -20,7 +20,7 @@ import optparse import os import signal -import six + import socket import ssl import sys @@ -34,6 +34,45 @@ from kmip.services.server import monitor from kmip.services.server import session +# Python 3.12 removed ssl.wrap_socket; provide a compatibility shim so the +# server and tests can still rely on the legacy API. +if not hasattr(ssl, 'wrap_socket'): + def _wrap_socket(sock, + keyfile=None, + certfile=None, + server_side=False, + cert_reqs=ssl.CERT_NONE, + ssl_version=None, + ca_certs=None, + do_handshake_on_connect=True, + suppress_ragged_eofs=True, + ciphers=None): + if ssl_version is None: + if server_side: + protocol = ssl.PROTOCOL_TLS_SERVER + else: + protocol = ssl.PROTOCOL_TLS_CLIENT + else: + protocol = ssl_version + + context = ssl.SSLContext(protocol) + context.verify_mode = cert_reqs + + if ca_certs: + context.load_verify_locations(ca_certs) + if certfile or keyfile: + context.load_cert_chain(certfile=certfile, keyfile=keyfile) + if ciphers: + context.set_ciphers(ciphers) + + return context.wrap_socket( + sock, + server_side=server_side, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs + ) + + ssl.wrap_socket = _wrap_socket class KmipServer(object): """ @@ -243,7 +282,7 @@ def start(self): self.manager = multiprocessing.Manager() self.policies = self.manager.dict() policies = copy.deepcopy(operation_policy.policies) - for policy_name, policy_set in six.iteritems(policies): + for policy_name, policy_set in policies.items(): self.policies[policy_name] = policy_set self.policy_monitor = monitor.PolicyDirectoryMonitor( @@ -479,7 +518,6 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, traceback): self.stop() - def build_argument_parser(): parser = optparse.OptionParser( usage="%prog [options]", @@ -634,7 +672,6 @@ def build_argument_parser(): return parser - def main(args=None): # Build argument parser and parser command-line arguments. parser = build_argument_parser() @@ -673,6 +710,5 @@ def main(args=None): with s: s.serve() - if __name__ == '__main__': main() diff --git a/kmip/services/server/session.py b/kmip/services/server/session.py index 887f1c83..e22a995d 100644 --- a/kmip/services/server/session.py +++ b/kmip/services/server/session.py @@ -31,7 +31,6 @@ from kmip.services.server import auth - class KmipSession(threading.Thread): """ A session thread representing a single KMIP client/server interaction. diff --git a/kmip/tests/functional/conftest.py b/kmip/tests/functional/conftest.py index 876a5b8d..c91ee04f 100644 --- a/kmip/tests/functional/conftest.py +++ b/kmip/tests/functional/conftest.py @@ -15,7 +15,6 @@ import pytest - def pytest_addoption(parser): parser.addoption( "--config-file", @@ -23,7 +22,6 @@ def pytest_addoption(parser): help="Config file path for client configuration settings" ) - @pytest.fixture(scope="class") def config_file(request): request.cls.config_file = request.config.getoption("--config-file") diff --git a/kmip/tests/functional/services/test_authentication.py b/kmip/tests/functional/services/test_authentication.py index 6f912eac..9f43a4b9 100644 --- a/kmip/tests/functional/services/test_authentication.py +++ b/kmip/tests/functional/services/test_authentication.py @@ -15,7 +15,7 @@ import os import pytest -import six + import testtools import time @@ -24,7 +24,6 @@ from kmip.pie import exceptions from kmip.pie import objects - @pytest.mark.usefixtures("config_file") class TestSLUGSAuthenticationAndAccessControl(testtools.TestCase): @@ -66,7 +65,7 @@ def test_group_level_access_control(self): 256, operation_policy_name="policy_1" ) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) key = c.get(uid) self.assertIsInstance(key, objects.SymmetricKey) @@ -116,7 +115,7 @@ def test_policy_live_loading(self): 256, operation_policy_name="policy_1" ) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) key = c.get(uid) self.assertIsInstance(key, objects.SymmetricKey) @@ -192,7 +191,7 @@ def test_policy_caching(self): 256, operation_policy_name="policy_1" ) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) key = c.get(uid) self.assertIsInstance(key, objects.SymmetricKey) diff --git a/kmip/tests/integration/conftest.py b/kmip/tests/integration/conftest.py index 1ecd50b8..5e5251db 100644 --- a/kmip/tests/integration/conftest.py +++ b/kmip/tests/integration/conftest.py @@ -18,7 +18,6 @@ from kmip.services import kmip_client from kmip.pie import client as pclient - def pytest_addoption(parser): parser.addoption( "--config", @@ -26,7 +25,6 @@ def pytest_addoption(parser): default="client", help="Config file section name for client configuration settings") - @pytest.fixture(scope="class") def client(request): config = request.config.getoption("--config") @@ -40,7 +38,6 @@ def finalize(): request.addfinalizer(finalize) request.cls.client = client - @pytest.fixture(scope="class") def simple(request): config = request.config.getoption("--config") diff --git a/kmip/tests/integration/services/test_integration.py b/kmip/tests/integration/services/test_integration.py index 901cc3c2..0e0859f6 100644 --- a/kmip/tests/integration/services/test_integration.py +++ b/kmip/tests/integration/services/test_integration.py @@ -57,7 +57,6 @@ from kmip.core.secrets import OpaqueObject from kmip.core.secrets import SplitKey - @pytest.mark.usefixtures("client") class TestIntegration(testtools.TestCase): diff --git a/kmip/tests/integration/services/test_kmip_client.py b/kmip/tests/integration/services/test_kmip_client.py index d4c24c2a..4336a82e 100644 --- a/kmip/tests/integration/services/test_kmip_client.py +++ b/kmip/tests/integration/services/test_kmip_client.py @@ -56,7 +56,6 @@ import kmip.core.utils as utils - @pytest.mark.ignore class TestKMIPClientIntegration(TestCase): STARTUP_TIME = 1.0 diff --git a/kmip/tests/integration/services/test_proxykmipclient.py b/kmip/tests/integration/services/test_proxykmipclient.py index 9af12636..f0920024 100644 --- a/kmip/tests/integration/services/test_proxykmipclient.py +++ b/kmip/tests/integration/services/test_proxykmipclient.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six import testtools import time import pytest @@ -25,7 +24,6 @@ from kmip.pie import factory from kmip.pie import objects - @pytest.mark.usefixtures("simple") class TestProxyKmipClientIntegration(testtools.TestCase): @@ -48,7 +46,7 @@ def test_symmetric_key_create_get_destroy(self): symmetric key. """ uid = self.client.create(enums.CryptographicAlgorithm.AES, 256) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: key = self.client.get(uid) @@ -124,7 +122,7 @@ def test_symmetric_key_register_get_destroy(self): ) uid = self.client.register(key) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -258,8 +256,8 @@ def test_asymmetric_key_pair_create_get_destroy(self): public_usage_mask=[enums.CryptographicUsageMask.ENCRYPT], private_usage_mask=[enums.CryptographicUsageMask.DECRYPT] ) - self.assertIsInstance(public_uid, six.string_types) - self.assertIsInstance(private_uid, six.string_types) + self.assertIsInstance(public_uid, str) + self.assertIsInstance(private_uid, str) try: public_key = self.client.get(public_uid) @@ -325,7 +323,7 @@ def test_public_key_register_get_destroy(self): enums.KeyFormatType.PKCS_1) uid = self.client.register(key) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -433,7 +431,7 @@ def test_private_key_register_get_destroy(self): enums.KeyFormatType.PKCS_8) uid = self.client.register(key) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -511,7 +509,7 @@ def test_x509_certificate_register_get_destroy(self): b'\xEB\x5F\x7E\xA8\x11\xEB\xB2\x5A\x7F\x86')) uid = self.client.register(cert) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -539,7 +537,7 @@ def test_secret_data_register_get_destroy(self): enums.SecretDataType.PASSWORD) uid = self.client.register(secret) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -578,7 +576,7 @@ def test_secret_data_register_get_destroy_app_specific(self): ) uid = self.client.register(secret) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -641,7 +639,7 @@ def test_opaque_object_register_get_destroy(self): b'\x53\x65\x63\x72\x65\x74\x50\x61\x73\x73\x77\x6F\x72\x64', enums.OpaqueDataType.NONE) uid = self.client.register(obj) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) @@ -987,7 +985,7 @@ def test_create_key_pair_sign_signature_verify(self): } ) - self.assertIsInstance(signature, six.binary_type) + self.assertIsInstance(signature, bytes) # Verify the message signature. result = self.client.signature_verify( @@ -1469,7 +1467,7 @@ def test_split_key_register_get_destroy(self): ) uid = self.client.register(key) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) try: result = self.client.get(uid) diff --git a/kmip/tests/unit/core/attributes/test_application_specific_information.py b/kmip/tests/unit/core/attributes/test_application_specific_information.py index f6e6794e..7760e722 100644 --- a/kmip/tests/unit/core/attributes/test_application_specific_information.py +++ b/kmip/tests/unit/core/attributes/test_application_specific_information.py @@ -19,7 +19,6 @@ from kmip.core import exceptions from kmip.core import utils - class TestApplicationSpecificInformation(testtools.TestCase): """ A test suite for the ApplicationSpecificInformation class. diff --git a/kmip/tests/unit/core/attributes/test_attributes.py b/kmip/tests/unit/core/attributes/test_attributes.py index 82b44556..2d817758 100644 --- a/kmip/tests/unit/core/attributes/test_attributes.py +++ b/kmip/tests/unit/core/attributes/test_attributes.py @@ -29,7 +29,6 @@ from kmip.core.utils import BytearrayStream - class TestNameValue(TestCase): def setUp(self): @@ -76,7 +75,6 @@ def test__str(self): self.assertEqual(self.stringName1, str(name_val)) self.assertEqual(repr_name, repr(name_val)) - class TestNameType(TestCase): def setUp(self): @@ -128,7 +126,6 @@ def test__str(self): self.assertEqual(str_uri, str(type_uri)) self.assertEqual(repr_uri, repr(type_uri)) - class TestName(TestCase): def setUp(self): @@ -220,7 +217,6 @@ def test__str(self): self.assertEqual(self.stringName1, str(name_obj)) self.assertEqual(repr_name, repr(name_obj)) - class TestOperationPolicyName(TestCase): def setUp(self): @@ -244,7 +240,6 @@ def test_operation_policy_name(self): def test_operation_policy_name_on_none(self): self._test_operation_policy_name(None) - class TestHashingAlgorithm(TestCase): """ A test suite for the HashingAlgorithm class. @@ -290,7 +285,6 @@ def test_init_with_invalid(self): """ self._test_init("invalid") - # TODO (peter-hamilton) Replace with generic Enumeration subclass test suite. class TestCertificateType(TestCase): """ @@ -334,7 +328,6 @@ def test_init_with_valid(self): """ self._test_init(enums.CertificateType.PGP) - class TestDigestValue(TestCase): """ A test suite for the DigestValue class. @@ -375,7 +368,6 @@ def test_init_with_valid(self): """ self._test_init(b'\x00\x01\x02\x03') - class TestCryptographicParameters(TestCase): """ Test suite for the CryptographicParameters struct. @@ -625,6 +617,40 @@ def test_invalid_cryptographic_algorithm(self): *args ) + def test_invalid_cryptographic_algorithm_enum_type(self): + """ + Test that a TypeError is raised when an enum of the wrong type is + used for the cryptographic algorithm. + """ + cryptographic_parameters = CryptographicParameters() + args = ( + cryptographic_parameters, + 'cryptographic_algorithm', + enums.ObjectType.SYMMETRIC_KEY + ) + self.assertRaisesRegex( + TypeError, + "cryptographic algorithm must be a CryptographicAlgorithm " + "enumeration", + setattr, + *args + ) + + def test_invalid_cryptographic_algorithm_int(self): + """ + Test that a TypeError is raised when an integer is used for the + cryptographic algorithm. + """ + cryptographic_parameters = CryptographicParameters() + args = (cryptographic_parameters, 'cryptographic_algorithm', 1) + self.assertRaisesRegex( + TypeError, + "cryptographic algorithm must be a CryptographicAlgorithm " + "enumeration", + setattr, + *args + ) + def test_invalid_random_iv(self): """ Test that a TypeError is raised when an invalid value is used to set @@ -1497,7 +1523,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestDerivationParameters(TestCase): """ Test suite for the DerivationParameters struct. diff --git a/kmip/tests/unit/core/attributes/test_digest.py b/kmip/tests/unit/core/attributes/test_digest.py index 5a95d962..618e1fea 100644 --- a/kmip/tests/unit/core/attributes/test_digest.py +++ b/kmip/tests/unit/core/attributes/test_digest.py @@ -25,7 +25,6 @@ from kmip.core.objects import KeyFormatType from kmip.core.utils import BytearrayStream - class TestDigest(TestCase): """ A test suite for the Digest class. diff --git a/kmip/tests/unit/core/factories/payloads/test_payload.py b/kmip/tests/unit/core/factories/payloads/test_payload.py index e04f91b8..e4bcab23 100644 --- a/kmip/tests/unit/core/factories/payloads/test_payload.py +++ b/kmip/tests/unit/core/factories/payloads/test_payload.py @@ -18,7 +18,6 @@ from kmip.core import enums from kmip.core.factories.payloads import PayloadFactory - class TestPayloadFactory(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/factories/payloads/test_request.py b/kmip/tests/unit/core/factories/payloads/test_request.py index ede8779c..2d97dfd0 100644 --- a/kmip/tests/unit/core/factories/payloads/test_request.py +++ b/kmip/tests/unit/core/factories/payloads/test_request.py @@ -20,7 +20,6 @@ from kmip.core.messages import payloads - class TestRequestPayloadFactory(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/factories/payloads/test_response.py b/kmip/tests/unit/core/factories/payloads/test_response.py index 5a6e877b..f8914642 100644 --- a/kmip/tests/unit/core/factories/payloads/test_response.py +++ b/kmip/tests/unit/core/factories/payloads/test_response.py @@ -20,7 +20,6 @@ from kmip.core.messages import payloads - class TestResponsePayloadFactory(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/factories/test_attribute.py b/kmip/tests/unit/core/factories/test_attribute.py index eea93c75..081e0301 100644 --- a/kmip/tests/unit/core/factories/test_attribute.py +++ b/kmip/tests/unit/core/factories/test_attribute.py @@ -19,7 +19,6 @@ from kmip.core.factories import attributes - class TestAttributeFactory(testtools.TestCase): """ Test suite for Attribute Factory diff --git a/kmip/tests/unit/core/factories/test_attribute_values.py b/kmip/tests/unit/core/factories/test_attribute_values.py index 6edc4482..4b46e952 100644 --- a/kmip/tests/unit/core/factories/test_attribute_values.py +++ b/kmip/tests/unit/core/factories/test_attribute_values.py @@ -21,7 +21,6 @@ from kmip.core.factories import attribute_values - class TestAttributeValueFactory(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/messages/contents/test_authentication.py b/kmip/tests/unit/core/messages/contents/test_authentication.py index 0b0e210c..435cb71e 100644 --- a/kmip/tests/unit/core/messages/contents/test_authentication.py +++ b/kmip/tests/unit/core/messages/contents/test_authentication.py @@ -20,7 +20,6 @@ from kmip.core import utils from kmip.core.messages import contents - class TestAuthentication(testtools.TestCase): """ Test suite for the Authentication struct. diff --git a/kmip/tests/unit/core/messages/contents/test_protocol_version.py b/kmip/tests/unit/core/messages/contents/test_protocol_version.py index 496876b1..75f6dab5 100644 --- a/kmip/tests/unit/core/messages/contents/test_protocol_version.py +++ b/kmip/tests/unit/core/messages/contents/test_protocol_version.py @@ -19,7 +19,6 @@ from kmip.core.messages import contents from kmip.core import utils - class TestProtocolVersion(testtools.TestCase): def setUp(self): @@ -349,7 +348,6 @@ def test_str(self): self.assertEqual("1.0", str(struct)) - class TestContents(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/messages/payloads/test_activate.py b/kmip/tests/unit/core/messages/payloads/test_activate.py index 0a85ab3f..52efbb63 100644 --- a/kmip/tests/unit/core/messages/payloads/test_activate.py +++ b/kmip/tests/unit/core/messages/payloads/test_activate.py @@ -20,7 +20,6 @@ from kmip.core.messages import payloads - class TestActivateRequestPayload(TestCase): """ Test suite for the ActivateRequestPayload class. @@ -58,6 +57,13 @@ def test_init_with_args(self): """ payloads.ActivateRequestPayload(unique_identifier=self.uuid) + def test_init(self): + """ + Test that a ActivateRequestPayload object can be constructed with no + arguments. + """ + self.test_init_with_none() + def test_validate_with_bad_uuid_type(self): """ Test that a TypeError exception is raised when an invalid UUID type @@ -105,6 +111,83 @@ def test_write_with_known_uuid(self): self.assertEqual(self.encoding_a, stream, msg) + def test_read_valid(self): + """ + Test that a ActivateRequestPayload object can be read from a valid + byte stream. + """ + self.test_read_with_known_uuid() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a request payload + missing the unique identifier. + """ + payload = payloads.ActivateRequestPayload() + empty_encoding = utils.BytearrayStream( + b'\x42\x00\x79\x01\x00\x00\x00\x00' + ) + self.assertRaises(Exception, payload.read, empty_encoding) + + def test_write_valid(self): + """ + Test that a ActivateRequestPayload object can be written to a byte + stream. + """ + self.test_write_with_known_uuid() + + def test_read_write_roundtrip(self): + """ + Test that a ActivateRequestPayload object can be read and written + without changing the encoded bytes. + """ + payload = payloads.ActivateRequestPayload() + payload.read(utils.BytearrayStream(self.encoding_a.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_a, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when the unique identifier type is + invalid. + """ + self.test_validate_with_bad_uuid_type() + + def test_eq(self): + """ + Test that a ActivateRequestPayload object compares equal to itself. + """ + payload = payloads.ActivateRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different ActivateRequestPayload objects are not equal. + """ + a = payloads.ActivateRequestPayload(self.uuid) + b = payloads.ActivateRequestPayload( + attributes.UniqueIdentifier( + '11111111-2222-3333-4444-555555555555' + ) + ) + self.assertTrue(a != b) + + def test_repr(self): + """ + Test the repr output for a ActivateRequestPayload object. + """ + payload = payloads.ActivateRequestPayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a ActivateRequestPayload object. + """ + payload = payloads.ActivateRequestPayload() + self.assertIsInstance(str(payload), str) class TestActivateResponsePayload(TestCase): """ @@ -141,6 +224,13 @@ def test_init_with_args(self): """ payloads.ActivateResponsePayload(unique_identifier=self.uuid) + def test_init(self): + """ + Test that a ActivateResponsePayload object can be constructed with no + arguments. + """ + self.test_init_with_none() + def test_validate_with_invalid_uuid(self): """ Test that a TypeError exception is raised when an invalid Operations @@ -187,3 +277,81 @@ def test_write_with_known_uuid(self): stream) self.assertEqual(self.encoding_a, stream, msg) + + def test_read_valid(self): + """ + Test that a ActivateResponsePayload object can be read from a valid + byte stream. + """ + self.test_read_with_known_uuid() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a response payload + missing the unique identifier. + """ + payload = payloads.ActivateResponsePayload() + empty_encoding = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x00\x00' + ) + self.assertRaises(Exception, payload.read, empty_encoding) + + def test_write_valid(self): + """ + Test that a ActivateResponsePayload object can be written to a byte + stream. + """ + self.test_write_with_known_uuid() + + def test_read_write_roundtrip(self): + """ + Test that a ActivateResponsePayload object can be read and written + without changing the encoded bytes. + """ + payload = payloads.ActivateResponsePayload() + payload.read(utils.BytearrayStream(self.encoding_a.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_a, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when the unique identifier type is + invalid. + """ + self.test_validate_with_invalid_uuid() + + def test_eq(self): + """ + Test that a ActivateResponsePayload object compares equal to itself. + """ + payload = payloads.ActivateResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different ActivateResponsePayload objects are not equal. + """ + a = payloads.ActivateResponsePayload(self.uuid) + b = payloads.ActivateResponsePayload( + attributes.UniqueIdentifier( + '11111111-2222-3333-4444-555555555555' + ) + ) + self.assertTrue(a != b) + + def test_repr(self): + """ + Test the repr output for a ActivateResponsePayload object. + """ + payload = payloads.ActivateResponsePayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a ActivateResponsePayload object. + """ + payload = payloads.ActivateResponsePayload() + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_archive.py b/kmip/tests/unit/core/messages/payloads/test_archive.py index db9c73d3..98983683 100644 --- a/kmip/tests/unit/core/messages/payloads/test_archive.py +++ b/kmip/tests/unit/core/messages/payloads/test_archive.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestArchiveRequestPayload(testtools.TestCase): """ Test suite for the Archive request payload. @@ -270,7 +269,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestArchiveResponsePayload(testtools.TestCase): """ Test suite for the Archive response payload. diff --git a/kmip/tests/unit/core/messages/payloads/test_cancel.py b/kmip/tests/unit/core/messages/payloads/test_cancel.py index d0ba6dd8..4ee82f15 100644 --- a/kmip/tests/unit/core/messages/payloads/test_cancel.py +++ b/kmip/tests/unit/core/messages/payloads/test_cancel.py @@ -19,7 +19,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestCancelRequestPayload(testtools.TestCase): """ Test suite for the Cancel request payload. @@ -265,7 +264,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestCancelResponsePayload(testtools.TestCase): """ Test suite for the Cancel response payload. diff --git a/kmip/tests/unit/core/messages/payloads/test_check.py b/kmip/tests/unit/core/messages/payloads/test_check.py index 63910886..630ae4e5 100644 --- a/kmip/tests/unit/core/messages/payloads/test_check.py +++ b/kmip/tests/unit/core/messages/payloads/test_check.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestCheckRequestPayload(testtools.TestCase): """ Test suite for the Check request payload. @@ -529,6 +528,162 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a Check response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.CheckResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Check response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Check response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CheckResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Check response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Check response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a Check response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.CheckResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Check response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Check response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CheckResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Check response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Check response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a Check request payload can be read from a valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.CheckRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Check request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Check request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CheckRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Check request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Check request payloads with different data are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestCheckResponsePayload(testtools.TestCase): """ @@ -1041,3 +1196,55 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a Check response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.CheckResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Check response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Check response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CheckResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Check response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Check response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_create.py b/kmip/tests/unit/core/messages/payloads/test_create.py index e62044bb..2dd05d21 100644 --- a/kmip/tests/unit/core/messages/payloads/test_create.py +++ b/kmip/tests/unit/core/messages/payloads/test_create.py @@ -23,7 +23,6 @@ from kmip.core.messages import payloads - class TestCreateRequestPayload(testtools.TestCase): def setUp(self): @@ -138,6 +137,60 @@ def setUp(self): def tearDown(self): super(TestCreateRequestPayload, self).tearDown() + def test_init(self): + """ + Test that a Create request payload can be constructed with no + arguments. + """ + payload = payloads.CreateRequestPayload() + self.assertIsNone(payload.object_type) + self.assertIsNone(payload.template_attribute) + self.assertIsNone(payload.protection_storage_masks) + + def test_init_with_args(self): + """ + Test that a Create request payload can be constructed with valid + values. + """ + payload = payloads.CreateRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + 'Cryptographic Algorithm' + ), + attribute_value=primitives.Enumeration( + enums.CryptographicAlgorithm, + value=enums.CryptographicAlgorithm.AES, + tag=enums.Tags.CRYPTOGRAPHIC_ALGORITHM + ) + ) + ] + ), + protection_storage_masks=objects.ProtectionStorageMasks( + protection_storage_masks=[ + ( + enums.ProtectionStorageMask.SOFTWARE.value | + enums.ProtectionStorageMask.HARDWARE.value + ) + ] + ) + ) + + self.assertEqual( + enums.ObjectType.SYMMETRIC_KEY, + payload.object_type + ) + self.assertIsInstance( + payload.template_attribute, + objects.TemplateAttribute + ) + self.assertIsInstance( + payload.protection_storage_masks, + objects.ProtectionStorageMasks + ) + def test_invalid_object_type(self): """ Test that a TypeError is raised when an invalid value is used to set @@ -906,6 +959,58 @@ def test_equal_on_type_mismatch(self): self.assertFalse(a == b) self.assertFalse(b == a) + def test_read_valid(self): + """ + Test that a Create request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_object_type() + + def test_write_valid(self): + """ + Test that a Create request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Create request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CreateRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two Create request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Create request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_object_type() + def test_not_equal_on_equal(self): """ Test that the inequality operator returns False when comparing two @@ -1108,7 +1213,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestCreateResponsePayload(testtools.TestCase): def setUp(self): @@ -1204,6 +1308,53 @@ def setUp(self): def tearDown(self): super(TestCreateResponsePayload, self).tearDown() + def test_init(self): + """ + Test that a Create response payload can be constructed with no + arguments. + """ + payload = payloads.CreateResponsePayload() + self.assertIsNone(payload.object_type) + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.template_attribute) + + def test_init_with_args(self): + """ + Test that a Create response payload can be constructed with valid + values. + """ + payload = payloads.CreateResponsePayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifier='00000000-1111-2222-3333-444444444444', + template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + 'Cryptographic Algorithm' + ), + attribute_value=primitives.Enumeration( + enums.CryptographicAlgorithm, + value=enums.CryptographicAlgorithm.AES, + tag=enums.Tags.CRYPTOGRAPHIC_ALGORITHM + ) + ) + ] + ) + ) + + self.assertEqual( + enums.ObjectType.SYMMETRIC_KEY, + payload.object_type + ) + self.assertEqual( + '00000000-1111-2222-3333-444444444444', + payload.unique_identifier + ) + self.assertIsInstance( + payload.template_attribute, + objects.TemplateAttribute + ) + def test_invalid_object_type(self): """ Test that a TypeError is raised when an invalid value is used to set @@ -1862,3 +2013,55 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_read_valid(self): + """ + Test that a Create response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_object_type() + + def test_write_valid(self): + """ + Test that a Create response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Create response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.CreateResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two Create response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Create response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_object_type() diff --git a/kmip/tests/unit/core/messages/payloads/test_create_key_pair.py b/kmip/tests/unit/core/messages/payloads/test_create_key_pair.py index d96842d6..90e8a008 100644 --- a/kmip/tests/unit/core/messages/payloads/test_create_key_pair.py +++ b/kmip/tests/unit/core/messages/payloads/test_create_key_pair.py @@ -24,7 +24,6 @@ from kmip.core.messages import payloads - class TestCreateKeyPairRequestPayload(testtools.TestCase): def setUp(self): @@ -2504,6 +2503,147 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a CreateKeyPair request payload can be constructed with no + arguments. + """ + payload = payloads.CreateKeyPairRequestPayload() + self.assertIsNone(payload.common_template_attribute) + self.assertIsNone(payload.private_key_template_attribute) + self.assertIsNone(payload.public_key_template_attribute) + + def test_init_with_args(self): + """ + Test that a CreateKeyPair request payload can be constructed with + valid values. + """ + payload = payloads.CreateKeyPairRequestPayload( + common_template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + 'Cryptographic Algorithm' + ), + attribute_value=primitives.Enumeration( + enums.CryptographicAlgorithm, + value=enums.CryptographicAlgorithm.RSA, + tag=enums.Tags.CRYPTOGRAPHIC_ALGORITHM + ) + ), + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + 'Cryptographic Length' + ), + attribute_value=primitives.Integer( + value=1024, + tag=enums.Tags.CRYPTOGRAPHIC_LENGTH + ) + ) + ], + tag=enums.Tags.COMMON_TEMPLATE_ATTRIBUTE + ), + private_key_template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName("Name"), + attribute_value=attributes.Name( + name_value=attributes.Name.NameValue( + "PrivateKey1" + ), + name_type=attributes.Name.NameType( + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + ) + ], + tag=enums.Tags.PRIVATE_KEY_TEMPLATE_ATTRIBUTE + ), + public_key_template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName("Name"), + attribute_value=attributes.Name( + name_value=attributes.Name.NameValue( + "PublicKey1" + ), + name_type=attributes.Name.NameType( + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + ) + ], + tag=enums.Tags.PUBLIC_KEY_TEMPLATE_ATTRIBUTE + ) + ) + + self.assertIsInstance( + payload.common_template_attribute, + objects.TemplateAttribute + ) + self.assertIsInstance( + payload.private_key_template_attribute, + objects.TemplateAttribute + ) + self.assertIsInstance( + payload.public_key_template_attribute, + objects.TemplateAttribute + ) + + def test_read_valid(self): + """ + Test that a CreateKeyPair request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.CreateKeyPairRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b'')) + + def test_write_valid(self): + """ + Test that a CreateKeyPair request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a CreateKeyPair request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.CreateKeyPairRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_common_template_attribute() + + def test_eq(self): + """ + Test that two CreateKeyPair request payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two CreateKeyPair request payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_common_template_attribute() class TestCreateKeyPairResponsePayload(testtools.TestCase): @@ -3804,3 +3944,129 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a CreateKeyPair response payload can be constructed with no + arguments. + """ + payload = payloads.CreateKeyPairResponsePayload() + self.assertIsNone(payload.private_key_unique_identifier) + self.assertIsNone(payload.public_key_unique_identifier) + self.assertIsNone(payload.private_key_template_attribute) + self.assertIsNone(payload.public_key_template_attribute) + + def test_init_with_args(self): + """ + Test that a CreateKeyPair response payload can be constructed with + valid values. + """ + payload = payloads.CreateKeyPairResponsePayload( + private_key_unique_identifier=( + "7f7ee394-40f9-444c-818c-fb1ae57bdf15" + ), + public_key_unique_identifier=( + "79c0eb55-d020-43de-b72f-5e18c862647c" + ), + private_key_template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + "State" + ), + attribute_value=primitives.Enumeration( + enums.State, + value=enums.State.PRE_ACTIVE, + tag=enums.Tags.STATE + ) + ) + ], + tag=enums.Tags.PRIVATE_KEY_TEMPLATE_ATTRIBUTE + ), + public_key_template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + "State" + ), + attribute_value=primitives.Enumeration( + enums.State, + value=enums.State.PRE_ACTIVE, + tag=enums.Tags.STATE + ) + ) + ], + tag=enums.Tags.PUBLIC_KEY_TEMPLATE_ATTRIBUTE + ) + ) + + self.assertEqual( + "7f7ee394-40f9-444c-818c-fb1ae57bdf15", + payload.private_key_unique_identifier + ) + self.assertEqual( + "79c0eb55-d020-43de-b72f-5e18c862647c", + payload.public_key_unique_identifier + ) + self.assertIsInstance( + payload.private_key_template_attribute, + objects.TemplateAttribute + ) + self.assertIsInstance( + payload.public_key_template_attribute, + objects.TemplateAttribute + ) + + def test_read_valid(self): + """ + Test that a CreateKeyPair response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_private_key_unique_identifier() + + def test_write_valid(self): + """ + Test that a CreateKeyPair response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a CreateKeyPair response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.CreateKeyPairResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_private_key_unique_identifier() + + def test_eq(self): + """ + Test that two CreateKeyPair response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two CreateKeyPair response payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_private_key_unique_identifiers() diff --git a/kmip/tests/unit/core/messages/payloads/test_decrypt.py b/kmip/tests/unit/core/messages/payloads/test_decrypt.py index 20b9747a..b24230e4 100644 --- a/kmip/tests/unit/core/messages/payloads/test_decrypt.py +++ b/kmip/tests/unit/core/messages/payloads/test_decrypt.py @@ -21,7 +21,6 @@ from kmip.core.messages import payloads - class TestDecryptRequestPayload(testtools.TestCase): """ Test suite for the Decrypt request payload. @@ -782,6 +781,109 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a Decrypt response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Decrypt response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Decrypt response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DecryptResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Decrypt response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Decrypt response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a Decrypt request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Decrypt request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Decrypt request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DecryptRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Decrypt request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Decrypt request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestDecryptResponsePayload(testtools.TestCase): """ @@ -1116,3 +1218,55 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + + def test_read_valid(self): + """ + Test that a Decrypt response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Decrypt response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Decrypt response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DecryptResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Decrypt response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Decrypt response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_delete_attribute.py b/kmip/tests/unit/core/messages/payloads/test_delete_attribute.py index a7582a8d..87ccd9b6 100644 --- a/kmip/tests/unit/core/messages/payloads/test_delete_attribute.py +++ b/kmip/tests/unit/core/messages/payloads/test_delete_attribute.py @@ -23,7 +23,6 @@ from kmip.core.messages import payloads - class TestDeleteAttributeRequestPayload(testtools.TestCase): """ A unit test suite for the DeleteAttribute request payload. @@ -740,6 +739,95 @@ def test_comparison_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a DeleteAttribute request payload can be constructed with no + arguments. + """ + payload = payloads.DeleteAttributeRequestPayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.attribute_name) + self.assertIsNone(payload.attribute_index) + self.assertIsNone(payload.current_attribute) + self.assertIsNone(payload.attribute_reference) + + def test_init_with_args(self): + """ + Test that a DeleteAttribute request payload can be constructed with + valid values. + """ + payload = payloads.DeleteAttributeRequestPayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959", + attribute_name="x-attribute1", + attribute_index=1 + ) + + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + self.assertEqual("x-attribute1", payload.attribute_name) + self.assertEqual(1, payload.attribute_index) + + def test_read_valid(self): + """ + Test that a DeleteAttribute request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_attribute_name() + + def test_write_valid(self): + """ + Test that a DeleteAttribute request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeleteAttribute request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.DeleteAttributeRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a DeleteAttribute request payload compares equal to itself. + """ + payload = payloads.DeleteAttributeRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different DeleteAttribute request payloads are not + equal. + """ + a = payloads.DeleteAttributeRequestPayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959" + ) + b = payloads.DeleteAttributeRequestPayload( + unique_identifier="11111111-2222-3333-4444-555555555555" + ) + self.assertTrue(a != b) class TestDeleteAttributeResponsePayload(testtools.TestCase): """ @@ -1164,3 +1252,94 @@ def test_comparison_on_type_mismatch(self): self.assertFalse(b == a) self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a DeleteAttribute response payload can be constructed with + no arguments. + """ + payload = payloads.DeleteAttributeResponsePayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.attribute) + + def test_init_with_args(self): + """ + Test that a DeleteAttribute response payload can be constructed with + valid values. + """ + payload = payloads.DeleteAttributeResponsePayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959", + attribute=objects.Attribute( + attribute_name=objects.Attribute.AttributeName("x-attribute1"), + attribute_value=primitives.TextString( + "ModifiedValue1", + tag=enums.Tags.ATTRIBUTE_VALUE + ) + ) + ) + + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + self.assertIsInstance(payload.attribute, objects.Attribute) + + def test_read_valid(self): + """ + Test that a DeleteAttribute response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_unique_identifier() + + def test_write_valid(self): + """ + Test that a DeleteAttribute response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeleteAttribute response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.DeleteAttributeResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a DeleteAttribute response payload compares equal to itself. + """ + payload = payloads.DeleteAttributeResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different DeleteAttribute response payloads are not + equal. + """ + a = payloads.DeleteAttributeResponsePayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959" + ) + b = payloads.DeleteAttributeResponsePayload( + unique_identifier="11111111-2222-3333-4444-555555555555" + ) + self.assertTrue(a != b) diff --git a/kmip/tests/unit/core/messages/payloads/test_derive_key.py b/kmip/tests/unit/core/messages/payloads/test_derive_key.py index 2f53e0c9..a14030e9 100644 --- a/kmip/tests/unit/core/messages/payloads/test_derive_key.py +++ b/kmip/tests/unit/core/messages/payloads/test_derive_key.py @@ -24,7 +24,6 @@ from kmip.core.messages import payloads - class TestDeriveKeyRequestPayload(testtools.TestCase): """ Test suite for the DeriveKey request payload. @@ -1631,6 +1630,161 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a DeriveKey response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a DeriveKey response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeriveKey response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DeriveKeyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two DeriveKey response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two DeriveKey response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a DeriveKey response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a DeriveKey response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeriveKey response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DeriveKeyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two DeriveKey response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two DeriveKey response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a DeriveKey request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_object_type() + + def test_write_valid(self): + """ + Test that a DeriveKey request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeriveKey request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DeriveKeyRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two DeriveKey request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two DeriveKey request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_object_type() class TestDeriveKeyResponsePayload(testtools.TestCase): """ @@ -2484,3 +2638,54 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a DeriveKey response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a DeriveKey response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a DeriveKey response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DeriveKeyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two DeriveKey response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two DeriveKey response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_destroy.py b/kmip/tests/unit/core/messages/payloads/test_destroy.py index 87b311ed..ab453fbc 100644 --- a/kmip/tests/unit/core/messages/payloads/test_destroy.py +++ b/kmip/tests/unit/core/messages/payloads/test_destroy.py @@ -12,3 +12,291 @@ # 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 testtools + +from kmip.core import attributes +from kmip.core import exceptions +from kmip.core import utils + +from kmip.core.messages import payloads + + +class TestDestroyRequestPayload(testtools.TestCase): + """ + Test suite for the Destroy request payload. + """ + + def setUp(self): + super(TestDestroyRequestPayload, self).setUp() + + self.uuid = attributes.UniqueIdentifier( + "668eff89-3010-4258-bc0e-8c402309c746" + ) + + self.full_encoding = utils.BytearrayStream( + b"\x42\x00\x79\x01\x00\x00\x00\x30" + b"\x42\x00\x94\x07\x00\x00\x00\x24" + b"\x36\x36\x38\x65\x66\x66\x38\x39\x2D\x33\x30\x31\x30\x2D\x34\x32" + b"\x35\x38\x2D\x62\x63\x30\x65\x2D\x38\x63\x34\x30\x32\x33\x30\x39" + b"\x63\x37\x34\x36\x00\x00\x00\x00" + ) + + self.empty_encoding = utils.BytearrayStream( + b"\x42\x00\x79\x01\x00\x00\x00\x00" + ) + + def tearDown(self): + super(TestDestroyRequestPayload, self).tearDown() + + def test_init(self): + """ + Test that a Destroy request payload can be constructed with no + arguments. + """ + payload = payloads.DestroyRequestPayload() + self.assertIsNone(payload.unique_identifier) + + def test_init_with_args(self): + """ + Test that a Destroy request payload can be constructed with valid + values. + """ + payload = payloads.DestroyRequestPayload(unique_identifier=self.uuid) + self.assertEqual(self.uuid, payload.unique_identifier) + + def test_read_valid(self): + """ + Test that a Destroy request payload can be read from a valid byte + stream. + """ + payload = payloads.DestroyRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + self.assertEqual(self.uuid.value, payload.unique_identifier.value) + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a Destroy request + payload missing the unique identifier. + """ + payload = payloads.DestroyRequestPayload() + self.assertRaises( + exceptions.InvalidKmipEncoding, + payload.read, + utils.BytearrayStream(self.empty_encoding.buffer), + ) + + def test_write_valid(self): + """ + Test that a Destroy request payload can be written to a byte stream. + """ + payload = payloads.DestroyRequestPayload(unique_identifier=self.uuid) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_read_write_roundtrip(self): + """ + Test that a Destroy request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DestroyRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_validate_invalid(self): + """ + Test that a TypeError is raised when the unique identifier type is + invalid. + """ + self.assertRaisesRegex( + TypeError, + "invalid unique identifier", + payloads.DestroyRequestPayload, + "not-a-uuid", + ) + + def test_eq(self): + """ + Test that two Destroy request payloads with the same data are equal. + """ + a = payloads.DestroyRequestPayload(unique_identifier=self.uuid) + b = payloads.DestroyRequestPayload(unique_identifier=self.uuid) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_ne(self): + """ + Test that two Destroy request payloads with different data are not + equal. + """ + a = payloads.DestroyRequestPayload(unique_identifier=self.uuid) + b = payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier( + "11111111-2222-3333-4444-555555555555" + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test the repr output for a Destroy request payload. + """ + payload = payloads.DestroyRequestPayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a Destroy request payload. + """ + payload = payloads.DestroyRequestPayload() + self.assertIsInstance(str(payload), str) + + +class TestDestroyResponsePayload(testtools.TestCase): + """ + Test suite for the Destroy response payload. + """ + + def setUp(self): + super(TestDestroyResponsePayload, self).setUp() + + self.uuid = attributes.UniqueIdentifier( + "668eff89-3010-4258-bc0e-8c402309c746" + ) + + self.full_encoding = utils.BytearrayStream( + b"\x42\x00\x7C\x01\x00\x00\x00\x30" + b"\x42\x00\x94\x07\x00\x00\x00\x24" + b"\x36\x36\x38\x65\x66\x66\x38\x39\x2D\x33\x30\x31\x30\x2D\x34\x32" + b"\x35\x38\x2D\x62\x63\x30\x65\x2D\x38\x63\x34\x30\x32\x33\x30\x39" + b"\x63\x37\x34\x36\x00\x00\x00\x00" + ) + + self.empty_encoding = utils.BytearrayStream( + b"\x42\x00\x7C\x01\x00\x00\x00\x00" + ) + + def tearDown(self): + super(TestDestroyResponsePayload, self).tearDown() + + def test_init(self): + """ + Test that a Destroy response payload can be constructed with no + arguments. + """ + payload = payloads.DestroyResponsePayload() + self.assertIsNone(payload.unique_identifier) + + def test_init_with_args(self): + """ + Test that a Destroy response payload can be constructed with valid + values. + """ + payload = payloads.DestroyResponsePayload(unique_identifier=self.uuid) + self.assertEqual(self.uuid, payload.unique_identifier) + + def test_read_valid(self): + """ + Test that a Destroy response payload can be read from a valid byte + stream. + """ + payload = payloads.DestroyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + self.assertEqual(self.uuid.value, payload.unique_identifier.value) + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a Destroy response + payload missing the unique identifier. + """ + payload = payloads.DestroyResponsePayload() + self.assertRaises( + exceptions.InvalidKmipEncoding, + payload.read, + utils.BytearrayStream(self.empty_encoding.buffer), + ) + + def test_write_valid(self): + """ + Test that a Destroy response payload can be written to a byte stream. + """ + payload = payloads.DestroyResponsePayload(unique_identifier=self.uuid) + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_read_write_roundtrip(self): + """ + Test that a Destroy response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.DestroyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.full_encoding, stream) + + def test_validate_invalid(self): + """ + Test that a TypeError is raised when the unique identifier type is + invalid. + """ + self.assertRaisesRegex( + TypeError, + "invalid unique identifier", + payloads.DestroyResponsePayload, + "not-a-uuid", + ) + + def test_eq(self): + """ + Test that two Destroy response payloads with the same data are equal. + """ + a = payloads.DestroyResponsePayload(unique_identifier=self.uuid) + b = payloads.DestroyResponsePayload(unique_identifier=self.uuid) + + self.assertTrue(a == b) + self.assertTrue(b == a) + + def test_ne(self): + """ + Test that two Destroy response payloads with different data are not + equal. + """ + a = payloads.DestroyResponsePayload(unique_identifier=self.uuid) + b = payloads.DestroyResponsePayload( + unique_identifier=attributes.UniqueIdentifier( + "11111111-2222-3333-4444-555555555555" + ) + ) + + self.assertTrue(a != b) + self.assertTrue(b != a) + + def test_repr(self): + """ + Test the repr output for a Destroy response payload. + """ + payload = payloads.DestroyResponsePayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a Destroy response payload. + """ + payload = payloads.DestroyResponsePayload() + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_discover_versions.py b/kmip/tests/unit/core/messages/payloads/test_discover_versions.py index 673fe421..422d1f7b 100644 --- a/kmip/tests/unit/core/messages/payloads/test_discover_versions.py +++ b/kmip/tests/unit/core/messages/payloads/test_discover_versions.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from six.moves import xrange - from testtools import TestCase from kmip.core import utils @@ -22,7 +20,6 @@ from kmip.core.messages.contents import ProtocolVersion from kmip.core.messages import payloads - class TestDiscoverVersionsRequestPayload(TestCase): def setUp(self): @@ -60,6 +57,9 @@ def test_init_with_args(self): payloads.DiscoverVersionsRequestPayload( self.protocol_versions_empty) + def test_init(self): + payloads.DiscoverVersionsRequestPayload() + def test_validate_with_invalid_protocol_versions(self): kwargs = {'protocol_versions': 'invalid'} self.assertRaisesRegex( @@ -82,7 +82,7 @@ def _test_read(self, stream, payload, protocol_versions): expected, observed) self.assertEqual(expected, observed, msg) - for i in xrange(len(protocol_versions)): + for i in range(len(protocol_versions)): expected = protocol_versions[i] observed = payload.protocol_versions[i] @@ -149,6 +149,51 @@ def test_write_with_two_protocol_versions(self): self._test_write(payload, expected) + def test_read_valid(self): + payload = payloads.DiscoverVersionsRequestPayload() + self._test_read(self.encoding_one, payload, self.protocol_versions_one) + + def test_read_missing_required_field(self): + payload = payloads.DiscoverVersionsRequestPayload() + self.assertRaises( + Exception, + payload.read, + utils.BytearrayStream(b'') + ) + + def test_write_valid(self): + payload = payloads.DiscoverVersionsRequestPayload( + self.protocol_versions_one) + self._test_write(payload, self.encoding_one) + + def test_read_write_roundtrip(self): + payload = payloads.DiscoverVersionsRequestPayload() + payload.read(utils.BytearrayStream(self.encoding_one.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_one, stream) + + def test_validate_invalid(self): + self.test_validate_with_invalid_protocol_versions() + + def test_eq(self): + payload = payloads.DiscoverVersionsRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + a = payloads.DiscoverVersionsRequestPayload(self.protocol_versions_one) + b = payloads.DiscoverVersionsRequestPayload(self.protocol_versions_two) + self.assertTrue(a != b) + + def test_repr(self): + payload = payloads.DiscoverVersionsRequestPayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + payload = payloads.DiscoverVersionsRequestPayload() + self.assertIsInstance(str(payload), str) class TestDiscoverVersionsResponsePayload(TestCase): @@ -187,6 +232,9 @@ def test_init_with_args(self): payloads.DiscoverVersionsResponsePayload( self.protocol_versions_empty) + def test_init(self): + payloads.DiscoverVersionsResponsePayload() + def test_validate_with_invalid_protocol_versions(self): kwargs = {'protocol_versions': 'invalid'} self.assertRaisesRegex( @@ -209,7 +257,7 @@ def _test_read(self, stream, payload, protocol_versions): expected, observed) self.assertEqual(expected, observed, msg) - for i in xrange(len(protocol_versions)): + for i in range(len(protocol_versions)): expected = protocol_versions[i] observed = payload.protocol_versions[i] @@ -275,3 +323,49 @@ def test_write_with_two_protocol_versions(self): expected = self.encoding_two self._test_write(payload, expected) + + def test_read_valid(self): + payload = payloads.DiscoverVersionsResponsePayload() + self._test_read(self.encoding_one, payload, self.protocol_versions_one) + + def test_read_missing_required_field(self): + payload = payloads.DiscoverVersionsResponsePayload() + self.assertRaises( + Exception, + payload.read, + utils.BytearrayStream(b'') + ) + + def test_write_valid(self): + payload = payloads.DiscoverVersionsResponsePayload( + self.protocol_versions_one) + self._test_write(payload, self.encoding_one) + + def test_read_write_roundtrip(self): + payload = payloads.DiscoverVersionsResponsePayload() + payload.read(utils.BytearrayStream(self.encoding_one.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_one, stream) + + def test_validate_invalid(self): + self.test_validate_with_invalid_protocol_versions() + + def test_eq(self): + payload = payloads.DiscoverVersionsResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + a = payloads.DiscoverVersionsResponsePayload(self.protocol_versions_one) + b = payloads.DiscoverVersionsResponsePayload(self.protocol_versions_two) + self.assertTrue(a != b) + + def test_repr(self): + payload = payloads.DiscoverVersionsResponsePayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + payload = payloads.DiscoverVersionsResponsePayload() + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_encrypt.py b/kmip/tests/unit/core/messages/payloads/test_encrypt.py index 82437a3f..bd865934 100644 --- a/kmip/tests/unit/core/messages/payloads/test_encrypt.py +++ b/kmip/tests/unit/core/messages/payloads/test_encrypt.py @@ -21,7 +21,6 @@ from kmip.core.messages import payloads - class TestEncryptRequestPayload(testtools.TestCase): """ Test suite for the Encrypt request payload. @@ -726,6 +725,109 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that an Encrypt response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that an Encrypt response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an Encrypt response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.EncryptResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Encrypt response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Encrypt response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that an Encrypt request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that an Encrypt request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an Encrypt request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.EncryptRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Encrypt request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Encrypt request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestEncryptResponsePayload(testtools.TestCase): """ @@ -1211,3 +1313,55 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + + def test_read_valid(self): + """ + Test that an Encrypt response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that an Encrypt response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an Encrypt response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.EncryptResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Encrypt response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Encrypt response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_get.py b/kmip/tests/unit/core/messages/payloads/test_get.py index 3154fbe2..448327f6 100644 --- a/kmip/tests/unit/core/messages/payloads/test_get.py +++ b/kmip/tests/unit/core/messages/payloads/test_get.py @@ -24,7 +24,6 @@ from kmip.core.messages import payloads - class TestGetRequestPayload(testtools.TestCase): """ Test suite for the Get request payload. @@ -760,6 +759,106 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a Get response payload can be read from a valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a Get response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Get response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.GetResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two Get response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Get response payloads with different data are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a Get request payload can be read from a valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Get request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Get request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.GetRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Get request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Get request payloads with different data are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestGetResponsePayload(testtools.TestCase): """ @@ -1534,3 +1633,53 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + + def test_read_valid(self): + """ + Test that a Get response payload can be read from a valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a Get response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Get response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.GetResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two Get response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Get response payloads with different data are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py b/kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py index 658358a8..2d96e806 100644 --- a/kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py +++ b/kmip/tests/unit/core/messages/payloads/test_get_attribute_list.py @@ -22,7 +22,6 @@ from kmip.core.messages import payloads - class TestGetAttributeListRequestPayload(testtools.TestCase): """ Test suite for the GetAttributeList request payload. @@ -315,6 +314,60 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_read_valid(self): + """ + Test that a GetAttributeList request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetAttributeListRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetAttributeList request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetAttributeList request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.GetAttributeListRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_unique_identifier_with_invalid_value() + + def test_eq(self): + """ + Test that two GetAttributeList request payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetAttributeList request payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestGetAttributeListResponsePayload(testtools.TestCase): """ @@ -1218,3 +1271,58 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_read_valid(self): + """ + Test that a GetAttributeList response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetAttributeListResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetAttributeList response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetAttributeList response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.GetAttributeListResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_unique_identifier_with_invalid_value() + + def test_eq(self): + """ + Test that two GetAttributeList response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetAttributeList response payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_get_attributes.py b/kmip/tests/unit/core/messages/payloads/test_get_attributes.py index f129c05a..cfb32523 100644 --- a/kmip/tests/unit/core/messages/payloads/test_get_attributes.py +++ b/kmip/tests/unit/core/messages/payloads/test_get_attributes.py @@ -22,7 +22,6 @@ from kmip.core.messages import payloads - class TestGetAttributesRequestPayload(testtools.TestCase): """ Test suite for the GetAttributes request payload. @@ -874,6 +873,60 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_read_valid(self): + """ + Test that a GetAttributes request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetAttributesRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetAttributes request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetAttributes request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.GetAttributesRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_unique_identifier_with_invalid_value() + + def test_eq(self): + """ + Test that two GetAttributes request payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetAttributes request payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestGetAttributesResponsePayload(testtools.TestCase): """ @@ -1585,3 +1638,57 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_read_valid(self): + """ + Test that a GetAttributes response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_attributes() + + def test_write_valid(self): + """ + Test that a GetAttributes response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetAttributes response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.GetAttributesResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_unique_identifier_with_invalid_value() + + def test_eq(self): + """ + Test that two GetAttributes response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetAttributes response payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py b/kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py index 222ffbc7..fed4a725 100644 --- a/kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py +++ b/kmip/tests/unit/core/messages/payloads/test_get_usage_allocation.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestGetUsageAllocationRequestPayload(testtools.TestCase): """ Test suite for the GetUsageAllocation request payload. @@ -379,6 +378,170 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a GetUsageAllocation response payload can be read from a + valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetUsageAllocationResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetUsageAllocation response payload can be written to a + byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetUsageAllocation response payload can be read and + written without changing the encoded bytes. + """ + payload = payloads.GetUsageAllocationResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two GetUsageAllocation response payloads with the same data + are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetUsageAllocation response payloads with different data + are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a GetUsageAllocation response payload can be read from a + valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetUsageAllocationResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetUsageAllocation response payload can be written to a + byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetUsageAllocation response payload can be read and + written without changing the encoded bytes. + """ + payload = payloads.GetUsageAllocationResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two GetUsageAllocation response payloads with the same data + are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetUsageAllocation response payloads with different data + are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a GetUsageAllocation request payload can be read from a + valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetUsageAllocationRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetUsageAllocation request payload can be written to a + byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetUsageAllocation request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.GetUsageAllocationRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two GetUsageAllocation request payloads with the same data + are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetUsageAllocation request payloads with different data + are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestGetUsageAllocationResponsePayload(testtools.TestCase): """ @@ -632,3 +795,57 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a GetUsageAllocation response payload can be read from a + valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.GetUsageAllocationResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a GetUsageAllocation response payload can be written to a + byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a GetUsageAllocation response payload can be read and + written without changing the encoded bytes. + """ + payload = payloads.GetUsageAllocationResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two GetUsageAllocation response payloads with the same data + are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two GetUsageAllocation response payloads with different data + are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_locate.py b/kmip/tests/unit/core/messages/payloads/test_locate.py index 06ddfcdd..f343eeee 100644 --- a/kmip/tests/unit/core/messages/payloads/test_locate.py +++ b/kmip/tests/unit/core/messages/payloads/test_locate.py @@ -22,7 +22,6 @@ from kmip.core.messages import payloads - class TestLocateRequestPayload(testtools.TestCase): def setUp(self): @@ -908,7 +907,7 @@ def test_repr(self): self.assertTrue(repr(payload).startswith(s)) - def str(self): + def test_str(self): """ Test that str can be applied to a Locate request payload structure. """ @@ -1233,6 +1232,109 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a Locate request payload can be constructed with no + arguments. + """ + payload = payloads.LocateRequestPayload() + self.assertIsNone(payload.maximum_items) + self.assertIsNone(payload.offset_items) + self.assertIsNone(payload.storage_status_mask) + self.assertIsNone(payload.object_group_member) + self.assertEqual([], payload.attributes) + + def test_init_with_args(self): + """ + Test that a Locate request payload can be constructed with valid + values. + """ + payload = payloads.LocateRequestPayload( + maximum_items=1, + offset_items=1, + storage_status_mask=3, + object_group_member=enums.ObjectGroupMember.GROUP_MEMBER_DEFAULT, + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + "Object Group" + ), + attribute_value=primitives.TextString( + value="RoundRobinTestGroup", + tag=enums.Tags.OBJECT_GROUP + ) + ) + ] + ) + + self.assertEqual(1, payload.maximum_items) + self.assertEqual(1, payload.offset_items) + self.assertEqual(3, payload.storage_status_mask) + self.assertEqual( + enums.ObjectGroupMember.GROUP_MEMBER_DEFAULT, + payload.object_group_member + ) + self.assertEqual(1, len(payload.attributes)) + + def test_read_valid(self): + """ + Test that a Locate request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.LocateRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Locate request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Locate request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.LocateRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_maximum_items() + + def test_eq(self): + """ + Test that two Locate request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Locate request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_maximum_items() + + def test_str(self): + """ + Test the str output for a Locate request payload. + """ + payload = payloads.LocateRequestPayload() + self.assertIsInstance(str(payload), str) class TestLocateResponsePayload(testtools.TestCase): @@ -1644,3 +1746,90 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a Locate response payload can be constructed with no + arguments. + """ + payload = payloads.LocateResponsePayload() + self.assertIsNone(payload.located_items) + self.assertEqual([], payload.unique_identifiers) + + def test_init_with_args(self): + """ + Test that a Locate response payload can be constructed with valid + values. + """ + payload = payloads.LocateResponsePayload( + located_items=1, + unique_identifiers=["8d945322-fd70-495d-bf7f-71481d1401f6"] + ) + + self.assertEqual(1, payload.located_items) + self.assertEqual( + ["8d945322-fd70-495d-bf7f-71481d1401f6"], + payload.unique_identifiers + ) + + def test_read_valid(self): + """ + Test that a Locate response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_located_items() + + def test_write_valid(self): + """ + Test that a Locate response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Locate response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.LocateResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_located_items() + + def test_eq(self): + """ + Test that two Locate response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Locate response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_located_items() + + def test_str(self): + """ + Test the str output for a Locate response payload. + """ + payload = payloads.LocateResponsePayload( + located_items=1, + unique_identifiers=["8d945322-fd70-495d-bf7f-71481d1401f6"] + ) + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_mac.py b/kmip/tests/unit/core/messages/payloads/test_mac.py index ce2cb557..0ddfa1b4 100644 --- a/kmip/tests/unit/core/messages/payloads/test_mac.py +++ b/kmip/tests/unit/core/messages/payloads/test_mac.py @@ -22,7 +22,6 @@ from kmip.core.messages import payloads - class TestMACRequestPayload(TestCase): def setUp(self): @@ -71,6 +70,12 @@ def test_init_valid(self): self.cryptographic_parameters) self.assertEqual(payload.data, self.data) + def test_init(self): + payloads.MACRequestPayload() + + def test_init_with_args(self): + self.test_init_valid() + def test_init_with_invalid_unique_identifier(self): kwargs = {'unique_identifier': 'invalid', 'cryptographic_parameters': None, @@ -150,6 +155,39 @@ def test_write_with_no_data(self): *args ) + def test_read_missing_required_field(self): + self.test_read_no_data() + + def test_read_write_roundtrip(self): + payload = payloads.MACRequestPayload() + payload.read(utils.BytearrayStream(self.encoding_full.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_full, stream) + + def test_validate_invalid(self): + self.test_init_with_invalid_unique_identifier() + + def test_eq(self): + payload = payloads.MACRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + a = payloads.MACRequestPayload(self.unique_identifier) + b = payloads.MACRequestPayload( + attributes.UniqueIdentifier(value='2') + ) + self.assertTrue(a != b) + + def test_repr(self): + payload = payloads.MACRequestPayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + payload = payloads.MACRequestPayload() + self.assertIsInstance(str(payload), str) class TestMACResponsePayload(TestCase): @@ -202,6 +240,12 @@ def test_init_valid(self): self.assertEqual(payload.unique_identifier, self.unique_identifier) self.assertEqual(payload.mac_data, self.mac_data) + def test_init(self): + payloads.MACResponsePayload() + + def test_init_with_args(self): + self.test_init_valid() + def test_init_with_invalid_unique_identifier(self): kwargs = {'unique_identifier': 'invalid', 'mac_data': None} @@ -296,3 +340,38 @@ def test_write_with_no_data(self): payload.write, *args ) + + def test_read_missing_required_field(self): + self.test_read_no_unique_identifier() + + def test_read_write_roundtrip(self): + payload = payloads.MACResponsePayload() + payload.read(utils.BytearrayStream(self.encoding_full.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_full, stream) + + def test_validate_invalid(self): + self.test_init_with_invalid_unique_identifier() + + def test_eq(self): + payload = payloads.MACResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + a = payloads.MACResponsePayload(self.unique_identifier, self.mac_data) + b = payloads.MACResponsePayload( + attributes.UniqueIdentifier(value='2'), + self.mac_data + ) + self.assertTrue(a != b) + + def test_repr(self): + payload = payloads.MACResponsePayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + payload = payloads.MACResponsePayload() + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_modify_attribute.py b/kmip/tests/unit/core/messages/payloads/test_modify_attribute.py index 25b299d3..c58c8f86 100644 --- a/kmip/tests/unit/core/messages/payloads/test_modify_attribute.py +++ b/kmip/tests/unit/core/messages/payloads/test_modify_attribute.py @@ -23,7 +23,6 @@ from kmip.core.messages import payloads - class TestModifyAttributeRequestPayload(testtools.TestCase): """ A unit test suite for the ModifyAttribute request payload. @@ -594,6 +593,97 @@ def test_comparison_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a ModifyAttribute request payload can be constructed with no + arguments. + """ + payload = payloads.ModifyAttributeRequestPayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.attribute) + self.assertIsNone(payload.current_attribute) + self.assertIsNone(payload.new_attribute) + + def test_init_with_args(self): + """ + Test that a ModifyAttribute request payload can be constructed with + valid values. + """ + payload = payloads.ModifyAttributeRequestPayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959", + attribute=objects.Attribute( + attribute_name=objects.Attribute.AttributeName("x-attribute1"), + attribute_value=primitives.TextString( + value="ModifiedValue1", + tag=enums.Tags.ATTRIBUTE_VALUE + ) + ) + ) + + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + self.assertIsInstance(payload.attribute, objects.Attribute) + + def test_read_valid(self): + """ + Test that a ModifyAttribute request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_attribute() + + def test_write_valid(self): + """ + Test that a ModifyAttribute request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a ModifyAttribute request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ModifyAttributeRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a ModifyAttribute request payload compares equal to itself. + """ + payload = payloads.ModifyAttributeRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different ModifyAttribute request payloads are not equal. + """ + a = payloads.ModifyAttributeRequestPayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959" + ) + b = payloads.ModifyAttributeRequestPayload( + unique_identifier="11111111-2222-3333-4444-555555555555" + ) + self.assertTrue(a != b) class TestModifyAttributeResponsePayload(testtools.TestCase): """ @@ -973,3 +1063,94 @@ def test_comparison_on_type_mismatch(self): self.assertFalse(b == a) self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a ModifyAttribute response payload can be constructed with + no arguments. + """ + payload = payloads.ModifyAttributeResponsePayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.attribute) + + def test_init_with_args(self): + """ + Test that a ModifyAttribute response payload can be constructed with + valid values. + """ + payload = payloads.ModifyAttributeResponsePayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959", + attribute=objects.Attribute( + attribute_name=objects.Attribute.AttributeName("x-attribute1"), + attribute_value=primitives.TextString( + value="ModifiedValue1", + tag=enums.Tags.ATTRIBUTE_VALUE + ) + ) + ) + + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + self.assertIsInstance(payload.attribute, objects.Attribute) + + def test_read_valid(self): + """ + Test that a ModifyAttribute response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_unique_identifier() + + def test_write_valid(self): + """ + Test that a ModifyAttribute response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a ModifyAttribute response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ModifyAttributeResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a ModifyAttribute response payload compares equal to itself. + """ + payload = payloads.ModifyAttributeResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different ModifyAttribute response payloads are not + equal. + """ + a = payloads.ModifyAttributeResponsePayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959" + ) + b = payloads.ModifyAttributeResponsePayload( + unique_identifier="11111111-2222-3333-4444-555555555555" + ) + self.assertTrue(a != b) diff --git a/kmip/tests/unit/core/messages/payloads/test_obtain_lease.py b/kmip/tests/unit/core/messages/payloads/test_obtain_lease.py index 135cef35..8d868da3 100644 --- a/kmip/tests/unit/core/messages/payloads/test_obtain_lease.py +++ b/kmip/tests/unit/core/messages/payloads/test_obtain_lease.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestObtainLeaseRequestPayload(testtools.TestCase): """ Test suite for the ObtainLease request payload. @@ -272,6 +271,170 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that an ObtainLease response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.ObtainLeaseResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that an ObtainLease response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an ObtainLease response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ObtainLeaseResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two ObtainLease response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two ObtainLease response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that an ObtainLease response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.ObtainLeaseResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that an ObtainLease response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an ObtainLease response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ObtainLeaseResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two ObtainLease response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two ObtainLease response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that an ObtainLease request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.ObtainLeaseRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that an ObtainLease request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an ObtainLease request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ObtainLeaseRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two ObtainLease request payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two ObtainLease request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestObtainLeaseResponsePayload(testtools.TestCase): """ @@ -710,3 +873,57 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that an ObtainLease response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.ObtainLeaseResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that an ObtainLease response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that an ObtainLease response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.ObtainLeaseResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two ObtainLease response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two ObtainLease response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_poll.py b/kmip/tests/unit/core/messages/payloads/test_poll.py index c8962cee..020d366c 100644 --- a/kmip/tests/unit/core/messages/payloads/test_poll.py +++ b/kmip/tests/unit/core/messages/payloads/test_poll.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestPollRequestPayload(testtools.TestCase): """ Test suite for the Poll request payload. diff --git a/kmip/tests/unit/core/messages/payloads/test_query.py b/kmip/tests/unit/core/messages/payloads/test_query.py index 5e9f894b..b198e698 100644 --- a/kmip/tests/unit/core/messages/payloads/test_query.py +++ b/kmip/tests/unit/core/messages/payloads/test_query.py @@ -24,7 +24,6 @@ from kmip.core.messages import payloads - class TestQueryRequestPayload(testtools.TestCase): """ Test suite for the QueryRequestPayload class. @@ -329,6 +328,84 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a Query request payload can be constructed with no + arguments. + """ + payload = payloads.QueryRequestPayload() + self.assertIsNone(payload.query_functions) + + def test_init_with_args(self): + """ + Test that a Query request payload can be constructed with valid + values. + """ + payload = payloads.QueryRequestPayload( + query_functions=[ + enums.QueryFunction.QUERY_OPERATIONS, + enums.QueryFunction.QUERY_OBJECTS + ] + ) + self.assertEqual( + [ + enums.QueryFunction.QUERY_OPERATIONS, + enums.QueryFunction.QUERY_OBJECTS + ], + payload.query_functions + ) + + def test_read_valid(self): + """ + Test that a Query request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_query_functions() + + def test_write_valid(self): + """ + Test that a Query request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Query request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.QueryRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_query_functions() + + def test_eq(self): + """ + Test that two Query request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Query request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_query_functions() class TestQueryResponsePayload(testtools.TestCase): """ @@ -4986,3 +5063,84 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a Query response payload can be constructed with no + arguments. + """ + payload = payloads.QueryResponsePayload() + self.assertIsNone(payload.operations) + self.assertIsNone(payload.object_types) + self.assertIsNone(payload.vendor_identification) + + def test_init_with_args(self): + """ + Test that a Query response payload can be constructed with valid + values. + """ + payload = payloads.QueryResponsePayload( + operations=[enums.Operation.CREATE], + object_types=[enums.ObjectType.SYMMETRIC_KEY], + vendor_identification="ExampleVendor" + ) + + self.assertEqual([enums.Operation.CREATE], payload.operations) + self.assertEqual( + [enums.ObjectType.SYMMETRIC_KEY], + payload.object_types + ) + self.assertEqual("ExampleVendor", payload.vendor_identification) + + def test_read_valid(self): + """ + Test that a Query response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = payloads.QueryResponsePayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a Query response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Query response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.QueryResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_operations() + + def test_eq(self): + """ + Test that two Query response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Query response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_operations() diff --git a/kmip/tests/unit/core/messages/payloads/test_recover.py b/kmip/tests/unit/core/messages/payloads/test_recover.py index e2af9b83..9debd629 100644 --- a/kmip/tests/unit/core/messages/payloads/test_recover.py +++ b/kmip/tests/unit/core/messages/payloads/test_recover.py @@ -18,7 +18,6 @@ from kmip.core import utils from kmip.core.messages import payloads - class TestRecoverRequestPayload(testtools.TestCase): """ Test suite for the Recover request payload. @@ -270,7 +269,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestRecoverResponsePayload(testtools.TestCase): """ Test suite for the Recover response payload. diff --git a/kmip/tests/unit/core/messages/payloads/test_register.py b/kmip/tests/unit/core/messages/payloads/test_register.py index 1f37c89e..908eb914 100644 --- a/kmip/tests/unit/core/messages/payloads/test_register.py +++ b/kmip/tests/unit/core/messages/payloads/test_register.py @@ -24,7 +24,6 @@ from kmip.core.messages import payloads - class TestRegisterRequestPayload(testtools.TestCase): def setUp(self): @@ -1206,6 +1205,102 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a Register request payload can be constructed with no + arguments. + """ + payload = payloads.RegisterRequestPayload() + self.assertIsNone(payload.object_type) + self.assertIsNone(payload.template_attribute) + self.assertIsNone(payload.managed_object) + self.assertIsNone(payload.protection_storage_masks) + + def test_init_with_args(self): + """ + Test that a Register request payload can be constructed with valid + values. + """ + payload = payloads.RegisterRequestPayload( + object_type=enums.ObjectType.CERTIFICATE, + template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + "Cryptographic Usage Mask" + ), + attribute_value=primitives.Integer( + enums.CryptographicUsageMask.SIGN.value | + enums.CryptographicUsageMask.VERIFY.value, + tag=enums.Tags.CRYPTOGRAPHIC_USAGE_MASK + ) + ) + ] + ), + managed_object=secrets.Certificate( + certificate_type=enums.CertificateType.X_509, + certificate_value=self.certificate_value + ) + ) + + self.assertEqual(enums.ObjectType.CERTIFICATE, payload.object_type) + self.assertIsInstance( + payload.template_attribute, + objects.TemplateAttribute + ) + self.assertIsInstance(payload.managed_object, secrets.Certificate) + + def test_read_valid(self): + """ + Test that a Register request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_object_type() + + def test_write_valid(self): + """ + Test that a Register request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Register request payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.RegisterRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_object_type() + + def test_eq(self): + """ + Test that two Register request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Register request payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_object_type() class TestRegisterResponsePayload(testtools.TestCase): @@ -1789,3 +1884,96 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a Register response payload can be constructed with no + arguments. + """ + payload = payloads.RegisterResponsePayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.template_attribute) + + def test_init_with_args(self): + """ + Test that a Register response payload can be constructed with valid + values. + """ + payload = payloads.RegisterResponsePayload( + unique_identifier="7091d0bf-548a-4d4a-93a6-6dd71cf75221", + template_attribute=objects.TemplateAttribute( + attributes=[ + objects.Attribute( + attribute_name=objects.Attribute.AttributeName( + "State" + ), + attribute_value=primitives.Enumeration( + enums.State, + value=enums.State.PRE_ACTIVE, + tag=enums.Tags.STATE + ) + ) + ] + ) + ) + + self.assertEqual( + "7091d0bf-548a-4d4a-93a6-6dd71cf75221", + payload.unique_identifier + ) + self.assertIsInstance( + payload.template_attribute, + objects.TemplateAttribute + ) + + def test_read_valid(self): + """ + Test that a Register response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a Register response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Register response payload can be read and written without + changing the encoded bytes. + """ + payload = payloads.RegisterResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(str(self.full_encoding), str(stream)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Register response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Register response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_rekey.py b/kmip/tests/unit/core/messages/payloads/test_rekey.py index 55d83375..a387d298 100644 --- a/kmip/tests/unit/core/messages/payloads/test_rekey.py +++ b/kmip/tests/unit/core/messages/payloads/test_rekey.py @@ -19,7 +19,6 @@ from kmip.core.messages import payloads - class TestRekeyRequestPayload(testtools.TestCase): """ Test suite for the Rekey request payload. @@ -697,7 +696,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestRekeyResponsePayload(testtools.TestCase): """ Test suite for the Rekey response payload. diff --git a/kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py b/kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py index 11b9b654..c1e9fdc4 100644 --- a/kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py +++ b/kmip/tests/unit/core/messages/payloads/test_rekey_key_pair.py @@ -22,7 +22,6 @@ from kmip.core.messages import payloads - class TestRekeyKeyPairRequestPayload(TestCase): def setUp(self): @@ -186,7 +185,6 @@ def test_write_with_args(self): self._test_write(stream, payload, self.encoding_full) - # TODO (ph) Replicate CreateKeyPairResponsePayload test suite here class TestRekeyKeyPairResponsePayload(TestCase): diff --git a/kmip/tests/unit/core/messages/payloads/test_revoke.py b/kmip/tests/unit/core/messages/payloads/test_revoke.py index ffdfe193..fd90db42 100644 --- a/kmip/tests/unit/core/messages/payloads/test_revoke.py +++ b/kmip/tests/unit/core/messages/payloads/test_revoke.py @@ -23,7 +23,6 @@ from kmip.core.messages import payloads - class TestRevokeRequestPayload(TestCase): """ Test suite for the RevokeRequestPayload class. @@ -64,6 +63,13 @@ def test_init_with_args(self): """ payloads.RevokeRequestPayload(unique_identifier=self.uuid) + def test_init(self): + """ + Test that a RevokeRequestPayload object can be constructed with no + arguments. + """ + self.test_init_with_none() + def test_validate_with_bad_uuid_type(self): """ Test that a TypeError exception is raised when an invalid UUID type @@ -138,6 +144,83 @@ def test_write_with_known_uuid(self): self.assertEqual(self.encoding_a, stream, msg) + def test_read_valid(self): + """ + Test that a RevokeRequestPayload object can be read from a valid byte + stream. + """ + self.test_read_with_known_uuid() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a request payload + missing the unique identifier. + """ + payload = payloads.RevokeRequestPayload() + empty_encoding = utils.BytearrayStream( + b'\x42\x00\x79\x01\x00\x00\x00\x00' + ) + self.assertRaises(Exception, payload.read, empty_encoding) + + def test_write_valid(self): + """ + Test that a RevokeRequestPayload object can be written to a byte + stream. + """ + self.test_write_with_known_uuid() + + def test_read_write_roundtrip(self): + """ + Test that a RevokeRequestPayload object can be read and written + without changing the encoded bytes. + """ + payload = payloads.RevokeRequestPayload() + payload.read(utils.BytearrayStream(self.encoding_a.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_a, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when the unique identifier type is + invalid. + """ + self.test_validate_with_bad_uuid_type() + + def test_eq(self): + """ + Test that a RevokeRequestPayload object compares equal to itself. + """ + payload = payloads.RevokeRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different RevokeRequestPayload objects are not equal. + """ + a = payloads.RevokeRequestPayload(self.uuid) + b = payloads.RevokeRequestPayload( + attributes.UniqueIdentifier( + '11111111-2222-3333-4444-555555555555' + ) + ) + self.assertTrue(a != b) + + def test_repr(self): + """ + Test the repr output for a RevokeRequestPayload object. + """ + payload = payloads.RevokeRequestPayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a RevokeRequestPayload object. + """ + payload = payloads.RevokeRequestPayload() + self.assertIsInstance(str(payload), str) class TestRevokeResponsePayload(TestCase): """ @@ -174,6 +257,13 @@ def test_init_with_args(self): """ payloads.RevokeResponsePayload(unique_identifier=self.uuid) + def test_init(self): + """ + Test that a RevokeResponsePayload object can be constructed with no + arguments. + """ + self.test_init_with_none() + def test_validate_with_invalid_uuid(self): """ Test that a TypeError exception is raised when an invalid Operations @@ -220,3 +310,81 @@ def test_write_with_known_uuid(self): stream) self.assertEqual(self.encoding_a, stream, msg) + + def test_read_valid(self): + """ + Test that a RevokeResponsePayload object can be read from a valid byte + stream. + """ + self.test_read_with_known_uuid() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a response payload + missing the unique identifier. + """ + payload = payloads.RevokeResponsePayload() + empty_encoding = utils.BytearrayStream( + b'\x42\x00\x7C\x01\x00\x00\x00\x00' + ) + self.assertRaises(Exception, payload.read, empty_encoding) + + def test_write_valid(self): + """ + Test that a RevokeResponsePayload object can be written to a byte + stream. + """ + self.test_write_with_known_uuid() + + def test_read_write_roundtrip(self): + """ + Test that a RevokeResponsePayload object can be read and written + without changing the encoded bytes. + """ + payload = payloads.RevokeResponsePayload() + payload.read(utils.BytearrayStream(self.encoding_a.buffer)) + + stream = utils.BytearrayStream() + payload.write(stream) + + self.assertEqual(self.encoding_a, stream) + + def test_validate_invalid(self): + """ + Test that an exception is raised when the unique identifier type is + invalid. + """ + self.test_validate_with_invalid_uuid() + + def test_eq(self): + """ + Test that a RevokeResponsePayload object compares equal to itself. + """ + payload = payloads.RevokeResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different RevokeResponsePayload objects are not equal. + """ + a = payloads.RevokeResponsePayload(self.uuid) + b = payloads.RevokeResponsePayload( + attributes.UniqueIdentifier( + '11111111-2222-3333-4444-555555555555' + ) + ) + self.assertTrue(a != b) + + def test_repr(self): + """ + Test the repr output for a RevokeResponsePayload object. + """ + payload = payloads.RevokeResponsePayload() + self.assertIsInstance(repr(payload), str) + + def test_str(self): + """ + Test the str output for a RevokeResponsePayload object. + """ + payload = payloads.RevokeResponsePayload() + self.assertIsInstance(str(payload), str) diff --git a/kmip/tests/unit/core/messages/payloads/test_set_attribute.py b/kmip/tests/unit/core/messages/payloads/test_set_attribute.py index bb113fa9..55836746 100644 --- a/kmip/tests/unit/core/messages/payloads/test_set_attribute.py +++ b/kmip/tests/unit/core/messages/payloads/test_set_attribute.py @@ -23,7 +23,6 @@ from kmip.core.messages import payloads - class TestSetAttributeRequestPayload(testtools.TestCase): """ A unit test suite for the SetAttribute request payload. @@ -410,6 +409,91 @@ def test_comparison_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) + def test_init(self): + """ + Test that a SetAttribute request payload can be constructed with no + arguments. + """ + payload = payloads.SetAttributeRequestPayload() + self.assertIsNone(payload.unique_identifier) + self.assertIsNone(payload.new_attribute) + + def test_init_with_args(self): + """ + Test that a SetAttribute request payload can be constructed with + valid values. + """ + payload = payloads.SetAttributeRequestPayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959", + new_attribute=objects.NewAttribute( + attribute=primitives.Enumeration( + enums.CryptographicAlgorithm, + enums.CryptographicAlgorithm.AES, + enums.Tags.CRYPTOGRAPHIC_ALGORITHM + ) + ) + ) + + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + self.assertIsInstance(payload.new_attribute, objects.NewAttribute) + + def test_read_valid(self): + """ + Test that a SetAttribute request payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_unique_identifier() + + def test_write_valid(self): + """ + Test that a SetAttribute request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a SetAttribute request payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.SetAttributeRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a SetAttribute request payload compares equal to itself. + """ + payload = payloads.SetAttributeRequestPayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different SetAttribute request payloads are not equal. + """ + a = payloads.SetAttributeRequestPayload(unique_identifier="1") + b = payloads.SetAttributeRequestPayload(unique_identifier="2") + self.assertTrue(a != b) class TestSetAttributeResponsePayload(testtools.TestCase): """ @@ -643,3 +727,79 @@ def test_comparison_on_type_mismatch(self): self.assertFalse(b == a) self.assertTrue(a != b) self.assertTrue(b != a) + + def test_init(self): + """ + Test that a SetAttribute response payload can be constructed with no + arguments. + """ + payload = payloads.SetAttributeResponsePayload() + self.assertIsNone(payload.unique_identifier) + + def test_init_with_args(self): + """ + Test that a SetAttribute response payload can be constructed with + valid values. + """ + payload = payloads.SetAttributeResponsePayload( + unique_identifier="b4faee10-aa2a-4446-8ad4-0881f3422959" + ) + self.assertEqual( + "b4faee10-aa2a-4446-8ad4-0881f3422959", + payload.unique_identifier + ) + + def test_read_valid(self): + """ + Test that a SetAttribute response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_no_unique_identifier() + + def test_write_valid(self): + """ + Test that a SetAttribute response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a SetAttribute response payload can be read and written + without changing the encoded bytes. + """ + payload = payloads.SetAttributeResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that a SetAttribute response payload compares equal to itself. + """ + payload = payloads.SetAttributeResponsePayload() + self.assertTrue(payload == payload) + + def test_ne(self): + """ + Test that two different SetAttribute response payloads are not equal. + """ + a = payloads.SetAttributeResponsePayload(unique_identifier="1") + b = payloads.SetAttributeResponsePayload(unique_identifier="2") + self.assertTrue(a != b) diff --git a/kmip/tests/unit/core/messages/payloads/test_sign.py b/kmip/tests/unit/core/messages/payloads/test_sign.py index 21b20511..d4a33a0a 100644 --- a/kmip/tests/unit/core/messages/payloads/test_sign.py +++ b/kmip/tests/unit/core/messages/payloads/test_sign.py @@ -21,7 +21,6 @@ from kmip.core.messages.payloads import sign - class TestSignRequestPayload(testtools.TestCase): """ Test suite for the Sign request payload. @@ -469,6 +468,107 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a Sign response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Sign response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Sign response payload can be read and written without + changing the encoded bytes. + """ + payload = sign.SignResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Sign response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Sign response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a Sign request payload can be read from a valid byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Sign request payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Sign request payload can be read and written without + changing the encoded bytes. + """ + payload = sign.SignRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Sign request payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Sign request payloads with different data are not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestSignResponsePayload(testtools.TestCase): """ @@ -780,3 +880,55 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + + def test_read_valid(self): + """ + Test that a Sign response payload can be read from a valid byte + stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_invalid() + + def test_write_valid(self): + """ + Test that a Sign response payload can be written to a byte stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a Sign response payload can be read and written without + changing the encoded bytes. + """ + payload = sign.SignResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two Sign response payloads with the same data are equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two Sign response payloads with different data are not + equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/payloads/test_signature_verify.py b/kmip/tests/unit/core/messages/payloads/test_signature_verify.py index 7d9ac859..ff05bba2 100644 --- a/kmip/tests/unit/core/messages/payloads/test_signature_verify.py +++ b/kmip/tests/unit/core/messages/payloads/test_signature_verify.py @@ -21,7 +21,6 @@ from kmip.core.messages.payloads import signature_verify - class TestSignatureVerifyRequestPayload(testtools.TestCase): """ Test suite for the SignatureVerify request payload. @@ -981,6 +980,114 @@ def test_str(self): self.assertEqual(expected, observed) + def test_read_valid(self): + """ + Test that a SignatureVerify response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a SignatureVerify response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a SignatureVerify response payload can be read and written + without changing the encoded bytes. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two SignatureVerify response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two SignatureVerify response payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() + + def test_read_valid(self): + """ + Test that a SignatureVerify request payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + self.assertRaises(Exception, payload.read, utils.BytearrayStream(b"")) + + def test_write_valid(self): + """ + Test that a SignatureVerify request payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a SignatureVerify request payload can be read and written + without changing the encoded bytes. + """ + payload = signature_verify.SignatureVerifyRequestPayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two SignatureVerify request payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two SignatureVerify request payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() class TestSignatureVerifyResponsePayload(testtools.TestCase): """ @@ -1583,3 +1690,57 @@ def test_str(self): observed = str(payload) self.assertEqual(expected, observed) + + def test_read_valid(self): + """ + Test that a SignatureVerify response payload can be read from a valid + byte stream. + """ + self.test_read() + + def test_read_missing_required_field(self): + """ + Test that an exception is raised when reading a payload missing a + required field. + """ + self.test_read_missing_unique_identifier() + + def test_write_valid(self): + """ + Test that a SignatureVerify response payload can be written to a byte + stream. + """ + self.test_write() + + def test_read_write_roundtrip(self): + """ + Test that a SignatureVerify response payload can be read and written + without changing the encoded bytes. + """ + payload = signature_verify.SignatureVerifyResponsePayload() + payload.read(utils.BytearrayStream(self.full_encoding.buffer)) + + buffer = utils.BytearrayStream() + payload.write(buffer) + + self.assertEqual(str(self.full_encoding), str(buffer)) + + def test_validate_invalid(self): + """ + Test that an exception is raised when a field has an invalid type. + """ + self.test_invalid_unique_identifier() + + def test_eq(self): + """ + Test that two SignatureVerify response payloads with the same data are + equal. + """ + self.test_equal_on_equal() + + def test_ne(self): + """ + Test that two SignatureVerify response payloads with different data are + not equal. + """ + self.test_not_equal_on_not_equal_unique_identifier() diff --git a/kmip/tests/unit/core/messages/test_messages.py b/kmip/tests/unit/core/messages/test_messages.py index 0e3feda1..8fa51349 100644 --- a/kmip/tests/unit/core/messages/test_messages.py +++ b/kmip/tests/unit/core/messages/test_messages.py @@ -16,7 +16,6 @@ import testtools from testtools import TestCase import binascii -import six from kmip.core.factories.secrets import SecretFactory from kmip.core.factories.attributes import AttributeFactory @@ -49,7 +48,6 @@ from kmip.core import utils from kmip.core.utils import BytearrayStream - class TestRequestBatchItem(testtools.TestCase): def setUp(self): @@ -147,7 +145,6 @@ def test_write_kmip_2_0(self): self.assertEqual(len(self.encoding_kmip_2_0), len(buffer)) self.assertEqual(str(self.encoding_kmip_2_0), str(buffer)) - class TestResponseHeader(testtools.TestCase): def setUp(self): @@ -266,7 +263,6 @@ def test_write_kmip_2_0(self): self.assertEqual(len(self.encoding_kmip_2_0), len(buffer)) self.assertEqual(str(self.encoding_kmip_2_0), str(buffer)) - class TestRequestMessage(TestCase): def setUp(self): @@ -1365,7 +1361,6 @@ def test_mac_request_write(self): msg = "Bad request message write: encoding mismatch" self.assertEqual(self.mac, result, msg) - class TestResponseMessage(TestCase): def setUp(self): @@ -1588,9 +1583,9 @@ def test_create_response_read(self): unique_identifier = response_payload.unique_identifier value = 'fb4b5b9c-6188-4c63-8142-fe9c328129fc' - self.assertIsInstance(unique_identifier, six.string_types, + self.assertIsInstance(unique_identifier, str, self.msg.format('unique identifier', 'type', - six.string_types, + str, type(unique_identifier))) self.assertEqual(value, unique_identifier, self.msg.format('unique identifier', 'value', @@ -2104,8 +2099,8 @@ def test_register_response_read(self): unique_identifier = response_payload.unique_identifier msg = "Bad unique identifier type: expected {0}, received {1}" - self.assertIsInstance(unique_identifier, six.string_types, - msg.format(six.string_types, + self.assertIsInstance(unique_identifier, str, + msg.format(str, type(unique_identifier))) msg = "Bad unique identifier value: expected {0}, received {1}" exp_value = '5c9b81ef-4ee5-42cd-ba2d-c002fdd0c7b3' diff --git a/kmip/tests/unit/core/misc/test_misc.py b/kmip/tests/unit/core/misc/test_misc.py index 508c893f..5e47dc90 100644 --- a/kmip/tests/unit/core/misc/test_misc.py +++ b/kmip/tests/unit/core/misc/test_misc.py @@ -13,9 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from six import binary_type -from six import string_types - from testtools import TestCase from kmip.core.enums import KeyFormatType as KeyFormatTypeEnum @@ -26,7 +23,6 @@ from kmip.core.misc import QueryFunction from kmip.core.misc import VendorIdentification - # TODO (peter-hamilton) Replace with generic ByteString subclass test suite. class TestCertificateValue(TestCase): """ @@ -43,7 +39,7 @@ def tearDown(self): super(TestCertificateValue, self).tearDown() def _test_init(self, value): - if (isinstance(value, binary_type)) or (value is None): + if (isinstance(value, bytes)) or (value is None): certificate_value = CertificateValue(value) if value is None: @@ -69,7 +65,6 @@ def test_init_with_valid(self): """ self._test_init(b'\x00\x01\x02') - class TestQueryFunction(TestCase): """ A test suite for the QueryFunction class. @@ -115,7 +110,6 @@ def test_init_with_invalid(self): """ self._test_init("invalid") - class TestVendorIdentification(TestCase): """ A test suite for the VendorIdentification class. @@ -131,7 +125,7 @@ def tearDown(self): super(TestVendorIdentification, self).tearDown() def _test_init(self, value): - if (isinstance(value, string_types)) or (value is None): + if (isinstance(value, str)) or (value is None): vendor_identification = VendorIdentification(value) if value is None: @@ -164,7 +158,6 @@ def test_init_with_invalid(self): """ self._test_init(0) - class TestKeyFormatType(TestCase): """ A test suite for the KeyFormatType class. diff --git a/kmip/tests/unit/core/misc/test_server_information.py b/kmip/tests/unit/core/misc/test_server_information.py index 863cc2b8..0d0159e6 100644 --- a/kmip/tests/unit/core/misc/test_server_information.py +++ b/kmip/tests/unit/core/misc/test_server_information.py @@ -13,13 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from six import string_types from testtools import TestCase from kmip.core.misc import ServerInformation from kmip.core.utils import BytearrayStream - class TestServerInformation(TestCase): """ A test suite for the ServerInformation class. @@ -229,9 +227,9 @@ def _test_str(self, data): msg = "expected {0}, observed {1}".format(expected, observed) self.assertEqual(expected, observed, msg) - # TODO (peter-hamilton) This should be binary_type. Fix involves + # TODO (peter-hamilton) This should be bytes. Fix involves # TODO (peter-hamilton) refining BytearrayStream implementation. - expected = string_types + expected = str observed = str_repr msg = "expected {0}, observed {1}".format(expected, observed) diff --git a/kmip/tests/unit/core/objects/test_attribute.py b/kmip/tests/unit/core/objects/test_attribute.py index 4146e4e6..59fcc04e 100644 --- a/kmip/tests/unit/core/objects/test_attribute.py +++ b/kmip/tests/unit/core/objects/test_attribute.py @@ -15,7 +15,6 @@ from kmip.core import attributes from kmip.core import objects - class TestAttribute(testtools.TestCase): """ Test suite for the Attribute object. diff --git a/kmip/tests/unit/core/objects/test_credentials.py b/kmip/tests/unit/core/objects/test_credentials.py index 9ecd2e03..9ac50c52 100644 --- a/kmip/tests/unit/core/objects/test_credentials.py +++ b/kmip/tests/unit/core/objects/test_credentials.py @@ -21,7 +21,6 @@ from kmip.core import objects from kmip.core import utils - class TestNonce(testtools.TestCase): """ Test suite for the Nonce struct. @@ -397,7 +396,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestUsernamePasswordCredential(testtools.TestCase): """ Test suite for the UsernamePasswordCredential struct. @@ -767,7 +765,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestDeviceCredential(testtools.TestCase): """ Test suite for the DeviceCredential struct. @@ -1713,7 +1710,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestAttestationCredential(testtools.TestCase): """ Test suite for the AttestationCredential struct. @@ -2495,7 +2491,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestCredential(testtools.TestCase): """ Test suite for the Credential struct. diff --git a/kmip/tests/unit/core/objects/test_current_attribute.py b/kmip/tests/unit/core/objects/test_current_attribute.py index 56acf67f..81210b9c 100644 --- a/kmip/tests/unit/core/objects/test_current_attribute.py +++ b/kmip/tests/unit/core/objects/test_current_attribute.py @@ -21,7 +21,6 @@ from kmip.core import primitives from kmip.core import utils - class TestCurrentAttribute(testtools.TestCase): """ A unit test suite for the CurrentAttribute structure. diff --git a/kmip/tests/unit/core/objects/test_extension_information.py b/kmip/tests/unit/core/objects/test_extension_information.py index b5d63e4d..2745ab83 100644 --- a/kmip/tests/unit/core/objects/test_extension_information.py +++ b/kmip/tests/unit/core/objects/test_extension_information.py @@ -22,7 +22,6 @@ from kmip.core.utils import BytearrayStream - class TestExtensionInformation(TestCase): """ A test suite for the ExtensionInformation class. diff --git a/kmip/tests/unit/core/objects/test_new_attribute.py b/kmip/tests/unit/core/objects/test_new_attribute.py index 442890ca..eaf08b93 100644 --- a/kmip/tests/unit/core/objects/test_new_attribute.py +++ b/kmip/tests/unit/core/objects/test_new_attribute.py @@ -21,7 +21,6 @@ from kmip.core import primitives from kmip.core import utils - class TestNewAttribute(testtools.TestCase): """ A unit test suite for the NewAttribute structure. diff --git a/kmip/tests/unit/core/objects/test_objects.py b/kmip/tests/unit/core/objects/test_objects.py index d794dfc6..252be788 100644 --- a/kmip/tests/unit/core/objects/test_objects.py +++ b/kmip/tests/unit/core/objects/test_objects.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from six import string_types import testtools from testtools import TestCase @@ -42,7 +41,6 @@ from kmip.core import utils from kmip.core.utils import BytearrayStream - class TestAttributeClass(TestCase): """ A test suite for the Attribute class @@ -135,7 +133,6 @@ def test_equal_on_equal(self): def test_not_equal_on_not_equal(self): self.assertTrue(self.attributeObj_a != self.attributeObj_b) - class TestAttributeReference(testtools.TestCase): def setUp(self): @@ -525,7 +522,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestAttributes(TestCase): def setUp(self): @@ -1170,7 +1166,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestAttributeUtilities(testtools.TestCase): def setUp(self): @@ -1472,7 +1467,6 @@ def test_convert_attributes_to_template_attribute_invalid(self): *args ) - class TestKeyMaterialStruct(TestCase): """ A test suite for the KeyMaterialStruct. @@ -1495,7 +1489,6 @@ def test_valid_tag(self): self.assertEqual(Tags.KEY_MATERIAL, struct.tag) - class TestExtensionName(TestCase): """ A test suite for the ExtensionName class. @@ -1511,7 +1504,7 @@ def tearDown(self): super(TestExtensionName, self).tearDown() def _test_init(self, value): - if (isinstance(value, string_types)) or (value is None): + if (isinstance(value, str)) or (value is None): extension_name = ExtensionName(value) if value is None: @@ -1544,7 +1537,6 @@ def test_init_with_invalid(self): """ self._test_init(0) - class TestExtensionTag(TestCase): """ A test suite for the ExtensionTag class. @@ -1593,7 +1585,6 @@ def test_init_with_invalid(self): """ self._test_init("invalid") - class TestExtensionType(TestCase): """ A test suite for the ExtensionType class. @@ -1642,7 +1633,6 @@ def test_init_with_invalid(self): """ self._test_init("invalid") - class TestEncryptionKeyInformation(testtools.TestCase): """ Test suite for the EncryptionKeyInformation struct. @@ -2111,7 +2101,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestMACSignatureKeyInformation(testtools.TestCase): """ Test suite for the MACSignatureKeyInformation struct. @@ -2588,7 +2577,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestKeyWrappingData(testtools.TestCase): """ Test suite for the KeyWrappingData struct. @@ -3596,7 +3584,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestKeyWrappingSpecification(testtools.TestCase): """ Test suite for the KeyWrappingSpecification struct. @@ -4523,7 +4510,6 @@ def test_str(self): self.assertEqual(expected, observed) - class TestObjectDefaults(testtools.TestCase): def setUp(self): @@ -5144,7 +5130,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestDefaultsInformation(testtools.TestCase): def setUp(self): @@ -5723,7 +5708,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestRNGParameters(testtools.TestCase): def setUp(self): @@ -6514,7 +6498,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestProfileInformation(testtools.TestCase): def setUp(self): @@ -6969,7 +6952,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestValidationInformation(testtools.TestCase): def setUp(self): @@ -8445,7 +8427,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestCapabilityInformation(testtools.TestCase): def setUp(self): @@ -9372,7 +9353,6 @@ def test_not_equal_on_type_mismatch(self): self.assertTrue(a != b) self.assertTrue(b != a) - class TestProtectionStorageMasks(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_base.py b/kmip/tests/unit/core/primitives/test_base.py index 0dfbdce7..24992e41 100644 --- a/kmip/tests/unit/core/primitives/test_base.py +++ b/kmip/tests/unit/core/primitives/test_base.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestBase(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_big_integer.py b/kmip/tests/unit/core/primitives/test_big_integer.py index 2037354a..61764307 100644 --- a/kmip/tests/unit/core/primitives/test_big_integer.py +++ b/kmip/tests/unit/core/primitives/test_big_integer.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestBigInteger(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_boolean.py b/kmip/tests/unit/core/primitives/test_boolean.py index 83f87460..5abebe0f 100644 --- a/kmip/tests/unit/core/primitives/test_boolean.py +++ b/kmip/tests/unit/core/primitives/test_boolean.py @@ -18,7 +18,6 @@ from kmip.core import primitives from kmip.core import utils - class TestBoolean(TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_byte_string.py b/kmip/tests/unit/core/primitives/test_byte_string.py index 13e218f0..b70bde51 100644 --- a/kmip/tests/unit/core/primitives/test_byte_string.py +++ b/kmip/tests/unit/core/primitives/test_byte_string.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestByteString(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_date_time.py b/kmip/tests/unit/core/primitives/test_date_time.py index 2ed334e5..12cf80ff 100644 --- a/kmip/tests/unit/core/primitives/test_date_time.py +++ b/kmip/tests/unit/core/primitives/test_date_time.py @@ -18,7 +18,6 @@ from kmip.core import primitives from kmip.core import utils - class TestDateTime(testtools.TestCase): """ Test suite for the DateTime primitive. diff --git a/kmip/tests/unit/core/primitives/test_enumeration.py b/kmip/tests/unit/core/primitives/test_enumeration.py index 686ad69d..505560e6 100644 --- a/kmip/tests/unit/core/primitives/test_enumeration.py +++ b/kmip/tests/unit/core/primitives/test_enumeration.py @@ -21,7 +21,6 @@ from kmip.core import primitives from kmip.core import utils - # flake8: noqa class DummyEnumeration(enumeration.Enum): SMALL = primitives.Enumeration.MIN @@ -30,7 +29,6 @@ class DummyEnumeration(enumeration.Enum): TOO_LARGE = primitives.Enumeration.MAX + 1 INVALID = 'invalid' - class TestEnumeration(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_integer.py b/kmip/tests/unit/core/primitives/test_integer.py index 9cfbfe2f..90e669ff 100644 --- a/kmip/tests/unit/core/primitives/test_integer.py +++ b/kmip/tests/unit/core/primitives/test_integer.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestInteger(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/primitives/test_interval.py b/kmip/tests/unit/core/primitives/test_interval.py index 5f8cbde4..ed7218a1 100644 --- a/kmip/tests/unit/core/primitives/test_interval.py +++ b/kmip/tests/unit/core/primitives/test_interval.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestInterval(testtools.TestCase): """ Test suite for the Interval primitive. diff --git a/kmip/tests/unit/core/primitives/test_long_integer.py b/kmip/tests/unit/core/primitives/test_long_integer.py index 95e8785f..57fbd5aa 100644 --- a/kmip/tests/unit/core/primitives/test_long_integer.py +++ b/kmip/tests/unit/core/primitives/test_long_integer.py @@ -19,7 +19,6 @@ from kmip.core import primitives from kmip.core import utils - class TestLongInteger(testtools.TestCase): """ Test suite for the LongInteger primitive. diff --git a/kmip/tests/unit/core/primitives/test_text_string.py b/kmip/tests/unit/core/primitives/test_text_string.py index fb1a78e4..e352f76a 100644 --- a/kmip/tests/unit/core/primitives/test_text_string.py +++ b/kmip/tests/unit/core/primitives/test_text_string.py @@ -13,14 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import six import testtools from kmip.core import exceptions from kmip.core import primitives from kmip.core import utils - class TestTextString(testtools.TestCase): def setUp(self): @@ -55,7 +53,7 @@ def test_init(self): def test_init_unset(self): text_string = primitives.TextString() - expected = six.string_types + expected = str observed = text_string.value msg = "expected {0}, observed {1}".format(expected, observed) diff --git a/kmip/tests/unit/core/secrets/test_certificate.py b/kmip/tests/unit/core/secrets/test_certificate.py index eace3f72..3056a7e9 100644 --- a/kmip/tests/unit/core/secrets/test_certificate.py +++ b/kmip/tests/unit/core/secrets/test_certificate.py @@ -21,7 +21,6 @@ from kmip.core.secrets import Certificate from kmip.core.utils import BytearrayStream - class TestCertificate(TestCase): """ A test suite for the Certificate class. diff --git a/kmip/tests/unit/core/secrets/test_split_key.py b/kmip/tests/unit/core/secrets/test_split_key.py index 27017f38..95b1a097 100644 --- a/kmip/tests/unit/core/secrets/test_split_key.py +++ b/kmip/tests/unit/core/secrets/test_split_key.py @@ -23,7 +23,6 @@ from kmip.core import secrets from kmip.core import utils - class TestSplitKey(testtools.TestCase): """ Test suite for the SplitKey secret object. diff --git a/kmip/tests/unit/core/test_config_helper.py b/kmip/tests/unit/core/test_config_helper.py index 76865999..eb506b60 100644 --- a/kmip/tests/unit/core/test_config_helper.py +++ b/kmip/tests/unit/core/test_config_helper.py @@ -24,7 +24,6 @@ from kmip.core.config_helper import ConfigHelper - class TestConfigHelper(TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/test_config_helper_extended.py b/kmip/tests/unit/core/test_config_helper_extended.py new file mode 100644 index 00000000..7d30fb4e --- /dev/null +++ b/kmip/tests/unit/core/test_config_helper_extended.py @@ -0,0 +1,112 @@ +# Copyright (c) 2026 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 logging +import os +import tempfile + +try: + import configparser +except ImportError: + import ConfigParser as configparser + +import mock +import testtools + +from kmip.core import config_helper +from kmip.core.config_helper import ConfigHelper + + +class TestConfigHelperExtended(testtools.TestCase): + def test_config_helper_init_default(self): + mock_conf = mock.MagicMock() + mock_conf.read.return_value = ["dummy"] + + with mock.patch("kmip.core.config_helper.ConfigParser", + return_value=mock_conf): + ConfigHelper() + + mock_conf.read.assert_called_with(config_helper.CONFIG_FILE) + + def test_config_helper_init_with_path(self): + temp_file = tempfile.NamedTemporaryFile(delete=False) + self.addCleanup(os.remove, temp_file.name) + temp_file.write(b"[client]\nhost=example.com\n") + temp_file.close() + + helper = ConfigHelper(temp_file.name) + value = helper.get_valid_value(None, "client", "host", "default") + self.assertEqual("example.com", value) + + def test_config_helper_missing_file(self): + mock_conf = mock.MagicMock() + mock_conf.read.return_value = [] + mock_logger = mock.MagicMock() + mock_logger.level = logging.NOTSET + + with mock.patch("kmip.core.config_helper.logging.getLogger", + return_value=mock_logger): + with mock.patch("kmip.core.config_helper.ConfigParser", + return_value=mock_conf): + ConfigHelper() + + self.assertTrue(mock_logger.warning.called) + + def test_get_valid_value_direct(self): + helper = ConfigHelper() + helper.conf = mock.MagicMock() + value = helper.get_valid_value("direct", "client", "host", "default") + self.assertEqual("direct", value) + self.assertFalse(helper.conf.get.called) + + def test_get_valid_value_empty_string_uses_config(self): + helper = ConfigHelper() + helper.conf = mock.MagicMock() + helper.conf.get.return_value = "conf_value" + value = helper.get_valid_value("", "client", "host", "default") + helper.conf.get.assert_called_once_with("client", "host") + self.assertEqual("conf_value", value) + + def test_get_valid_value_zero_uses_config(self): + helper = ConfigHelper() + helper.conf = mock.MagicMock() + helper.conf.get.return_value = "conf_value" + value = helper.get_valid_value(0, "client", "port", "default") + helper.conf.get.assert_called_once_with("client", "port") + self.assertEqual("conf_value", value) + + def test_get_valid_value_from_config(self): + temp_file = tempfile.NamedTemporaryFile(delete=False) + self.addCleanup(os.remove, temp_file.name) + temp_file.write(b"[client]\nport=5696\n") + temp_file.close() + + helper = ConfigHelper(temp_file.name) + value = helper.get_valid_value(None, "client", "port", "default") + self.assertEqual("5696", value) + + def test_get_valid_value_default_fallback(self): + helper = ConfigHelper() + helper.conf = mock.MagicMock() + helper.conf.get.side_effect = configparser.NoSectionError("missing") + value = helper.get_valid_value(None, "missing", "option", "fallback") + self.assertEqual("fallback", value) + + def test_get_valid_value_none_section(self): + helper = ConfigHelper() + helper.conf = mock.MagicMock() + helper.conf.get.side_effect = configparser.NoSectionError("missing") + value = helper.get_valid_value(None, None, None, "fallback") + self.assertEqual("fallback", value) diff --git a/kmip/tests/unit/core/test_enums.py b/kmip/tests/unit/core/test_enums.py index 9a419309..e43e52ee 100644 --- a/kmip/tests/unit/core/test_enums.py +++ b/kmip/tests/unit/core/test_enums.py @@ -17,7 +17,6 @@ from kmip.core import enums - class TestOrderedEnum(testtools.TestCase): def setUp(self): @@ -78,7 +77,6 @@ def test_less_than(self): enums.KMIPVersion.KMIP_2_0.__lt__(enums.WrappingMethod.ENCRYPT) ) - class TestEnumUtilityFunctions(testtools.TestCase): def setUp(self): @@ -179,6 +177,23 @@ def test_convert_attribute_name_to_tag(self): *args ) + def test_convert_attribute_name_to_tag_case_and_whitespace(self): + args = ("object type", ) + self.assertRaisesRegex( + ValueError, + "Unrecognized attribute name: 'object type'", + enums.convert_attribute_name_to_tag, + *args + ) + + args = (" Object Type ", ) + self.assertRaisesRegex( + ValueError, + "Unrecognized attribute name: ' Object Type '", + enums.convert_attribute_name_to_tag, + *args + ) + def test_convert_attribute_tag_to_name(self): self.assertEqual( "Always Sensitive", diff --git a/kmip/tests/unit/core/test_exceptions_extended.py b/kmip/tests/unit/core/test_exceptions_extended.py new file mode 100644 index 00000000..09dcc962 --- /dev/null +++ b/kmip/tests/unit/core/test_exceptions_extended.py @@ -0,0 +1,131 @@ +# Copyright (c) 2026 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 testtools + +from kmip.core import enums +from kmip.core import exceptions + + +def _build_exception_instances(): + status = enums.ResultStatus.OPERATION_FAILED + reason = enums.ResultReason.GENERAL_FAILURE + + return [ + exceptions.KmipError(status, reason, "base"), + exceptions.CryptographicFailure("crypto"), + exceptions.EncodingOptionError("encoding"), + exceptions.IllegalOperation("illegal"), + exceptions.IndexOutOfBounds("index"), + exceptions.InvalidField("invalid field"), + exceptions.InvalidMessage("invalid message"), + exceptions.ItemNotFound("not found"), + exceptions.KeyCompressionTypeNotSupported("compression"), + exceptions.KeyFormatTypeNotSupported("format"), + exceptions.OperationFailure(status, reason, "operation failed"), + exceptions.OperationNotSupported("op not supported"), + exceptions.PermissionDenied("denied"), + exceptions.AttributeNotSupported("attr"), + exceptions.ConfigurationError("config"), + exceptions.ConnectionClosed("closed"), + exceptions.NetworkingError("network"), + exceptions.InvalidKmipEncoding("encoding"), + exceptions.InvalidPaddingBytes("padding"), + exceptions.InvalidPrimitiveLength("length"), + exceptions.ShutdownError("shutdown"), + exceptions.VersionNotSupported("version"), + exceptions.StreamNotEmptyError("Foo", 7), + exceptions.ReadValueError("Foo", "bar", "exp", "recv"), + exceptions.WriteOverflowError("Foo", "bar", 1, 2), + exceptions.KMIPServerZombieError(123), + exceptions.KMIPServerSuicideError(321) + ] + + +class TestExceptionsExtended(testtools.TestCase): + def test_each_exception_class_init(self): + for exc in _build_exception_instances(): + self.assertIsInstance(exc, Exception) + + def test_each_exception_str_repr(self): + for exc in _build_exception_instances(): + self.assertIsInstance(str(exc), str) + self.assertIsInstance(repr(exc), str) + + def test_exception_hierarchy(self): + kmip_subclasses = [ + exceptions.CryptographicFailure, + exceptions.EncodingOptionError, + exceptions.IllegalOperation, + exceptions.IndexOutOfBounds, + exceptions.InvalidField, + exceptions.InvalidMessage, + exceptions.ItemNotFound, + exceptions.KeyCompressionTypeNotSupported, + exceptions.KeyFormatTypeNotSupported, + exceptions.OperationFailure, + exceptions.OperationNotSupported, + exceptions.PermissionDenied + ] + for cls in kmip_subclasses: + instance = cls("message") if cls is not exceptions.OperationFailure \ + else cls(enums.ResultStatus.OPERATION_FAILED, + enums.ResultReason.GENERAL_FAILURE, + "operation failed") + self.assertIsInstance(instance, exceptions.KmipError) + + def test_kmip_operation_failure_attributes(self): + status = enums.ResultStatus.OPERATION_FAILED + reason = enums.ResultReason.GENERAL_FAILURE + message = "operation failed" + exc = exceptions.OperationFailure(status, reason, message) + self.assertEqual(status, exc.status) + self.assertEqual(reason, exc.reason) + self.assertEqual(message, str(exc)) + self.assertEqual(message, exc.args[0]) + + def test_stream_not_empty_error_str(self): + exc = exceptions.StreamNotEmptyError("Foo", 3) + self.assertEqual( + "Invalid length used to read Foo, bytes remaining: 3", + str(exc) + ) + + def test_read_value_error_str(self): + exc = exceptions.ReadValueError("Foo", "bar", "exp", "recv") + self.assertEqual( + "Tried to read Foo.bar: expected exp, received recv", + str(exc) + ) + + def test_write_overflow_error_str(self): + exc = exceptions.WriteOverflowError("Foo", "bar", 1, 2) + self.assertEqual( + "Tried to write Foo.bar with too many bytes: expected 1, " + "received 2", + str(exc) + ) + + def test_kmip_server_errors_str(self): + zombie = exceptions.KMIPServerZombieError(10) + suicide = exceptions.KMIPServerSuicideError(20) + self.assertEqual( + "KMIP server alive after termination: PID 10", + str(zombie) + ) + self.assertEqual( + "KMIP server dead prematurely: PID 20", + str(suicide) + ) diff --git a/kmip/tests/unit/core/test_policy.py b/kmip/tests/unit/core/test_policy.py index 510b5e0b..fc81d6df 100644 --- a/kmip/tests/unit/core/test_policy.py +++ b/kmip/tests/unit/core/test_policy.py @@ -14,13 +14,13 @@ # under the License. import shutil +import re import tempfile import testtools from kmip.core import enums from kmip.core import policy - class TestPolicy(testtools.TestCase): def setUp(self): @@ -256,12 +256,13 @@ def test_read_policy_from_file_empty(self): dir=self.temp_dir, delete=False ) + policy_file.close() with open(policy_file.name, 'w') as f: f.write('') args = (policy_file.name, ) regex = "Loading the policy file '{}' generated a JSON error:".format( - policy_file.name + re.escape(policy_file.name) ) self.assertRaisesRegex( ValueError, @@ -278,6 +279,7 @@ def test_read_policy_from_file_empty_policy(self): dir=self.temp_dir, delete=False ) + policy_file.close() with open(policy_file.name, 'w') as f: f.write( '{"test": {}}' diff --git a/kmip/tests/unit/core/test_policy_extended.py b/kmip/tests/unit/core/test_policy_extended.py new file mode 100644 index 00000000..e28af41e --- /dev/null +++ b/kmip/tests/unit/core/test_policy_extended.py @@ -0,0 +1,98 @@ +# Copyright (c) 2026 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 os +import re +import tempfile + +import testtools + +from kmip.core import enums +from kmip.core import policy + + +class TestPolicyExtended(testtools.TestCase): + def setUp(self): + super(TestPolicyExtended, self).setUp() + self.temp_dir = tempfile.mkdtemp() + self.addCleanup(self._cleanup_temp_dir) + + def _cleanup_temp_dir(self): + for root, _, files in os.walk(self.temp_dir): + for filename in files: + os.remove(os.path.join(root, filename)) + os.rmdir(self.temp_dir) + + def _write_policy(self, content): + path = os.path.join(self.temp_dir, "policy.json") + with open(path, "w") as handle: + handle.write(content) + return path + + def test_parse_policy_from_file(self): + policy_path = self._write_policy( + '{"default": {"preset": {"CERTIFICATE": {"LOCATE": "ALLOW_ALL"}}}}' + ) + policies = policy.read_policy_from_file(policy_path) + self.assertIn("default", policies) + preset = policies["default"]["preset"] + self.assertEqual( + enums.Policy.ALLOW_ALL, + preset[enums.ObjectType.CERTIFICATE][enums.Operation.LOCATE] + ) + + def test_parse_policy_invalid_json(self): + policy_path = self._write_policy("{") + error = "Loading the policy file '{}' generated a JSON error:".format( + policy_path + ) + self.assertRaisesRegex( + ValueError, + re.escape(error), + policy.read_policy_from_file, + policy_path + ) + + def test_policy_default_permissions(self): + default = policy.policies["default"]["preset"] + self.assertEqual( + enums.Policy.ALLOW_ALL, + default[enums.ObjectType.CERTIFICATE][enums.Operation.LOCATE] + ) + + def test_policy_custom_permissions(self): + public = policy.policies["public"]["preset"] + self.assertEqual( + enums.Policy.DISALLOW_ALL, + public[enums.ObjectType.TEMPLATE][enums.Operation.ADD_ATTRIBUTE] + ) + + def test_policy_check_allowed(self): + default = policy.policies["default"]["preset"] + allowed = default[enums.ObjectType.CERTIFICATE][enums.Operation.GET] + self.assertEqual(enums.Policy.ALLOW_ALL, allowed) + + def test_policy_check_denied(self): + public = policy.policies["public"]["preset"] + denied = public[enums.ObjectType.TEMPLATE][enums.Operation.DESTROY] + self.assertEqual(enums.Policy.DISALLOW_ALL, denied) + + def test_policy_unknown_object_type(self): + object_policy = {"INVALID": {"LOCATE": "ALLOW_ALL"}} + self.assertRaises(ValueError, policy.parse_policy, object_policy) + + def test_policy_unknown_operation(self): + object_policy = {"CERTIFICATE": {"INVALID": "ALLOW_ALL"}} + self.assertRaises(ValueError, policy.parse_policy, object_policy) diff --git a/kmip/tests/unit/core/test_primitives_extended.py b/kmip/tests/unit/core/test_primitives_extended.py new file mode 100644 index 00000000..f19160db --- /dev/null +++ b/kmip/tests/unit/core/test_primitives_extended.py @@ -0,0 +1,1667 @@ + +# Copyright (c) 2014 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 enum +import struct +import time + +import testtools +from unittest import mock + +from kmip.core import enums +from kmip.core import exceptions +from kmip.core import primitives +from kmip.core import utils + + +def _ttlv(tag, typ, length, value_bytes): + return ( + struct.pack('!I', tag.value)[1:] + + struct.pack('!B', typ.value) + + struct.pack('!I', length) + + value_bytes + ) + + +def _pad_to_eight(value_bytes): + pad_len = (8 - (len(value_bytes) % 8)) % 8 + return value_bytes + (b'\x00' * pad_len) + + +def _encode_integer(tag, value): + return _ttlv( + tag, + enums.Types.INTEGER, + 4, + _pad_to_eight(struct.pack('!i', value)) + ) + + +def _encode_long_integer(tag, typ, value): + return _ttlv(tag, typ, 8, struct.pack('!q', value)) + + +def _encode_unsigned_int(tag, typ, value): + return _ttlv( + tag, + typ, + 4, + _pad_to_eight(struct.pack('!I', value)) + ) + + +def _encode_boolean(tag, value): + return _ttlv(tag, enums.Types.BOOLEAN, 8, struct.pack('!Q', value)) + + +def _encode_text(tag, value): + value_bytes = value.encode() + return _ttlv( + tag, + enums.Types.TEXT_STRING, + len(value_bytes), + _pad_to_eight(value_bytes) + ) + + +def _encode_bytes(tag, value_bytes): + return _ttlv( + tag, + enums.Types.BYTE_STRING, + len(value_bytes), + _pad_to_eight(value_bytes) + ) + + +def _encode_big_integer(tag, value_bytes): + return _ttlv(tag, enums.Types.BIG_INTEGER, len(value_bytes), value_bytes) + + +class SampleEnum(enum.Enum): + ONE = 1 + TWO = 2 + + +class EdgeEnum(enum.Enum): + MIN = 0 + MAX = 4294967295 + + +class LargeEnum(enum.Enum): + TOO_BIG = 4294967297 + TOO_SMALL = -1 + + +class TestBase(testtools.TestCase): + + def setUp(self): + super(TestBase, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestBase, self).tearDown() + + def test_init_with_none(self): + """Test Base initializes with defaults.""" + base = primitives.Base() + self.assertEqual(enums.Tags.DEFAULT, base.tag) + self.assertEqual(enums.Types.DEFAULT, base.type) + self.assertIsNone(base.length) + + def test_init_with_valid_value(self): + """Test Base accepts an explicit tag and type.""" + base = primitives.Base(tag=self.other_tag, type=enums.Types.INTEGER) + self.assertEqual(self.other_tag, base.tag) + self.assertEqual(enums.Types.INTEGER, base.type) + + def test_init_with_invalid_value(self): + """Test Base rejects invalid type values during write.""" + base = primitives.Base(type='invalid') + self.assertRaises(TypeError, base.write_type, self.stream) + + def test_init_with_tag(self): + """Test Base stores a custom tag.""" + base = primitives.Base(tag=self.other_tag) + self.assertEqual(self.other_tag, base.tag) + + def test_read_valid_encoding(self): + """Test Base reads a valid TTLV header.""" + encoding = _ttlv(self.tag, enums.Types.DEFAULT, 0, b'') + stream = utils.BytearrayStream(encoding) + base = primitives.Base() + base.read(stream) + self.assertEqual(0, base.length) + + def test_read_invalid_encoding(self): + """Test Base rejects a TTLV header with the wrong type.""" + encoding = _ttlv(self.tag, enums.Types.INTEGER, 0, b'') + stream = utils.BytearrayStream(encoding) + base = primitives.Base() + self.assertRaises(exceptions.ReadValueError, base.read, stream) + + def test_read_oversized(self): + """Test Base detects extra bytes after reading.""" + encoding = _ttlv(self.tag, enums.Types.DEFAULT, 0, b'') + b'\x00' + stream = utils.BytearrayStream(encoding) + base = primitives.Base() + base.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + base.is_oversized, stream) + + def test_write_valid(self): + """Test Base writes a valid TTLV header.""" + base = primitives.Base() + base.length = 0 + base.write(self.stream) + self.assertEqual( + _ttlv(self.tag, enums.Types.DEFAULT, 0, b''), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test Base read/write round-trip preserves header data.""" + base = primitives.Base() + base.length = 0 + stream = utils.BytearrayStream() + base.write(stream) + clone = primitives.Base() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(base.tag, clone.tag) + self.assertEqual(base.type, clone.type) + self.assertEqual(base.length, clone.length) + + def test_validate_valid(self): + """Test Base validate is abstract.""" + base = primitives.Base() + self.assertRaises(NotImplementedError, base.validate) + + def test_validate_invalid_type(self): + """Test Base validate is abstract for invalid types.""" + base = primitives.Base() + self.assertRaises(NotImplementedError, base.validate) + + def test_validate_out_of_range(self): + """Test Base validate is abstract for range checks.""" + base = primitives.Base() + self.assertRaises(NotImplementedError, base.validate) + + def test_eq_same_value(self): + """Test Base equality on identical objects.""" + base = primitives.Base() + self.assertTrue(base == base) + + def test_eq_different_value(self): + """Test Base inequality for different objects.""" + base_one = primitives.Base() + base_two = primitives.Base() + self.assertFalse(base_one == base_two) + + def test_eq_different_type(self): + """Test Base equality returns NotImplemented for other types.""" + base = primitives.Base() + self.assertIs(base.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Base inequality operator.""" + base_one = primitives.Base() + base_two = primitives.Base() + self.assertTrue(base_one != base_two) + + def test_hash_same_value(self): + """Test Base hashes consistently for the same object.""" + base = primitives.Base() + self.assertEqual(hash(base), hash(base)) + + def test_repr(self): + """Test Base representation includes the class name.""" + base = primitives.Base() + self.assertIn('Base', repr(base)) + + def test_str(self): + """Test Base string conversion includes the class name.""" + base = primitives.Base() + self.assertIn('Base', str(base)) + + def test_boundary_values(self): + """Test Base tag/type inspection helpers with boundary streams.""" + encoding = _ttlv(self.other_tag, enums.Types.INTEGER, 0, b'') + stream = utils.BytearrayStream(encoding) + empty = utils.BytearrayStream(b'') + self.assertTrue(primitives.Base.is_tag_next(self.other_tag, stream)) + self.assertTrue( + primitives.Base.is_type_next(enums.Types.INTEGER, stream)) + self.assertFalse(primitives.Base.is_tag_next(self.other_tag, empty)) + self.assertFalse( + primitives.Base.is_type_next(enums.Types.INTEGER, empty)) + +class TestStruct(testtools.TestCase): + + def setUp(self): + super(TestStruct, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestStruct, self).tearDown() + + def test_init_with_none(self): + """Test Struct initializes with defaults.""" + struct_obj = primitives.Struct() + self.assertEqual(enums.Tags.DEFAULT, struct_obj.tag) + self.assertEqual(enums.Types.STRUCTURE, struct_obj.type) + self.assertIsNone(struct_obj.length) + + def test_init_with_valid_value(self): + """Test Struct accepts a custom tag.""" + struct_obj = primitives.Struct(tag=self.other_tag) + self.assertEqual(self.other_tag, struct_obj.tag) + + def test_init_with_invalid_value(self): + """Test Struct rejects invalid type values during write.""" + struct_obj = primitives.Struct() + struct_obj.type = 'invalid' + self.assertRaises(TypeError, struct_obj.write_type, self.stream) + + def test_init_with_tag(self): + """Test Struct stores a custom tag.""" + struct_obj = primitives.Struct(tag=self.other_tag) + self.assertEqual(self.other_tag, struct_obj.tag) + + def test_read_valid_encoding(self): + """Test Struct reads a valid TTLV header.""" + encoding = _ttlv(self.tag, enums.Types.STRUCTURE, 0, b'') + stream = utils.BytearrayStream(encoding) + struct_obj = primitives.Struct() + struct_obj.read(stream) + self.assertEqual(0, struct_obj.length) + + def test_read_invalid_encoding(self): + """Test Struct rejects a TTLV header with the wrong type.""" + encoding = _ttlv(self.tag, enums.Types.INTEGER, 0, b'') + stream = utils.BytearrayStream(encoding) + struct_obj = primitives.Struct() + self.assertRaises(exceptions.ReadValueError, struct_obj.read, stream) + + def test_read_oversized(self): + """Test Struct detects extra bytes after reading.""" + encoding = _ttlv(self.tag, enums.Types.STRUCTURE, 0, b'') + b'\x00' + stream = utils.BytearrayStream(encoding) + struct_obj = primitives.Struct() + struct_obj.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + struct_obj.is_oversized, stream) + + def test_write_valid(self): + """Test Struct writes a valid TTLV header.""" + struct_obj = primitives.Struct() + struct_obj.length = 0 + struct_obj.write(self.stream) + self.assertEqual( + _ttlv(self.tag, enums.Types.STRUCTURE, 0, b''), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test Struct read/write round-trip preserves header data.""" + struct_obj = primitives.Struct() + struct_obj.length = 0 + stream = utils.BytearrayStream() + struct_obj.write(stream) + clone = primitives.Struct() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(struct_obj.tag, clone.tag) + self.assertEqual(struct_obj.type, clone.type) + self.assertEqual(struct_obj.length, clone.length) + + def test_validate_valid(self): + """Test Struct validate is abstract.""" + struct_obj = primitives.Struct() + self.assertRaises(NotImplementedError, struct_obj.validate) + + def test_validate_invalid_type(self): + """Test Struct validate is abstract for invalid types.""" + struct_obj = primitives.Struct() + self.assertRaises(NotImplementedError, struct_obj.validate) + + def test_validate_out_of_range(self): + """Test Struct validate is abstract for range checks.""" + struct_obj = primitives.Struct() + self.assertRaises(NotImplementedError, struct_obj.validate) + + def test_eq_same_value(self): + """Test Struct equality on identical objects.""" + struct_obj = primitives.Struct() + self.assertTrue(struct_obj == struct_obj) + + def test_eq_different_value(self): + """Test Struct inequality for different objects.""" + struct_one = primitives.Struct() + struct_two = primitives.Struct() + self.assertFalse(struct_one == struct_two) + + def test_eq_different_type(self): + """Test Struct equality returns NotImplemented for other types.""" + struct_obj = primitives.Struct() + self.assertIs(struct_obj.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Struct inequality operator.""" + struct_one = primitives.Struct() + struct_two = primitives.Struct() + self.assertTrue(struct_one != struct_two) + + def test_hash_same_value(self): + """Test Struct hashes consistently for the same object.""" + struct_obj = primitives.Struct() + self.assertEqual(hash(struct_obj), hash(struct_obj)) + + def test_repr(self): + """Test Struct representation formatting.""" + struct_obj = primitives.Struct() + self.assertEqual('Struct()', repr(struct_obj)) + + def test_str(self): + """Test Struct string conversion includes the class name.""" + struct_obj = primitives.Struct() + self.assertIn('Struct', str(struct_obj)) + + def test_boundary_values(self): + """Test Struct tag/type inspection helpers with boundary streams.""" + encoding = _ttlv(self.other_tag, enums.Types.STRUCTURE, 0, b'') + stream = utils.BytearrayStream(encoding) + empty = utils.BytearrayStream(b'') + self.assertTrue(primitives.Base.is_tag_next(self.other_tag, stream)) + self.assertTrue( + primitives.Base.is_type_next(enums.Types.STRUCTURE, stream)) + self.assertFalse(primitives.Base.is_tag_next(self.other_tag, empty)) + self.assertFalse( + primitives.Base.is_type_next(enums.Types.STRUCTURE, empty)) + + def test_empty_structure(self): + """Test encoding and decoding an empty structure.""" + struct_obj = primitives.Struct() + struct_obj.length = 0 + stream = utils.BytearrayStream() + struct_obj.write(stream) + clone = primitives.Struct() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(0, clone.length) + + def test_nested_structures(self): + """Test decoding nested structure headers.""" + inner = primitives.Struct(tag=enums.Tags.APPLICATION_DATA) + inner.length = 0 + inner_stream = utils.BytearrayStream() + inner.write(inner_stream) + inner_bytes = inner_stream.read() + + outer = primitives.Struct(tag=enums.Tags.APPLICATION_NAMESPACE) + outer.length = len(inner_bytes) + outer_stream = utils.BytearrayStream() + outer.write(outer_stream) + outer_bytes = outer_stream.read() + inner_bytes + + stream = utils.BytearrayStream(outer_bytes) + read_outer = primitives.Struct(tag=enums.Tags.APPLICATION_NAMESPACE) + read_outer.read(stream) + self.assertEqual(len(inner_bytes), read_outer.length) + + read_inner = primitives.Struct(tag=enums.Tags.APPLICATION_DATA) + read_inner.read(stream) + self.assertEqual(0, read_inner.length) + +class TestInteger(testtools.TestCase): + + def setUp(self): + super(TestInteger, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestInteger, self).tearDown() + + def test_init_with_none(self): + """Test Integer initializes with default values.""" + integer = primitives.Integer() + self.assertEqual(0, integer.value) + self.assertEqual(primitives.Integer.LENGTH, integer.length) + self.assertEqual(primitives.Integer.LENGTH, integer.padding_length) + + def test_init_with_valid_value(self): + """Test Integer initializes with a valid value.""" + integer = primitives.Integer(8) + self.assertEqual(8, integer.value) + + def test_init_with_invalid_value(self): + """Test Integer rejects invalid types.""" + self.assertRaises(TypeError, primitives.Integer, 'invalid') + + def test_init_with_tag(self): + """Test Integer stores a custom tag.""" + integer = primitives.Integer(1, tag=self.other_tag) + self.assertEqual(self.other_tag, integer.tag) + + def test_read_valid_encoding(self): + """Test Integer reads a valid TTLV encoding.""" + encoding = _encode_integer(self.tag, 8) + stream = utils.BytearrayStream(encoding) + integer = primitives.Integer() + integer.read(stream) + self.assertEqual(8, integer.value) + + def test_read_invalid_encoding(self): + """Test Integer rejects invalid TTLV lengths.""" + encoding = _ttlv(self.tag, enums.Types.INTEGER, 0, b'') + stream = utils.BytearrayStream(encoding) + integer = primitives.Integer() + self.assertRaises(exceptions.ReadValueError, integer.read, stream) + + def test_read_oversized(self): + """Test Integer detects extra bytes after reading.""" + encoding = _encode_integer(self.tag, 1) + b'\x00' + stream = utils.BytearrayStream(encoding) + integer = primitives.Integer() + integer.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + integer.is_oversized, stream) + + def test_write_valid(self): + """Test Integer writes a valid TTLV encoding.""" + integer = primitives.Integer(8) + integer.write(self.stream) + self.assertEqual(_encode_integer(self.tag, 8), self.stream.read()) + + def test_read_write_roundtrip(self): + """Test Integer read/write round-trip.""" + integer = primitives.Integer(-1) + stream = utils.BytearrayStream() + integer.write(stream) + clone = primitives.Integer() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(integer.value, clone.value) + + def test_validate_valid(self): + """Test Integer validate accepts valid values.""" + integer = primitives.Integer(0) + integer.validate() + + def test_validate_invalid_type(self): + """Test Integer validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.Integer, 'bad') + + def test_validate_out_of_range(self): + """Test Integer validate rejects out-of-range values.""" + self.assertRaises(ValueError, primitives.Integer, + primitives.Integer.MAX + 1) + self.assertRaises(ValueError, primitives.Integer, + primitives.Integer.MIN - 1) + + def test_eq_same_value(self): + """Test Integer equality for identical values.""" + self.assertTrue(primitives.Integer(1) == primitives.Integer(1)) + + def test_eq_different_value(self): + """Test Integer inequality for different values.""" + self.assertFalse(primitives.Integer(1) == primitives.Integer(2)) + + def test_eq_different_type(self): + """Test Integer equality returns NotImplemented for other types.""" + integer = primitives.Integer(1) + self.assertIs(integer.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Integer inequality operator.""" + self.assertTrue(primitives.Integer(1) != primitives.Integer(2)) + + def test_hash_same_value(self): + """Test Integer is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.Integer(1)) + + def test_repr(self): + """Test Integer representation formatting.""" + integer = primitives.Integer(8) + self.assertEqual('Integer(value=8)', repr(integer)) + + def test_str(self): + """Test Integer string conversion formatting.""" + self.assertEqual('8', str(primitives.Integer(8))) + + def test_max_value(self): + """Test Integer accepts the maximum value.""" + integer = primitives.Integer(primitives.Integer.MAX) + self.assertEqual(primitives.Integer.MAX, integer.value) + + def test_min_value(self): + """Test Integer accepts the minimum value.""" + integer = primitives.Integer(primitives.Integer.MIN) + self.assertEqual(primitives.Integer.MIN, integer.value) + + def test_boundary_values(self): + """Test Integer boundary values round-trip correctly.""" + values = [primitives.Integer.MIN, -1, 0, 1, primitives.Integer.MAX] + for value in values: + integer = primitives.Integer(value) + stream = utils.BytearrayStream() + integer.write(stream) + clone = primitives.Integer() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_specific_values(self): + """Test Integer negative, zero, and boundary values.""" + self.assertEqual(-5, primitives.Integer(-5).value) + self.assertEqual(0, primitives.Integer(0).value) + self.assertEqual(primitives.Integer.MAX, + primitives.Integer(primitives.Integer.MAX).value) + +class TestLongInteger(testtools.TestCase): + + def setUp(self): + super(TestLongInteger, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestLongInteger, self).tearDown() + + def test_init_with_none(self): + """Test LongInteger initializes with default values.""" + long_int = primitives.LongInteger() + self.assertEqual(0, long_int.value) + self.assertEqual(primitives.LongInteger.LENGTH, long_int.length) + + def test_init_with_valid_value(self): + """Test LongInteger initializes with a valid value.""" + long_int = primitives.LongInteger(5) + self.assertEqual(5, long_int.value) + + def test_init_with_invalid_value(self): + """Test LongInteger rejects invalid types.""" + self.assertRaises(TypeError, primitives.LongInteger, 'invalid') + + def test_init_with_tag(self): + """Test LongInteger stores a custom tag.""" + long_int = primitives.LongInteger(1, tag=self.other_tag) + self.assertEqual(self.other_tag, long_int.tag) + + def test_read_valid_encoding(self): + """Test LongInteger reads a valid TTLV encoding.""" + encoding = _encode_long_integer( + self.tag, enums.Types.LONG_INTEGER, 5) + stream = utils.BytearrayStream(encoding) + long_int = primitives.LongInteger() + long_int.read(stream) + self.assertEqual(5, long_int.value) + + def test_read_invalid_encoding(self): + """Test LongInteger rejects invalid TTLV lengths.""" + encoding = _ttlv(self.tag, enums.Types.LONG_INTEGER, 4, b'') + stream = utils.BytearrayStream(encoding) + long_int = primitives.LongInteger() + self.assertRaises(exceptions.InvalidPrimitiveLength, + long_int.read, stream) + + def test_read_oversized(self): + """Test LongInteger detects extra bytes after reading.""" + encoding = _encode_long_integer( + self.tag, enums.Types.LONG_INTEGER, 1) + b'\x00' + stream = utils.BytearrayStream(encoding) + long_int = primitives.LongInteger() + long_int.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + long_int.is_oversized, stream) + + def test_write_valid(self): + """Test LongInteger writes a valid TTLV encoding.""" + long_int = primitives.LongInteger(5) + long_int.write(self.stream) + self.assertEqual( + _encode_long_integer(self.tag, enums.Types.LONG_INTEGER, 5), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test LongInteger read/write round-trip.""" + long_int = primitives.LongInteger(1234567890123) + stream = utils.BytearrayStream() + long_int.write(stream) + clone = primitives.LongInteger() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(long_int.value, clone.value) + + def test_validate_valid(self): + """Test LongInteger validate accepts valid values.""" + long_int = primitives.LongInteger(0) + long_int.validate() + + def test_validate_invalid_type(self): + """Test LongInteger validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.LongInteger, 'bad') + + def test_validate_out_of_range(self): + """Test LongInteger validate rejects out-of-range values.""" + self.assertRaises(ValueError, primitives.LongInteger, + primitives.LongInteger.MAX + 1) + self.assertRaises(ValueError, primitives.LongInteger, + primitives.LongInteger.MIN - 1) + + def test_eq_same_value(self): + """Test LongInteger equality for identical values.""" + self.assertTrue(primitives.LongInteger(1) == primitives.LongInteger(1)) + + def test_eq_different_value(self): + """Test LongInteger inequality for different values.""" + self.assertFalse(primitives.LongInteger(1) == primitives.LongInteger(2)) + + def test_eq_different_type(self): + """Test LongInteger equality returns NotImplemented for other types.""" + long_int = primitives.LongInteger(1) + self.assertIs(long_int.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test LongInteger inequality operator.""" + self.assertTrue(primitives.LongInteger(1) != primitives.LongInteger(2)) + + def test_hash_same_value(self): + """Test LongInteger is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.LongInteger(1)) + + def test_repr(self): + """Test LongInteger representation formatting.""" + long_int = primitives.LongInteger(5) + self.assertEqual( + 'LongInteger(value=5, tag={0})'.format(enums.Tags.DEFAULT), + repr(long_int) + ) + + def test_str(self): + """Test LongInteger string conversion formatting.""" + self.assertEqual('5', str(primitives.LongInteger(5))) + + def test_boundary_values(self): + """Test LongInteger boundary values round-trip correctly.""" + values = [primitives.LongInteger.MIN, 0, primitives.LongInteger.MAX] + for value in values: + long_int = primitives.LongInteger(value) + stream = utils.BytearrayStream() + long_int.write(stream) + clone = primitives.LongInteger() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_specific_values(self): + """Test LongInteger supports values larger than 2^31.""" + value = 2 ** 40 + self.assertEqual(value, primitives.LongInteger(value).value) + +class TestBigInteger(testtools.TestCase): + + def setUp(self): + super(TestBigInteger, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestBigInteger, self).tearDown() + + def test_init_with_none(self): + """Test BigInteger initializes with a None value.""" + big_int = primitives.BigInteger(None) + self.assertIsNone(big_int.value) + + def test_init_with_valid_value(self): + """Test BigInteger initializes with a valid value.""" + big_int = primitives.BigInteger(1) + self.assertEqual(1, big_int.value) + + def test_init_with_invalid_value(self): + """Test BigInteger rejects invalid types.""" + self.assertRaises(TypeError, primitives.BigInteger, 'invalid') + + def test_init_with_tag(self): + """Test BigInteger stores a custom tag.""" + big_int = primitives.BigInteger(1, tag=self.other_tag) + self.assertEqual(self.other_tag, big_int.tag) + + def test_read_valid_encoding(self): + """Test BigInteger reads a valid TTLV encoding.""" + value_bytes = b'\x00' * 7 + b'\x01' + encoding = _encode_big_integer(self.tag, value_bytes) + stream = utils.BytearrayStream(encoding) + big_int = primitives.BigInteger() + big_int.read(stream) + self.assertEqual(1, big_int.value) + + def test_read_invalid_encoding(self): + """Test BigInteger rejects invalid TTLV lengths.""" + encoding = _ttlv(self.tag, enums.Types.BIG_INTEGER, 7, b'\x00' * 7) + stream = utils.BytearrayStream(encoding) + big_int = primitives.BigInteger() + self.assertRaises(exceptions.InvalidPrimitiveLength, + big_int.read, stream) + + def test_read_oversized(self): + """Test BigInteger detects extra bytes after reading.""" + value_bytes = b'\x00' * 7 + b'\x01' + encoding = _encode_big_integer(self.tag, value_bytes) + b'\x00' + stream = utils.BytearrayStream(encoding) + big_int = primitives.BigInteger() + big_int.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + big_int.is_oversized, stream) + + def test_write_valid(self): + """Test BigInteger writes a valid TTLV encoding.""" + big_int = primitives.BigInteger(1) + big_int.write(self.stream) + value_bytes = b'\x00' * 7 + b'\x01' + self.assertEqual( + _encode_big_integer(self.tag, value_bytes), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test BigInteger read/write round-trip for large values.""" + value = (1 << 1023) + 12345 + big_int = primitives.BigInteger(value) + stream = utils.BytearrayStream() + big_int.write(stream) + clone = primitives.BigInteger() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_validate_valid(self): + """Test BigInteger validate accepts valid values.""" + big_int = primitives.BigInteger(0) + big_int.validate() + + def test_validate_invalid_type(self): + """Test BigInteger validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.BigInteger, 'bad') + + def test_eq_same_value(self): + """Test BigInteger equality for identical values.""" + self.assertTrue(primitives.BigInteger(1) == primitives.BigInteger(1)) + + def test_eq_different_value(self): + """Test BigInteger inequality for different values.""" + self.assertFalse(primitives.BigInteger(1) == primitives.BigInteger(2)) + + def test_eq_different_type(self): + """Test BigInteger equality returns NotImplemented for other types.""" + big_int = primitives.BigInteger(1) + self.assertIs(big_int.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test BigInteger inequality operator.""" + self.assertTrue(primitives.BigInteger(1) != primitives.BigInteger(2)) + + def test_hash_same_value(self): + """Test BigInteger is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.BigInteger(1)) + + def test_repr(self): + """Test BigInteger representation formatting.""" + big_int = primitives.BigInteger(5) + self.assertEqual( + 'BigInteger(value=5, tag={0})'.format(enums.Tags.DEFAULT), + repr(big_int) + ) + + def test_str(self): + """Test BigInteger string conversion formatting.""" + self.assertEqual('5', str(primitives.BigInteger(5))) + + def test_boundary_values(self): + """Test BigInteger boundary values round-trip correctly.""" + values = [0, 1, (1 << 64) - 1] + for value in values: + big_int = primitives.BigInteger(value) + stream = utils.BytearrayStream() + big_int.write(stream) + clone = primitives.BigInteger() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_specific_values(self): + """Test BigInteger supports 1024-bit values.""" + value = (1 << 1023) + 1 + self.assertEqual(value, primitives.BigInteger(value).value) + +class TestEnumeration(testtools.TestCase): + + def setUp(self): + super(TestEnumeration, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestEnumeration, self).tearDown() + + def test_init_with_none(self): + """Test Enumeration initializes with a None value.""" + enum_obj = primitives.Enumeration(SampleEnum, value=None) + self.assertIsNone(enum_obj.value) + + def test_init_with_valid_value(self): + """Test Enumeration initializes with a valid value.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE) + self.assertEqual(SampleEnum.ONE, enum_obj.value) + + def test_init_with_invalid_value(self): + """Test Enumeration rejects invalid enum values.""" + self.assertRaises(TypeError, primitives.Enumeration, SampleEnum, 1) + + def test_init_with_tag(self): + """Test Enumeration stores a custom tag.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE, + tag=self.other_tag) + self.assertEqual(self.other_tag, enum_obj.tag) + + def test_read_valid_encoding(self): + """Test Enumeration reads a valid TTLV encoding.""" + encoding = _encode_unsigned_int( + self.tag, enums.Types.ENUMERATION, SampleEnum.ONE.value) + stream = utils.BytearrayStream(encoding) + enum_obj = primitives.Enumeration(SampleEnum) + enum_obj.read(stream) + self.assertEqual(SampleEnum.ONE, enum_obj.value) + + def test_read_invalid_encoding(self): + """Test Enumeration rejects invalid padding bytes.""" + value_bytes = struct.pack('!I', SampleEnum.ONE.value) + b'\x00\x00\x00\x01' + encoding = _ttlv(self.tag, enums.Types.ENUMERATION, 4, value_bytes) + stream = utils.BytearrayStream(encoding) + enum_obj = primitives.Enumeration(SampleEnum) + self.assertRaises(exceptions.InvalidPaddingBytes, + enum_obj.read, stream) + + def test_read_oversized(self): + """Test Enumeration detects extra bytes after reading.""" + encoding = _encode_unsigned_int( + self.tag, enums.Types.ENUMERATION, SampleEnum.ONE.value) + b'\x00' + stream = utils.BytearrayStream(encoding) + enum_obj = primitives.Enumeration(SampleEnum) + enum_obj.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + enum_obj.is_oversized, stream) + + def test_write_valid(self): + """Test Enumeration writes a valid TTLV encoding.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE) + enum_obj.write(self.stream) + self.assertEqual( + _encode_unsigned_int( + self.tag, enums.Types.ENUMERATION, SampleEnum.ONE.value), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test Enumeration read/write round-trip.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.TWO) + stream = utils.BytearrayStream() + enum_obj.write(stream) + clone = primitives.Enumeration(SampleEnum) + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(enum_obj.value, clone.value) + + def test_validate_valid(self): + """Test Enumeration validate accepts valid values.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE) + enum_obj.validate() + + def test_validate_invalid_type(self): + """Test Enumeration validate rejects invalid enum types.""" + self.assertRaises(TypeError, primitives.Enumeration, 'bad', None) + + def test_validate_out_of_range(self): + """Test Enumeration validate rejects out-of-range values.""" + self.assertRaises(ValueError, + primitives.Enumeration, LargeEnum, LargeEnum.TOO_BIG) + self.assertRaises(ValueError, + primitives.Enumeration, LargeEnum, LargeEnum.TOO_SMALL) + + def test_eq_same_value(self): + """Test Enumeration equality for identical values.""" + self.assertTrue( + primitives.Enumeration(SampleEnum, SampleEnum.ONE) == + primitives.Enumeration(SampleEnum, SampleEnum.ONE) + ) + + def test_eq_different_value(self): + """Test Enumeration inequality for different values.""" + self.assertFalse( + primitives.Enumeration(SampleEnum, SampleEnum.ONE) == + primitives.Enumeration(SampleEnum, SampleEnum.TWO) + ) + + def test_eq_different_type(self): + """Test Enumeration equality returns NotImplemented for other types.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE) + self.assertIs(enum_obj.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Enumeration inequality operator.""" + self.assertTrue( + primitives.Enumeration(SampleEnum, SampleEnum.ONE) != + primitives.Enumeration(SampleEnum, SampleEnum.TWO) + ) + + def test_hash_same_value(self): + """Test Enumeration is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, + primitives.Enumeration(SampleEnum, SampleEnum.ONE)) + + def test_repr(self): + """Test Enumeration representation formatting.""" + enum_obj = primitives.Enumeration(SampleEnum, SampleEnum.ONE) + self.assertIn('Enumeration(enum=SampleEnum', repr(enum_obj)) + self.assertIn('value=SampleEnum.ONE', repr(enum_obj)) + self.assertIn('tag=Tags.DEFAULT', repr(enum_obj)) + + def test_str(self): + """Test Enumeration string conversion formatting.""" + self.assertEqual('SampleEnum.ONE', + str(primitives.Enumeration(SampleEnum, SampleEnum.ONE))) + + def test_boundary_values(self): + """Test Enumeration boundary values round-trip correctly.""" + for value in (EdgeEnum.MIN, EdgeEnum.MAX): + enum_obj = primitives.Enumeration(EdgeEnum, value) + stream = utils.BytearrayStream() + enum_obj.write(stream) + clone = primitives.Enumeration(EdgeEnum) + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_specific_values(self): + """Test Enumeration with valid and invalid enum values.""" + self.assertEqual(SampleEnum.ONE, + primitives.Enumeration(SampleEnum, SampleEnum.ONE).value) + self.assertRaises(TypeError, primitives.Enumeration, SampleEnum, 'bad') + +class TestBoolean(testtools.TestCase): + + def setUp(self): + super(TestBoolean, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestBoolean, self).tearDown() + + def test_init_with_none(self): + """Test Boolean initializes with a None value.""" + boolean = primitives.Boolean(None) + self.assertIsNone(boolean.value) + self.assertEqual(primitives.Boolean.LENGTH, boolean.length) + + def test_init_with_valid_value(self): + """Test Boolean initializes with a valid value.""" + boolean = primitives.Boolean(True) + self.assertTrue(boolean.value) + + def test_init_with_invalid_value(self): + """Test Boolean rejects invalid values.""" + self.assertRaises(TypeError, primitives.Boolean, 1) + + def test_init_with_tag(self): + """Test Boolean stores a custom tag.""" + boolean = primitives.Boolean(True, tag=self.other_tag) + self.assertEqual(self.other_tag, boolean.tag) + + def test_read_valid_encoding(self): + """Test Boolean reads a valid TTLV encoding.""" + encoding = _encode_boolean(self.tag, 1) + stream = utils.BytearrayStream(encoding) + boolean = primitives.Boolean() + boolean.read(stream) + self.assertTrue(boolean.value) + + def test_read_invalid_encoding(self): + """Test Boolean rejects invalid TTLV values.""" + encoding = _encode_boolean(self.tag, 2) + stream = utils.BytearrayStream(encoding) + boolean = primitives.Boolean() + self.assertRaises(ValueError, boolean.read, stream) + + def test_read_oversized(self): + """Test Boolean detects extra bytes after reading.""" + encoding = _encode_boolean(self.tag, 0) + b'\x00' + stream = utils.BytearrayStream(encoding) + boolean = primitives.Boolean() + boolean.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + boolean.is_oversized, stream) + + def test_write_valid(self): + """Test Boolean writes a valid TTLV encoding.""" + boolean = primitives.Boolean(True) + boolean.write(self.stream) + self.assertEqual(_encode_boolean(self.tag, 1), self.stream.read()) + + def test_read_write_roundtrip(self): + """Test Boolean read/write round-trip.""" + boolean = primitives.Boolean(False) + stream = utils.BytearrayStream() + boolean.write(stream) + clone = primitives.Boolean() + clone.read(utils.BytearrayStream(stream.read())) + self.assertFalse(clone.value) + + def test_validate_valid(self): + """Test Boolean validate accepts valid values.""" + boolean = primitives.Boolean(True) + boolean.validate() + + def test_validate_invalid_type(self): + """Test Boolean validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.Boolean, 'bad') + + def test_eq_same_value(self): + """Test Boolean equality for identical values.""" + self.assertTrue(primitives.Boolean(True) == primitives.Boolean(True)) + + def test_eq_different_value(self): + """Test Boolean inequality for different values.""" + self.assertFalse(primitives.Boolean(True) == primitives.Boolean(False)) + + def test_eq_different_type(self): + """Test Boolean equality returns NotImplemented for other types.""" + boolean = primitives.Boolean(True) + self.assertIs(boolean.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Boolean inequality operator.""" + self.assertTrue(primitives.Boolean(True) != primitives.Boolean(False)) + + def test_hash_same_value(self): + """Test Boolean is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.Boolean(True)) + + def test_repr(self): + """Test Boolean representation formatting.""" + boolean = primitives.Boolean(True) + self.assertEqual('Boolean(value=True)', repr(boolean)) + + def test_str(self): + """Test Boolean string conversion formatting.""" + self.assertEqual('True', str(primitives.Boolean(True))) + + def test_boundary_values(self): + """Test Boolean accepts True and False values.""" + self.assertTrue(primitives.Boolean(True).value) + self.assertFalse(primitives.Boolean(False).value) + + def test_specific_values(self): + """Test Boolean handling of True/False/None/0/1.""" + self.assertIsNone(primitives.Boolean(None).value) + self.assertEqual(0, primitives.Boolean(0).value) + self.assertTrue(primitives.Boolean(True).value) + self.assertFalse(primitives.Boolean(False).value) + self.assertRaises(TypeError, primitives.Boolean, 1) + +class TestTextString(testtools.TestCase): + + def setUp(self): + super(TestTextString, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestTextString, self).tearDown() + + def test_init_with_none(self): + """Test TextString initializes with empty string.""" + text = primitives.TextString(None) + self.assertEqual('', text.value) + + def test_init_with_valid_value(self): + """Test TextString initializes with a valid value.""" + text = primitives.TextString('test') + self.assertEqual('test', text.value) + + def test_init_with_invalid_value(self): + """Test TextString rejects invalid types.""" + self.assertRaises(TypeError, primitives.TextString, b'bad') + + def test_init_with_tag(self): + """Test TextString stores a custom tag.""" + text = primitives.TextString('test', tag=self.other_tag) + self.assertEqual(self.other_tag, text.tag) + + def test_read_valid_encoding(self): + """Test TextString reads a valid TTLV encoding.""" + encoding = _encode_text(self.tag, 'test') + stream = utils.BytearrayStream(encoding) + text = primitives.TextString() + text.read(stream) + self.assertEqual('test', text.value) + + def test_read_invalid_encoding(self): + """Test TextString rejects invalid padding bytes.""" + value_bytes = b'test' + b'\x00\x00\x00\x01' + encoding = _ttlv(self.tag, enums.Types.TEXT_STRING, 4, value_bytes) + stream = utils.BytearrayStream(encoding) + text = primitives.TextString() + self.assertRaises(exceptions.ReadValueError, text.read, stream) + + def test_read_oversized(self): + """Test TextString detects extra bytes after reading.""" + encoding = _encode_text(self.tag, 'test') + b'\x00' + stream = utils.BytearrayStream(encoding) + text = primitives.TextString() + text.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + text.is_oversized, stream) + + def test_write_valid(self): + """Test TextString writes a valid TTLV encoding.""" + text = primitives.TextString('test') + text.write(self.stream) + self.assertEqual(_encode_text(self.tag, 'test'), self.stream.read()) + + def test_read_write_roundtrip(self): + """Test TextString read/write round-trip.""" + text = primitives.TextString('roundtrip') + stream = utils.BytearrayStream() + text.write(stream) + clone = primitives.TextString() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(text.value, clone.value) + + def test_validate_valid(self): + """Test TextString validate accepts valid values.""" + text = primitives.TextString('ok') + text.validate() + + def test_validate_invalid_type(self): + """Test TextString validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.TextString, b'bad') + + def test_eq_same_value(self): + """Test TextString equality for identical values.""" + self.assertTrue(primitives.TextString('a') == primitives.TextString('a')) + + def test_eq_different_value(self): + """Test TextString inequality for different values.""" + self.assertFalse(primitives.TextString('a') == primitives.TextString('b')) + + def test_eq_different_type(self): + """Test TextString equality returns NotImplemented for other types.""" + text = primitives.TextString('a') + self.assertIs(text.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test TextString inequality operator.""" + self.assertTrue(primitives.TextString('a') != primitives.TextString('b')) + + def test_hash_same_value(self): + """Test TextString is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.TextString('a')) + + def test_repr(self): + """Test TextString representation formatting.""" + text = primitives.TextString('test') + self.assertEqual("TextString(value='test')", repr(text)) + + def test_str(self): + """Test TextString string conversion formatting.""" + self.assertEqual('test', str(primitives.TextString('test'))) + + def test_empty_value(self): + """Test TextString handles empty values.""" + self.assertEqual('', primitives.TextString('').value) + + def test_boundary_values(self): + """Test TextString padding boundary lengths.""" + value_eight = 'a' * 8 + value_nine = 'b' * 9 + text_eight = primitives.TextString(value_eight) + text_nine = primitives.TextString(value_nine) + self.assertEqual(0, text_eight.padding_length) + self.assertEqual(7, text_nine.padding_length) + + def test_specific_values(self): + """Test TextString unicode, empty, and long values.""" + unicode_value = 'Unicode-' + chr(0x2603) + long_value = 'x' * 1024 + self.assertEqual(unicode_value, + primitives.TextString(unicode_value).value) + self.assertEqual('', primitives.TextString('').value) + self.assertEqual(long_value, primitives.TextString(long_value).value) + +class TestByteString(testtools.TestCase): + + def setUp(self): + super(TestByteString, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestByteString, self).tearDown() + + def test_init_with_none(self): + """Test ByteString initializes with empty bytes.""" + data = primitives.ByteString(None) + self.assertEqual(b'', data.value) + + def test_init_with_valid_value(self): + """Test ByteString initializes with a valid value.""" + data = primitives.ByteString(b'\x01\x02') + self.assertEqual(b'\x01\x02', data.value) + + def test_init_with_invalid_value(self): + """Test ByteString rejects invalid types.""" + self.assertRaises(TypeError, primitives.ByteString, 'bad') + + def test_init_with_tag(self): + """Test ByteString stores a custom tag.""" + data = primitives.ByteString(b'\x01', tag=self.other_tag) + self.assertEqual(self.other_tag, data.tag) + + def test_read_valid_encoding(self): + """Test ByteString reads a valid TTLV encoding.""" + encoding = _encode_bytes(self.tag, b'\x01\x02\x03') + stream = utils.BytearrayStream(encoding) + data = primitives.ByteString() + data.read(stream) + self.assertEqual(b'\x01\x02\x03', data.value) + + def test_read_invalid_encoding(self): + """Test ByteString rejects invalid padding bytes.""" + value_bytes = b'\x01\x02\x03' + b'\x00\x00\x00\x01\x00' + encoding = _ttlv(self.tag, enums.Types.BYTE_STRING, 3, value_bytes) + stream = utils.BytearrayStream(encoding) + data = primitives.ByteString() + self.assertRaises(exceptions.ReadValueError, data.read, stream) + + def test_read_oversized(self): + """Test ByteString detects extra bytes after reading.""" + encoding = _encode_bytes(self.tag, b'\x01') + b'\x00' + stream = utils.BytearrayStream(encoding) + data = primitives.ByteString() + data.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + data.is_oversized, stream) + + def test_write_valid(self): + """Test ByteString writes a valid TTLV encoding.""" + data = primitives.ByteString(b'\x01\x02\x03') + data.write(self.stream) + self.assertEqual( + _encode_bytes(self.tag, b'\x01\x02\x03'), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test ByteString read/write round-trip.""" + data = primitives.ByteString(b'roundtrip') + stream = utils.BytearrayStream() + data.write(stream) + clone = primitives.ByteString() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(data.value, clone.value) + + def test_validate_valid(self): + """Test ByteString validate accepts valid values.""" + data = primitives.ByteString(b'\x01') + data.validate() + + def test_validate_invalid_type(self): + """Test ByteString validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.ByteString, 'bad') + + def test_eq_same_value(self): + """Test ByteString equality for identical values.""" + self.assertTrue(primitives.ByteString(b'a') == + primitives.ByteString(b'a')) + + def test_eq_different_value(self): + """Test ByteString inequality for different values.""" + self.assertFalse(primitives.ByteString(b'a') == + primitives.ByteString(b'b')) + + def test_eq_different_type(self): + """Test ByteString equality returns NotImplemented for other types.""" + data = primitives.ByteString(b'a') + self.assertIs(data.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test ByteString inequality operator.""" + self.assertTrue(primitives.ByteString(b'a') != + primitives.ByteString(b'b')) + + def test_hash_same_value(self): + """Test ByteString is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.ByteString(b'a')) + + def test_repr(self): + """Test ByteString representation formatting.""" + data = primitives.ByteString(b'\x01') + self.assertEqual("ByteString(value=b'\\x01')", repr(data)) + + def test_str(self): + """Test ByteString string conversion formatting.""" + self.assertEqual("b'\\x01'", str(primitives.ByteString(b'\x01'))) + + def test_empty_value(self): + """Test ByteString handles empty values.""" + self.assertEqual(b'', primitives.ByteString(b'').value) + + def test_boundary_values(self): + """Test ByteString padding boundary lengths.""" + value_eight = b'a' * 8 + value_nine = b'b' * 9 + data_eight = primitives.ByteString(value_eight) + data_nine = primitives.ByteString(value_nine) + self.assertEqual(0, data_eight.padding_length) + self.assertEqual(7, data_nine.padding_length) + + def test_specific_values(self): + """Test ByteString empty and repeated byte values.""" + self.assertEqual(b'', primitives.ByteString(b'').value) + self.assertEqual(b'\x00' * 16, + primitives.ByteString(b'\x00' * 16).value) + +class TestDateTime(testtools.TestCase): + + def setUp(self): + super(TestDateTime, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestDateTime, self).tearDown() + + def test_init_with_none(self): + """Test DateTime initializes from current time.""" + with mock.patch('time.time', return_value=1234567890): + date_time = primitives.DateTime() + self.assertEqual(1234567890, date_time.value) + + def test_init_with_valid_value(self): + """Test DateTime initializes with a valid value.""" + date_time = primitives.DateTime(0) + self.assertEqual(0, date_time.value) + + def test_init_with_invalid_value(self): + """Test DateTime rejects invalid types.""" + self.assertRaises(TypeError, primitives.DateTime, 'invalid') + + def test_init_with_tag(self): + """Test DateTime stores a custom tag.""" + date_time = primitives.DateTime(0, tag=self.other_tag) + self.assertEqual(self.other_tag, date_time.tag) + + def test_read_valid_encoding(self): + """Test DateTime reads a valid TTLV encoding.""" + encoding = _encode_long_integer( + self.tag, enums.Types.DATE_TIME, 0) + stream = utils.BytearrayStream(encoding) + date_time = primitives.DateTime(0) + date_time.read(stream) + self.assertEqual(0, date_time.value) + + def test_read_invalid_encoding(self): + """Test DateTime rejects invalid TTLV lengths.""" + encoding = _ttlv(self.tag, enums.Types.DATE_TIME, 4, b'') + stream = utils.BytearrayStream(encoding) + date_time = primitives.DateTime(0) + self.assertRaises(exceptions.InvalidPrimitiveLength, + date_time.read, stream) + + def test_read_oversized(self): + """Test DateTime detects extra bytes after reading.""" + encoding = _encode_long_integer( + self.tag, enums.Types.DATE_TIME, 0) + b'\x00' + stream = utils.BytearrayStream(encoding) + date_time = primitives.DateTime(0) + date_time.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + date_time.is_oversized, stream) + + def test_write_valid(self): + """Test DateTime writes a valid TTLV encoding.""" + date_time = primitives.DateTime(0) + date_time.write(self.stream) + self.assertEqual( + _encode_long_integer(self.tag, enums.Types.DATE_TIME, 0), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test DateTime read/write round-trip.""" + date_time = primitives.DateTime(1439299135) + stream = utils.BytearrayStream() + date_time.write(stream) + clone = primitives.DateTime(0) + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(date_time.value, clone.value) + + def test_validate_valid(self): + """Test DateTime validate accepts valid values.""" + date_time = primitives.DateTime(0) + date_time.validate() + + def test_validate_invalid_type(self): + """Test DateTime validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.DateTime, 'bad') + + def test_validate_out_of_range(self): + """Test DateTime validate rejects out-of-range values.""" + self.assertRaises(ValueError, primitives.DateTime, + primitives.LongInteger.MAX + 1) + + def test_eq_same_value(self): + """Test DateTime equality for identical values.""" + self.assertTrue(primitives.DateTime(1) == primitives.DateTime(1)) + + def test_eq_different_value(self): + """Test DateTime inequality for different values.""" + self.assertFalse(primitives.DateTime(1) == primitives.DateTime(2)) + + def test_eq_different_type(self): + """Test DateTime equality returns NotImplemented for other types.""" + date_time = primitives.DateTime(1) + self.assertIs(date_time.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test DateTime inequality operator.""" + self.assertTrue(primitives.DateTime(1) != primitives.DateTime(2)) + + def test_hash_same_value(self): + """Test DateTime is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.DateTime(1)) + + def test_repr(self): + """Test DateTime representation formatting.""" + date_time = primitives.DateTime(0) + self.assertEqual( + 'DateTime(value=0, tag={0})'.format(enums.Tags.DEFAULT), + repr(date_time) + ) + + def test_str(self): + """Test DateTime string conversion formatting.""" + self.assertEqual('Thu Jan 1 00:00:00 1970', + str(primitives.DateTime(0))) + + def test_boundary_values(self): + """Test DateTime boundary values round-trip correctly.""" + values = [0, 1, 2147483648] + for value in values: + date_time = primitives.DateTime(value) + stream = utils.BytearrayStream() + date_time.write(stream) + clone = primitives.DateTime(0) + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) + + def test_specific_values(self): + """Test DateTime epoch, current time, and future values.""" + with mock.patch('time.time', return_value=100): + now = primitives.DateTime() + future = primitives.DateTime(100000) + epoch = primitives.DateTime(0) + self.assertEqual(100, now.value) + self.assertEqual(100000, future.value) + self.assertEqual(0, epoch.value) + +class TestInterval(testtools.TestCase): + + def setUp(self): + super(TestInterval, self).setUp() + self.stream = utils.BytearrayStream() + self.tag = enums.Tags.DEFAULT + self.other_tag = enums.Tags.ACTIVATION_DATE + + def tearDown(self): + super(TestInterval, self).tearDown() + + def test_init_with_none(self): + """Test Interval initializes with default values.""" + interval = primitives.Interval() + self.assertEqual(0, interval.value) + self.assertEqual(primitives.Interval.LENGTH, interval.length) + + def test_init_with_valid_value(self): + """Test Interval initializes with a valid value.""" + interval = primitives.Interval(5) + self.assertEqual(5, interval.value) + + def test_init_with_invalid_value(self): + """Test Interval rejects invalid types.""" + self.assertRaises(TypeError, primitives.Interval, 'invalid') + + def test_init_with_tag(self): + """Test Interval stores a custom tag.""" + interval = primitives.Interval(1, tag=self.other_tag) + self.assertEqual(self.other_tag, interval.tag) + + def test_read_valid_encoding(self): + """Test Interval reads a valid TTLV encoding.""" + encoding = _encode_unsigned_int(self.tag, enums.Types.INTERVAL, 5) + stream = utils.BytearrayStream(encoding) + interval = primitives.Interval() + interval.read(stream) + self.assertEqual(5, interval.value) + + def test_read_invalid_encoding(self): + """Test Interval rejects invalid TTLV lengths.""" + encoding = _ttlv(self.tag, enums.Types.INTERVAL, 8, b'') + stream = utils.BytearrayStream(encoding) + interval = primitives.Interval() + self.assertRaises(exceptions.InvalidPrimitiveLength, + interval.read, stream) + + def test_read_oversized(self): + """Test Interval detects extra bytes after reading.""" + encoding = _encode_unsigned_int(self.tag, enums.Types.INTERVAL, 5) + b'\x00' + stream = utils.BytearrayStream(encoding) + interval = primitives.Interval() + interval.read(stream) + self.assertRaises(exceptions.StreamNotEmptyError, + interval.is_oversized, stream) + + def test_write_valid(self): + """Test Interval writes a valid TTLV encoding.""" + interval = primitives.Interval(5) + interval.write(self.stream) + self.assertEqual( + _encode_unsigned_int(self.tag, enums.Types.INTERVAL, 5), + self.stream.read() + ) + + def test_read_write_roundtrip(self): + """Test Interval read/write round-trip.""" + interval = primitives.Interval(123) + stream = utils.BytearrayStream() + interval.write(stream) + clone = primitives.Interval() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(interval.value, clone.value) + + def test_validate_valid(self): + """Test Interval validate accepts valid values.""" + interval = primitives.Interval(0) + interval.validate() + + def test_validate_invalid_type(self): + """Test Interval validate rejects invalid types.""" + self.assertRaises(TypeError, primitives.Interval, 'bad') + + def test_validate_out_of_range(self): + """Test Interval validate rejects out-of-range values.""" + self.assertRaises(ValueError, primitives.Interval, + primitives.Interval.MAX + 1) + self.assertRaises(ValueError, primitives.Interval, + primitives.Interval.MIN - 1) + + def test_eq_same_value(self): + """Test Interval equality for identical values.""" + self.assertTrue(primitives.Interval(1) == primitives.Interval(1)) + + def test_eq_different_value(self): + """Test Interval inequality for different values.""" + self.assertFalse(primitives.Interval(1) == primitives.Interval(2)) + + def test_eq_different_type(self): + """Test Interval equality returns NotImplemented for other types.""" + interval = primitives.Interval(1) + self.assertIs(interval.__eq__('invalid'), NotImplemented) + + def test_ne(self): + """Test Interval inequality operator.""" + self.assertTrue(primitives.Interval(1) != primitives.Interval(2)) + + def test_hash_same_value(self): + """Test Interval is unhashable when equality is defined.""" + self.assertRaises(TypeError, hash, primitives.Interval(1)) + + def test_repr(self): + """Test Interval representation formatting.""" + interval = primitives.Interval(5) + self.assertEqual( + 'Interval(value=5, tag={0})'.format(enums.Tags.DEFAULT), + repr(interval) + ) + + def test_str(self): + """Test Interval string conversion formatting.""" + self.assertEqual('5', str(primitives.Interval(5))) + + def test_boundary_values(self): + """Test Interval boundary values round-trip correctly.""" + values = [primitives.Interval.MIN, 0, primitives.Interval.MAX] + for value in values: + interval = primitives.Interval(value) + stream = utils.BytearrayStream() + interval.write(stream) + clone = primitives.Interval() + clone.read(utils.BytearrayStream(stream.read())) + self.assertEqual(value, clone.value) diff --git a/kmip/tests/unit/core/test_utils.py b/kmip/tests/unit/core/test_utils.py index 8c6bb28b..58557695 100644 --- a/kmip/tests/unit/core/test_utils.py +++ b/kmip/tests/unit/core/test_utils.py @@ -18,7 +18,6 @@ from kmip.core import exceptions from kmip.core import utils - class TestUtils(TestCase): def setUp(self): @@ -54,7 +53,6 @@ def test_count_bytes_zero(self): 'received {2} byte(s)'.format(num, bytes_exp, bytes_obs)) - class TestBytearrayStream(TestCase): def setUp(self): diff --git a/kmip/tests/unit/core/test_utils_extended.py b/kmip/tests/unit/core/test_utils_extended.py new file mode 100644 index 00000000..cb529da3 --- /dev/null +++ b/kmip/tests/unit/core/test_utils_extended.py @@ -0,0 +1,69 @@ +# Copyright (c) 2026 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 testtools + +from kmip.core import utils + + +class TestBytearrayStreamExtended(testtools.TestCase): + def test_bytearraystream_init_empty(self): + stream = utils.BytearrayStream() + self.assertEqual(b"", stream.buffer) + self.assertEqual(0, stream.length()) + self.assertEqual(0, len(stream)) + + def test_bytearraystream_init_with_data(self): + data = b"\x00\x01\x02" + stream = utils.BytearrayStream(data) + self.assertEqual(data, stream.buffer) + self.assertEqual(len(data), stream.length()) + + def test_bytearraystream_read_write(self): + stream = utils.BytearrayStream() + written = stream.write(b"abc") + self.assertEqual(3, written) + self.assertEqual(3, stream.length()) + self.assertEqual(b"a", stream.read(1)) + self.assertEqual(2, stream.length()) + self.assertEqual(b"bc", stream.read()) + self.assertEqual(0, stream.length()) + + def test_bytearraystream_peek(self): + stream = utils.BytearrayStream(b"hello") + self.assertEqual(b"he", stream.peek(2)) + self.assertEqual(5, stream.length()) + self.assertEqual(b"hello", stream.peek()) + self.assertEqual(5, stream.length()) + + def test_bytearraystream_length(self): + stream = utils.BytearrayStream(b"data") + self.assertEqual(4, stream.length()) + self.assertEqual(4, len(stream)) + + def test_bytearraystream_read_past_end(self): + stream = utils.BytearrayStream(b"xyz") + self.assertEqual(b"xyz", stream.read(10)) + self.assertEqual(0, stream.length()) + self.assertEqual(b"", stream.read(1)) + + def test_bytearraystream_write_large_data(self): + payload = b"a" * (1024 * 1024) + stream = utils.BytearrayStream() + written = stream.write(payload) + self.assertEqual(len(payload), written) + self.assertEqual(len(payload), stream.length()) + self.assertEqual(payload[:1024], stream.read(1024)) + self.assertEqual(len(payload) - 1024, stream.length()) diff --git a/kmip/tests/unit/pie/objects/test_application_specific_information.py b/kmip/tests/unit/pie/objects/test_application_specific_information.py index 10385c1b..525906d5 100644 --- a/kmip/tests/unit/pie/objects/test_application_specific_information.py +++ b/kmip/tests/unit/pie/objects/test_application_specific_information.py @@ -19,7 +19,6 @@ from kmip.pie import objects from kmip.pie import sqltypes - class TestApplicationSpecificInformation(testtools.TestCase): """ Test suite for ApplicationSpecificInformation. diff --git a/kmip/tests/unit/pie/objects/test_certificate.py b/kmip/tests/unit/pie/objects/test_certificate.py index f628c958..cd579ae6 100644 --- a/kmip/tests/unit/pie/objects/test_certificate.py +++ b/kmip/tests/unit/pie/objects/test_certificate.py @@ -18,7 +18,6 @@ from kmip.core import enums from kmip.pie import objects - class DummyCertificate(objects.Certificate): """ A dummy Certificate subclass for testing purposes. @@ -47,7 +46,6 @@ def __eq__(self, other): def __ne__(self, other): return False - class TestCertificate(testtools.TestCase): """ Test suite for Certificate. diff --git a/kmip/tests/unit/pie/objects/test_cryptographic_object.py b/kmip/tests/unit/pie/objects/test_cryptographic_object.py index c1f0813e..184da134 100644 --- a/kmip/tests/unit/pie/objects/test_cryptographic_object.py +++ b/kmip/tests/unit/pie/objects/test_cryptographic_object.py @@ -13,12 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. - from testtools import TestCase from kmip.pie.objects import CryptographicObject - class DummyCryptographicObject(CryptographicObject): """ A dummy CryptographicObject subclass for testing purposes. @@ -45,7 +43,6 @@ def __eq__(self, other): def __ne__(self, other): return False - class TestCryptographicObject(TestCase): """ Test suite for CryptographicObject. diff --git a/kmip/tests/unit/pie/objects/test_key.py b/kmip/tests/unit/pie/objects/test_key.py index 0c5fb857..9c739b4c 100644 --- a/kmip/tests/unit/pie/objects/test_key.py +++ b/kmip/tests/unit/pie/objects/test_key.py @@ -13,12 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. - from testtools import TestCase from kmip.pie.objects import Key - class DummyKey(Key): """ A dummy Key subclass for testing purposes. @@ -45,7 +43,6 @@ def __eq__(self, other): def __ne__(self, other): return False - class TestKey(TestCase): """ Test suite for Key. diff --git a/kmip/tests/unit/pie/objects/test_managed_object.py b/kmip/tests/unit/pie/objects/test_managed_object.py index 3f860fe5..a67537e0 100644 --- a/kmip/tests/unit/pie/objects/test_managed_object.py +++ b/kmip/tests/unit/pie/objects/test_managed_object.py @@ -17,7 +17,6 @@ from kmip.pie.objects import ManagedObject - class DummyManagedObject(ManagedObject): """ A dummy ManagedObject subclass for testing purposes. @@ -55,7 +54,6 @@ def __ne__(self, other): super(DummyManagedObject, self).__ne__(other) return False - class TestManagedObject(TestCase): """ Test suite for ManagedObject. diff --git a/kmip/tests/unit/pie/objects/test_object_group.py b/kmip/tests/unit/pie/objects/test_object_group.py index ebf9c6c2..8c6732ae 100644 --- a/kmip/tests/unit/pie/objects/test_object_group.py +++ b/kmip/tests/unit/pie/objects/test_object_group.py @@ -19,7 +19,6 @@ from kmip.pie import objects from kmip.pie import sqltypes - class TestObjectGroup(testtools.TestCase): """ Test suite for ObjectGroup. diff --git a/kmip/tests/unit/pie/objects/test_opaque_object.py b/kmip/tests/unit/pie/objects/test_opaque_object.py index 6a7542ce..ba0739bd 100644 --- a/kmip/tests/unit/pie/objects/test_opaque_object.py +++ b/kmip/tests/unit/pie/objects/test_opaque_object.py @@ -22,7 +22,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestOpaqueObject(testtools.TestCase): """ Test suite for OpaqueObject. diff --git a/kmip/tests/unit/pie/objects/test_private_key.py b/kmip/tests/unit/pie/objects/test_private_key.py index d03fbdb2..c3eeae8c 100644 --- a/kmip/tests/unit/pie/objects/test_private_key.py +++ b/kmip/tests/unit/pie/objects/test_private_key.py @@ -36,7 +36,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestPrivateKey(testtools.TestCase): """ Test suite for PrivateKey. diff --git a/kmip/tests/unit/pie/objects/test_public_key.py b/kmip/tests/unit/pie/objects/test_public_key.py index be63da38..ca933cd5 100644 --- a/kmip/tests/unit/pie/objects/test_public_key.py +++ b/kmip/tests/unit/pie/objects/test_public_key.py @@ -22,7 +22,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestPublicKey(testtools.TestCase): """ Test suite for PublicKey. diff --git a/kmip/tests/unit/pie/objects/test_secret_data.py b/kmip/tests/unit/pie/objects/test_secret_data.py index c11317b3..cf911302 100644 --- a/kmip/tests/unit/pie/objects/test_secret_data.py +++ b/kmip/tests/unit/pie/objects/test_secret_data.py @@ -22,7 +22,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestSecretData(testtools.TestCase): """ Test suite for SecretData. diff --git a/kmip/tests/unit/pie/objects/test_split_key.py b/kmip/tests/unit/pie/objects/test_split_key.py index 755d7bc8..10927ef2 100644 --- a/kmip/tests/unit/pie/objects/test_split_key.py +++ b/kmip/tests/unit/pie/objects/test_split_key.py @@ -22,7 +22,6 @@ from kmip.pie import objects from kmip.pie import sqltypes - class TestSplitKey(testtools.TestCase): """ Test suite for SplitKey. diff --git a/kmip/tests/unit/pie/objects/test_sqltypes.py b/kmip/tests/unit/pie/objects/test_sqltypes.py index dafe503f..715aadcb 100644 --- a/kmip/tests/unit/pie/objects/test_sqltypes.py +++ b/kmip/tests/unit/pie/objects/test_sqltypes.py @@ -18,7 +18,6 @@ from kmip.core import enums from kmip.pie.sqltypes import ManagedObjectName - class TestSqlTypesManagedObjectName(testtools.TestCase): """ Test suite for objects in sqltypes.py. diff --git a/kmip/tests/unit/pie/objects/test_sqltypes_extended.py b/kmip/tests/unit/pie/objects/test_sqltypes_extended.py new file mode 100644 index 00000000..dfbc99d9 --- /dev/null +++ b/kmip/tests/unit/pie/objects/test_sqltypes_extended.py @@ -0,0 +1,50 @@ +# Copyright (c) 2026 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 testtools + +from kmip.core import enums +from kmip.pie import sqltypes + + +class TestSqlTypesExtended(testtools.TestCase): + def test_enum_type_process_bind(self): + enum_type = sqltypes.EnumType(enums.NameType) + self.assertEqual( + enums.NameType.URI.value, + enum_type.process_bind_param(enums.NameType.URI, None) + ) + self.assertEqual(-1, enum_type.process_bind_param(None, None)) + + def test_enum_type_process_result(self): + enum_type = sqltypes.EnumType(enums.NameType) + self.assertIsNone(enum_type.process_result_value(-1, None)) + self.assertEqual( + enums.NameType.URI, + enum_type.process_result_value(enums.NameType.URI.value, None) + ) + + def test_usage_mask_type_roundtrip(self): + usage_type = sqltypes.UsageMaskType() + masks = [ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + bitmask = usage_type.process_bind_param(masks, None) + result_masks = usage_type.process_result_value(bitmask, None) + self.assertEqual(set(masks), set(result_masks)) + + empty_mask = usage_type.process_bind_param([], None) + self.assertEqual([], usage_type.process_result_value(empty_mask, None)) diff --git a/kmip/tests/unit/pie/objects/test_symmetric_key.py b/kmip/tests/unit/pie/objects/test_symmetric_key.py index f0c7ebad..78d5b2b0 100644 --- a/kmip/tests/unit/pie/objects/test_symmetric_key.py +++ b/kmip/tests/unit/pie/objects/test_symmetric_key.py @@ -22,7 +22,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestSymmetricKey(testtools.TestCase): """ Test suite for SymmetricKey. diff --git a/kmip/tests/unit/pie/objects/test_x509_certificate.py b/kmip/tests/unit/pie/objects/test_x509_certificate.py index dba77617..b2eb74d9 100644 --- a/kmip/tests/unit/pie/objects/test_x509_certificate.py +++ b/kmip/tests/unit/pie/objects/test_x509_certificate.py @@ -22,7 +22,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - class TestX509Certificate(testtools.TestCase): """ Test suite for X509Certificate. diff --git a/kmip/tests/unit/pie/test_client.py b/kmip/tests/unit/pie/test_client.py index c9947a8f..4857f839 100644 --- a/kmip/tests/unit/pie/test_client.py +++ b/kmip/tests/unit/pie/test_client.py @@ -14,7 +14,7 @@ # under the License. import mock -import six + import ssl import testtools @@ -40,7 +40,6 @@ from kmip.pie import factory from kmip.pie import objects - class TestProxyKmipClient(testtools.TestCase): """ Test suite for the ProxyKmipClient. @@ -132,6 +131,23 @@ def test_open_on_proxy_failure(self): client.proxy.open.side_effect = Exception self.assertRaises(Exception, client.open) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_open_on_proxy_failure_logs_error(self): + """ + Test that open logs an error when the proxy fails to open. + """ + client = ProxyKmipClient() + client.logger = mock.MagicMock() + test_exception = Exception("test") + client.proxy.open.side_effect = test_exception + + self.assertRaises(Exception, client.open) + client.logger.error.assert_called_once_with( + "could not open client connection: %s", + test_exception + ) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_close(self): @@ -164,6 +180,24 @@ def test_close_on_proxy_failure(self): client.proxy.close.side_effect = Exception self.assertRaises(Exception, client.close) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_close_on_proxy_failure_logs_error(self): + """ + Test that close logs an error when the proxy fails to close. + """ + client = ProxyKmipClient() + client._is_open = True + client.logger = mock.MagicMock() + test_exception = Exception("test") + client.proxy.close.side_effect = test_exception + + self.assertRaises(Exception, client.close) + client.logger.error.assert_called_once_with( + "could not close client connection: %s", + test_exception + ) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_enter(self): @@ -240,7 +274,7 @@ def test_create(self): uid = client.create(algorithm, length) client.proxy.create.assert_called_with( enums.ObjectType.SYMMETRIC_KEY, template) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) self.assertEqual(uid, key_id) @mock.patch('kmip.pie.client.KMIPProxy', @@ -343,6 +377,86 @@ def test_create_with_name(self): client.proxy.create.assert_called_with( enums.ObjectType.SYMMETRIC_KEY, template) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_with_empty_name(self): + """ + Test that an empty name is ignored during create. + """ + algorithm = enums.CryptographicAlgorithm.AES + length = 256 + algorithm_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, algorithm) + length_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, length) + mask_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + [enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT]) + + attributes = [algorithm_attribute, length_attribute, mask_attribute] + template = obj.TemplateAttribute(attributes=attributes) + + key_id = 'aaaaaaaa-1111-2222-3333-ffffffffffff' + status = enums.ResultStatus.SUCCESS + result = results.CreateResult( + contents.ResultStatus(status), + uuid=key_id) + + with ProxyKmipClient() as client: + client.proxy.create.return_value = result + + uid = client.create( + algorithm, + length, + operation_policy_name=None, + name="", + cryptographic_usage_mask=None + ) + client.proxy.create.assert_called_with( + enums.ObjectType.SYMMETRIC_KEY, template) + self.assertEqual(uid, key_id) + + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_with_none_optionals(self): + """ + Test that create accepts explicit None optional parameters. + """ + algorithm = enums.CryptographicAlgorithm.AES + length = 256 + algorithm_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, algorithm) + length_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, length) + mask_attribute = self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + [enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT]) + + attributes = [algorithm_attribute, length_attribute, mask_attribute] + template = obj.TemplateAttribute(attributes=attributes) + + key_id = 'aaaaaaaa-1111-2222-3333-ffffffffffff' + status = enums.ResultStatus.SUCCESS + result = results.CreateResult( + contents.ResultStatus(status), + uuid=key_id) + + with ProxyKmipClient() as client: + client.proxy.create.return_value = result + + uid = client.create( + algorithm, + length, + operation_policy_name=None, + name=None, + cryptographic_usage_mask=None + ) + client.proxy.create.assert_called_with( + enums.ObjectType.SYMMETRIC_KEY, template) + self.assertEqual(uid, key_id) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_with_cryptographic_usage_mask(self): @@ -403,6 +517,26 @@ def test_create_on_invalid_algorithm(self): with ProxyKmipClient() as client: self.assertRaises(TypeError, client.create, *args) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_on_invalid_algorithm_enum_type(self): + """ + Test that a TypeError is raised for an enum of the wrong type. + """ + args = [enums.ObjectType.SYMMETRIC_KEY, 256] + with ProxyKmipClient() as client: + self.assertRaises(TypeError, client.create, *args) + + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_on_invalid_algorithm_int(self): + """ + Test that a TypeError is raised for a non-enum algorithm value. + """ + args = [1, 256] + with ProxyKmipClient() as client: + self.assertRaises(TypeError, client.create, *args) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_on_invalid_length(self): @@ -414,6 +548,21 @@ def test_create_on_invalid_length(self): with ProxyKmipClient() as client: self.assertRaises(TypeError, client.create, *args) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_on_non_positive_length(self): + """ + Test that a TypeError is raised for non-positive key lengths. + """ + for length in (0, -1): + with ProxyKmipClient() as client: + self.assertRaises( + TypeError, + client.create, + enums.CryptographicAlgorithm.AES, + length + ) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_on_invalid_cryptographic_usage_mask(self): @@ -511,8 +660,8 @@ def test_create_key_pair(self): "public_key_template_attribute": None } client.proxy.create_key_pair.assert_called_with(**kwargs) - self.assertIsInstance(public_uid, six.string_types) - self.assertIsInstance(private_uid, six.string_types) + self.assertIsInstance(public_uid, str) + self.assertIsInstance(private_uid, str) @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) @@ -631,6 +780,50 @@ def test_create_key_pair_with_key_names(self): } client.proxy.create_key_pair.assert_called_with(**kwargs) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_key_pair_with_empty_names(self): + """ + Test that empty key names are ignored. + """ + common_template = obj.TemplateAttribute( + attributes=[ + self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.RSA + ), + self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, + 2048 + ) + ], + tag=enums.Tags.COMMON_TEMPLATE_ATTRIBUTE + ) + + status = enums.ResultStatus.SUCCESS + result = results.CreateKeyPairResult( + contents.ResultStatus(status), + public_key_uuid="aaaaaaaa-1111-2222-3333-ffffffffffff", + private_key_uuid="ffffffff-3333-2222-1111-aaaaaaaaaaaa" + ) + + with ProxyKmipClient() as client: + client.proxy.create_key_pair.return_value = result + + client.create_key_pair( + enums.CryptographicAlgorithm.RSA, + 2048, + public_name="", + private_name="" + ) + + kwargs = { + "common_template_attribute": common_template, + "private_key_template_attribute": None, + "public_key_template_attribute": None + } + client.proxy.create_key_pair.assert_called_with(**kwargs) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_key_pair_with_cryptographic_usage_masks(self): @@ -710,6 +903,28 @@ def test_create_key_pair_on_invalid_algorithm(self): self.assertRaises( TypeError, client.create_key_pair, *args) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_key_pair_on_invalid_algorithm_enum_type(self): + """ + Test that a TypeError is raised for an enum of the wrong type. + """ + args = [enums.ObjectType.PUBLIC_KEY, 2048] + with ProxyKmipClient() as client: + self.assertRaises( + TypeError, client.create_key_pair, *args) + + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_key_pair_on_invalid_algorithm_int(self): + """ + Test that a TypeError is raised for a non-enum algorithm value. + """ + args = [1, 2048] + with ProxyKmipClient() as client: + self.assertRaises( + TypeError, client.create_key_pair, *args) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_key_pair_on_invalid_length(self): @@ -722,6 +937,68 @@ def test_create_key_pair_on_invalid_length(self): self.assertRaises( TypeError, client.create_key_pair, *args) + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_key_pair_on_non_positive_length(self): + """ + Test that a TypeError is raised for non-positive key lengths. + """ + for length in (0, -1): + with ProxyKmipClient() as client: + self.assertRaises( + TypeError, + client.create_key_pair, + enums.CryptographicAlgorithm.RSA, + length + ) + + @mock.patch('kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy)) + def test_create_key_pair_with_none_optionals(self): + """ + Test that create_key_pair accepts explicit None optional parameters. + """ + common_template = obj.TemplateAttribute( + attributes=[ + self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.RSA + ), + self.attribute_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, + 2048 + ) + ], + tag=enums.Tags.COMMON_TEMPLATE_ATTRIBUTE + ) + + status = enums.ResultStatus.SUCCESS + result = results.CreateKeyPairResult( + contents.ResultStatus(status), + public_key_uuid="aaaaaaaa-1111-2222-3333-ffffffffffff", + private_key_uuid="ffffffff-3333-2222-1111-aaaaaaaaaaaa" + ) + + with ProxyKmipClient() as client: + client.proxy.create_key_pair.return_value = result + + client.create_key_pair( + enums.CryptographicAlgorithm.RSA, + 2048, + operation_policy_name=None, + public_name=None, + public_usage_mask=None, + private_name=None, + private_usage_mask=None + ) + + kwargs = { + "common_template_attribute": common_template, + "private_key_template_attribute": None, + "public_key_template_attribute": None + } + client.proxy.create_key_pair.assert_called_with(**kwargs) + @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) def test_create_key_pair_on_closed(self): @@ -1278,7 +1555,7 @@ def test_get_attributes(self): 'aaaaaaaa-1111-2222-3333-ffffffffffff', ['Name', 'Object Type'] ) - self.assertIsInstance(result[0], six.string_types) + self.assertIsInstance(result[0], str) self.assertIsInstance(result[1], list) for r in result[1]: self.assertIsInstance(r, obj.Attribute) @@ -1406,7 +1683,7 @@ def test_get_attribute_list(self): result = client.get_attribute_list(uid) client.proxy.get_attribute_list.assert_called_with(uid) self.assertIsInstance(result, list) - six.assertCountEqual(self, attribute_names, result) + self.assertCountEqual(attribute_names, result) @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) @@ -1739,7 +2016,7 @@ def test_register(self): client.proxy.register.return_value = result uid = client.register(key) self.assertTrue(client.proxy.register.called) - self.assertIsInstance(uid, six.string_types) + self.assertIsInstance(uid, str) @mock.patch('kmip.pie.client.KMIPProxy', mock.MagicMock(spec_set=KMIPProxy)) diff --git a/kmip/tests/unit/pie/test_client_extended.py b/kmip/tests/unit/pie/test_client_extended.py new file mode 100644 index 00000000..de8c5e6a --- /dev/null +++ b/kmip/tests/unit/pie/test_client_extended.py @@ -0,0 +1,1224 @@ +# 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 mock +import testtools + +from kmip.core import attributes as attr +from kmip.core import enums +from kmip.core import objects as obj + +from kmip.core.factories import attributes +from kmip.core.messages import contents +from kmip.core.messages import payloads +from kmip.core.messages.contents import Operation +from kmip.core.messages.contents import ResultMessage +from kmip.core.messages.contents import ResultReason +from kmip.core.messages.contents import ResultStatus +from kmip.core.messages.messages import ResponseBatchItem +from kmip.core.messages.messages import ResponseMessage + +from kmip.services import results +from kmip.services.kmip_client import KMIPProxy + +from kmip.pie import factory +from kmip.pie import objects +from kmip.pie.client import ProxyKmipClient +from kmip.pie.exceptions import ClientConnectionFailure +from kmip.pie.exceptions import ClientConnectionNotOpen +from kmip.pie.exceptions import KmipOperationFailure + + +class TestProxyKmipClientExtended(testtools.TestCase): + def setUp(self): + super(TestProxyKmipClientExtended, self).setUp() + self.attribute_factory = attributes.AttributeFactory() + self.object_factory = factory.ObjectFactory() + self._kmip_proxy_patcher = mock.patch( + 'kmip.pie.client.KMIPProxy', + mock.MagicMock(spec_set=KMIPProxy) + ) + self.addCleanup(self._kmip_proxy_patcher.stop) + self._kmip_proxy_class = self._kmip_proxy_patcher.start() + self.proxy = mock.MagicMock(spec_set=KMIPProxy) + self._kmip_proxy_class.return_value = self.proxy + + def _open_client(self): + client = ProxyKmipClient() + client.open() + return client + + def _build_failure_result(self): + status = enums.ResultStatus.OPERATION_FAILED + reason = enums.ResultReason.GENERAL_FAILURE + message = "Test failure message" + result = results.OperationResult( + contents.ResultStatus(status), + contents.ResultReason(reason), + contents.ResultMessage(message) + ) + error_msg = str(KmipOperationFailure(status, reason, message)) + return result, error_msg + + def _build_failure_dict(self): + status = enums.ResultStatus.OPERATION_FAILED + reason = enums.ResultReason.GENERAL_FAILURE + message = "Test failure message" + result = { + "result_status": status, + "result_reason": reason, + "result_message": message + } + error_msg = str(KmipOperationFailure(status, reason, message)) + return result, error_msg + + def _build_failure_exception(self): + status = enums.ResultStatus.OPERATION_FAILED + reason = enums.ResultReason.GENERAL_FAILURE + message = "Test failure message" + exc = KmipOperationFailure(status, reason, message) + return exc, str(exc) + + def _build_core_attribute(self, name, value): + return self.attribute_factory.create_attribute(name, value) + + def _build_symmetric_key(self, name="Symmetric Key", masks=None, + app_specific_info=None): + return objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + (b'\x00' * 16), + masks=masks, + name=name, + app_specific_info=app_specific_info + ) + + def _assert_operation_success(self, op_name, variant): + case = OPERATION_CASES[op_name] + config = case[variant](self) + client = self._open_client() + proxy_method = case["proxy_method"] + getattr(client.proxy, proxy_method).return_value = config["result"] + result = getattr(client, op_name)(*config["args"], **config["kwargs"]) + self.assertEqual(config["expected"], result) + + def _assert_operation_invalid(self, op_name): + case = OPERATION_CASES[op_name] + config = case["invalid"](self) + client = self._open_client() + exc = config.get("exc", TypeError) + self.assertRaises( + exc, + getattr(client, op_name), + *config["args"], + **config["kwargs"] + ) + + def _assert_operation_closed(self, op_name): + case = OPERATION_CASES[op_name] + config = case["minimal"](self) + client = ProxyKmipClient() + self.assertRaises( + ClientConnectionNotOpen, + getattr(client, op_name), + *config["args"], + **config["kwargs"] + ) + + def _assert_operation_failure(self, op_name): + case = OPERATION_CASES[op_name] + config = case["minimal"](self) + client = self._open_client() + if case["category"] == "payload_response": + exc, error_msg = self._build_failure_exception() + client.proxy.send_request_payload.side_effect = exc + self.assertRaisesRegex( + KmipOperationFailure, + error_msg, + getattr(client, op_name), + *config["args"], + **config["kwargs"] + ) + return + + if case["category"] == "dict_result": + result, error_msg = self._build_failure_dict() + else: + result, error_msg = self._build_failure_result() + + proxy_method = case["proxy_method"] + getattr(client.proxy, proxy_method).return_value = result + self.assertRaisesRegex( + KmipOperationFailure, + error_msg, + getattr(client, op_name), + *config["args"], + **config["kwargs"] + ) + + def _assert_operation_none_response(self, op_name): + case = OPERATION_CASES[op_name] + config = case["minimal"](self) + client = self._open_client() + proxy_method = case["proxy_method"] + getattr(client.proxy, proxy_method).return_value = None + self.assertRaises( + AttributeError, + getattr(client, op_name), + *config["args"], + **config["kwargs"] + ) + + def test_open_already_open(self): + client = ProxyKmipClient() + client.open() + self.assertRaises(ClientConnectionFailure, client.open) + + def test_close_already_closed(self): + client = ProxyKmipClient() + client.close() + client.proxy.close.assert_not_called() + + def test_context_manager_exception_in_body(self): + client = ProxyKmipClient() + with self.assertRaises(ValueError): + with client: + raise ValueError("boom") + self.assertFalse(client._is_open) + client.proxy.close.assert_called_once_with() + + def test_context_manager_nested(self): + with ProxyKmipClient() as outer: + self.assertTrue(outer._is_open) + with ProxyKmipClient() as inner: + self.assertTrue(inner._is_open) + self.assertFalse(inner._is_open) + self.assertTrue(outer._is_open) + self.assertFalse(outer._is_open) + + def test_locate_by_name(self): + attribute = self._build_core_attribute("Name", "locate-name") + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-name"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate(attributes=[attribute]) + self.assertEqual(["uid-name"], uuids) + + def test_locate_by_algorithm(self): + attribute = self._build_core_attribute( + "Cryptographic Algorithm", + enums.CryptographicAlgorithm.AES + ) + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-alg"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate(attributes=[attribute]) + self.assertEqual(["uid-alg"], uuids) + + def test_locate_by_state(self): + attribute = self._build_core_attribute("State", enums.State.ACTIVE) + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-state"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate(attributes=[attribute]) + self.assertEqual(["uid-state"], uuids) + + def test_locate_by_object_type(self): + attribute = self._build_core_attribute( + "Object Type", + enums.ObjectType.SYMMETRIC_KEY + ) + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-type"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate(attributes=[attribute]) + self.assertEqual(["uid-type"], uuids) + + def test_locate_with_offset_and_maximum_items(self): + attributes_list = [ + self._build_core_attribute("Name", "locate-offset"), + self._build_core_attribute( + "Object Type", + enums.ObjectType.SYMMETRIC_KEY + ) + ] + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-offset"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate( + maximum_items=10, + offset_items=5, + storage_status_mask=1, + object_group_member=enums.ObjectGroupMember.GROUP_MEMBER_FRESH, + attributes=attributes_list + ) + self.assertEqual(["uid-offset"], uuids) + + def test_locate_empty_results(self): + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=[] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate() + self.assertEqual([], uuids) + + def test_locate_multiple_filters(self): + attributes_list = [ + self._build_core_attribute("Name", "locate-multi"), + self._build_core_attribute( + "Object Type", + enums.ObjectType.SYMMETRIC_KEY + ), + self._build_core_attribute( + "Cryptographic Algorithm", + enums.CryptographicAlgorithm.AES + ) + ] + result = results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-multi"] + ) + client = self._open_client() + client.proxy.locate.return_value = result + uuids = client.locate(attributes=attributes_list) + self.assertEqual(["uid-multi"], uuids) + + def test_operations_with_kmip_1_0(self): + client = self._open_client() + client.kmip_version = enums.KMIPVersion.KMIP_1_0 + self.assertEqual(enums.KMIPVersion.KMIP_1_0, client.proxy.kmip_version) + client.proxy.activate.return_value = results.ActivateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ) + client.activate("uid") + + def test_operations_with_kmip_1_2(self): + client = self._open_client() + client.kmip_version = enums.KMIPVersion.KMIP_1_2 + self.assertEqual(enums.KMIPVersion.KMIP_1_2, client.proxy.kmip_version) + client.proxy.activate.return_value = results.ActivateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ) + client.activate("uid") + + def test_operations_with_kmip_2_0(self): + client = self._open_client() + client.kmip_version = enums.KMIPVersion.KMIP_2_0 + self.assertEqual(enums.KMIPVersion.KMIP_2_0, client.proxy.kmip_version) + client.proxy.activate.return_value = results.ActivateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ) + client.activate("uid") + + +class TestProxyKmipClientBatchOps(testtools.TestCase): + def setUp(self): + super(TestProxyKmipClientBatchOps, self).setUp() + self.proxy = KMIPProxy() + + def test_batch_items_processing(self): + batch_item = ResponseBatchItem( + operation=Operation(enums.Operation.CREATE_KEY_PAIR), + response_payload=payloads.CreateKeyPairResponsePayload() + ) + response = ResponseMessage(batch_items=[batch_item, batch_item]) + results_list = self.proxy._process_batch_items(response) + + self.assertIsInstance(results_list, list) + self.assertEqual(2, len(results_list)) + for result in results_list: + self.assertIsInstance(result, results.CreateKeyPairResult) + + def test_batch_with_mixed_results(self): + success_item = ResponseBatchItem( + operation=Operation(enums.Operation.CREATE_KEY_PAIR), + result_status=ResultStatus(enums.ResultStatus.SUCCESS), + response_payload=payloads.CreateKeyPairResponsePayload() + ) + failure_item = ResponseBatchItem( + result_status=ResultStatus(enums.ResultStatus.OPERATION_FAILED), + result_reason=ResultReason(enums.ResultReason.INVALID_MESSAGE), + result_message=ResultMessage("failure") + ) + response = ResponseMessage(batch_items=[success_item, failure_item]) + results_list = self.proxy._process_batch_items(response) + + self.assertEqual(2, len(results_list)) + self.assertIsInstance(results_list[0], results.CreateKeyPairResult) + self.assertIsInstance(results_list[1], results.OperationResult) + + +def _register_full_case(self): + managed_object = self._build_symmetric_key( + name="sym-full", + masks=[enums.CryptographicUsageMask.ENCRYPT], + app_specific_info=[ + { + "application_namespace": "ns", + "application_data": "data" + } + ] + ) + managed_object.operation_policy_name = "policy" + managed_object.names.append("alias") + return { + "args": (managed_object,), + "kwargs": {}, + "result": results.RegisterResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-register-full" + ), + "expected": "uid-register-full" + } + + +def _register_min_case(self): + managed_object = self._build_symmetric_key() + return { + "args": (managed_object,), + "kwargs": {}, + "result": results.RegisterResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-register-min" + ), + "expected": "uid-register-min" + } + + +def _get_full_case(self): + pie_secret = self._build_symmetric_key(name="sym-get-full") + core_secret = self.object_factory.convert(pie_secret) + spec = { + "wrapping_method": enums.WrappingMethod.ENCRYPT, + "encryption_key_information": { + "unique_identifier": "1", + "cryptographic_parameters": { + "cryptographic_algorithm": enums.CryptographicAlgorithm.AES + } + }, + "mac_signature_key_information": { + "unique_identifier": "2", + "cryptographic_parameters": { + "padding_method": enums.PaddingMethod.PKCS5 + } + }, + "attribute_names": [ + "Cryptographic Algorithm", + "Cryptographic Length" + ], + "encoding_option": enums.EncodingOption.NO_ENCODING + } + return { + "args": ("uid-get-full",), + "kwargs": {"key_wrapping_specification": spec}, + "result": results.GetResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid=attr.PublicKeyUniqueIdentifier("uid-get-full"), + secret=core_secret + ), + "expected": pie_secret + } + + +def _get_min_case(self): + pie_secret = self._build_symmetric_key(name="sym-get-min") + core_secret = self.object_factory.convert(pie_secret) + return { + "args": ("uid-get-min",), + "kwargs": {}, + "result": results.GetResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid=attr.PublicKeyUniqueIdentifier("uid-get-min"), + secret=core_secret + ), + "expected": pie_secret + } + + +def _get_attributes_full_case(self): + attribute_names = ["Name", "Object Type"] + attributes_list = [ + self._build_core_attribute("Name", "test"), + self._build_core_attribute( + "Object Type", + enums.ObjectType.SYMMETRIC_KEY + ) + ] + return { + "args": ("uid-attrs-full", attribute_names), + "kwargs": {}, + "result": results.GetAttributesResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-attrs-full", + attributes=attributes_list + ), + "expected": ("uid-attrs-full", attributes_list) + } + + +def _get_attributes_min_case(self): + attributes_list = [] + return { + "args": (), + "kwargs": {}, + "result": results.GetAttributesResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-attrs-min", + attributes=attributes_list + ), + "expected": ("uid-attrs-min", attributes_list) + } + + +def _get_attribute_list_full_case(self): + names = ["Object Type", "Name"] + return { + "args": ("uid-attr-list-full",), + "kwargs": {}, + "result": results.GetAttributeListResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uid="uid-attr-list-full", + names=names + ), + "expected": sorted(names) + } + + +def _get_attribute_list_min_case(self): + names = ["b", "a"] + return { + "args": (), + "kwargs": {}, + "result": results.GetAttributeListResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uid="uid-attr-list-min", + names=names + ), + "expected": sorted(names) + } + + +def _delete_attribute_full_case(self): + attribute = self._build_core_attribute("State", enums.State.ACTIVE) + current_attribute = obj.CurrentAttribute(attribute) + attribute_reference = obj.AttributeReference("vendor", "State") + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-del-full", + "attribute_name": "State", + "attribute_index": 0, + "current_attribute": current_attribute, + "attribute_reference": attribute_reference + }, + "result": payloads.DeleteAttributeResponsePayload( + unique_identifier="uid-del-full", + attribute=attribute + ), + "expected": ("uid-del-full", attribute) + } + + +def _delete_attribute_min_case(self): + attribute = self._build_core_attribute("State", enums.State.ACTIVE) + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-del-min", + "attribute_name": "State" + }, + "result": payloads.DeleteAttributeResponsePayload( + unique_identifier="uid-del-min", + attribute=attribute + ), + "expected": ("uid-del-min", attribute) + } + + +def _modify_attribute_full_case(self): + attribute = self._build_core_attribute("State", enums.State.ACTIVE) + current_attribute = obj.CurrentAttribute(attribute) + new_attribute = obj.NewAttribute(attribute=attribute) + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-mod-full", + "attribute": attribute, + "current_attribute": current_attribute, + "new_attribute": new_attribute + }, + "result": payloads.ModifyAttributeResponsePayload( + unique_identifier="uid-mod-full", + attribute=attribute + ), + "expected": ("uid-mod-full", attribute) + } + + +def _modify_attribute_min_case(self): + attribute = self._build_core_attribute("State", enums.State.ACTIVE) + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-mod-min", + "attribute": attribute + }, + "result": payloads.ModifyAttributeResponsePayload( + unique_identifier="uid-mod-min", + attribute=attribute + ), + "expected": ("uid-mod-min", attribute) + } + + +def _set_attribute_full_case(self): + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-set-full", + "attribute_name": "Sensitive", + "attribute_value": True + }, + "result": payloads.SetAttributeResponsePayload( + unique_identifier="uid-set-full" + ), + "expected": "uid-set-full" + } + + +def _set_attribute_min_case(self): + return { + "args": (), + "kwargs": { + "unique_identifier": "uid-set-min", + "attribute_name": "State", + "attribute_value": enums.State.ACTIVE + }, + "result": payloads.SetAttributeResponsePayload( + unique_identifier="uid-set-min" + ), + "expected": "uid-set-min" + } + + +def _locate_full_case(self): + attributes_list = [ + self._build_core_attribute("Name", "locate-full"), + self._build_core_attribute( + "Object Type", + enums.ObjectType.SYMMETRIC_KEY + ) + ] + return { + "args": (), + "kwargs": { + "maximum_items": 10, + "offset_items": 2, + "storage_status_mask": 1, + "object_group_member": enums.ObjectGroupMember.GROUP_MEMBER_FRESH, + "attributes": attributes_list + }, + "result": results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-locate-full", "uid-locate-full-2"] + ), + "expected": ["uid-locate-full", "uid-locate-full-2"] + } + + +def _locate_min_case(self): + return { + "args": (), + "kwargs": {}, + "result": results.LocateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuids=["uid-locate-min"] + ), + "expected": ["uid-locate-min"] + } + + +OPERATION_CASES = { + "create": { + "proxy_method": "create", + "category": "result_object", + "full": lambda self: { + "args": (enums.CryptographicAlgorithm.AES, 256), + "kwargs": { + "operation_policy_name": "policy", + "name": "sym-full", + "cryptographic_usage_mask": [ + enums.CryptographicUsageMask.MAC_GENERATE + ] + }, + "result": results.CreateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-create-full" + ), + "expected": "uid-create-full" + }, + "minimal": lambda self: { + "args": (enums.CryptographicAlgorithm.AES, 128), + "kwargs": {}, + "result": results.CreateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid="uid-create-min" + ), + "expected": "uid-create-min" + }, + "invalid": lambda self: { + "args": ("invalid", 128), + "kwargs": {}, + "exc": TypeError + } + }, + "create_key_pair": { + "proxy_method": "create_key_pair", + "category": "result_object", + "full": lambda self: { + "args": (enums.CryptographicAlgorithm.RSA, 2048), + "kwargs": { + "operation_policy_name": "policy", + "public_name": "pub", + "public_usage_mask": [ + enums.CryptographicUsageMask.VERIFY + ], + "private_name": "priv", + "private_usage_mask": [ + enums.CryptographicUsageMask.SIGN + ] + }, + "result": results.CreateKeyPairResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + public_key_uuid="pub", + private_key_uuid="priv" + ), + "expected": ("pub", "priv") + }, + "minimal": lambda self: { + "args": (enums.CryptographicAlgorithm.RSA, 1024), + "kwargs": {}, + "result": results.CreateKeyPairResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + public_key_uuid="pub-min", + private_key_uuid="priv-min" + ), + "expected": ("pub-min", "priv-min") + }, + "invalid": lambda self: { + "args": ("invalid", 1024), + "kwargs": {}, + "exc": TypeError + } + }, + "register": { + "proxy_method": "register", + "category": "result_object", + "full": _register_full_case, + "minimal": _register_min_case, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "get": { + "proxy_method": "get", + "category": "result_object", + "full": _get_full_case, + "minimal": _get_min_case, + "invalid": lambda self: { + "args": (123,), + "kwargs": {}, + "exc": TypeError + } + }, + "destroy": { + "proxy_method": "destroy", + "category": "result_object", + "full": lambda self: { + "args": ("uid-destroy-full",), + "kwargs": {}, + "result": results.DestroyResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "minimal": lambda self: { + "args": (), + "kwargs": {}, + "result": results.DestroyResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "invalid": lambda self: { + "args": (123,), + "kwargs": {}, + "exc": TypeError + } + }, + "locate": { + "proxy_method": "locate", + "category": "result_object", + "full": _locate_full_case, + "minimal": _locate_min_case, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "activate": { + "proxy_method": "activate", + "category": "result_object", + "full": lambda self: { + "args": ("uid-activate-full",), + "kwargs": {}, + "result": results.ActivateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "minimal": lambda self: { + "args": (), + "kwargs": {}, + "result": results.ActivateResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "invalid": lambda self: { + "args": (123,), + "kwargs": {}, + "exc": TypeError + } + }, + "revoke": { + "proxy_method": "revoke", + "category": "result_object", + "full": lambda self: { + "args": (enums.RevocationReasonCode.CESSATION_OF_OPERATION, + "uid-revoke-full"), + "kwargs": { + "revocation_message": "message", + "compromise_occurrence_date": 1234 + }, + "result": results.RevokeResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "minimal": lambda self: { + "args": (enums.RevocationReasonCode.CESSATION_OF_OPERATION,), + "kwargs": {}, + "result": results.RevokeResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS) + ), + "expected": None + }, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "encrypt": { + "proxy_method": "encrypt", + "category": "dict_result", + "full": lambda self: { + "args": (b"data-full",), + "kwargs": { + "uid": "uid-enc-full", + "cryptographic_parameters": { + "block_cipher_mode": enums.BlockCipherMode.CBC, + "padding_method": enums.PaddingMethod.PKCS5, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.AES + }, + "iv_counter_nonce": b"iv-full" + }, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "data": b"enc-full", + "iv_counter_nonce": b"iv-full" + }, + "expected": (b"enc-full", b"iv-full") + }, + "minimal": lambda self: { + "args": (b"data-min",), + "kwargs": {}, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "data": b"enc-min", + "iv_counter_nonce": None + }, + "expected": (b"enc-min", None) + }, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "decrypt": { + "proxy_method": "decrypt", + "category": "dict_result", + "full": lambda self: { + "args": (b"data-full",), + "kwargs": { + "uid": "uid-dec-full", + "cryptographic_parameters": { + "block_cipher_mode": enums.BlockCipherMode.CBC, + "padding_method": enums.PaddingMethod.PKCS5, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.AES + }, + "iv_counter_nonce": b"iv-full" + }, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "data": b"dec-full" + }, + "expected": b"dec-full" + }, + "minimal": lambda self: { + "args": (b"data-min",), + "kwargs": {}, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "data": b"dec-min" + }, + "expected": b"dec-min" + }, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "sign": { + "proxy_method": "sign", + "category": "dict_result", + "full": lambda self: { + "args": (b"data-full",), + "kwargs": { + "uid": "uid-sign-full", + "cryptographic_parameters": { + "padding_method": enums.PaddingMethod.PKCS1v15, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.RSA, + "hashing_algorithm": enums.HashingAlgorithm.SHA_256 + } + }, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "signature": b"sig-full" + }, + "expected": b"sig-full" + }, + "minimal": lambda self: { + "args": (b"data-min",), + "kwargs": {}, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "signature": b"sig-min" + }, + "expected": b"sig-min" + }, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "signature_verify": { + "proxy_method": "signature_verify", + "category": "dict_result", + "full": lambda self: { + "args": (b"message-full", b"signature-full"), + "kwargs": { + "uid": "uid-verify-full", + "cryptographic_parameters": { + "padding_method": enums.PaddingMethod.PKCS1v15, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.RSA, + "hashing_algorithm": enums.HashingAlgorithm.SHA_256 + } + }, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "validity_indicator": enums.ValidityIndicator.VALID + }, + "expected": enums.ValidityIndicator.VALID + }, + "minimal": lambda self: { + "args": (b"message-min", b"signature-min"), + "kwargs": {}, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "validity_indicator": enums.ValidityIndicator.INVALID + }, + "expected": enums.ValidityIndicator.INVALID + }, + "invalid": lambda self: { + "args": ("invalid", b"signature"), + "kwargs": {}, + "exc": TypeError + } + }, + "mac": { + "proxy_method": "mac", + "category": "result_object", + "full": lambda self: { + "args": (b"data-full", "uid-mac-full", + enums.CryptographicAlgorithm.HMAC_SHA256), + "kwargs": {}, + "result": results.MACResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid=attr.UniqueIdentifier("uid-mac-full"), + mac_data=obj.MACData(b"mac-full") + ), + "expected": ("uid-mac-full", b"mac-full") + }, + "minimal": lambda self: { + "args": (b"data-min",), + "kwargs": {}, + "result": results.MACResult( + contents.ResultStatus(enums.ResultStatus.SUCCESS), + uuid=attr.UniqueIdentifier("uid-mac-min"), + mac_data=obj.MACData(b"mac-min") + ), + "expected": ("uid-mac-min", b"mac-min") + }, + "invalid": lambda self: { + "args": ("invalid",), + "kwargs": {}, + "exc": TypeError + } + }, + "derive_key": { + "proxy_method": "derive_key", + "category": "dict_result", + "full": lambda self: { + "args": ( + enums.ObjectType.SYMMETRIC_KEY, + ["id1", "id2"], + enums.DerivationMethod.ENCRYPT, + { + "cryptographic_parameters": { + "block_cipher_mode": enums.BlockCipherMode.CBC, + "padding_method": enums.PaddingMethod.PKCS1v15, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.AES + }, + "initialization_vector": b"iv", + "derivation_data": b"data", + "salt": b"salt", + "iteration_count": 10 + } + ), + "kwargs": { + "cryptographic_length": 128, + "cryptographic_algorithm": + enums.CryptographicAlgorithm.AES, + "cryptographic_usage_mask": [ + enums.CryptographicUsageMask.DERIVE_KEY + ] + }, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "unique_identifier": "uid-derive-full" + }, + "expected": "uid-derive-full" + }, + "minimal": lambda self: { + "args": ( + enums.ObjectType.SYMMETRIC_KEY, + ["id1"], + enums.DerivationMethod.ENCRYPT, + {} + ), + "kwargs": {}, + "result": { + "result_status": enums.ResultStatus.SUCCESS, + "unique_identifier": "uid-derive-min" + }, + "expected": "uid-derive-min" + }, + "invalid": lambda self: { + "args": ("invalid", ["id1"], + enums.DerivationMethod.ENCRYPT, {}), + "kwargs": {}, + "exc": TypeError + } + }, + "get_attributes": { + "proxy_method": "get_attributes", + "category": "result_object", + "full": _get_attributes_full_case, + "minimal": _get_attributes_min_case, + "invalid": lambda self: { + "args": (None, [1]), + "kwargs": {}, + "exc": TypeError + } + }, + "get_attribute_list": { + "proxy_method": "get_attribute_list", + "category": "result_object", + "full": _get_attribute_list_full_case, + "minimal": _get_attribute_list_min_case, + "invalid": lambda self: { + "args": (123,), + "kwargs": {}, + "exc": TypeError + } + }, + "delete_attribute": { + "proxy_method": "send_request_payload", + "category": "payload_response", + "full": _delete_attribute_full_case, + "minimal": _delete_attribute_min_case, + "invalid": lambda self: { + "args": (), + "kwargs": {"unique_identifier": 123, "attribute_name": "State"}, + "exc": TypeError + } + }, + "modify_attribute": { + "proxy_method": "send_request_payload", + "category": "payload_response", + "full": _modify_attribute_full_case, + "minimal": _modify_attribute_min_case, + "invalid": lambda self: { + "args": (), + "kwargs": { + "unique_identifier": "uid-mod", + "attribute": "invalid" + }, + "exc": TypeError + } + }, + "set_attribute": { + "proxy_method": "send_request_payload", + "category": "payload_response", + "full": _set_attribute_full_case, + "minimal": _set_attribute_min_case, + "invalid": lambda self: { + "args": (), + "kwargs": { + "unique_identifier": "uid-set", + "attribute_name": "Cryptographic Length", + "attribute_value": "invalid" + }, + "exc": TypeError + } + } +} + + +# Generate repetitive operation tests from the OPERATION_CASES map. + +def _make_success_test(op_name): + def test(self): + self._assert_operation_success(op_name, "full") + test.__name__ = "test_{}_success".format(op_name) + return test + + +def _make_minimal_test(op_name): + def test(self): + self._assert_operation_success(op_name, "minimal") + test.__name__ = "test_{}_with_minimal_params".format(op_name) + return test + + +def _make_invalid_test(op_name): + def test(self): + self._assert_operation_invalid(op_name) + test.__name__ = "test_{}_invalid_param_types".format(op_name) + return test + + +def _make_closed_test(op_name): + def test(self): + self._assert_operation_closed(op_name) + test.__name__ = "test_{}_on_closed_connection".format(op_name) + return test + + +def _make_failure_test(op_name): + def test(self): + self._assert_operation_failure(op_name) + test.__name__ = "test_{}_on_operation_failure".format(op_name) + return test + + +def _make_none_response_test(op_name): + def test(self): + self._assert_operation_none_response(op_name) + test.__name__ = "test_{}_with_none_response".format(op_name) + return test + + +for _op_name in OPERATION_CASES: + setattr( + TestProxyKmipClientExtended, + "test_{}_success".format(_op_name), + _make_success_test(_op_name) + ) + setattr( + TestProxyKmipClientExtended, + "test_{}_with_minimal_params".format(_op_name), + _make_minimal_test(_op_name) + ) + setattr( + TestProxyKmipClientExtended, + "test_{}_invalid_param_types".format(_op_name), + _make_invalid_test(_op_name) + ) + setattr( + TestProxyKmipClientExtended, + "test_{}_on_closed_connection".format(_op_name), + _make_closed_test(_op_name) + ) + setattr( + TestProxyKmipClientExtended, + "test_{}_on_operation_failure".format(_op_name), + _make_failure_test(_op_name) + ) + setattr( + TestProxyKmipClientExtended, + "test_{}_with_none_response".format(_op_name), + _make_none_response_test(_op_name) + ) diff --git a/kmip/tests/unit/pie/test_exceptions.py b/kmip/tests/unit/pie/test_exceptions.py index 8f2fe92b..b760c11d 100644 --- a/kmip/tests/unit/pie/test_exceptions.py +++ b/kmip/tests/unit/pie/test_exceptions.py @@ -22,7 +22,6 @@ from kmip.pie.exceptions import ClientConnectionNotOpen from kmip.pie.exceptions import KmipOperationFailure - class TestClientConnectionFailure(TestCase): """ Test suite for ClientConnectionFailure. @@ -49,7 +48,6 @@ def test_message(self): exc = ClientConnectionFailure("test message") self.assertEqual("test message", str(exc)) - class TestClientConnectionNotOpen(TestCase): """ Test suite for ClientConnectionNotOpen. @@ -69,7 +67,6 @@ def test_init(self): self.assertIsInstance(exc, Exception) self.assertEqual("client connection not open", str(exc)) - class TestKmipOperationFailure(TestCase): """ Test suite for KmipOperationFailure. diff --git a/kmip/tests/unit/pie/test_factory.py b/kmip/tests/unit/pie/test_factory.py index c52360f4..26ce70fc 100644 --- a/kmip/tests/unit/pie/test_factory.py +++ b/kmip/tests/unit/pie/test_factory.py @@ -24,7 +24,6 @@ from kmip.pie import factory from kmip.pie import objects as pobjects - class TestObjectFactory(testtools.TestCase): """ Test suite for the ObjectFactory. diff --git a/kmip/tests/unit/services/server/auth/test_slugs.py b/kmip/tests/unit/services/server/auth/test_slugs.py index 49fa0c99..a773885c 100644 --- a/kmip/tests/unit/services/server/auth/test_slugs.py +++ b/kmip/tests/unit/services/server/auth/test_slugs.py @@ -20,7 +20,6 @@ from kmip.core import exceptions from kmip.services.server import auth - class TestSLUGSConnector(testtools.TestCase): """ Test suite for the SLUGSConnector. diff --git a/kmip/tests/unit/services/server/auth/test_utils.py b/kmip/tests/unit/services/server/auth/test_utils.py index 2f96c226..11b57683 100644 --- a/kmip/tests/unit/services/server/auth/test_utils.py +++ b/kmip/tests/unit/services/server/auth/test_utils.py @@ -26,7 +26,6 @@ from kmip.core import exceptions from kmip.services.server.auth import utils - class TestUtils(testtools.TestCase): """ Test suite for authentication utilities. diff --git a/kmip/tests/unit/services/server/crypto/test_engine.py b/kmip/tests/unit/services/server/crypto/test_engine.py index edb52832..db6794e2 100644 --- a/kmip/tests/unit/services/server/crypto/test_engine.py +++ b/kmip/tests/unit/services/server/crypto/test_engine.py @@ -29,7 +29,6 @@ from kmip.core import exceptions from kmip.services.server import crypto - class TestCryptographyEngine(testtools.TestCase): """ Test suite for the CryptographyEngine. @@ -1257,7 +1256,6 @@ def test_verify_signature_invalid_signing_algorithm(self): **kwargs ) - # TODO(peter-hamilton): Replace this with actual fixture files from NIST CAPV. # Most of these test vectors were obtained from the pyca/cryptography test # suite. @@ -1507,7 +1505,6 @@ def test_verify_signature_invalid_signing_algorithm(self): def symmetric_parameters(request): return request.param - def test_encrypt_symmetric(symmetric_parameters): """ Test that various encryption algorithms and block cipher modes can be @@ -1542,7 +1539,6 @@ def test_encrypt_symmetric(symmetric_parameters): assert symmetric_parameters.get('cipher_text') == result.get('cipher_text') assert symmetric_parameters.get('auth_tag') == result.get('auth_tag') - def test_decrypt_symmetric(symmetric_parameters): """ Test that various decryption algorithms and block cipher modes can be @@ -1576,7 +1572,6 @@ def test_decrypt_symmetric(symmetric_parameters): assert symmetric_parameters.get('plain_text') == result - # Most of these test vectors were obtained from the pyca/cryptography test # suite: # @@ -1710,7 +1705,6 @@ def test_decrypt_symmetric(symmetric_parameters): def asymmetric_parameters(request): return request.param - def test_encrypt_decrypt_asymmetric(asymmetric_parameters): """ Test that various encryption/decryption algorithms can be used to @@ -1766,7 +1760,6 @@ def test_encrypt_decrypt_asymmetric(asymmetric_parameters): assert asymmetric_parameters.get('plain_text') == result - @pytest.fixture( scope='function', params=[ @@ -1786,7 +1779,6 @@ def test_encrypt_decrypt_asymmetric(asymmetric_parameters): def symmetric_padding_parameters(request): return request.param - def test_handle_symmetric_padding(symmetric_padding_parameters): """ Test that data of various lengths can be padded correctly using different @@ -1802,7 +1794,6 @@ def test_handle_symmetric_padding(symmetric_padding_parameters): assert result == symmetric_padding_parameters.get('padded_text') - def test_handle_symmetric_padding_undo(symmetric_padding_parameters): """ Test that data of various lengths can be unpadded correctly using @@ -1819,7 +1810,6 @@ def test_handle_symmetric_padding_undo(symmetric_padding_parameters): assert result == symmetric_padding_parameters.get('plain_text') - # PBKDF2 test vectors were obtained from IETF RFC 6070: # # https://www.ietf.org/rfc/rfc6070.txt @@ -2424,7 +2414,6 @@ def test_handle_symmetric_padding_undo(symmetric_padding_parameters): def derivation_parameters(request): return request.param - def test_derive_key(derivation_parameters): """ Test that various derivation methods and settings can be used to correctly @@ -2448,7 +2437,6 @@ def test_derive_key(derivation_parameters): assert derivation_parameters.get('derived_data') == result - # AES Key Wrap test vectors were obtained from IETF RFC 3394: # # https://www.ietf.org/rfc/rfc3394.txt @@ -2566,7 +2554,6 @@ def test_derive_key(derivation_parameters): def wrapping_parameters(request): return request.param - def test_wrap_key(wrapping_parameters): """ Test that various wrapping methods and settings can be used to correctly @@ -2583,11 +2570,9 @@ def test_wrap_key(wrapping_parameters): assert wrapping_parameters.get('wrapped_data') == result - # Test vectors obtained from pyca/cryptography # https://cryptography.io/en/latest/ - DER_RSA_KEY = ( b'\x30\x82\x02\x5e\x02\x01\x00\x02\x81\x81\x00\xae\xba\xc1\xb9\xa1\x74\x31' b'\x5d\x27\xcc\x3c\x20\x1e\x21\x57\x89\x43\x72\xd6\x45\x0d\x4c\xf8\x0c\xe0' @@ -2679,11 +2664,9 @@ def test_wrap_key(wrapping_parameters): b'\x52\x49\x56\x41\x54\x45\x20\x4b\x45\x59\x2d\x2d\x2d\x2d\x2d\x0a' ) - SIGN_TEST_DATA = (b'\x01\x02\x03\x04\x05\x06\x07\x08' b'\x09\x10\x11\x12\x13\x14\x15\x16') - @pytest.fixture( scope='function', params=[ @@ -2745,7 +2728,6 @@ def test_wrap_key(wrapping_parameters): def signing_parameters(request): return request.param - def load_private_key(key): try: return serialization.load_der_private_key( @@ -2760,7 +2742,6 @@ def load_private_key(key): backend=default_backend() ) - def test_sign(signing_parameters): engine = crypto.CryptographyEngine() result = engine.sign( @@ -2782,7 +2763,6 @@ def test_sign(signing_parameters): signing_parameters.get('verify_args')[1] ) - # RSA signing test vectors were obtained from pyca/cryptography: # # https://github.com/pyca/cryptography/blob/master/vectors/ @@ -2916,7 +2896,6 @@ def test_sign(signing_parameters): def signature_parameters(request): return request.param - def test_verify_signature(signature_parameters): """ Test that various signature verification methods and settings can be used diff --git a/kmip/tests/unit/services/server/crypto/test_engine_extended.py b/kmip/tests/unit/services/server/crypto/test_engine_extended.py new file mode 100644 index 00000000..5e3c9166 --- /dev/null +++ b/kmip/tests/unit/services/server/crypto/test_engine_extended.py @@ -0,0 +1,773 @@ +# Copyright (c) 2026 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 os + +import testtools + +from cryptography import exceptions as crypto_exceptions +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hmac as crypto_hmac +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import padding as asym_padding +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.hazmat.primitives import keywrap + +from kmip.core import enums +from kmip.core import exceptions +from kmip.services.server import crypto + + +class TestCryptographyEngineExtended(testtools.TestCase): + + _rsa_2048_private = None + _rsa_2048_public = None + _rsa_4096_private = None + _rsa_4096_public = None + + def setUp(self): + super(TestCryptographyEngineExtended, self).setUp() + self.engine = crypto.CryptographyEngine() + + self.aes_128 = os.urandom(16) + self.aes_192 = os.urandom(24) + self.aes_256 = os.urandom(32) + self.tdes_128 = os.urandom(16) + self.tdes_192 = os.urandom(24) + self.blowfish_128 = os.urandom(16) + self.blowfish_192 = os.urandom(24) + self.blowfish_256 = os.urandom(32) + self.camellia_128 = os.urandom(16) + self.camellia_192 = os.urandom(24) + self.camellia_256 = os.urandom(32) + + self.iv_16 = os.urandom(16) + self.iv_12 = os.urandom(12) + + self._ensure_rsa_keys() + + def tearDown(self): + super(TestCryptographyEngineExtended, self).tearDown() + + @classmethod + def _serialize_rsa_keypair(cls, private_key): + private_bytes = private_key.private_bytes( + serialization.Encoding.DER, + serialization.PrivateFormat.PKCS8, + serialization.NoEncryption() + ) + public_bytes = private_key.public_key().public_bytes( + serialization.Encoding.DER, + serialization.PublicFormat.PKCS1 + ) + return private_bytes, public_bytes + + def _ensure_rsa_keys(self): + if self.__class__._rsa_2048_private is None: + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend() + ) + private_bytes, public_bytes = self._serialize_rsa_keypair( + private_key + ) + self.__class__._rsa_2048_private = private_bytes + self.__class__._rsa_2048_public = public_bytes + + if self.__class__._rsa_4096_private is None: + private_key = rsa.generate_private_key( + public_exponent=65537, + key_size=4096, + backend=default_backend() + ) + private_bytes, public_bytes = self._serialize_rsa_keypair( + private_key + ) + self.__class__._rsa_4096_private = private_bytes + self.__class__._rsa_4096_public = public_bytes + + self.rsa_2048_private = self.__class__._rsa_2048_private + self.rsa_2048_public = self.__class__._rsa_2048_public + self.rsa_4096_private = self.__class__._rsa_4096_private + self.rsa_4096_public = self.__class__._rsa_4096_public + + def _load_public_key(self, public_bytes): + return serialization.load_der_public_key( + public_bytes, + backend=default_backend() + ) + + def test_create_symmetric_key_aes_128(self): + """Test AES-128 symmetric key generation.""" + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.AES, + 128 + ) + self.assertEqual(16, len(key.get('value'))) + + def test_create_symmetric_key_aes_192(self): + """Test AES-192 symmetric key generation.""" + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.AES, + 192 + ) + self.assertEqual(24, len(key.get('value'))) + + def test_create_symmetric_key_aes_256(self): + """Test AES-256 symmetric key generation.""" + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.AES, + 256 + ) + self.assertEqual(32, len(key.get('value'))) + + def test_create_symmetric_key_3des_128(self): + """Test 3DES 128-bit symmetric key generation.""" + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.TRIPLE_DES, + 128 + ) + self.assertEqual(16, len(key.get('value'))) + + def test_create_symmetric_key_3des_192(self): + """Test 3DES 192-bit symmetric key generation.""" + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.TRIPLE_DES, + 192 + ) + self.assertEqual(24, len(key.get('value'))) + + def test_create_symmetric_key_blowfish_various_lengths(self): + """Test Blowfish key generation for multiple lengths.""" + for length in [128, 192, 256]: + with self.subTest(length=length): + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.BLOWFISH, + length + ) + self.assertEqual(length // 8, len(key.get('value'))) + + def _assert_camellia_length(self, length): + key = self.engine.create_symmetric_key( + enums.CryptographicAlgorithm.CAMELLIA, + length + ) + self.assertEqual(length // 8, len(key.get('value'))) + + def test_create_symmetric_key_camellia_128(self): + """Test Camellia 128-bit symmetric key generation.""" + self._assert_camellia_length(128) + + def test_create_symmetric_key_camellia_192(self): + """Test Camellia 192-bit symmetric key generation.""" + self._assert_camellia_length(192) + + def test_create_symmetric_key_camellia_256(self): + """Test Camellia 256-bit symmetric key generation.""" + self._assert_camellia_length(256) + + def test_create_symmetric_key_unsupported_algorithm(self): + """Test unsupported symmetric algorithm raises InvalidField.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.create_symmetric_key, + enums.CryptographicAlgorithm.RSA, + 128 + ) + + def test_create_symmetric_key_invalid_length(self): + """Test invalid symmetric key length raises InvalidField.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.create_symmetric_key, + enums.CryptographicAlgorithm.AES, + 127 + ) + + def test_create_asymmetric_key_pair_rsa_2048(self): + """Test RSA 2048 key pair generation.""" + public_key, private_key = self.engine.create_asymmetric_key_pair( + enums.CryptographicAlgorithm.RSA, + 2048 + ) + private = serialization.load_der_private_key( + private_key.get('value'), + password=None, + backend=default_backend() + ) + self.assertEqual(2048, private.key_size) + public = self._load_public_key(public_key.get('value')) + self.assertEqual(2048, public.key_size) + + def test_create_asymmetric_key_pair_rsa_4096(self): + """Test RSA 4096 key pair generation.""" + public_key, private_key = self.engine.create_asymmetric_key_pair( + enums.CryptographicAlgorithm.RSA, + 4096 + ) + private = serialization.load_der_private_key( + private_key.get('value'), + password=None, + backend=default_backend() + ) + self.assertEqual(4096, private.key_size) + public = self._load_public_key(public_key.get('value')) + self.assertEqual(4096, public.key_size) + + def test_create_asymmetric_key_pair_invalid_algorithm(self): + """Test invalid algorithm for asymmetric keys raises InvalidField.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.create_asymmetric_key_pair, + enums.CryptographicAlgorithm.AES, + 2048 + ) + + def test_create_asymmetric_key_pair_invalid_length(self): + """Test invalid RSA key length raises CryptographicFailure.""" + self.assertRaises( + exceptions.CryptographicFailure, + self.engine.create_asymmetric_key_pair, + enums.CryptographicAlgorithm.RSA, + 0 + ) + + def test_encrypt_aes_cbc_pkcs5_padding(self): + """Test AES-CBC encryption with PKCS5 padding.""" + plain_text = b'kmip-plain-text' + result = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_128, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5 + ) + self.assertIn('cipher_text', result) + self.assertIn('iv_nonce', result) + + def test_encrypt_aes_gcm_with_aad(self): + """Test AES-GCM encryption with additional authenticated data.""" + plain_text = b'kmip-gcm-plain-text' + aad = b'kmip-aad' + result = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_256, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag_length=16 + ) + self.assertIn('cipher_text', result) + self.assertIn('auth_tag', result) + + def test_encrypt_aes_ctr_mode(self): + """Test AES-CTR encryption.""" + plain_text = b'kmip-ctr-plain-text' + result = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_128, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.CTR, + iv_nonce=self.iv_16 + ) + self.assertIn('cipher_text', result) + + def test_decrypt_aes_cbc_pkcs5_padding(self): + """Test AES-CBC decryption with PKCS5 padding.""" + plain_text = b'kmip-cbc-plain-text' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_128, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ) + dec = self.engine.decrypt( + decryption_algorithm=enums.CryptographicAlgorithm.AES, + decryption_key=self.aes_128, + cipher_text=enc.get('cipher_text'), + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ) + self.assertEqual(plain_text, dec) + + def test_decrypt_aes_gcm_with_aad(self): + """Test AES-GCM decryption with additional authenticated data.""" + plain_text = b'kmip-gcm-plain-text' + aad = b'kmip-aad' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_256, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag_length=16 + ) + dec = self.engine.decrypt( + decryption_algorithm=enums.CryptographicAlgorithm.AES, + decryption_key=self.aes_256, + cipher_text=enc.get('cipher_text'), + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag=enc.get('auth_tag') + ) + self.assertEqual(plain_text, dec) + + def test_decrypt_wrong_key(self): + """Test AES-GCM decryption with wrong key raises InvalidTag.""" + plain_text = b'kmip-gcm-plain-text' + aad = b'kmip-aad' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_256, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag_length=16 + ) + self.assertRaises( + crypto_exceptions.InvalidTag, + self.engine.decrypt, + enums.CryptographicAlgorithm.AES, + self.aes_128, + enc.get('cipher_text'), + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag=enc.get('auth_tag') + ) + + def test_decrypt_corrupted_ciphertext(self): + """Test AES-GCM decryption fails with corrupted ciphertext.""" + plain_text = b'kmip-gcm-plain-text' + aad = b'kmip-aad' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_256, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag_length=16 + ) + cipher_text = bytearray(enc.get('cipher_text')) + cipher_text[0] ^= 0xFF + self.assertRaises( + crypto_exceptions.InvalidTag, + self.engine.decrypt, + enums.CryptographicAlgorithm.AES, + self.aes_256, + bytes(cipher_text), + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag=enc.get('auth_tag') + ) + + def test_encrypt_decrypt_roundtrip_aes_128_cbc(self): + """Test AES-128 CBC roundtrip encryption/decryption.""" + plain_text = b'kmip-roundtrip-plain-text' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_128, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ) + dec = self.engine.decrypt( + decryption_algorithm=enums.CryptographicAlgorithm.AES, + decryption_key=self.aes_128, + cipher_text=enc.get('cipher_text'), + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ) + self.assertEqual(plain_text, dec) + + def test_encrypt_decrypt_roundtrip_aes_256_gcm(self): + """Test AES-256 GCM roundtrip encryption/decryption.""" + plain_text = b'kmip-roundtrip-gcm' + aad = b'kmip-aad' + enc = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_256, + plain_text=plain_text, + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag_length=16 + ) + dec = self.engine.decrypt( + decryption_algorithm=enums.CryptographicAlgorithm.AES, + decryption_key=self.aes_256, + cipher_text=enc.get('cipher_text'), + cipher_mode=enums.BlockCipherMode.GCM, + iv_nonce=self.iv_12, + auth_additional_data=aad, + auth_tag=enc.get('auth_tag') + ) + self.assertEqual(plain_text, dec) + + def test_sign_rsa_pkcs1v15_sha256(self): + """Test RSA PKCS#1 v1.5 signing with SHA-256.""" + data = b'kmip-sign-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + padding=enums.PaddingMethod.PKCS1v15, + signing_key=self.rsa_2048_private, + data=data + ) + public_key = self._load_public_key(self.rsa_2048_public) + public_key.verify( + signature, + data, + asym_padding.PKCS1v15(), + hashes.SHA256() + ) + + def test_sign_rsa_pss_sha256(self): + """Test RSA PSS signing with SHA-256.""" + data = b'kmip-sign-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + padding=enums.PaddingMethod.PSS, + signing_key=self.rsa_2048_private, + data=data + ) + public_key = self._load_public_key(self.rsa_2048_public) + public_key.verify( + signature, + data, + asym_padding.PSS( + mgf=asym_padding.MGF1(hashes.SHA256()), + salt_length=asym_padding.PSS.MAX_LENGTH + ), + hashes.SHA256() + ) + + def test_sign_rsa_pss_sha512(self): + """Test RSA PSS signing with SHA-512.""" + data = b'kmip-sign-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_512, + padding=enums.PaddingMethod.PSS, + signing_key=self.rsa_2048_private, + data=data + ) + public_key = self._load_public_key(self.rsa_2048_public) + public_key.verify( + signature, + data, + asym_padding.PSS( + mgf=asym_padding.MGF1(hashes.SHA512()), + salt_length=asym_padding.PSS.MAX_LENGTH + ), + hashes.SHA512() + ) + + def test_verify_signature_valid(self): + """Test signature verification returns True for valid signatures.""" + data = b'kmip-verify-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + padding=enums.PaddingMethod.PKCS1v15, + signing_key=self.rsa_2048_private, + data=data + ) + result = self.engine.verify_signature( + signing_key=self.rsa_2048_public, + message=data, + signature=signature, + padding_method=enums.PaddingMethod.PKCS1v15, + signing_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ) + self.assertTrue(result) + + def test_verify_signature_invalid(self): + """Test signature verification returns False for invalid signatures.""" + data = b'kmip-verify-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + padding=enums.PaddingMethod.PKCS1v15, + signing_key=self.rsa_2048_private, + data=data + ) + signature = signature[:-1] + bytes([signature[-1] ^ 0xFF]) + result = self.engine.verify_signature( + signing_key=self.rsa_2048_public, + message=data, + signature=signature, + padding_method=enums.PaddingMethod.PKCS1v15, + signing_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ) + self.assertFalse(result) + + def test_verify_signature_wrong_key(self): + """Test signature verification returns False with wrong key.""" + data = b'kmip-verify-data' + signature = self.engine.sign( + digital_signature_algorithm=None, + crypto_alg=enums.CryptographicAlgorithm.RSA, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + padding=enums.PaddingMethod.PKCS1v15, + signing_key=self.rsa_2048_private, + data=data + ) + result = self.engine.verify_signature( + signing_key=self.rsa_4096_public, + message=data, + signature=signature, + padding_method=enums.PaddingMethod.PKCS1v15, + signing_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ) + self.assertFalse(result) + + def test_sign_verify_roundtrip(self): + """Test sign/verify roundtrip with RSA.""" + data = b'kmip-sign-verify' + signature = self.engine.sign( + digital_signature_algorithm= + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION, + crypto_alg=None, + hash_algorithm=None, + padding=enums.PaddingMethod.PKCS1v15, + signing_key=self.rsa_2048_private, + data=data + ) + result = self.engine.verify_signature( + signing_key=self.rsa_2048_public, + message=data, + signature=signature, + padding_method=enums.PaddingMethod.PKCS1v15, + digital_signature_algorithm= + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ) + self.assertTrue(result) + + def test_mac_hmac_sha256(self): + """Test HMAC-SHA256 MAC generation.""" + data = b'kmip-mac-data' + key = os.urandom(32) + mac = self.engine.mac( + enums.CryptographicAlgorithm.HMAC_SHA256, + key, + data + ) + h = crypto_hmac.HMAC(key, hashes.SHA256(), backend=default_backend()) + h.update(data) + expected = h.finalize() + self.assertEqual(expected, mac) + + def test_mac_hmac_sha512(self): + """Test HMAC-SHA512 MAC generation.""" + data = b'kmip-mac-data' + key = os.urandom(64) + mac = self.engine.mac( + enums.CryptographicAlgorithm.HMAC_SHA512, + key, + data + ) + h = crypto_hmac.HMAC(key, hashes.SHA512(), backend=default_backend()) + h.update(data) + expected = h.finalize() + self.assertEqual(expected, mac) + + def test_mac_invalid_algorithm(self): + """Test MAC rejects unsupported algorithm.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.mac, + enums.CryptographicAlgorithm.RSA, + os.urandom(16), + b'data' + ) + + def test_mac_verify_roundtrip(self): + """Test HMAC roundtrip verification.""" + data = b'kmip-mac-data' + key = os.urandom(32) + mac = self.engine.mac( + enums.CryptographicAlgorithm.HMAC_SHA256, + key, + data + ) + verifier = crypto_hmac.HMAC( + key, + hashes.SHA256(), + backend=default_backend() + ) + verifier.update(data) + verifier.verify(mac) + + def test_derive_key_pbkdf2_hmac_sha256(self): + """Test PBKDF2 key derivation using HMAC-SHA256.""" + derived = self.engine.derive_key( + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_length=32, + key_material=self.aes_256, + hash_algorithm=enums.HashingAlgorithm.SHA_256, + salt=b'kmip-salt', + iteration_count=1000 + ) + self.assertEqual(32, len(derived)) + + def test_derive_key_hmac(self): + """Test HMAC-based key derivation.""" + derived = self.engine.derive_key( + derivation_method=enums.DerivationMethod.HMAC, + derivation_length=32, + derivation_data=b'kmip-info', + key_material=self.aes_256, + hash_algorithm=enums.HashingAlgorithm.SHA_256 + ) + self.assertEqual(32, len(derived)) + + def test_derive_key_encrypt(self): + """Test encryption-based key derivation.""" + derivation_data = b'kmip-derive-data' + encrypted = self.engine.derive_key( + derivation_method=enums.DerivationMethod.ENCRYPT, + derivation_length=16, + derivation_data=derivation_data, + key_material=self.aes_128, + encryption_algorithm=enums.CryptographicAlgorithm.AES, + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ) + expected = self.engine.encrypt( + encryption_algorithm=enums.CryptographicAlgorithm.AES, + encryption_key=self.aes_128, + plain_text=derivation_data, + cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + iv_nonce=self.iv_16 + ).get('cipher_text') + self.assertEqual(expected, encrypted) + + def test_derive_key_nist_800_108c(self): + """Test NIST 800-108 counter mode derivation.""" + derived = self.engine.derive_key( + derivation_method=enums.DerivationMethod.NIST800_108_C, + derivation_length=32, + derivation_data=b'kmip-context', + key_material=self.aes_256, + hash_algorithm=enums.HashingAlgorithm.SHA_256 + ) + self.assertEqual(32, len(derived)) + + def test_derive_key_missing_parameters(self): + """Test key derivation errors for missing parameters.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.derive_key, + enums.DerivationMethod.HMAC, + 16, + derivation_data=b'kmip', + key_material=self.aes_128, + hash_algorithm=None + ) + self.assertRaises( + exceptions.InvalidField, + self.engine.derive_key, + enums.DerivationMethod.PBKDF2, + 16, + key_material=self.aes_128, + hash_algorithm=enums.HashingAlgorithm.SHA_256 + ) + + def test_derive_key_invalid_method(self): + """Test invalid key derivation method raises InvalidField.""" + self.assertRaises( + exceptions.InvalidField, + self.engine.derive_key, + enums.DerivationMethod.ASYMMETRIC_KEY, + 16, + key_material=self.aes_128, + hash_algorithm=enums.HashingAlgorithm.SHA_256 + ) + + def test_wrap_key_aes_key_wrap(self): + """Test AES key wrap produces expected output.""" + key_material = os.urandom(16) + wrapping_key = os.urandom(16) + wrapped = self.engine.wrap_key( + key_material=key_material, + wrapping_method=enums.WrappingMethod.ENCRYPT, + key_wrap_algorithm=enums.BlockCipherMode.NIST_KEY_WRAP, + encryption_key=wrapping_key + ) + expected = keywrap.aes_key_wrap( + wrapping_key, + key_material, + backend=default_backend() + ) + self.assertEqual(expected, wrapped) + + def test_unwrap_key_aes_key_wrap(self): + """Test AES key wrap can be unwrapped to original key material.""" + key_material = os.urandom(16) + wrapping_key = os.urandom(16) + wrapped = self.engine.wrap_key( + key_material=key_material, + wrapping_method=enums.WrappingMethod.ENCRYPT, + key_wrap_algorithm=enums.BlockCipherMode.NIST_KEY_WRAP, + encryption_key=wrapping_key + ) + unwrapped = keywrap.aes_key_unwrap( + wrapping_key, + wrapped, + backend=default_backend() + ) + self.assertEqual(key_material, unwrapped) + + def test_wrap_unwrap_roundtrip(self): + """Test wrap/unwrap roundtrip for larger key material.""" + key_material = os.urandom(32) + wrapping_key = os.urandom(32) + wrapped = self.engine.wrap_key( + key_material=key_material, + wrapping_method=enums.WrappingMethod.ENCRYPT, + key_wrap_algorithm=enums.BlockCipherMode.NIST_KEY_WRAP, + encryption_key=wrapping_key + ) + unwrapped = keywrap.aes_key_unwrap( + wrapping_key, + wrapped, + backend=default_backend() + ) + self.assertEqual(key_material, unwrapped) diff --git a/kmip/tests/unit/services/server/test_config.py b/kmip/tests/unit/services/server/test_config.py index e4b97508..b8fa3234 100644 --- a/kmip/tests/unit/services/server/test_config.py +++ b/kmip/tests/unit/services/server/test_config.py @@ -16,15 +16,12 @@ import logging import mock -import six -from six.moves import configparser - +import configparser import testtools from kmip.core import exceptions from kmip.services.server import config - class TestKmipServerConfig(testtools.TestCase): """ A test suite for the KmipServerConfig tool. @@ -135,7 +132,7 @@ def test_load_settings(self): with mock.patch('os.path.exists') as os_mock: os_mock.return_value = True with mock.patch( - 'six.moves.configparser.ConfigParser.read' + 'configparser.ConfigParser.read' ) as parser_mock: c.load_settings("/test/path/server.conf") c._logger.info.assert_any_call( @@ -189,14 +186,14 @@ def test_parse_auth_settings(self): self.assertIsInstance(c[1], dict) if c[0] == 'auth:slugs': - self.assertIn('enabled', six.iterkeys(c[1])) + self.assertIn('enabled', c[1].keys()) self.assertEqual('True', c[1]['enabled']) - self.assertIn('url', six.iterkeys(c[1])) + self.assertIn('url', c[1].keys()) self.assertEqual('http://127.0.0.1:8080/slugs/', c[1]['url']) elif c[0] == 'auth:ldap': - self.assertIn('enabled', six.iterkeys(c[1])) + self.assertIn('enabled', c[1].keys()) self.assertEqual('False', c[1]['enabled']) - self.assertIn('url', six.iterkeys(c[1])) + self.assertIn('url', c[1].keys()) self.assertEqual('http://127.0.0.1:8080/ldap/', c[1]['url']) def test_parse_auth_settings_no_config(self): @@ -388,6 +385,26 @@ def test_set_port(self): ) self.assertNotEqual('invalid', c.settings.get('port')) + args = (0, ) + regex = "The port value must be an integer in the range 0 - 65535." + self.assertRaisesRegex( + exceptions.ConfigurationError, + regex, + c._set_port, + *args + ) + self.assertNotEqual(0, c.settings.get('port')) + + args = (65535, ) + regex = "The port value must be an integer in the range 0 - 65535." + self.assertRaisesRegex( + exceptions.ConfigurationError, + regex, + c._set_port, + *args + ) + self.assertNotEqual(65535, c.settings.get('port')) + args = (65536, ) regex = "The port value must be an integer in the range 0 - 65535." self.assertRaisesRegex( diff --git a/kmip/tests/unit/services/server/test_engine.py b/kmip/tests/unit/services/server/test_engine.py index ad596dfe..8469b2ed 100644 --- a/kmip/tests/unit/services/server/test_engine.py +++ b/kmip/tests/unit/services/server/test_engine.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import six import mock +import os import shutil import sqlalchemy @@ -45,7 +45,6 @@ from kmip.services.server import engine - class MockRegexString(str): """ A comparator string for doing simple containment regex comparisons @@ -54,7 +53,6 @@ class MockRegexString(str): def __eq__(self, other): return self in other - class TestKmipEngine(testtools.TestCase): """ A test suite for the KmipEngine. @@ -141,7 +139,9 @@ def test_init_create_engine(self, create_engine_mock): backend. """ engine.KmipEngine() - args = ("sqlite:////tmp/pykmip.database",) + db_path = os.path.join(tempfile.gettempdir(), 'pykmip.database') + db_uri = 'sqlite:///{}'.format(db_path.replace('\\', '/')) + args = (db_uri,) fargs = { 'echo': False, 'connect_args': {'check_same_thread': False} @@ -172,9 +172,7 @@ def test_version_operation_mismatch(self): regex = "DiscoverVersions is not supported by KMIP {0}".format( e._protocol_version ) - six.assertRaisesRegex( - self, - exceptions.OperationNotSupported, + self.assertRaisesRegex(exceptions.OperationNotSupported, regex, e._process_discover_versions, *args @@ -261,6 +259,42 @@ def test_process_request(self): ) self.assertIsNone(batch_item.message_extension) + def test_process_request_without_max_response_size(self): + """ + Test that max_response_size is None when not provided. + """ + e = engine.KmipEngine(database_path=':memory:') + e._logger = mock.MagicMock() + + protocol = contents.ProtocolVersion(1, 1) + header = messages.RequestHeader( + protocol_version=protocol, + authentication=contents.Authentication(), + batch_error_cont_option=contents.BatchErrorContinuationOption( + enums.BatchErrorContinuationOption.STOP + ), + batch_order_option=contents.BatchOrderOption(True), + time_stamp=contents.TimeStamp(int(time.time())), + batch_count=contents.BatchCount(1) + ) + payload = payloads.DiscoverVersionsRequestPayload() + batch = list([ + messages.RequestBatchItem( + operation=contents.Operation( + enums.Operation.DISCOVER_VERSIONS + ), + request_payload=payload + ) + ]) + request = messages.RequestMessage( + request_header=header, + batch_items=batch + ) + + _, max_size, _ = e.process_request(request) + + self.assertIsNone(max_size) + def test_process_request_unsupported_version(self): """ Test that an InvalidMessage exception is raised when processing a @@ -281,8 +315,29 @@ def test_process_request_unsupported_version(self): regex = "KMIP {0} is not supported by the server.".format( protocol ) - six.assertRaisesRegex( - self, + self.assertRaisesRegex(exceptions.InvalidMessage, + regex, + e.process_request, + *args + ) + + def test_process_request_protocol_version_none(self): + """ + Test that an InvalidMessage exception is raised when protocol version + is None. + """ + e = engine.KmipEngine(database_path=':memory:') + e._logger = mock.MagicMock() + + header = messages.RequestHeader(protocol_version=None) + request = messages.RequestMessage( + request_header=header, + batch_items=[] + ) + + args = (request, ) + regex = "KMIP None is not supported by the server." + self.assertRaisesRegex( exceptions.InvalidMessage, regex, e.process_request, @@ -308,9 +363,7 @@ def test_process_request_stale_timestamp(self): args = (request, ) regex = "Stale request rejected by server." - six.assertRaisesRegex( - self, - exceptions.InvalidMessage, + self.assertRaisesRegex(exceptions.InvalidMessage, regex, e.process_request, *args @@ -341,9 +394,7 @@ def test_process_request_future_timestamp(self): args = (request, ) regex = "Future request rejected by server." - six.assertRaisesRegex( - self, - exceptions.InvalidMessage, + self.assertRaisesRegex(exceptions.InvalidMessage, regex, e.process_request, *args @@ -374,9 +425,7 @@ def test_process_request_unsupported_async_indicator(self): args = (request, ) regex = "Asynchronous operations are not supported." - six.assertRaisesRegex( - self, - exceptions.InvalidMessage, + self.assertRaisesRegex(exceptions.InvalidMessage, regex, e.process_request, *args @@ -404,9 +453,7 @@ def test_process_request_unsupported_batch_option(self): args = (request, ) regex = "Undo option for batch handling is not supported." - six.assertRaisesRegex( - self, - exceptions.InvalidMessage, + self.assertRaisesRegex(exceptions.InvalidMessage, regex, e.process_request, *args @@ -447,6 +494,41 @@ def test_process_request_missing_credential(self): e.process_request(request) + def test_process_request_empty_credentials_list(self): + """ + Test that an empty authentication credential list is handled without + error. + """ + e = engine.KmipEngine(database_path=':memory:') + e._logger = mock.MagicMock() + e._verify_credential = mock.MagicMock() + + auth = contents.Authentication() + auth.credentials = [] + + header = messages.RequestHeader( + protocol_version=contents.ProtocolVersion(1, 1), + authentication=auth, + time_stamp=contents.TimeStamp(int(time.time())), + batch_count=contents.BatchCount(1) + ) + payload = payloads.DiscoverVersionsRequestPayload() + batch = list([ + messages.RequestBatchItem( + operation=contents.Operation( + enums.Operation.DISCOVER_VERSIONS + ), + request_payload=payload + ) + ]) + request = messages.RequestMessage( + request_header=header, + batch_items=batch + ) + + e.process_request(request) + e._verify_credential.assert_called_once_with(None, None) + def test_build_error_response(self): """ Test that a bare bones response containing a single error result can @@ -501,7 +583,7 @@ def test_process_batch(self): """ Test that a batch is processed correctly. """ - e = engine.KmipEngine() + e = engine.KmipEngine(database_path=':memory:') e._logger = mock.MagicMock() payload = payloads.DiscoverVersionsRequestPayload() @@ -523,6 +605,22 @@ def test_process_batch(self): self.assertIsNotNone(results) self.assertEqual(1, len(results)) + def test_process_empty_batch(self): + """ + Test that an empty batch is processed correctly. + """ + e = engine.KmipEngine(database_path=':memory:') + e._logger = mock.MagicMock() + + results = e._process_batch( + [], + enums.BatchErrorContinuationOption.STOP, + True + ) + + self.assertIsNotNone(results) + self.assertEqual(0, len(results)) + def test_process_multibatch(self): """ Test that a batch containing multiple operations is processed @@ -572,9 +670,7 @@ def test_process_batch_missing_batch_id(self): ]) args = (batch, None, None) - six.assertRaisesRegex( - self, - exceptions.InvalidMessage, + self.assertRaisesRegex(exceptions.InvalidMessage, "Batch item ID is undefined.", e._process_batch, *args @@ -694,6 +790,44 @@ def test_process_batch_unexpected_error(self): self.assertIsNone(result.response_payload) self.assertIsNone(result.message_extension) + def test_process_batch_stop_on_first_error(self): + """ + Test that batch processing stops after the first error when STOP is + configured. + """ + e = engine.KmipEngine(database_path=':memory:') + e._logger = mock.MagicMock() + e._process_operation = mock.MagicMock( + side_effect=[ + exceptions.OperationNotSupported("boom"), + None + ] + ) + + batch = [ + messages.RequestBatchItem( + operation=contents.Operation( + enums.Operation.DISCOVER_VERSIONS + ), + unique_batch_item_id=contents.UniqueBatchItemID(b'1') + ), + messages.RequestBatchItem( + operation=contents.Operation( + enums.Operation.DISCOVER_VERSIONS + ), + unique_batch_item_id=contents.UniqueBatchItemID(b'2') + ) + ] + + results = e._process_batch( + batch, + enums.BatchErrorContinuationOption.STOP, + True + ) + + self.assertEqual(1, len(results)) + self.assertEqual(1, e._process_operation.call_count) + def test_process_operation(self): """ Test that the right subroutine is called when invoking operations @@ -780,9 +914,7 @@ def test_unsupported_operation(self): regex = "{0} operation is not supported by the server.".format( args[0].name.title() ) - six.assertRaisesRegex( - self, - exceptions.OperationNotSupported, + self.assertRaisesRegex(exceptions.OperationNotSupported, regex, e._process_operation, *args @@ -827,9 +959,7 @@ def test_get_object_type_missing_object(self): args = ('1', ) regex = "Could not locate object: 1" - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._get_object_type, *args @@ -895,9 +1025,7 @@ def test_get_object_type_unsupported_type(self): ) ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._get_object_type, *args @@ -1041,9 +1169,7 @@ def test_build_core_object_unsupported_type(self): args = (None, ) regex = "Cannot build an unsupported object type." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._build_core_object, *args @@ -1055,9 +1181,7 @@ def __init__(self): args = (DummyObject(), ) regex = "The Template object type is not supported." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._build_core_object, *args @@ -1149,9 +1273,7 @@ def test_process_template_attribute_unsupported_features(self): args = (template_attribute, ) regex = "Attribute templates are not supported." - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_template_attribute, *args @@ -1170,9 +1292,7 @@ def test_process_template_attribute_unsupported_features(self): args = (template_attribute, ) regex = "The invalid attribute is unsupported." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_template_attribute, *args @@ -1200,9 +1320,7 @@ def test_process_template_attribute_unsupported_features(self): args = (template_attribute, ) regex = "Attribute index missing from multivalued attribute." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_template_attribute, *args @@ -1218,9 +1336,7 @@ def test_process_template_attribute_unsupported_features(self): args = (template_attribute, ) regex = "Non-zero attribute index found for single-valued attribute." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_template_attribute, *args @@ -1246,9 +1362,7 @@ def test_process_template_attribute_unsupported_features(self): "Cannot set multiple instances of the Cryptographic Algorithm " "attribute." ) - six.assertRaisesRegex( - self, - exceptions.IndexOutOfBounds, + self.assertRaisesRegex(exceptions.IndexOutOfBounds, regex, e._process_template_attribute, *args @@ -1538,7 +1652,7 @@ def test_get_attribute_from_managed_object(self): 'Initial Date' ) self.assertIsNotNone(result) - self.assertIsInstance(result, six.integer_types) + self.assertIsInstance(result, int) result = e._get_attribute_from_managed_object( symmetric_key, @@ -2060,9 +2174,7 @@ def test_set_attributes_on_managed_object_attribute_mismatch(self): "Cannot set Cryptographic Usage Mask attribute on OpaqueData " "object." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._set_attributes_on_managed_object, *args @@ -2207,9 +2319,7 @@ def test_set_attribute_on_managed_object_unsupported_features(self): ('Name', [name_a.attribute_value, name_b.attribute_value]) ) regex = "Cannot set duplicate name values." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._set_attribute_on_managed_object, *args @@ -2237,9 +2347,7 @@ def test_set_attribute_on_managed_object_unsupported_features(self): ('Digest', [name_a.attribute_value, name_b.attribute_value]) ) regex = "The Digest attribute is unsupported." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._set_attribute_on_managed_object, *args @@ -2256,9 +2364,7 @@ def test_set_attribute_on_managed_object_unsupported_features(self): ('Cryptographic Length', length.attribute_value) ) regex = "Cannot overwrite the Cryptographic Length attribute." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._set_attribute_on_managed_object, *args @@ -2275,9 +2381,7 @@ def test_set_attribute_on_managed_object_unsupported_features(self): ("Custom Attribute", custom_attribute.attribute_value) ) regex = "The Custom Attribute attribute is unsupported." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._set_attribute_on_managed_object, *args @@ -3227,9 +3331,7 @@ def test_get_object_with_access_controls(self): # Test by specifying the ID of the object to retrieve and the # operation context. args = [id_a, enums.Operation.GET] - six.assertRaisesRegex( - self, - exceptions.PermissionDenied, + self.assertRaisesRegex(exceptions.PermissionDenied, "Could not locate object: {0}".format(id_a), e._get_object_with_access_controls, *args @@ -3369,9 +3471,7 @@ def test_create_unsupported_object_type(self): args = (payload, ) regex = "Cannot create a PublicKey object with the Create operation." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create, *args @@ -3427,9 +3527,7 @@ def test_create_omitting_attributes(self): regex = ( "The cryptographic algorithm must be specified as an attribute." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create, *args @@ -3473,9 +3571,7 @@ def test_create_omitting_attributes(self): regex = ( "The cryptographic length must be specified as an attribute." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create, *args @@ -3516,9 +3612,7 @@ def test_create_omitting_attributes(self): regex = ( "The cryptographic usage mask must be specified as an attribute." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create, *args @@ -3729,9 +3823,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic algorithm must be specified as an attribute " "for the public key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -3799,9 +3891,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic algorithm must be specified as an attribute " "for the private key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -3869,9 +3959,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic length must be specified as an attribute for " "the public key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -3939,9 +4027,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic length must be specified as an attribute for " "the private key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -4007,9 +4093,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic usage mask must be specified as an attribute " "for the public key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -4075,9 +4159,7 @@ def test_create_key_pair_omitting_attributes(self): "The cryptographic usage mask must be specified as an attribute " "for the private key." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -4161,9 +4243,7 @@ def test_create_key_pair_mismatched_attributes(self): regex = ( "The public and private key algorithms must be the same." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -4234,9 +4314,7 @@ def test_create_key_pair_mismatched_attributes(self): regex = ( "The public and private key lengths must be the same." ) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_create_key_pair, *args @@ -5575,9 +5653,7 @@ def test_register_unsupported_object_type(self): args = (payload, ) regex = "The Template object type is not supported." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_register, *args @@ -5599,9 +5675,7 @@ def test_request_omitting_secret(self): args = (payload, ) regex = "Cannot register a secret in absentia." - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, regex, e._process_register, *args @@ -6467,9 +6541,7 @@ def test_track_date_attributes(self): # Verify that the third date given triggers an exception. args = (enums.AttributeType.INITIAL_DATE, date_values, 1563564520) - six.assertRaisesRegex( - self, - exceptions.InvalidField, + self.assertRaisesRegex(exceptions.InvalidField, "Too many Initial Date attributes provided. " "Include one for an exact match. " "Include two for a ranged match.", @@ -6760,17 +6832,11 @@ def test_locate_with_initial_date(self): name='name1' ) obj_a.initial_date = int(time.time()) - obj_a_time_str = time.strftime( - "%a %b %-2d %H:%M:%S %Y", - time.gmtime(obj_a.initial_date) - ) + obj_a_time_str = time.asctime(time.gmtime(obj_a.initial_date)) time.sleep(2) mid_time = int(time.time()) - mid_time_str = time.strftime( - "%a %b %-2d %H:%M:%S %Y", - time.gmtime(mid_time) - ) + mid_time_str = time.asctime(time.gmtime(mid_time)) time.sleep(2) obj_b = pie_objects.SymmetricKey( @@ -6780,10 +6846,7 @@ def test_locate_with_initial_date(self): name='name2' ) obj_b.initial_date = int(time.time()) - obj_b_time_str = time.strftime( - "%a %b %-2d %H:%M:%S %Y", - time.gmtime(obj_b.initial_date) - ) + obj_b_time_str = time.asctime(time.gmtime(obj_b.initial_date)) time.sleep(2) end_time = int(time.time()) @@ -7995,9 +8058,7 @@ def test_get_unsupported_key_compression(self): args = (payload, ) regex = "Key compression is not supported." - six.assertRaisesRegex( - self, - exceptions.KeyCompressionTypeNotSupported, + self.assertRaisesRegex(exceptions.KeyCompressionTypeNotSupported, regex, e._process_get, *args @@ -8072,9 +8133,7 @@ def test_get_with_key_format_type(self): args = (payload, ) regex = "Key format conversion from RAW to OPAQUE is unsupported." - six.assertRaisesRegex( - self, - exceptions.KeyFormatTypeNotSupported, + self.assertRaisesRegex(exceptions.KeyFormatTypeNotSupported, regex, e._process_get, *args @@ -8103,9 +8162,7 @@ def test_get_with_key_format_type(self): args = (payload, ) regex = "Key format is not applicable to the specified object." - six.assertRaisesRegex( - self, - exceptions.KeyFormatTypeNotSupported, + self.assertRaisesRegex(exceptions.KeyFormatTypeNotSupported, regex, e._process_get, *args @@ -8138,9 +8195,7 @@ def test_get_not_allowed_by_policy(self): # Test by specifying the ID of the object to get. args = [payload] - six.assertRaisesRegex( - self, - exceptions.PermissionDenied, + self.assertRaisesRegex(exceptions.PermissionDenied, "Could not locate object: {0}".format(id_a), e._process_get, *args @@ -9729,9 +9784,7 @@ def test_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(id_a) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -9756,9 +9809,7 @@ def test_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(id_b) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -9783,9 +9834,7 @@ def test_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(id_c) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -9819,9 +9868,7 @@ def test_destroy_not_allowed_by_policy(self): # Test by specifying the ID of the object to destroy. args = [payload] - six.assertRaisesRegex( - self, - exceptions.PermissionDenied, + self.assertRaisesRegex(exceptions.PermissionDenied, "Could not locate object: {0}".format(id_a), e._process_destroy, *args @@ -9858,9 +9905,7 @@ def test_destroy_active_state(self): args = (payload, ) regex = "Object is active and cannot be destroyed." - six.assertRaisesRegex( - self, - exceptions.PermissionDenied, + self.assertRaisesRegex(exceptions.PermissionDenied, regex, e._process_destroy, *args @@ -11579,9 +11624,7 @@ def test_create_get_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(uid) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -11758,9 +11801,7 @@ def test_create_key_pair_get_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(public_id) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -11793,9 +11834,7 @@ def test_create_key_pair_get_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(private_id) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -11934,9 +11973,7 @@ def test_register_get_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(uid) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args @@ -12145,9 +12182,7 @@ def test_register_activate_encrypt_decrypt_revoke_destroy(self): args = (payload, ) regex = "Could not locate object: {0}".format(uuid) - six.assertRaisesRegex( - self, - exceptions.ItemNotFound, + self.assertRaisesRegex(exceptions.ItemNotFound, regex, e._process_destroy, *args diff --git a/kmip/tests/unit/services/server/test_engine_extended.py b/kmip/tests/unit/services/server/test_engine_extended.py new file mode 100644 index 00000000..82e8787d --- /dev/null +++ b/kmip/tests/unit/services/server/test_engine_extended.py @@ -0,0 +1,1884 @@ +# 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. + +import sqlalchemy +import testtools +import time + +from unittest import mock + +from kmip.core import attributes +from kmip.core import enums +from kmip.core import exceptions +from kmip.core import objects as core_objects +from kmip.core import secrets +from kmip.core.factories import attributes as attribute_factory +from kmip.core.messages import contents +from kmip.core.messages import payloads + +from kmip.pie import objects as pie_objects +from kmip.pie import sqltypes + +from kmip.services.server import engine as kmip_engine + + +def _mask_value(masks): + mask = 0 + for flag in masks: + mask |= flag.value + return mask + + +def _build_attribute_dict(algorithm=None, length=None, usage_masks=None): + attributes_dict = {} + if algorithm is not None: + attributes_dict['Cryptographic Algorithm'] = \ + attributes.CryptographicAlgorithm(algorithm) + if length is not None: + attributes_dict['Cryptographic Length'] = \ + attributes.CryptographicLength(length) + if usage_masks is not None: + attributes_dict['Cryptographic Usage Mask'] = \ + attributes.CryptographicUsageMask(_mask_value(usage_masks)) + return attributes_dict + + +class DummyManagedObject(object): + def __init__(self, unique_identifier, object_type, attributes_map=None): + self.unique_identifier = unique_identifier + self.object_type = object_type + self._object_type = object_type + self.initial_date = 0 + self._attributes = attributes_map or {} + + +class TestKmipEngineProcessExtended(testtools.TestCase): + + def setUp(self): + super(TestKmipEngineProcessExtended, self).setUp() + self.engine_instance = sqlalchemy.create_engine('sqlite://', echo=False) + sqltypes.Base.metadata.create_all(self.engine_instance) + self.session_factory = sqlalchemy.orm.sessionmaker( + bind=self.engine_instance, + expire_on_commit=False + ) + + self.engine = kmip_engine.KmipEngine() + self.engine._data_store = self.engine_instance + self.engine._data_store_session_factory = self.session_factory + self.engine._data_session = self.engine._data_store_session_factory() + self.engine._logger = mock.MagicMock() + self.engine._is_allowed_by_operation_policy = \ + mock.Mock(return_value=True) + self.engine._cryptography_engine = mock.MagicMock() + + def tearDown(self): + self.engine._data_session.close() + super(TestKmipEngineProcessExtended, self).tearDown() + + def _make_symmetric_key(self, state=enums.State.ACTIVE, masks=None): + if masks is None: + masks = [enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT] + key = pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + b'\x01' * 16, + masks=masks + ) + key.state = state + return key + + def _make_public_key(self, state=enums.State.ACTIVE, masks=None): + if masks is None: + masks = [enums.CryptographicUsageMask.VERIFY] + key = pie_objects.PublicKey( + enums.CryptographicAlgorithm.RSA, + 1024, + b'pub', + format_type=enums.KeyFormatType.PKCS_1, + masks=masks + ) + key.state = state + return key + + def _make_private_key(self, state=enums.State.ACTIVE, masks=None): + if masks is None: + masks = [enums.CryptographicUsageMask.SIGN] + key = pie_objects.PrivateKey( + enums.CryptographicAlgorithm.RSA, + 1024, + b'priv', + format_type=enums.KeyFormatType.PKCS_8, + masks=masks + ) + key.state = state + return key + + def _add_managed_object(self, managed_object): + self.engine._data_session.add(managed_object) + self.engine._data_session.commit() + return str(managed_object.unique_identifier) + + def _build_new_attribute(self, attribute_type, value): + factory = attribute_factory.AttributeFactory() + attribute = factory.create_attribute(attribute_type, value) + return core_objects.NewAttribute(attribute) + + def test_process_create_multiple_algorithms(self): + """Test Create succeeds for multiple symmetric key algorithms.""" + e = self.engine + e._process_template_attribute = mock.Mock() + + def _create_key(algorithm, length): + return {'value': b'\x00' * (length // 8)} + + e._cryptography_engine.create_symmetric_key.side_effect = _create_key + + cases = [ + (enums.CryptographicAlgorithm.AES, 128), + (enums.CryptographicAlgorithm.TRIPLE_DES, 192), + (enums.CryptographicAlgorithm.BLOWFISH, 128), + (enums.CryptographicAlgorithm.CAMELLIA, 128) + ] + + for algorithm, length in cases: + with self.subTest(algorithm=algorithm, length=length): + e._process_template_attribute.return_value = \ + _build_attribute_dict( + algorithm=algorithm, + length=length, + usage_masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template_attribute=core_objects.TemplateAttribute() + ) + response = e._process_create(payload) + self.assertEqual(enums.ObjectType.SYMMETRIC_KEY, + response.object_type) + e._cryptography_engine.create_symmetric_key.assert_called_with( + algorithm, + length + ) + e._cryptography_engine.create_symmetric_key.reset_mock() + + def test_process_create_missing_attributes(self): + """Test Create raises for missing required attributes.""" + e = self.engine + e._process_template_attribute = mock.Mock() + + cases = [ + ({'Cryptographic Length': attributes.CryptographicLength(128)}, + "The cryptographic algorithm must be specified as an attribute."), + ({ + 'Cryptographic Algorithm': + attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + 'Cryptographic Usage Mask': + attributes.CryptographicUsageMask( + _mask_value([enums.CryptographicUsageMask.ENCRYPT]) + ) + }, "The cryptographic length must be specified as an attribute."), + ({ + 'Cryptographic Algorithm': + attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + 'Cryptographic Length': + attributes.CryptographicLength(128) + }, "The cryptographic usage mask must be specified as an attribute.") + ] + + for attrs, message in cases: + with self.subTest(message=message): + e._process_template_attribute.return_value = attrs + payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template_attribute=core_objects.TemplateAttribute() + ) + self.assertRaisesRegex( + exceptions.InvalidField, + message, + e._process_create, + payload + ) + + def test_process_create_invalid_length(self): + """Test Create propagates invalid cryptographic length errors.""" + e = self.engine + e._process_template_attribute = mock.Mock(return_value= + _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.AES, + length=999, + usage_masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + ) + + e._cryptography_engine.create_symmetric_key.side_effect = \ + exceptions.InvalidField("invalid length") + + payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template_attribute=core_objects.TemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "invalid length", + e._process_create, + payload + ) + + def test_process_create_key_pair_rsa_multiple_lengths(self): + """Test CreateKeyPair succeeds for RSA with multiple lengths.""" + e = self.engine + e._process_template_attribute = mock.Mock() + + def _create_pair(algorithm, length): + return ({'value': b'pub', 'format': enums.KeyFormatType.PKCS_1}, + {'value': b'priv', 'format': enums.KeyFormatType.PKCS_8}) + + e._cryptography_engine.create_asymmetric_key_pair.side_effect = \ + _create_pair + + lengths = [1024, 2048] + for length in lengths: + with self.subTest(length=length): + public_attrs = _build_attribute_dict( + usage_masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + private_attrs = _build_attribute_dict( + usage_masks=[enums.CryptographicUsageMask.DECRYPT] + ) + common_attrs = _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=length + ) + e._process_template_attribute.side_effect = [ + public_attrs, + private_attrs, + common_attrs + ] + payload = payloads.CreateKeyPairRequestPayload( + common_template_attribute=core_objects.CommonTemplateAttribute(), + private_key_template_attribute=core_objects.PrivateKeyTemplateAttribute(), + public_key_template_attribute=core_objects.PublicKeyTemplateAttribute() + ) + response = e._process_create_key_pair(payload) + self.assertIsNotNone(response.public_key_unique_identifier) + self.assertIsNotNone(response.private_key_unique_identifier) + e._cryptography_engine.create_asymmetric_key_pair.\ + assert_called_with(enums.CryptographicAlgorithm.RSA, length) + e._cryptography_engine.create_asymmetric_key_pair.reset_mock() + + def test_process_create_key_pair_missing_usage_mask(self): + """Test CreateKeyPair raises when usage masks are missing.""" + e = self.engine + e._process_template_attribute = mock.Mock() + e._process_template_attribute.side_effect = [ + _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=1024 + ), + _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=1024 + ), + _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=1024 + ) + ] + + payload = payloads.CreateKeyPairRequestPayload( + common_template_attribute=core_objects.CommonTemplateAttribute(), + private_key_template_attribute=core_objects.PrivateKeyTemplateAttribute(), + public_key_template_attribute=core_objects.PublicKeyTemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic usage mask must be specified", + e._process_create_key_pair, + payload + ) + + def test_process_create_key_pair_mismatched_lengths(self): + """Test CreateKeyPair raises for mismatched key lengths.""" + e = self.engine + e._process_template_attribute = mock.Mock() + + public_attrs = _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=1024, + usage_masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + private_attrs = _build_attribute_dict( + algorithm=enums.CryptographicAlgorithm.RSA, + length=2048, + usage_masks=[enums.CryptographicUsageMask.DECRYPT] + ) + common_attrs = {} + + e._process_template_attribute.side_effect = [ + public_attrs, + private_attrs, + common_attrs + ] + + payload = payloads.CreateKeyPairRequestPayload( + common_template_attribute=core_objects.CommonTemplateAttribute(), + private_key_template_attribute=core_objects.PrivateKeyTemplateAttribute(), + public_key_template_attribute=core_objects.PublicKeyTemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "public and private key lengths must be the same", + e._process_create_key_pair, + payload + ) + + def test_process_register_supported_object_types(self): + """Test Register succeeds for all supported object types.""" + e = self.engine + + secret_map = { + enums.ObjectType.SYMMETRIC_KEY: secrets.SymmetricKey(), + enums.ObjectType.PUBLIC_KEY: secrets.PublicKey(), + enums.ObjectType.PRIVATE_KEY: secrets.PrivateKey(), + enums.ObjectType.CERTIFICATE: secrets.Certificate(), + enums.ObjectType.SECRET_DATA: secrets.SecretData(), + enums.ObjectType.OPAQUE_DATA: secrets.OpaqueObject(), + enums.ObjectType.SPLIT_KEY: secrets.SplitKey() + } + + pie_map = { + enums.ObjectType.SYMMETRIC_KEY: pie_objects.SymmetricKey( + enums.CryptographicAlgorithm.AES, + 128, + b'\x00' * 16 + ), + enums.ObjectType.PUBLIC_KEY: pie_objects.PublicKey( + enums.CryptographicAlgorithm.RSA, + 1024, + b'pub', + format_type=enums.KeyFormatType.PKCS_1 + ), + enums.ObjectType.PRIVATE_KEY: pie_objects.PrivateKey( + enums.CryptographicAlgorithm.RSA, + 1024, + b'priv', + format_type=enums.KeyFormatType.PKCS_8 + ), + enums.ObjectType.CERTIFICATE: pie_objects.X509Certificate( + b'cert' + ), + enums.ObjectType.SECRET_DATA: pie_objects.SecretData( + b'secret', + enums.SecretDataType.PASSWORD + ), + enums.ObjectType.OPAQUE_DATA: pie_objects.OpaqueObject( + b'opaque', + enums.OpaqueDataType.NONE + ), + enums.ObjectType.SPLIT_KEY: pie_objects.SplitKey( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + cryptographic_length=128, + key_value=b'\x00' * 16, + split_key_parts=2, + key_part_identifier=1, + split_key_threshold=2, + split_key_method=enums.SplitKeyMethod.XOR, + prime_field_size=257 + ) + } + + def _convert(secret): + for obj_type, obj in secret_map.items(): + if isinstance(secret, type(obj)): + return pie_map[obj_type] + raise TypeError("unsupported") + + with mock.patch( + 'kmip.services.server.engine.factory.ObjectFactory' + ) as factory_mock: + factory_instance = factory_mock.return_value + factory_instance.convert.side_effect = _convert + + for obj_type, secret in secret_map.items(): + with self.subTest(object_type=obj_type): + payload = payloads.RegisterRequestPayload( + object_type=obj_type, + managed_object=secret + ) + response = e._process_register(payload) + self.assertIsNotNone(response.unique_identifier) + + def test_process_register_unsupported_object_type(self): + """Test Register rejects unsupported object types.""" + e = self.engine + payload = payloads.RegisterRequestPayload( + object_type=enums.ObjectType.TEMPLATE, + managed_object=secrets.Template() + ) + self.assertRaisesRegex( + exceptions.InvalidField, + "object type is not supported", + e._process_register, + payload + ) + + def test_process_register_missing_managed_object(self): + """Test Register rejects missing managed objects.""" + e = self.engine + payload = payloads.RegisterRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + managed_object=None + ) + self.assertRaisesRegex( + exceptions.InvalidField, + "Cannot register a secret in absentia", + e._process_register, + payload + ) + + def test_process_get_without_wrapping(self): + """Test Get returns a core secret without wrapping.""" + e = self.engine + managed_object = self._make_symmetric_key() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + + payload = payloads.GetRequestPayload( + unique_identifier='1' + ) + response = e._process_get(payload) + self.assertEqual(enums.ObjectType.SYMMETRIC_KEY, response.object_type) + self.assertEqual('1', response.unique_identifier) + + def test_process_get_with_wrapping(self): + """Test Get wraps keys when a wrapping specification is provided.""" + e = self.engine + target_object = self._make_symmetric_key() + wrapping_key = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.WRAP_KEY] + ) + + e._get_object_with_access_controls = mock.Mock( + side_effect=[target_object, wrapping_key] + ) + e._cryptography_engine.wrap_key.return_value = b'wrapped' + + key_info = core_objects.EncryptionKeyInformation( + unique_identifier='wrap-id', + cryptographic_parameters=attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.NIST_KEY_WRAP + ) + ) + spec = core_objects.KeyWrappingSpecification( + wrapping_method=enums.WrappingMethod.ENCRYPT, + encryption_key_information=key_info, + encoding_option=enums.EncodingOption.NO_ENCODING + ) + payload = payloads.GetRequestPayload( + unique_identifier='1', + key_wrapping_specification=spec + ) + + response = e._process_get(payload) + self.assertEqual('1', response.unique_identifier) + e._cryptography_engine.wrap_key.assert_called_once() + + def test_process_get_key_format_mismatch(self): + """Test Get rejects unsupported key format conversions.""" + e = self.engine + managed_object = self._make_symmetric_key() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + + payload = payloads.GetRequestPayload( + unique_identifier='1', + key_format_type=enums.KeyFormatType.PKCS_1 + ) + self.assertRaisesRegex( + exceptions.KeyFormatTypeNotSupported, + "Key format conversion", + e._process_get, + payload + ) + + def test_process_destroy_states(self): + """Test Destroy succeeds for pre-active and deactivated objects.""" + e = self.engine + + for state in [enums.State.PRE_ACTIVE, enums.State.DEACTIVATED]: + with self.subTest(state=state): + obj = self._make_symmetric_key(state=state) + uid = self._add_managed_object(obj) + payload = payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(uid) + ) + response = e._process_destroy(payload) + self.assertEqual(uid, response.unique_identifier.value) + + def test_process_destroy_active_denied(self): + """Test Destroy rejects active objects.""" + e = self.engine + obj = self._make_symmetric_key(state=enums.State.ACTIVE) + uid = self._add_managed_object(obj) + payload = payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(uid) + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "Object is active", + e._process_destroy, + payload + ) + + def test_process_destroy_compromised(self): + """Test Destroy succeeds for compromised objects.""" + e = self.engine + obj = self._make_symmetric_key(state=enums.State.COMPROMISED) + uid = self._add_managed_object(obj) + payload = payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(uid) + ) + response = e._process_destroy(payload) + self.assertEqual(uid, response.unique_identifier.value) + + def test_process_locate_filters(self): + """Test Locate filters by name, algorithm, and state.""" + e = self.engine + e._attribute_policy.is_attribute_applicable_to_object_type = \ + mock.Mock(return_value=True) + + obj_match = DummyManagedObject( + unique_identifier='1', + object_type=enums.ObjectType.SYMMETRIC_KEY, + attributes_map={ + 'Name': [attributes.Name.create( + 'Key-1', + enums.NameType.UNINTERPRETED_TEXT_STRING + )], + 'Cryptographic Algorithm': enums.CryptographicAlgorithm.AES, + 'State': enums.State.ACTIVE + } + ) + obj_miss = DummyManagedObject( + unique_identifier='2', + object_type=enums.ObjectType.SYMMETRIC_KEY, + attributes_map={ + 'Name': [attributes.Name.create( + 'Other', + enums.NameType.UNINTERPRETED_TEXT_STRING + )], + 'Cryptographic Algorithm': enums.CryptographicAlgorithm.AES, + 'State': enums.State.DESTROYED + } + ) + + def _get_attr(obj, name): + return obj._attributes.get(name) + + e._get_attribute_from_managed_object = mock.Mock(side_effect=_get_attr) + e._list_objects_with_access_controls = mock.Mock( + return_value=[obj_match, obj_miss] + ) + + factory = attribute_factory.AttributeFactory() + attrs = [ + factory.create_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'Key-1', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ), + factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.AES + ), + factory.create_attribute( + enums.AttributeType.STATE, + enums.State.ACTIVE + ) + ] + payload = payloads.LocateRequestPayload(attributes=attrs) + response = e._process_locate(payload) + self.assertEqual(['1'], response.unique_identifiers) + + def test_process_locate_offset_and_max_items(self): + """Test Locate applies offset and maximum items after sorting.""" + e = self.engine + e._attribute_policy.is_attribute_applicable_to_object_type = \ + mock.Mock(return_value=True) + + obj_a = DummyManagedObject('1', enums.ObjectType.SYMMETRIC_KEY) + obj_b = DummyManagedObject('2', enums.ObjectType.SYMMETRIC_KEY) + obj_c = DummyManagedObject('3', enums.ObjectType.SYMMETRIC_KEY) + obj_a.initial_date = 1 + obj_b.initial_date = 2 + obj_c.initial_date = 3 + + e._get_attribute_from_managed_object = mock.Mock(return_value=None) + e._list_objects_with_access_controls = mock.Mock( + return_value=[obj_a, obj_b, obj_c] + ) + + payload = payloads.LocateRequestPayload( + maximum_items=1, + offset_items=1 + ) + response = e._process_locate(payload) + self.assertEqual(['2'], response.unique_identifiers) + + def test_process_locate_invalid_date_filters(self): + """Test Locate rejects too many date attributes.""" + e = self.engine + e._attribute_policy.is_attribute_applicable_to_object_type = \ + mock.Mock(return_value=True) + + obj = DummyManagedObject('1', enums.ObjectType.SYMMETRIC_KEY) + obj.initial_date = 10 + e._get_attribute_from_managed_object = \ + mock.Mock(return_value=obj.initial_date) + e._list_objects_with_access_controls = mock.Mock(return_value=[obj]) + + factory = attribute_factory.AttributeFactory() + attrs = [ + factory.create_attribute( + enums.AttributeType.INITIAL_DATE, + 1 + ), + factory.create_attribute( + enums.AttributeType.INITIAL_DATE, + 2 + ), + factory.create_attribute( + enums.AttributeType.INITIAL_DATE, + 3 + ) + ] + + payload = payloads.LocateRequestPayload(attributes=attrs) + self.assertRaisesRegex( + exceptions.InvalidField, + "Too many Initial Date attributes", + e._process_locate, + payload + ) + + def test_process_activate_success(self): + """Test Activate succeeds for pre-active objects.""" + e = self.engine + managed_object = mock.Mock() + managed_object._object_type = enums.ObjectType.SYMMETRIC_KEY + managed_object.state = enums.State.PRE_ACTIVE + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.ActivateRequestPayload( + attributes.UniqueIdentifier('1') + ) + response = e._process_activate(payload) + self.assertEqual(enums.State.ACTIVE, managed_object.state) + self.assertEqual('1', response.unique_identifier.value) + + def test_process_activate_invalid_state(self): + """Test Activate rejects non-pre-active objects.""" + e = self.engine + managed_object = mock.Mock() + managed_object._object_type = enums.ObjectType.SYMMETRIC_KEY + managed_object.state = enums.State.ACTIVE + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.ActivateRequestPayload( + attributes.UniqueIdentifier('1') + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "not pre-active", + e._process_activate, + payload + ) + + def test_process_activate_no_state(self): + """Test Activate rejects objects without state.""" + e = self.engine + managed_object = mock.Mock() + managed_object._object_type = enums.ObjectType.OPAQUE_DATA + managed_object.state = None + del managed_object.state + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.ActivateRequestPayload( + attributes.UniqueIdentifier('1') + ) + self.assertRaisesRegex( + exceptions.IllegalOperation, + "has no state", + e._process_activate, + payload + ) + + def test_process_revoke_key_compromise(self): + """Test Revoke with KEY_COMPROMISE transitions state.""" + e = self.engine + managed_object = mock.Mock() + managed_object._object_type = enums.ObjectType.SYMMETRIC_KEY + managed_object.state = enums.State.ACTIVE + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + + reason = core_objects.RevocationReason( + code=enums.RevocationReasonCode.KEY_COMPROMISE + ) + payload = payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1'), + revocation_reason=reason + ) + response = e._process_revoke(payload) + self.assertEqual(enums.State.COMPROMISED, managed_object.state) + self.assertEqual('1', response.unique_identifier.value) + + def test_process_revoke_missing_reason(self): + """Test Revoke rejects requests without revocation reason.""" + e = self.engine + payload = payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1') + ) + payload.revocation_reason = None + self.assertRaisesRegex( + exceptions.InvalidField, + "revocation reason code must be specified", + e._process_revoke, + payload + ) + + def test_process_revoke_non_active(self): + """Test Revoke rejects non-active objects for non-compromise reasons.""" + e = self.engine + managed_object = mock.Mock() + managed_object._object_type = enums.ObjectType.SYMMETRIC_KEY + managed_object.state = enums.State.PRE_ACTIVE + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + reason = core_objects.RevocationReason( + code=enums.RevocationReasonCode.CESSATION_OF_OPERATION + ) + payload = payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1'), + revocation_reason=reason + ) + self.assertRaisesRegex( + exceptions.IllegalOperation, + "not active", + e._process_revoke, + payload + ) + + def test_process_delete_attribute_v2_current_attribute(self): + """Test DeleteAttribute (KMIP 2.0) deletes by current attribute.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._delete_attribute_from_managed_object = mock.Mock() + + name_attr = attributes.Name( + attributes.Name.NameValue('delete-me'), + attributes.Name.NameType(enums.NameType.UNINTERPRETED_TEXT_STRING) + ) + current_attr = core_objects.CurrentAttribute(attribute=name_attr) + payload = payloads.DeleteAttributeRequestPayload( + unique_identifier='1', + current_attribute=current_attr + ) + + response = e._process_delete_attribute(payload) + self.assertEqual('1', response.unique_identifier) + e._delete_attribute_from_managed_object.assert_called_once() + args, _ = e._delete_attribute_from_managed_object.call_args + self.assertEqual(managed_object, args[0]) + self.assertEqual('Name', args[1][0]) + self.assertIsNone(args[1][1]) + self.assertEqual(name_attr, args[1][2]) + + def test_process_delete_attribute_v2_missing_reference(self): + """Test DeleteAttribute (KMIP 2.0) rejects missing attribute data.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + e._get_object_with_access_controls = mock.Mock() + + payload = payloads.DeleteAttributeRequestPayload( + unique_identifier='1' + ) + self.assertRaisesRegex( + exceptions.InvalidMessage, + "must specify the current", + e._process_delete_attribute, + payload + ) + + def test_process_delete_attribute_v1_index_out_of_range(self): + """Test DeleteAttribute (KMIP 1.x) rejects out-of-range index.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(1, 2) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._get_attributes_from_managed_object = mock.Mock( + return_value=[mock.Mock()] + ) + + payload = payloads.DeleteAttributeRequestPayload( + unique_identifier='1', + attribute_name='Name', + attribute_index=1 + ) + self.assertRaisesRegex( + exceptions.ItemNotFound, + "specified index", + e._process_delete_attribute, + payload + ) + + def test_process_set_attribute_success(self): + """Test SetAttribute (KMIP 2.0) sets a single-valued attribute.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=False + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=True + ) + e._set_attributes_on_managed_object = mock.Mock() + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'new-name', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.SetAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + response = e._process_set_attribute(payload) + self.assertEqual('1', response.unique_identifier) + e._set_attributes_on_managed_object.assert_called_once() + + def test_process_set_attribute_multivalued_rejected(self): + """Test SetAttribute rejects multi-valued attributes.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=True + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=True + ) + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'multi', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.SetAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + self.assertRaisesRegex( + exceptions.KmipError, + "multi-valued", + e._process_set_attribute, + payload + ) + + def test_process_set_attribute_read_only_rejected(self): + """Test SetAttribute rejects read-only attributes.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=False + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=False + ) + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'readonly', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.SetAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + self.assertRaisesRegex( + exceptions.KmipError, + "read-only", + e._process_set_attribute, + payload + ) + + def test_process_modify_attribute_v2_single_value_success(self): + """Test ModifyAttribute (KMIP 2.0) updates a single-valued attribute.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=True + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=False + ) + e._get_attribute_from_managed_object = mock.Mock( + return_value='existing' + ) + e._set_attribute_on_managed_object = mock.Mock() + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'updated', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.ModifyAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + response = e._process_modify_attribute(payload) + self.assertEqual('1', response.unique_identifier) + e._set_attribute_on_managed_object.assert_called_once() + + def test_process_modify_attribute_v2_multivalue_missing_current(self): + """Test ModifyAttribute (KMIP 2.0) requires current attribute.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=True + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=True + ) + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'new', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.ModifyAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + self.assertRaisesRegex( + exceptions.KmipError, + "current attribute must be specified", + e._process_modify_attribute, + payload + ) + + def test_process_modify_attribute_v2_read_only(self): + """Test ModifyAttribute (KMIP 2.0) rejects read-only attributes.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(2, 0) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=False + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=False + ) + + new_attr = self._build_new_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + 'readonly', + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + payload = payloads.ModifyAttributeRequestPayload( + unique_identifier='1', + new_attribute=new_attr + ) + + self.assertRaisesRegex( + exceptions.KmipError, + "read-only", + e._process_modify_attribute, + payload + ) + + def test_process_modify_attribute_v1_invalid_index(self): + """Test ModifyAttribute (KMIP 1.x) rejects index on single value.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(1, 2) + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._attribute_policy.is_attribute_modifiable_by_client = mock.Mock( + return_value=True + ) + e._attribute_policy.is_attribute_multivalued = mock.Mock( + return_value=False + ) + e._get_attributes_from_managed_object = mock.Mock( + return_value=[mock.Mock()] + ) + + attribute = core_objects.Attribute( + attribute_name=core_objects.Attribute.AttributeName('State'), + attribute_index=core_objects.Attribute.AttributeIndex(1), + attribute_value=attributes.State(enums.State.ACTIVE) + ) + payload = payloads.ModifyAttributeRequestPayload( + unique_identifier='1', + attribute=attribute + ) + + self.assertRaisesRegex( + exceptions.KmipError, + "attribute index cannot be specified", + e._process_modify_attribute, + payload + ) + + def test_process_get_attributes_success(self): + """Test GetAttributes returns attributes for a managed object.""" + e = self.engine + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + attr_factory = attribute_factory.AttributeFactory() + attr = attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.AES + ) + e._get_attributes_from_managed_object = mock.Mock( + return_value=[attr] + ) + payload = payloads.GetAttributesRequestPayload( + unique_identifier='1', + attribute_names=['Cryptographic Algorithm'] + ) + + response = e._process_get_attributes(payload) + self.assertEqual('1', response.unique_identifier) + self.assertEqual([attr], response.attributes) + + def test_process_get_attributes_permission_denied(self): + """Test GetAttributes propagates permission errors.""" + e = self.engine + e._get_object_with_access_controls = mock.Mock( + side_effect=exceptions.PermissionDenied("denied") + ) + payload = payloads.GetAttributesRequestPayload( + unique_identifier='1' + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "denied", + e._process_get_attributes, + payload + ) + + def test_process_get_attributes_id_placeholder(self): + """Test GetAttributes uses the ID placeholder when missing.""" + e = self.engine + e._id_placeholder = 'placeholder' + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._get_attributes_from_managed_object = mock.Mock(return_value=[]) + payload = payloads.GetAttributesRequestPayload() + + response = e._process_get_attributes(payload) + self.assertEqual('placeholder', response.unique_identifier) + e._get_object_with_access_controls.assert_called_with( + 'placeholder', + enums.Operation.GET_ATTRIBUTES + ) + + def test_process_get_attribute_list_success(self): + """Test GetAttributeList returns attribute names.""" + e = self.engine + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + attr_factory = attribute_factory.AttributeFactory() + attrs_list = [ + attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.AES + ), + attr_factory.create_attribute( + enums.AttributeType.STATE, + enums.State.ACTIVE + ) + ] + e._get_attributes_from_managed_object = mock.Mock( + return_value=attrs_list + ) + payload = payloads.GetAttributeListRequestPayload( + unique_identifier='1' + ) + + response = e._process_get_attribute_list(payload) + self.assertIn('Cryptographic Algorithm', response.attribute_names) + self.assertIn('State', response.attribute_names) + + def test_process_get_attribute_list_permission_denied(self): + """Test GetAttributeList propagates permission errors.""" + e = self.engine + e._get_object_with_access_controls = mock.Mock( + side_effect=exceptions.PermissionDenied("denied") + ) + payload = payloads.GetAttributeListRequestPayload( + unique_identifier='1' + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "denied", + e._process_get_attribute_list, + payload + ) + + def test_process_get_attribute_list_id_placeholder(self): + """Test GetAttributeList uses the ID placeholder when missing.""" + e = self.engine + e._id_placeholder = 'placeholder' + managed_object = mock.Mock() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._get_attributes_from_managed_object = mock.Mock(return_value=[]) + payload = payloads.GetAttributeListRequestPayload() + + response = e._process_get_attribute_list(payload) + self.assertEqual('placeholder', response.unique_identifier) + e._get_object_with_access_controls.assert_called_with( + 'placeholder', + enums.Operation.GET_ATTRIBUTE_LIST + ) + + def test_process_derive_key_pbdkf2_symmetric_key(self): + """Test DeriveKey derives a symmetric key via PBKDF2.""" + e = self.engine + keying_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=keying_object + ) + e._process_template_attribute = mock.Mock( + return_value={ + 'Cryptographic Algorithm': + attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + 'Cryptographic Length': + attributes.CryptographicLength(128) + } + ) + crypto_params = attributes.CryptographicParameters( + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ) + derivation_params = attributes.DerivationParameters( + cryptographic_parameters=crypto_params, + salt=b'salt', + iteration_count=1 + ) + e._cryptography_engine.derive_key.return_value = b'\x00' * 16 + + payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifiers=['key-id'], + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_parameters=derivation_params, + template_attribute=core_objects.TemplateAttribute() + ) + + response = e._process_derive_key(payload) + self.assertIsNotNone(response.unique_identifier) + e._cryptography_engine.derive_key.assert_called_once() + + def test_process_derive_key_secret_data_hmac_method(self): + """Test DeriveKey supports HMAC and ENCRYPT for secret data.""" + e = self.engine + keying_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + secret_object = pie_objects.SecretData( + b'data', + enums.SecretDataType.PASSWORD, + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + e._process_template_attribute = mock.Mock( + side_effect=lambda _: + {'Cryptographic Length': attributes.CryptographicLength(64)} + ) + crypto_params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ) + derivation_params = attributes.DerivationParameters( + cryptographic_parameters=crypto_params, + derivation_data=None, + salt=b'salt', + iteration_count=1 + ) + e._cryptography_engine.derive_key.return_value = b'\x01' * 8 + + for method in [ + enums.DerivationMethod.HMAC, + enums.DerivationMethod.ENCRYPT + ]: + with self.subTest(method=method): + e._get_object_with_access_controls = mock.Mock( + side_effect=[keying_object, secret_object] + ) + payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SECRET_DATA, + unique_identifiers=['key-id', 'data-id'], + derivation_method=method, + derivation_parameters=derivation_params, + template_attribute=core_objects.TemplateAttribute() + ) + response = e._process_derive_key(payload) + self.assertIsNotNone(response.unique_identifier) + + def test_process_derive_key_missing_length(self): + """Test DeriveKey rejects missing cryptographic length.""" + e = self.engine + keying_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=keying_object + ) + e._process_template_attribute = mock.Mock(return_value={}) + derivation_params = attributes.DerivationParameters( + cryptographic_parameters=attributes.CryptographicParameters() + ) + payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifiers=['key-id'], + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_parameters=derivation_params, + template_attribute=core_objects.TemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic length", + e._process_derive_key, + payload + ) + + def test_process_derive_key_invalid_length_multiple(self): + """Test DeriveKey rejects cryptographic length not multiple of 8.""" + e = self.engine + keying_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=keying_object + ) + e._process_template_attribute = mock.Mock( + return_value={ + 'Cryptographic Length': + attributes.CryptographicLength(7) + } + ) + derivation_params = attributes.DerivationParameters( + cryptographic_parameters=attributes.CryptographicParameters() + ) + payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifiers=['key-id'], + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_parameters=derivation_params, + template_attribute=core_objects.TemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "multiple of 8", + e._process_derive_key, + payload + ) + + def test_process_derive_key_short_output(self): + """Test DeriveKey rejects derived data shorter than requested.""" + e = self.engine + keying_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=keying_object + ) + e._process_template_attribute = mock.Mock( + return_value={ + 'Cryptographic Algorithm': + attributes.CryptographicAlgorithm( + enums.CryptographicAlgorithm.AES + ), + 'Cryptographic Length': + attributes.CryptographicLength(128) + } + ) + derivation_params = attributes.DerivationParameters( + cryptographic_parameters=attributes.CryptographicParameters() + ) + e._cryptography_engine.derive_key.return_value = b'\x00' * 8 + + payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifiers=['key-id'], + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_parameters=derivation_params, + template_attribute=core_objects.TemplateAttribute() + ) + + self.assertRaisesRegex( + exceptions.CryptographicFailure, + "specified length", + e._process_derive_key, + payload + ) + + def test_process_query_operations_protocol_1_0(self): + """Test Query returns operations for KMIP 1.0.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(1, 0) + payload = payloads.QueryRequestPayload( + query_functions=[enums.QueryFunction.QUERY_OPERATIONS] + ) + + response = e._process_query(payload) + self.assertIn(enums.Operation.CREATE, response.operations) + self.assertNotIn(enums.Operation.DISCOVER_VERSIONS, response.operations) + self.assertNotIn(enums.Operation.ENCRYPT, response.operations) + + def test_process_query_operations_protocol_1_2(self): + """Test Query returns extended operations for KMIP 1.2.""" + e = self.engine + e._protocol_version = contents.ProtocolVersion(1, 2) + payload = payloads.QueryRequestPayload( + query_functions=[enums.QueryFunction.QUERY_OPERATIONS] + ) + + response = e._process_query(payload) + self.assertIn(enums.Operation.ENCRYPT, response.operations) + self.assertIn(enums.Operation.DISCOVER_VERSIONS, response.operations) + + def test_process_query_vendor_info(self): + """Test Query returns vendor identification.""" + e = self.engine + payload = payloads.QueryRequestPayload( + query_functions=[enums.QueryFunction.QUERY_SERVER_INFORMATION] + ) + + response = e._process_query(payload) + self.assertIn('PyKMIP', response.vendor_identification) + + def test_process_discover_versions_subset(self): + """Test DiscoverVersions returns supported subset.""" + e = self.engine + payload = payloads.DiscoverVersionsRequestPayload( + protocol_versions=[ + contents.ProtocolVersion(1, 4), + contents.ProtocolVersion(9, 9) + ] + ) + + response = e._process_discover_versions(payload) + self.assertEqual(1, len(response.protocol_versions)) + self.assertEqual(1, response.protocol_versions[0].major) + self.assertEqual(4, response.protocol_versions[0].minor) + + def test_process_discover_versions_empty_list(self): + """Test DiscoverVersions returns all when request is empty.""" + e = self.engine + payload = payloads.DiscoverVersionsRequestPayload( + protocol_versions=[] + ) + + response = e._process_discover_versions(payload) + self.assertEqual(len(e._protocol_versions), len(response.protocol_versions)) + + def test_process_discover_versions_none_supported(self): + """Test DiscoverVersions returns empty when none supported.""" + e = self.engine + payload = payloads.DiscoverVersionsRequestPayload( + protocol_versions=[contents.ProtocolVersion(9, 9)] + ) + + response = e._process_discover_versions(payload) + self.assertEqual([], response.protocol_versions) + + def test_process_encrypt_aes_cbc_success(self): + """Test Encrypt succeeds for AES-CBC.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + block_cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5 + ) + e._cryptography_engine.encrypt.return_value = { + 'cipher_text': b'cipher', + 'iv_nonce': b'iv', + 'auth_tag': None + } + + payload = payloads.EncryptRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'plain', + iv_counter_nonce=b'iv' + ) + + response = e._process_encrypt(payload) + self.assertEqual(b'cipher', response.data) + self.assertEqual(b'iv', response.iv_counter_nonce) + + def test_process_encrypt_missing_parameters(self): + """Test Encrypt rejects missing cryptographic parameters.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.EncryptRequestPayload( + unique_identifier='1', + data=b'plain' + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic parameters", + e._process_encrypt, + payload + ) + + def test_process_encrypt_gcm_missing_iv(self): + """Test Encrypt propagates errors for missing IVs in GCM.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.ENCRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + block_cipher_mode=enums.BlockCipherMode.GCM, + tag_length=128 + ) + e._cryptography_engine.encrypt.side_effect = \ + exceptions.InvalidField("iv required") + + payload = payloads.EncryptRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'plain' + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "iv required", + e._process_encrypt, + payload + ) + + def test_process_decrypt_aes_gcm_success(self): + """Test Decrypt succeeds for AES-GCM.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DECRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + block_cipher_mode=enums.BlockCipherMode.GCM, + tag_length=128 + ) + e._cryptography_engine.decrypt.return_value = b'plain' + + payload = payloads.DecryptRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'cipher', + iv_counter_nonce=b'iv', + auth_tag=b'tag' + ) + + response = e._process_decrypt(payload) + self.assertEqual(b'plain', response.data) + + def test_process_decrypt_missing_parameters(self): + """Test Decrypt rejects missing cryptographic parameters.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DECRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.DecryptRequestPayload( + unique_identifier='1', + data=b'cipher' + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic parameters", + e._process_decrypt, + payload + ) + + def test_process_decrypt_missing_iv(self): + """Test Decrypt propagates errors for missing IVs.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.DECRYPT] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES, + block_cipher_mode=enums.BlockCipherMode.GCM, + tag_length=128 + ) + e._cryptography_engine.decrypt.side_effect = \ + exceptions.InvalidField("iv required") + + payload = payloads.DecryptRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'cipher', + auth_tag=b'tag' + ) + + self.assertRaisesRegex( + exceptions.InvalidField, + "iv required", + e._process_decrypt, + payload + ) + + def test_process_sign_rsa_success(self): + """Test Sign succeeds for RSA with different padding/hash options.""" + e = self.engine + managed_object = self._make_private_key( + masks=[enums.CryptographicUsageMask.SIGN] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + e._cryptography_engine.sign.return_value = b'signature' + + cases = [ + (enums.PaddingMethod.PKCS1v15, enums.HashingAlgorithm.SHA_256, + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION), + (enums.PaddingMethod.PSS, enums.HashingAlgorithm.SHA_512, + enums.DigitalSignatureAlgorithm.RSASSA_PSS) + ] + + for padding, hashing, dsa in cases: + with self.subTest(padding=padding, hashing=hashing): + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=hashing, + padding_method=padding, + digital_signature_algorithm=dsa + ) + payload = payloads.SignRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'data' + ) + response = e._process_sign(payload) + self.assertEqual(b'signature', response.signature_data) + + def test_process_sign_missing_parameters(self): + """Test Sign rejects missing cryptographic parameters.""" + e = self.engine + managed_object = self._make_private_key( + masks=[enums.CryptographicUsageMask.SIGN] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.SignRequestPayload( + unique_identifier='1', + data=b'data' + ) + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic parameters", + e._process_sign, + payload + ) + + def test_process_sign_invalid_key_type(self): + """Test Sign rejects non-private-key objects.""" + e = self.engine + managed_object = self._make_symmetric_key() + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256, + padding_method=enums.PaddingMethod.PKCS1v15, + digital_signature_algorithm= + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ) + payload = payloads.SignRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'data' + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "private key", + e._process_sign, + payload + ) + + def test_process_signature_verify_valid_invalid(self): + """Test SignatureVerify returns valid/invalid indicators.""" + e = self.engine + managed_object = self._make_public_key( + masks=[enums.CryptographicUsageMask.VERIFY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256, + padding_method=enums.PaddingMethod.PKCS1v15, + digital_signature_algorithm= + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ) + + e._cryptography_engine.verify_signature.return_value = True + payload = payloads.SignatureVerifyRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'data', + signature_data=b'sig' + ) + response = e._process_signature_verify(payload) + self.assertEqual(enums.ValidityIndicator.VALID, + response.validity_indicator) + + e._cryptography_engine.verify_signature.return_value = False + response = e._process_signature_verify(payload) + self.assertEqual(enums.ValidityIndicator.INVALID, + response.validity_indicator) + + def test_process_signature_verify_missing_parameters(self): + """Test SignatureVerify rejects missing cryptographic parameters.""" + e = self.engine + managed_object = self._make_public_key( + masks=[enums.CryptographicUsageMask.VERIFY] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + payload = payloads.SignatureVerifyRequestPayload( + unique_identifier='1', + data=b'data', + signature_data=b'sig' + ) + self.assertRaisesRegex( + exceptions.InvalidField, + "cryptographic parameters", + e._process_signature_verify, + payload + ) + + def test_process_signature_verify_wrong_key_type(self): + """Test SignatureVerify rejects non-public keys.""" + e = self.engine + managed_object = self._make_private_key( + masks=[enums.CryptographicUsageMask.SIGN] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256, + padding_method=enums.PaddingMethod.PKCS1v15, + digital_signature_algorithm= + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ) + payload = payloads.SignatureVerifyRequestPayload( + unique_identifier='1', + cryptographic_parameters=params, + data=b'data', + signature_data=b'sig' + ) + self.assertRaisesRegex( + exceptions.PermissionDenied, + "public key", + e._process_signature_verify, + payload + ) + + def test_process_mac_hmac_sha256_success(self): + """Test MAC succeeds for HMAC-SHA256.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.MAC_GENERATE] + ) + managed_object.cryptographic_algorithm = \ + enums.CryptographicAlgorithm.HMAC_SHA256 + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.HMAC_SHA256 + ) + e._cryptography_engine.mac.return_value = b'mac' + + payload = payloads.MACRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1'), + cryptographic_parameters=params, + data=core_objects.Data(b'data') + ) + response = e._process_mac(payload) + self.assertEqual(b'mac', response.mac_data.value) + + def test_process_mac_invalid_algorithm(self): + """Test MAC propagates cryptography engine errors for invalid algs.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.MAC_GENERATE] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.AES + ) + e._cryptography_engine.mac.side_effect = \ + exceptions.InvalidField("invalid algorithm") + + payload = payloads.MACRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1'), + cryptographic_parameters=params, + data=core_objects.Data(b'data') + ) + self.assertRaisesRegex( + exceptions.InvalidField, + "invalid algorithm", + e._process_mac, + payload + ) + + def test_process_mac_missing_data(self): + """Test MAC rejects requests missing data.""" + e = self.engine + managed_object = self._make_symmetric_key( + masks=[enums.CryptographicUsageMask.MAC_GENERATE] + ) + e._get_object_with_access_controls = mock.Mock( + return_value=managed_object + ) + params = attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.HMAC_SHA256 + ) + payload = payloads.MACRequestPayload( + unique_identifier=attributes.UniqueIdentifier('1'), + cryptographic_parameters=params, + data=None + ) + + self.assertRaisesRegex( + exceptions.PermissionDenied, + "No data", + e._process_mac, + payload + ) diff --git a/kmip/tests/unit/services/server/test_monitor.py b/kmip/tests/unit/services/server/test_monitor.py index 7f4c4357..0fc23883 100644 --- a/kmip/tests/unit/services/server/test_monitor.py +++ b/kmip/tests/unit/services/server/test_monitor.py @@ -25,7 +25,6 @@ from kmip.core import enums from kmip.services.server import monitor - class TestMonitorUtilities(testtools.TestCase): def setUp(self): @@ -52,7 +51,6 @@ def test_get_json_files(self): self.assertIn(os.path.join(self.tmp_dir, "policy_1.json"), result) self.assertIn(os.path.join(self.tmp_dir, "policy_2.json"), result) - POLICY_1 = """ { "policy_A": { @@ -188,12 +186,10 @@ def test_get_json_files(self): } """ - def write_file(path, file_name, content): with open(os.path.join(path, file_name), "w") as f: f.write("{}\n".format(content)) - def side_effects(effects): for effect in effects: if isinstance(effect, bool): @@ -202,19 +198,16 @@ def side_effects(effects): effect() yield False - def build_write_effect(path, file_name, content): def side_effect(): write_file(path, file_name, content) return side_effect - def build_delete_effect(path, file_name): def side_effect(): os.remove(os.path.join(path, file_name)) return side_effect - class TestPolicyDirectoryMonitor(testtools.TestCase): def setUp(self): diff --git a/kmip/tests/unit/services/server/test_policy.py b/kmip/tests/unit/services/server/test_policy.py index fd17e3a3..713422b8 100644 --- a/kmip/tests/unit/services/server/test_policy.py +++ b/kmip/tests/unit/services/server/test_policy.py @@ -19,7 +19,6 @@ from kmip.core.messages import contents from kmip.services.server import policy - class TestAttributePolicy(testtools.TestCase): """ A test engine for AttributePolicy. diff --git a/kmip/tests/unit/services/server/test_server.py b/kmip/tests/unit/services/server/test_server.py index a9e9f194..1410766e 100644 --- a/kmip/tests/unit/services/server/test_server.py +++ b/kmip/tests/unit/services/server/test_server.py @@ -28,7 +28,6 @@ from kmip.services import auth from kmip.services.server import server - class TestKmipServer(testtools.TestCase): """ A test suite for the KmipServer. diff --git a/kmip/tests/unit/services/server/test_server_extended.py b/kmip/tests/unit/services/server/test_server_extended.py new file mode 100644 index 00000000..d2713a5d --- /dev/null +++ b/kmip/tests/unit/services/server/test_server_extended.py @@ -0,0 +1,565 @@ +# Copyright (c) 2026 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 logging +import os +import socket +import tempfile + +import testtools + +from unittest import mock + +from kmip.core import exceptions +from kmip.services.server import server as kmip_server + + +class TestKmipServerExtended(testtools.TestCase): + + def setUp(self): + super(TestKmipServerExtended, self).setUp() + + def tearDown(self): + super(TestKmipServerExtended, self).tearDown() + + def _build_server_for_start(self): + with mock.patch.object(kmip_server.KmipServer, '_setup_logging'), \ + mock.patch.object( + kmip_server.auth, 'BasicAuthenticationSuite' + ) as basic_suite: + basic_suite.return_value = mock.Mock( + ciphers='cipher1:cipher2', + protocol='PROTO' + ) + server = kmip_server.KmipServer( + config_path=None, + log_path='log' + ) + + server._logger = mock.MagicMock() + server.config.settings.update({ + 'hostname': '127.0.0.1', + 'port': 5696, + 'certificate_path': 'cert.pem', + 'key_path': 'key.pem', + 'ca_path': 'ca.pem', + 'policy_path': '/tmp/policy', + 'tls_cipher_suites': ['TLS_TEST'], + 'database_path': None, + 'enable_tls_client_auth': True, + 'auth_suite': 'Basic' + }) + server.auth_suite = mock.Mock(protocol='PROTO', ciphers='cipher1:cipher2') + return server + + def test_init_defaults(self): + """Test KmipServer initializes with default values.""" + with mock.patch.object( + kmip_server.KmipServer, + '_setup_logging' + ) as logging_mock, mock.patch.object( + kmip_server.KmipServer, + '_setup_configuration' + ) as config_mock, mock.patch.object( + kmip_server.auth, + 'BasicAuthenticationSuite' + ) as basic_suite: + suite = mock.Mock(ciphers='cipher', protocol='proto') + basic_suite.return_value = suite + + server = kmip_server.KmipServer(config_path=None, log_path='log') + + logging_mock.assert_called_once_with('log') + config_mock.assert_called_once() + basic_suite.assert_called_once_with([]) + self.assertEqual(1, server._session_id) + self.assertFalse(server._is_serving) + self.assertEqual(suite, server.auth_suite) + self.assertEqual(logging.INFO, server.config.settings.get('logging_level')) + + def test_init_with_all_params(self): + """Test KmipServer initializes with all explicit parameters.""" + with tempfile.TemporaryDirectory() as temp_dir: + cert_path = os.path.join(temp_dir, 'server.crt') + key_path = os.path.join(temp_dir, 'server.key') + ca_path = os.path.join(temp_dir, 'ca.crt') + for path in [cert_path, key_path, ca_path]: + with open(path, 'w'): + pass + + with mock.patch.object( + kmip_server.KmipServer, + '_setup_logging' + ), mock.patch.object( + kmip_server.auth, + 'TLS12AuthenticationSuite' + ) as tls_suite: + tls_suite.return_value = mock.Mock( + ciphers='cipher', + protocol='proto' + ) + server = kmip_server.KmipServer( + hostname='127.0.0.1', + port=5696, + certificate_path=cert_path, + key_path=key_path, + ca_path=ca_path, + auth_suite='TLS1.2', + config_path=None, + log_path='log', + policy_path='/tmp/policy', + enable_tls_client_auth=False, + tls_cipher_suites='TLS_ONE,TLS_TWO', + logging_level='ERROR', + live_policies=True, + database_path='/tmp/server.db' + ) + + self.assertEqual('127.0.0.1', server.config.settings.get('hostname')) + self.assertEqual(5696, server.config.settings.get('port')) + self.assertEqual(cert_path, server.config.settings.get('certificate_path')) + self.assertEqual(key_path, server.config.settings.get('key_path')) + self.assertEqual(ca_path, server.config.settings.get('ca_path')) + self.assertEqual('TLS1.2', server.config.settings.get('auth_suite')) + self.assertEqual('/tmp/policy', server.config.settings.get('policy_path')) + self.assertFalse(server.config.settings.get('enable_tls_client_auth')) + self.assertEqual( + {'TLS_ONE', 'TLS_TWO'}, + set(server.config.settings.get('tls_cipher_suites')) + ) + self.assertEqual(logging.ERROR, server.config.settings.get('logging_level')) + self.assertEqual('/tmp/server.db', server.config.settings.get('database_path')) + self.assertTrue(server.live_policies) + self.assertTrue(tls_suite.called) + + def test_init_with_config_file(self): + """Test KmipServer loads settings from a config file.""" + with tempfile.TemporaryDirectory() as temp_dir: + cert_path = os.path.join(temp_dir, 'server.crt') + key_path = os.path.join(temp_dir, 'server.key') + ca_path = os.path.join(temp_dir, 'ca.crt') + config_path = os.path.join(temp_dir, 'server.conf') + for path in [cert_path, key_path, ca_path]: + with open(path, 'w'): + pass + + with open(config_path, 'w') as config_file: + config_file.write( + "[server]\n" + "hostname=127.0.0.1\n" + "port=5696\n" + "certificate_path={}\n" + "key_path={}\n" + "ca_path={}\n" + "auth_suite=TLS1.2\n" + "policy_path=/tmp/policy\n" + "enable_tls_client_auth=True\n" + "tls_cipher_suites=TLS_RSA_WITH_AES_128_CBC_SHA256 " + "TLS_RSA_WITH_AES_256_CBC_SHA256\n" + "logging_level=DEBUG\n" + "database_path=/tmp/server.db\n".format( + cert_path, + key_path, + ca_path + ) + ) + + with mock.patch.object( + kmip_server.KmipServer, + '_setup_logging' + ), mock.patch.object( + kmip_server.auth, + 'TLS12AuthenticationSuite' + ) as tls_suite: + tls_suite.return_value = mock.Mock( + ciphers='cipher', + protocol='proto' + ) + server = kmip_server.KmipServer( + config_path=config_path, + log_path='log' + ) + + self.assertEqual('127.0.0.1', server.config.settings.get('hostname')) + self.assertEqual(5696, server.config.settings.get('port')) + self.assertEqual(cert_path, server.config.settings.get('certificate_path')) + self.assertEqual(key_path, server.config.settings.get('key_path')) + self.assertEqual(ca_path, server.config.settings.get('ca_path')) + self.assertEqual('TLS1.2', server.config.settings.get('auth_suite')) + self.assertEqual('/tmp/policy', server.config.settings.get('policy_path')) + self.assertTrue(server.config.settings.get('enable_tls_client_auth')) + self.assertEqual( + { + 'TLS_RSA_WITH_AES_128_CBC_SHA256', + 'TLS_RSA_WITH_AES_256_CBC_SHA256' + }, + set(server.config.settings.get('tls_cipher_suites')) + ) + self.assertEqual(logging.DEBUG, server.config.settings.get('logging_level')) + self.assertEqual('/tmp/server.db', server.config.settings.get('database_path')) + self.assertTrue(tls_suite.called) + + def test_init_invalid_hostname(self): + """Test KmipServer rejects invalid hostname values.""" + with mock.patch.object(kmip_server.KmipServer, '_setup_logging'): + self.assertRaises( + exceptions.ConfigurationError, + kmip_server.KmipServer, + hostname=123, + config_path=None, + log_path='log' + ) + + def test_init_invalid_port(self): + """Test KmipServer rejects invalid port values.""" + with mock.patch.object(kmip_server.KmipServer, '_setup_logging'): + self.assertRaises( + exceptions.ConfigurationError, + kmip_server.KmipServer, + port=70000, + config_path=None, + log_path='log' + ) + + def test_start_creates_socket(self): + """Test start sets up and binds the server socket.""" + server = self._build_server_for_start() + wrapped_socket = mock.MagicMock() + base_socket = mock.MagicMock() + + with mock.patch( + 'kmip.services.server.server.multiprocessing.Manager' + ) as manager_mock, mock.patch( + 'kmip.services.server.server.monitor.PolicyDirectoryMonitor' + ) as monitor_mock, mock.patch( + 'kmip.services.server.server.engine.KmipEngine' + ), mock.patch( + 'kmip.services.server.server.socket.socket' + ) as socket_mock, mock.patch( + 'kmip.services.server.server.socket.setdefaulttimeout' + ), mock.patch( + 'kmip.services.server.server.ssl.wrap_socket' + ) as wrap_socket_mock, mock.patch( + 'kmip.services.server.server.operation_policy.policies', + {} + ): + manager_mock.return_value.dict.return_value = {} + socket_mock.return_value = base_socket + wrap_socket_mock.return_value = wrapped_socket + + server.start() + + socket_mock.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM) + base_socket.setsockopt.assert_called_once_with( + socket.SOL_SOCKET, + socket.SO_REUSEADDR, + 1 + ) + wrapped_socket.bind.assert_called_once_with(('127.0.0.1', 5696)) + self.assertTrue(server._is_serving) + monitor_mock.return_value.start.assert_called_once() + + def test_start_with_ssl_context(self): + """Test start configures SSL with expected parameters.""" + server = self._build_server_for_start() + wrapped_socket = mock.MagicMock() + base_socket = mock.MagicMock() + + with mock.patch( + 'kmip.services.server.server.multiprocessing.Manager' + ) as manager_mock, mock.patch( + 'kmip.services.server.server.monitor.PolicyDirectoryMonitor' + ) as monitor_mock, mock.patch( + 'kmip.services.server.server.engine.KmipEngine' + ), mock.patch( + 'kmip.services.server.server.socket.socket' + ) as socket_mock, mock.patch( + 'kmip.services.server.server.socket.setdefaulttimeout' + ), mock.patch( + 'kmip.services.server.server.ssl.wrap_socket' + ) as wrap_socket_mock, mock.patch( + 'kmip.services.server.server.operation_policy.policies', + {} + ): + manager_mock.return_value.dict.return_value = {} + socket_mock.return_value = base_socket + wrap_socket_mock.return_value = wrapped_socket + + server.start() + + wrap_socket_mock.assert_called_once_with( + base_socket, + keyfile='key.pem', + certfile='cert.pem', + server_side=True, + cert_reqs=kmip_server.ssl.CERT_REQUIRED, + ssl_version=server.auth_suite.protocol, + ca_certs='ca.pem', + do_handshake_on_connect=False, + suppress_ragged_eofs=True, + ciphers=server.auth_suite.ciphers + ) + monitor_mock.return_value.start.assert_called_once() + + def test_start_with_invalid_cert(self): + """Test start raises when SSL setup fails with invalid certs.""" + server = self._build_server_for_start() + base_socket = mock.MagicMock() + + with mock.patch( + 'kmip.services.server.server.multiprocessing.Manager' + ) as manager_mock, mock.patch( + 'kmip.services.server.server.monitor.PolicyDirectoryMonitor' + ), mock.patch( + 'kmip.services.server.server.engine.KmipEngine' + ), mock.patch( + 'kmip.services.server.server.socket.socket' + ) as socket_mock, mock.patch( + 'kmip.services.server.server.socket.setdefaulttimeout' + ), mock.patch( + 'kmip.services.server.server.ssl.wrap_socket', + side_effect=FileNotFoundError("missing cert") + ), mock.patch( + 'kmip.services.server.server.operation_policy.policies', + {} + ): + manager_mock.return_value.dict.return_value = {} + socket_mock.return_value = base_socket + + self.assertRaises(FileNotFoundError, server.start) + + def test_stop_graceful(self): + """Test stop gracefully shuts down socket and threads.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server.policy_monitor = mock.MagicMock() + + current_thread = mock.MagicMock() + other_thread = mock.MagicMock() + other_thread.name = 'thread-1' + other_thread.is_alive.return_value = False + + with mock.patch( + 'kmip.services.server.server.threading.enumerate', + return_value=[current_thread, other_thread] + ), mock.patch( + 'kmip.services.server.server.threading.current_thread', + return_value=current_thread + ): + server.stop() + + other_thread.join.assert_called_once_with(10.0) + server._socket.shutdown.assert_called_once_with(socket.SHUT_RDWR) + server._socket.close.assert_called_once_with() + server.policy_monitor.stop.assert_called_once_with() + server.policy_monitor.join.assert_called_once_with() + + def test_stop_with_active_sessions(self): + """Test stop handles active sessions that fail to terminate.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server.policy_monitor = mock.MagicMock() + + current_thread = mock.MagicMock() + other_thread = mock.MagicMock() + other_thread.name = 'thread-2' + other_thread.is_alive.return_value = True + + with mock.patch( + 'kmip.services.server.server.threading.enumerate', + return_value=[current_thread, other_thread] + ), mock.patch( + 'kmip.services.server.server.threading.current_thread', + return_value=current_thread + ): + server.stop() + + other_thread.join.assert_called_once_with(10.0) + server._logger.warning.assert_called() + + def test_serve_accepts_connection(self): + """Test serve accepts a connection and creates a session.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server._is_serving = True + server._setup_connection_handler = mock.MagicMock() + + connection = mock.MagicMock() + address = ('127.0.0.1', 1234) + server._socket.accept.side_effect = [ (connection, address), KeyboardInterrupt() ] + + with mock.patch('kmip.services.server.server.signal.signal'): + server.serve() + + server._socket.listen.assert_called_once_with(5) + server._setup_connection_handler.assert_called_once_with( + connection, + address + ) + self.assertFalse(server._is_serving) + + def test_serve_socket_timeout(self): + """Test serve handles socket.accept timeouts.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server._is_serving = True + server._setup_connection_handler = mock.MagicMock() + + def _accept_side_effect(): + server._is_serving = False + raise socket.timeout() + + server._socket.accept.side_effect = _accept_side_effect + + with mock.patch('kmip.services.server.server.signal.signal'): + server.serve() + + server._setup_connection_handler.assert_not_called() + self.assertFalse(server._is_serving) + + def test_serve_keyboard_interrupt(self): + """Test serve handles KeyboardInterrupt and stops.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server._is_serving = True + server._setup_connection_handler = mock.MagicMock() + + server._socket.accept.side_effect = KeyboardInterrupt() + + with mock.patch('kmip.services.server.server.signal.signal'): + server.serve() + + server._setup_connection_handler.assert_not_called() + self.assertFalse(server._is_serving) + + def test_setup_logging_creates_handler(self): + """Test setup_logging creates a rotating file handler.""" + server = kmip_server.KmipServer.__new__(kmip_server.KmipServer) + server._logger = mock.MagicMock() + + with mock.patch( + 'kmip.services.server.server.os.path.exists', + return_value=False + ), mock.patch( + 'kmip.services.server.server.os.path.isdir', + return_value=False + ), mock.patch( + 'kmip.services.server.server.os.makedirs' + ) as makedirs_mock, mock.patch( + 'kmip.services.server.server.open', + mock.mock_open() + ), mock.patch( + 'kmip.services.server.server.handlers.RotatingFileHandler' + ) as handler_cls, mock.patch( + 'kmip.services.server.server.logging.Formatter' + ) as formatter_cls: + handler_instance = mock.MagicMock() + formatter_instance = mock.MagicMock() + handler_cls.return_value = handler_instance + formatter_cls.return_value = formatter_instance + + server._setup_logging('C:\\logs\\server.log') + + makedirs_mock.assert_called_once_with('C:\\logs') + handler_cls.assert_called_once_with( + 'C:\\logs\\server.log', + mode='a', + maxBytes=1000000, + backupCount=5 + ) + handler_instance.setFormatter.assert_called_once_with( + formatter_instance + ) + server._logger.addHandler.assert_called_once_with(handler_instance) + server._logger.setLevel.assert_called_once_with(logging.DEBUG) + + def test_setup_logging_custom_level(self): + """Test init applies custom logging levels.""" + logger = mock.MagicMock() + with mock.patch( + 'kmip.services.server.server.logging.getLogger', + return_value=logger + ), mock.patch.object( + kmip_server.KmipServer, + '_setup_logging' + ), mock.patch.object( + kmip_server.auth, + 'BasicAuthenticationSuite' + ) as basic_suite: + basic_suite.return_value = mock.Mock( + ciphers='cipher', + protocol='proto' + ) + kmip_server.KmipServer( + config_path=None, + log_path='log', + logging_level='ERROR' + ) + + logger.setLevel.assert_called_with(logging.ERROR) + + def test_signal_handler_sigint(self): + """Test SIGINT handler raises KeyboardInterrupt and stops serving.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server._is_serving = False + + handlers = {} + + def _record_handler(sig, handler): + handlers[sig] = handler + + with mock.patch( + 'kmip.services.server.server.signal.signal', + side_effect=_record_handler + ): + server.serve() + + server._is_serving = True + self.assertRaises( + KeyboardInterrupt, + handlers[kmip_server.signal.SIGINT], + kmip_server.signal.SIGINT, + None + ) + self.assertFalse(server._is_serving) + + def test_signal_handler_sigterm(self): + """Test SIGTERM handler stops serving without exception.""" + server = self._build_server_for_start() + server._logger = mock.MagicMock() + server._socket = mock.MagicMock() + server._is_serving = False + + handlers = {} + + def _record_handler(sig, handler): + handlers[sig] = handler + + with mock.patch( + 'kmip.services.server.server.signal.signal', + side_effect=_record_handler + ): + server.serve() + + server._is_serving = True + handlers[kmip_server.signal.SIGTERM](kmip_server.signal.SIGTERM, None) + self.assertFalse(server._is_serving) diff --git a/kmip/tests/unit/services/server/test_session.py b/kmip/tests/unit/services/server/test_session.py index b6661c5b..7832dff8 100644 --- a/kmip/tests/unit/services/server/test_session.py +++ b/kmip/tests/unit/services/server/test_session.py @@ -18,7 +18,6 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa - import datetime import mock import socket @@ -36,7 +35,6 @@ from kmip.services.server import engine from kmip.services.server import session - def build_certificate( common_names, include_extension=True, @@ -106,7 +104,6 @@ def build_certificate( return builder.sign(private_key, hashes.SHA256(), default_backend()) - class TestKmipSession(testtools.TestCase): """ A test suite for the KmipSession. @@ -357,6 +354,72 @@ def test_handle_message_loop_with_response_too_long(self, kmip_session._logger.exception.assert_not_called() self.assertTrue(kmip_session._send_response.called) + @mock.patch('kmip.services.server.auth.get_certificate_from_connection') + @mock.patch('kmip.core.messages.messages.RequestMessage') + def test_handle_message_loop_with_response_size_equal_limit( + self, + request_mock, + cert_mock): + """ + Test that a response exactly at the max size is allowed. + """ + data = utils.BytearrayStream(()) + + cert_mock.return_value = 'test_certificate' + kmip_engine = engine.KmipEngine(database_path=':memory:') + kmip_session = session.KmipSession( + kmip_engine, + None, + None, + name='name', + enable_tls_client_auth=False + ) + kmip_session.authenticate = mock.MagicMock( + return_value=("John Doe", ["Group A"]) + ) + kmip_session._logger = mock.MagicMock() + kmip_session._connection = mock.MagicMock() + kmip_session._connection.shared_ciphers = mock.MagicMock( + return_value=None + ) + kmip_session._connection.cipher = mock.MagicMock( + return_value=('AES128-SHA256', 'TLSv1/SSLv3', 128) + ) + kmip_session._receive_request = mock.MagicMock(return_value=data) + kmip_session._send_response = mock.MagicMock() + + batch_item = messages.ResponseBatchItem( + result_status=contents.ResultStatus( + enums.ResultStatus.SUCCESS + ) + ) + batch_items = [batch_item] + header = messages.ResponseHeader( + protocol_version=contents.ProtocolVersion(1, 2), + time_stamp=contents.TimeStamp(int(time.time())), + batch_count=contents.BatchCount(len(batch_items)) + ) + response = messages.ResponseMessage( + response_header=header, + batch_items=batch_items + ) + + response_data = utils.BytearrayStream() + kmip_version = contents.protocol_version_to_kmip_version( + header.protocol_version + ) + response.write(response_data, kmip_version=kmip_version) + max_size = len(response_data) + + kmip_engine.process_request = mock.MagicMock( + return_value=(response, max_size, header.protocol_version) + ) + + kmip_session._handle_message_loop() + + kmip_session._logger.warning.assert_not_called() + self.assertTrue(kmip_session._send_response.called) + @mock.patch('kmip.services.server.auth.get_certificate_from_connection') @mock.patch('kmip.core.messages.messages.RequestMessage') def test_handle_message_loop_with_unexpected_error(self, diff --git a/kmip/tests/unit/services/test_auth.py b/kmip/tests/unit/services/test_auth.py index 92ec1f27..681e906d 100644 --- a/kmip/tests/unit/services/test_auth.py +++ b/kmip/tests/unit/services/test_auth.py @@ -19,7 +19,6 @@ from kmip.services import auth - class TestBasicAuthenticationSuite(testtools.TestCase): """ A test suite for the BasicAuthenticationSuite. @@ -118,7 +117,6 @@ def test_custom_ciphers_empty(self): self.assertIn('DHE-DSS-AES256-SHA', suites) self.assertIn('DHE-RSA-AES256-SHA', suites) - @pytest.mark.skipif(not hasattr(ssl, 'PROTOCOL_TLSv1_2'), reason="Requires ssl.PROTOCOL_TLSv1_2") class TestTLS12AuthenticationSuite(testtools.TestCase): diff --git a/kmip/tests/unit/services/test_kmip_client.py b/kmip/tests/unit/services/test_kmip_client.py index fa13a204..9430c464 100644 --- a/kmip/tests/unit/services/test_kmip_client.py +++ b/kmip/tests/unit/services/test_kmip_client.py @@ -18,6 +18,7 @@ from kmip.core.attributes import CryptographicParameters from kmip.core.attributes import DerivationParameters from kmip.core.attributes import PrivateKeyUniqueIdentifier +from kmip.core.attributes import UniqueIdentifier from kmip.core import enums from kmip.core.enums import AuthenticationSuite @@ -71,7 +72,6 @@ import socket import ssl - class TestKMIPClient(TestCase): def setUp(self): @@ -962,7 +962,7 @@ def test_send_request_payload_mismatch_response_payload( is returned from the server. """ response_payload = payloads.DestroyResponsePayload( - unique_identifier="1" + unique_identifier=UniqueIdentifier("1") ) batch_item = ResponseBatchItem( @@ -1649,7 +1649,6 @@ def verify_request(message): self.assertEqual(result.uuid, None) self.assertEqual(result.mac_data, None) - class TestClientProfileInformation(TestCase): """ A test suite for client profile information support. diff --git a/kmip/tests/unit/services/test_kmip_protocol.py b/kmip/tests/unit/services/test_kmip_protocol.py index e84e43a5..e5ce8629 100644 --- a/kmip/tests/unit/services/test_kmip_protocol.py +++ b/kmip/tests/unit/services/test_kmip_protocol.py @@ -22,7 +22,6 @@ from kmip.services.kmip_protocol import RequestLengthMismatch from kmip.services.kmip_protocol import KMIPProtocolFactory - class TestKMIPProtocol(TestCase): request = binascii.unhexlify( diff --git a/kmip/tests/unit/test_integration_inmemory.py b/kmip/tests/unit/test_integration_inmemory.py new file mode 100644 index 00000000..366ef3c4 --- /dev/null +++ b/kmip/tests/unit/test_integration_inmemory.py @@ -0,0 +1,800 @@ +# Copyright (c) 2026 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 time + +import testtools + +from kmip.core import attributes +from kmip.core import enums +from kmip.core import objects as core_objects +from kmip.core import policy as operation_policy +from kmip.core.factories import attributes as attribute_factory +from kmip.core.factories import secrets as secret_factory +from kmip.core.messages import contents +from kmip.core.messages import messages +from kmip.core.messages import payloads +from kmip.services.server import engine as kmip_engine + + +class TestIntegrationInMemory(testtools.TestCase): + def setUp(self): + super(TestIntegrationInMemory, self).setUp() + self.engine = kmip_engine.KmipEngine( + policies=operation_policy.policies, + database_path=':memory:' + ) + self.attr_factory = attribute_factory.AttributeFactory() + self.secret_factory = secret_factory.SecretFactory() + self.protocol_version = contents.ProtocolVersion(1, 2) + self.default_credential = ["user-a", None] + + def _batch_item(self, operation, request_payload, batch_id=None): + unique_batch_item_id = None + if batch_id is not None: + unique_batch_item_id = contents.UniqueBatchItemID(batch_id) + return messages.RequestBatchItem( + operation=contents.Operation(operation), + unique_batch_item_id=unique_batch_item_id, + request_payload=request_payload + ) + + def _build_request(self, batch_items): + if len(batch_items) > 1: + for index, batch_item in enumerate(batch_items, start=1): + if batch_item.unique_batch_item_id is None: + batch_item.unique_batch_item_id = \ + contents.UniqueBatchItemID(index) + + header = messages.RequestHeader( + protocol_version=self.protocol_version, + maximum_response_size=contents.MaximumResponseSize(2 ** 20), + authentication=contents.Authentication(), + batch_error_cont_option=contents.BatchErrorContinuationOption( + enums.BatchErrorContinuationOption.STOP + ), + batch_order_option=contents.BatchOrderOption(True), + time_stamp=contents.TimeStamp(int(time.time())), + batch_count=contents.BatchCount(len(batch_items)) + ) + + return messages.RequestMessage( + request_header=header, + batch_items=batch_items + ) + + def _send_request(self, batch_items, credential=None): + if credential is None: + credential = self.default_credential + request = self._build_request(batch_items) + response, _, _ = self.engine.process_request( + request, + credential=credential + ) + return response + + def _assert_success(self, response, index=0): + batch_item = response.batch_items[index] + self.assertEqual( + enums.ResultStatus.SUCCESS, + batch_item.result_status.value + ) + return batch_item.response_payload + + def _assert_error(self, response, reason=None, index=0): + batch_item = response.batch_items[index] + self.assertEqual( + enums.ResultStatus.OPERATION_FAILED, + batch_item.result_status.value + ) + if reason is not None: + self.assertEqual(reason, batch_item.result_reason.value) + return batch_item + + def _name_attribute(self, name): + return self.attr_factory.create_attribute( + enums.AttributeType.NAME, + attributes.Name.create( + name, + enums.NameType.UNINTERPRETED_TEXT_STRING + ) + ) + + def _symmetric_template( + self, + name, + algorithm, + length, + masks, + policy_name="default"): + attrs = [] + if name is not None: + attrs.append(self._name_attribute(name)) + if algorithm is not None: + attrs.append(self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + algorithm + )) + if length is not None: + attrs.append(self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, + length + )) + if masks is not None: + attrs.append(self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + masks + )) + if policy_name is not None: + attrs.append(self.attr_factory.create_attribute( + enums.AttributeType.OPERATION_POLICY_NAME, + policy_name + )) + return core_objects.TemplateAttribute(attributes=attrs) + + def _attributes_to_dict(self, attribute_list): + result = {} + for attribute in attribute_list: + name = attribute.attribute_name.value + value = attribute.attribute_value + if name == "Name": + result.setdefault(name, []).append(value.name_value.value) + elif name == "Cryptographic Usage Mask": + result[name] = enums.get_enumerations_from_bit_mask( + enums.CryptographicUsageMask, + value.value + ) + elif hasattr(value, "value"): + result[name] = value.value + else: + result[name] = value + return result + + def _get_state(self, unique_identifier, credential=None): + payload = payloads.GetAttributesRequestPayload( + unique_identifier=unique_identifier, + attribute_names=["State"] + ) + response = self._send_request( + [self._batch_item(enums.Operation.GET_ATTRIBUTES, payload)], + credential=credential + ) + response_payload = self._assert_success(response) + attrs = self._attributes_to_dict(response_payload.attributes) + return attrs.get("State") + + def _aes_cbc_parameters(self): + return attributes.CryptographicParameters( + block_cipher_mode=enums.BlockCipherMode.CBC, + padding_method=enums.PaddingMethod.PKCS5, + cryptographic_algorithm=enums.CryptographicAlgorithm.AES + ) + + def _rsa_signature_parameters(self): + return attributes.CryptographicParameters( + cryptographic_algorithm=enums.CryptographicAlgorithm.RSA, + hashing_algorithm=enums.HashingAlgorithm.SHA_256, + digital_signature_algorithm=( + enums.DigitalSignatureAlgorithm.SHA256_WITH_RSA_ENCRYPTION + ), + padding_method=enums.PaddingMethod.PKCS1v15 + ) + + def test_full_key_lifecycle(self): + template = self._symmetric_template( + name="lifecycle-aes-256", + algorithm=enums.CryptographicAlgorithm.AES, + length=256, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + create_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, create_payload)] + ) + create_response = self._assert_success(response) + key_id = create_response.unique_identifier + + self.assertEqual(enums.State.PRE_ACTIVE, self._get_state(key_id)) + + activate_payload = payloads.ActivateRequestPayload( + unique_identifier=attributes.UniqueIdentifier(key_id) + ) + response = self._send_request( + [self._batch_item(enums.Operation.ACTIVATE, activate_payload)] + ) + self._assert_success(response) + self.assertEqual(enums.State.ACTIVE, self._get_state(key_id)) + + data = b"kmip integration data" + crypto_params = self._aes_cbc_parameters() + encrypt_payload = payloads.EncryptRequestPayload( + unique_identifier=key_id, + cryptographic_parameters=crypto_params, + data=data, + iv_counter_nonce=None + ) + response = self._send_request( + [self._batch_item(enums.Operation.ENCRYPT, encrypt_payload)] + ) + encrypt_response = self._assert_success(response) + + decrypt_payload = payloads.DecryptRequestPayload( + unique_identifier=key_id, + cryptographic_parameters=crypto_params, + data=encrypt_response.data, + iv_counter_nonce=encrypt_response.iv_counter_nonce + ) + response = self._send_request( + [self._batch_item(enums.Operation.DECRYPT, decrypt_payload)] + ) + decrypt_response = self._assert_success(response) + self.assertEqual(data, decrypt_response.data) + + revoke_payload = payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier(key_id), + revocation_reason=core_objects.RevocationReason( + code=enums.RevocationReasonCode.CESSATION_OF_OPERATION + ) + ) + response = self._send_request( + [self._batch_item(enums.Operation.REVOKE, revoke_payload)] + ) + self._assert_success(response) + self.assertEqual(enums.State.DEACTIVATED, self._get_state(key_id)) + + destroy_payload = payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(key_id) + ) + response = self._send_request( + [self._batch_item(enums.Operation.DESTROY, destroy_payload)] + ) + self._assert_success(response) + + get_payload = payloads.GetRequestPayload(unique_identifier=key_id) + response = self._send_request( + [self._batch_item(enums.Operation.GET, get_payload)] + ) + self._assert_error(response, enums.ResultReason.ITEM_NOT_FOUND) + + def test_key_pair_lifecycle(self): + common_template = core_objects.TemplateAttribute( + attributes=[ + self._name_attribute("rsa-keypair"), + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.RSA + ), + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_LENGTH, + 2048 + ), + self.attr_factory.create_attribute( + enums.AttributeType.OPERATION_POLICY_NAME, + "default" + ) + ], + tag=enums.Tags.COMMON_TEMPLATE_ATTRIBUTE + ) + public_template = core_objects.TemplateAttribute( + attributes=[ + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + [enums.CryptographicUsageMask.VERIFY] + ) + ], + tag=enums.Tags.PUBLIC_KEY_TEMPLATE_ATTRIBUTE + ) + private_template = core_objects.TemplateAttribute( + attributes=[ + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + [enums.CryptographicUsageMask.SIGN] + ) + ], + tag=enums.Tags.PRIVATE_KEY_TEMPLATE_ATTRIBUTE + ) + create_pair_payload = payloads.CreateKeyPairRequestPayload( + common_template_attribute=common_template, + public_key_template_attribute=public_template, + private_key_template_attribute=private_template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE_KEY_PAIR, + create_pair_payload)] + ) + create_pair_response = self._assert_success(response) + public_id = create_pair_response.public_key_unique_identifier + private_id = create_pair_response.private_key_unique_identifier + + response = self._send_request( + [ + self._batch_item( + enums.Operation.ACTIVATE, + payloads.ActivateRequestPayload( + unique_identifier=attributes.UniqueIdentifier(public_id) + ) + ), + self._batch_item( + enums.Operation.ACTIVATE, + payloads.ActivateRequestPayload( + unique_identifier=attributes.UniqueIdentifier(private_id) + ) + ) + ] + ) + self._assert_success(response, index=0) + self._assert_success(response, index=1) + + data = b"sign me" + sig_params = self._rsa_signature_parameters() + sign_payload = payloads.SignRequestPayload( + unique_identifier=private_id, + cryptographic_parameters=sig_params, + data=data + ) + response = self._send_request( + [self._batch_item(enums.Operation.SIGN, sign_payload)] + ) + sign_response = self._assert_success(response) + + verify_payload = payloads.SignatureVerifyRequestPayload( + unique_identifier=public_id, + cryptographic_parameters=sig_params, + data=data, + signature_data=sign_response.signature_data + ) + response = self._send_request( + [self._batch_item(enums.Operation.SIGNATURE_VERIFY, + verify_payload)] + ) + verify_response = self._assert_success(response) + self.assertEqual( + enums.ValidityIndicator.VALID, + verify_response.validity_indicator + ) + + revoke_reason = core_objects.RevocationReason( + code=enums.RevocationReasonCode.CESSATION_OF_OPERATION + ) + response = self._send_request( + [ + self._batch_item( + enums.Operation.REVOKE, + payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier(public_id), + revocation_reason=revoke_reason + ) + ), + self._batch_item( + enums.Operation.REVOKE, + payloads.RevokeRequestPayload( + unique_identifier=attributes.UniqueIdentifier(private_id), + revocation_reason=revoke_reason + ) + ) + ] + ) + self._assert_success(response, index=0) + self._assert_success(response, index=1) + + response = self._send_request( + [ + self._batch_item( + enums.Operation.DESTROY, + payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(public_id) + ) + ), + self._batch_item( + enums.Operation.DESTROY, + payloads.DestroyRequestPayload( + unique_identifier=attributes.UniqueIdentifier(private_id) + ) + ) + ] + ) + self._assert_success(response, index=0) + self._assert_success(response, index=1) + + def test_registration_and_retrieval(self): + key_bytes = b"\x11" * 32 + secret = self.secret_factory.create( + enums.ObjectType.SYMMETRIC_KEY, + { + "key_format_type": enums.KeyFormatType.RAW, + "key_value": key_bytes, + "cryptographic_algorithm": enums.CryptographicAlgorithm.AES, + "cryptographic_length": 256 + } + ) + template = core_objects.TemplateAttribute( + attributes=[ + self._name_attribute("external-key"), + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_USAGE_MASK, + [ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ), + self.attr_factory.create_attribute( + enums.AttributeType.OPERATION_POLICY_NAME, + "default" + ) + ] + ) + register_payload = payloads.RegisterRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + template_attribute=template, + managed_object=secret + ) + response = self._send_request( + [self._batch_item(enums.Operation.REGISTER, register_payload)] + ) + register_response = self._assert_success(response) + key_id = register_response.unique_identifier + + get_payload = payloads.GetRequestPayload(unique_identifier=key_id) + response = self._send_request( + [self._batch_item(enums.Operation.GET, get_payload)] + ) + get_response = self._assert_success(response) + self.assertEqual(enums.ObjectType.SYMMETRIC_KEY, get_response.object_type) + self.assertEqual(key_bytes, + get_response.secret.key_block.key_value.key_material + .value) + self.assertEqual( + enums.CryptographicAlgorithm.AES, + get_response.secret.key_block.cryptographic_algorithm.value + ) + self.assertEqual( + 256, + get_response.secret.key_block.cryptographic_length.value + ) + + attrs_payload = payloads.GetAttributesRequestPayload( + unique_identifier=key_id, + attribute_names=[ + "Name", + "Cryptographic Algorithm", + "Cryptographic Length", + "Cryptographic Usage Mask", + "Operation Policy Name" + ] + ) + response = self._send_request( + [self._batch_item(enums.Operation.GET_ATTRIBUTES, attrs_payload)] + ) + attrs_response = self._assert_success(response) + attrs = self._attributes_to_dict(attrs_response.attributes) + self.assertIn("external-key", attrs.get("Name")) + self.assertEqual(enums.CryptographicAlgorithm.AES, + attrs.get("Cryptographic Algorithm")) + self.assertEqual(256, attrs.get("Cryptographic Length")) + self.assertEqual( + set([ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ]), + set(attrs.get("Cryptographic Usage Mask")) + ) + self.assertEqual("default", attrs.get("Operation Policy Name")) + + def test_locate_with_filters(self): + created_ids = [] + key_specs = [ + ("locate-0", enums.CryptographicAlgorithm.AES, 128), + ("locate-1", enums.CryptographicAlgorithm.AES, 256), + ("locate-2", enums.CryptographicAlgorithm.BLOWFISH, 128), + ("locate-3", enums.CryptographicAlgorithm.CAMELLIA, 128), + ("locate-4", enums.CryptographicAlgorithm.TRIPLE_DES, 192) + ] + for name, algorithm, length in key_specs: + template = self._symmetric_template( + name=name, + algorithm=algorithm, + length=length, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, payload)] + ) + create_response = self._assert_success(response) + created_ids.append(create_response.unique_identifier) + + locate_name_payload = payloads.LocateRequestPayload( + attributes=[ + self._name_attribute("locate-3") + ] + ) + response = self._send_request( + [self._batch_item(enums.Operation.LOCATE, locate_name_payload)] + ) + locate_name_response = self._assert_success(response) + self.assertEqual([created_ids[3]], + locate_name_response.unique_identifiers) + + locate_algo_payload = payloads.LocateRequestPayload( + attributes=[ + self.attr_factory.create_attribute( + enums.AttributeType.CRYPTOGRAPHIC_ALGORITHM, + enums.CryptographicAlgorithm.AES + ) + ] + ) + response = self._send_request( + [self._batch_item(enums.Operation.LOCATE, locate_algo_payload)] + ) + locate_algo_response = self._assert_success(response) + self.assertEqual( + set([created_ids[0], created_ids[1]]), + set(locate_algo_response.unique_identifiers) + ) + + locate_slice_payload = payloads.LocateRequestPayload( + offset_items=2, + maximum_items=2 + ) + response = self._send_request( + [self._batch_item(enums.Operation.LOCATE, locate_slice_payload)] + ) + locate_slice_response = self._assert_success(response) + self.assertEqual(2, len(locate_slice_response.unique_identifiers)) + self.assertEqual( + created_ids[2:4], + locate_slice_response.unique_identifiers + ) + + def test_access_control(self): + template = self._symmetric_template( + name="access-control", + algorithm=enums.CryptographicAlgorithm.AES, + length=128, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + create_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, create_payload)], + credential=["user-a", None] + ) + create_response = self._assert_success(response) + key_id = create_response.unique_identifier + + get_payload = payloads.GetRequestPayload(unique_identifier=key_id) + response = self._send_request( + [self._batch_item(enums.Operation.GET, get_payload)], + credential=["user-b", None] + ) + self._assert_error(response, enums.ResultReason.PERMISSION_DENIED) + + def test_derive_key_workflow(self): + base_template = self._symmetric_template( + name="derive-base", + algorithm=enums.CryptographicAlgorithm.AES, + length=256, + masks=[enums.CryptographicUsageMask.DERIVE_KEY] + ) + create_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + base_template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, create_payload)] + ) + create_response = self._assert_success(response) + base_id = create_response.unique_identifier + + derived_template = self._symmetric_template( + name="derive-result", + algorithm=enums.CryptographicAlgorithm.AES, + length=256, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + derive_payload = payloads.DeriveKeyRequestPayload( + object_type=enums.ObjectType.SYMMETRIC_KEY, + unique_identifiers=[base_id], + derivation_method=enums.DerivationMethod.PBKDF2, + derivation_parameters=attributes.DerivationParameters( + cryptographic_parameters=attributes.CryptographicParameters( + hashing_algorithm=enums.HashingAlgorithm.SHA_256 + ), + salt=b"kmip-salt", + iteration_count=1000 + ), + template_attribute=derived_template + ) + response = self._send_request( + [self._batch_item(enums.Operation.DERIVE_KEY, derive_payload)] + ) + derive_response = self._assert_success(response) + derived_id = derive_response.unique_identifier + + activate_payload = payloads.ActivateRequestPayload( + unique_identifier=attributes.UniqueIdentifier(derived_id) + ) + response = self._send_request( + [self._batch_item(enums.Operation.ACTIVATE, activate_payload)] + ) + self._assert_success(response) + + data = b"derived data" + crypto_params = self._aes_cbc_parameters() + encrypt_payload = payloads.EncryptRequestPayload( + unique_identifier=derived_id, + cryptographic_parameters=crypto_params, + data=data, + iv_counter_nonce=None + ) + response = self._send_request( + [self._batch_item(enums.Operation.ENCRYPT, encrypt_payload)] + ) + encrypt_response = self._assert_success(response) + + decrypt_payload = payloads.DecryptRequestPayload( + unique_identifier=derived_id, + cryptographic_parameters=crypto_params, + data=encrypt_response.data, + iv_counter_nonce=encrypt_response.iv_counter_nonce + ) + response = self._send_request( + [self._batch_item(enums.Operation.DECRYPT, decrypt_payload)] + ) + decrypt_response = self._assert_success(response) + self.assertEqual(data, decrypt_response.data) + + def test_certificate_handling(self): + cert_bytes = b"dummy-x509-cert" + cert = self.secret_factory.create( + enums.ObjectType.CERTIFICATE, + { + "certificate_type": enums.CertificateType.X_509, + "certificate_value": cert_bytes + } + ) + template = core_objects.TemplateAttribute( + attributes=[ + self._name_attribute("certificate"), + self.attr_factory.create_attribute( + enums.AttributeType.OPERATION_POLICY_NAME, + "default" + ) + ] + ) + register_payload = payloads.RegisterRequestPayload( + object_type=enums.ObjectType.CERTIFICATE, + template_attribute=template, + managed_object=cert + ) + response = self._send_request( + [self._batch_item(enums.Operation.REGISTER, register_payload)] + ) + register_response = self._assert_success(response) + cert_id = register_response.unique_identifier + + get_payload = payloads.GetRequestPayload(unique_identifier=cert_id) + response = self._send_request( + [self._batch_item(enums.Operation.GET, get_payload)] + ) + get_response = self._assert_success(response) + self.assertEqual(enums.ObjectType.CERTIFICATE, get_response.object_type) + self.assertEqual( + enums.CertificateType.X_509, + get_response.secret.certificate_type.value + ) + self.assertEqual( + cert_bytes, + get_response.secret.certificate_value.value + ) + + def test_batch_processing(self): + template = self._symmetric_template( + name="batch-key", + algorithm=enums.CryptographicAlgorithm.AES, + length=128, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + create_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + template + ) + activate_payload = payloads.ActivateRequestPayload() + get_payload = payloads.GetRequestPayload() + response = self._send_request( + [ + self._batch_item(enums.Operation.CREATE, create_payload), + self._batch_item(enums.Operation.ACTIVATE, activate_payload), + self._batch_item(enums.Operation.GET, get_payload) + ] + ) + create_response = self._assert_success(response, index=0) + self._assert_success(response, index=1) + get_response = self._assert_success(response, index=2) + self.assertEqual( + create_response.unique_identifier, + get_response.unique_identifier + ) + + def test_discover_versions(self): + payload = payloads.DiscoverVersionsRequestPayload( + protocol_versions=[] + ) + response = self._send_request( + [self._batch_item(enums.Operation.DISCOVER_VERSIONS, payload)] + ) + discover_response = self._assert_success(response) + versions = [ + (version.major, version.minor) + for version in discover_response.protocol_versions + ] + self.assertIn((1, 2), versions) + + def test_error_recovery(self): + invalid_template = self._symmetric_template( + name="invalid-key", + algorithm=enums.CryptographicAlgorithm.AES, + length=128, + masks=None + ) + invalid_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + invalid_template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, invalid_payload)] + ) + self._assert_error(response, enums.ResultReason.INVALID_FIELD) + + valid_template = self._symmetric_template( + name="valid-key", + algorithm=enums.CryptographicAlgorithm.AES, + length=128, + masks=[ + enums.CryptographicUsageMask.ENCRYPT, + enums.CryptographicUsageMask.DECRYPT + ] + ) + valid_payload = payloads.CreateRequestPayload( + enums.ObjectType.SYMMETRIC_KEY, + valid_template + ) + response = self._send_request( + [self._batch_item(enums.Operation.CREATE, valid_payload)] + ) + self._assert_success(response) diff --git a/kmip/tests/unit/test_kmip.py b/kmip/tests/unit/test_kmip.py index 5ad8cf99..68d0f4e4 100644 --- a/kmip/tests/unit/test_kmip.py +++ b/kmip/tests/unit/test_kmip.py @@ -15,7 +15,6 @@ from testtools import TestCase - class TestKMIP(TestCase): """ A test suite for the overall `kmip` module. diff --git a/requirements.txt b/requirements.txt index c74a7baf..3088c26c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,3 @@ cryptography>=2.5 -enum-compat requests -six>=1.11.0 sqlalchemy>=1.0 diff --git a/setup.py b/setup.py index 4cc8a39c..4d8f7886 100644 --- a/setup.py +++ b/setup.py @@ -52,12 +52,10 @@ }, install_requires=[ "cryptography", - "enum-compat", "requests", - "six", "sqlalchemy" ], - python_requires=">= 3.8", + python_requires=">= 3.12", classifiers=[ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", @@ -68,9 +66,8 @@ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ], ) diff --git a/tox.ini b/tox.ini index 31cb52fd..8cdc9716 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = pep8,py38,py310,bandit,docs +envlist = pep8,py312,py313,py314,bandit,docs [testenv] passenv = *