From bea9bf08b2d6d920cd8f6d432afa3b52de0df458 Mon Sep 17 00:00:00 2001 From: Peter Hamilton Date: Thu, 9 Apr 2015 10:45:59 -0400 Subject: [PATCH] Adding KMIP profile information to the client This change updates the client with the KMIP profile information of the conformance clauses and authentication suites that the client supports. Several new methods are added to the client, allowing for the retrieval and basic predicate querying of the profile data. A new test suite has also been added to test this new capability. --- kmip/core/enums.py | 36 ++++++++ kmip/services/kmip_client.py | 103 ++++++++++++++++++++- kmip/tests/services/test_kmip_client.py | 114 ++++++++++++++++++++++++ 3 files changed, 252 insertions(+), 1 deletion(-) diff --git a/kmip/core/enums.py b/kmip/core/enums.py index f01b069..3f7f3f1 100644 --- a/kmip/core/enums.py +++ b/kmip/core/enums.py @@ -61,6 +61,42 @@ class AttributeType(Enum): CUSTOM_ATTRIBUTE = 'Custom Attribute' +class ConformanceClause(Enum): + """ + The specification of KMIP features supported by KMIP clients and servers. + + The conformance clause defines the KMIP objects and operations that need + to be supported for a specific feature set. The clause is one of two core + components that make up a KMIP client/server profile. For more information, + see Section 5 of the KMIP 1.1 profiles document. + """ + DISCOVER_VERSIONS = 1 + BASELINE = 2 + SECRET_DATA = 3 + SYMMETRIC_KEY_STORE = 4 + SYMMETRIC_KEY_FOUNDRY = 5 + ASYMMETRIC_KEY_STORE = 6 + ASYMMETRIC_KEY_AND_CERTIFICATE_STORE = 7 + ASYMMETRIC_KEY_FOUNDRY = 8 + CERTIFICATE = 9 + ASYMMETRIC_KEY_FOUNDRY_AND_CERTIFICATE = 10 + STORAGE = 11 + + +class AuthenticationSuite(Enum): + """ + The type of authentication suite used by KMIP clients and servers. + + The authentication suite defines the protocol versions and cipher suites + that should be used to secure KMIP client/server communications. An + authentication suite is one of two core components that make up a KMIP + client/server profile. For more information, see Section 3 of the KMIP + 1.1 profiles document. + """ + BASIC = 1 + TLS12 = 2 + + # 9.1.1.2 class Types(Enum): DEFAULT = 0x00 diff --git a/kmip/services/kmip_client.py b/kmip/services/kmip_client.py index 141b4e3..a32703c 100644 --- a/kmip/services/kmip_client.py +++ b/kmip/services/kmip_client.py @@ -25,8 +25,10 @@ from kmip.services.results import RekeyKeyPairResult from kmip.core import attributes as attr -from kmip.core.enums import Operation as OperationEnum +from kmip.core.enums import AuthenticationSuite +from kmip.core.enums import ConformanceClause from kmip.core.enums import CredentialType +from kmip.core.enums import Operation as OperationEnum from kmip.core.factories.credentials import CredentialFactory @@ -84,6 +86,105 @@ class KMIPProxy(KMIP): username, password) self.batch_items = [] + self.conformance_clauses = [ + ConformanceClause.DISCOVER_VERSIONS] + + self.authentication_suites = [ + AuthenticationSuite.BASIC, + AuthenticationSuite.TLS12] + + def get_supported_conformance_clauses(self): + """ + Get the list of conformance clauses supported by the client. + + Returns: + list: A shallow copy of the list of supported conformance clauses. + + Example: + >>> client.get_supported_conformance_clauses() + [] + """ + return self.conformance_clauses[:] + + def get_supported_authentication_suites(self): + """ + Get the list of authentication suites supported by the client. + + Returns: + list: A shallow copy of the list of supported authentication + suites. + + Example: + >>> client.get_supported_authentication_suites() + [, ] + """ + return self.authentication_suites[:] + + def is_conformance_clause_supported(self, conformance_clause): + """ + Check if a ConformanceClause is supported by the client. + + Args: + conformance_clause (ConformanceClause): A ConformanceClause + enumeration to check against the list of supported + ConformanceClauses. + + Returns: + bool: True if the ConformanceClause is supported, False otherwise. + + Example: + >>> clause = ConformanceClause.DISCOVER_VERSIONS + >>> client.is_conformance_clause_supported(clause) + True + >>> clause = ConformanceClause.BASELINE + >>> client.is_conformance_clause_supported(clause) + False + """ + return conformance_clause in self.conformance_clauses + + def is_authentication_suite_supported(self, authentication_suite): + """ + Check if an AuthenticationSuite is supported by the client. + + Args: + authentication_suite (AuthenticationSuite): An AuthenticationSuite + enumeration to check against the list of supported + AuthenticationSuites. + + Returns: + bool: True if the AuthenticationSuite is supported, False + otherwise. + + Example: + >>> suite = AuthenticationSuite.BASIC + >>> client.is_authentication_suite_supported(suite) + True + >>> suite = AuthenticationSuite.TLS12 + >>> client.is_authentication_suite_supported(suite) + False + """ + return authentication_suite in self.authentication_suites + + def is_profile_supported(self, conformance_clause, authentication_suite): + """ + Check if a profile is supported by the client. + + Args: + conformance_clause (ConformanceClause): + authentication_suite (AuthenticationSuite): + + Returns: + bool: True if the profile is supported, False otherwise. + + Example: + >>> client.is_profile_supported( + ... ConformanceClause.DISCOVER_VERSIONS, + ... AuthenticationSuite.BASIC) + True + """ + return (self.is_conformance_clause_supported(conformance_clause) and + self.is_authentication_suite_supported(authentication_suite)) + def open(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/kmip/tests/services/test_kmip_client.py b/kmip/tests/services/test_kmip_client.py index 8592859..2d9f659 100644 --- a/kmip/tests/services/test_kmip_client.py +++ b/kmip/tests/services/test_kmip_client.py @@ -26,6 +26,8 @@ from kmip.core.attributes import CryptographicLength from kmip.core.attributes import PrivateKeyUniqueIdentifier from kmip.core.enums import AttributeType +from kmip.core.enums import AuthenticationSuite +from kmip.core.enums import ConformanceClause from kmip.core.enums import CredentialType from kmip.core.enums import CryptographicAlgorithm as CryptoAlgorithmEnum from kmip.core.enums import CryptographicUsageMask @@ -837,3 +839,115 @@ class TestKMIPClient(TestCase): def test_process_discover_versions_batch_item_no_results(self): protocol_versions = None self._test_process_discover_versions_batch_item(protocol_versions) + + +class TestClientProfileInformation(TestCase): + """ + A test suite for client profile information support. + """ + + def setUp(self): + super(TestClientProfileInformation, self).setUp() + + self.client = KMIPProxy() + + self.conformance_clauses = [ConformanceClause.DISCOVER_VERSIONS] + self.authentication_suites = [AuthenticationSuite.BASIC] + + self.client.conformance_clauses = self.conformance_clauses + self.client.authentication_suites = self.authentication_suites + + def tearDown(self): + super(TestClientProfileInformation, self).tearDown() + + def test_get_supported_conformance_clauses(self): + """ + Test that the list of supporting conformance clauses can be retrieved. + """ + conformance_clauses = self.client.get_supported_conformance_clauses() + self.assertEqual(self.conformance_clauses, conformance_clauses) + + def test_get_supported_authentication_suites(self): + """ + Test that the list of supporting authentication suites can be + retrieved. + """ + auth_suites = self.client.get_supported_authentication_suites() + self.assertEqual(self.authentication_suites, auth_suites) + + def test_is_conformance_clause_supported_with_valid(self): + """ + Test that the conformance clause support predicate returns True for + a ConformanceClause that is supported. + """ + clause = ConformanceClause.DISCOVER_VERSIONS + supported = self.client.is_conformance_clause_supported(clause) + self.assertTrue(supported) + + def test_is_conformance_clause_supported_with_invalid(self): + """ + Test that the conformance clause support predicate returns False for + a ConformanceClause that is not supported. + """ + clause = ConformanceClause.BASELINE + supported = self.client.is_conformance_clause_supported(clause) + self.assertFalse(supported) + + def test_is_authentication_suite_supported_with_valid(self): + """ + Test that the authentication suite support predicate returns True for + an AuthenticationSuite that is supported. + """ + suite = AuthenticationSuite.BASIC + supported = self.client.is_authentication_suite_supported(suite) + self.assertTrue(supported) + + def test_is_authentication_suite_supported_with_invalid(self): + """ + Test that the authentication suite support predicate returns False for + an AuthenticationSuite that is not supported. + """ + suite = AuthenticationSuite.TLS12 + supported = self.client.is_authentication_suite_supported(suite) + self.assertFalse(supported) + + def test_is_profile_supported(self): + """ + Test that the profile support predicate returns True for valid profile + components. + """ + supported = self.client.is_profile_supported( + ConformanceClause.DISCOVER_VERSIONS, + AuthenticationSuite.BASIC) + self.assertTrue(supported) + + # TODO (peter-hamilton) Replace following 3 tests with 1 parameterized test + def test_is_profile_supported_with_invalid_conformance_clause(self): + """ + Test that the profile support predicate returns False for an invalid + conformance clause. + """ + supported = self.client.is_profile_supported( + ConformanceClause.BASELINE, + AuthenticationSuite.BASIC) + self.assertFalse(supported) + + def test_is_profile_supported_with_invalid_authentication_suite(self): + """ + Test that the profile support predicate returns False for an invalid + authentication suite. + """ + supported = self.client.is_profile_supported( + ConformanceClause.DISCOVER_VERSIONS, + AuthenticationSuite.TLS12) + self.assertFalse(supported) + + def test_is_profile_supported_with_invalid_profile_components(self): + """ + Test that the profile support predicate returns False for invalid + profile components. + """ + supported = self.client.is_profile_supported( + ConformanceClause.BASELINE, + AuthenticationSuite.TLS12) + self.assertFalse(supported)