diff --git a/kmip/core/primitives.py b/kmip/core/primitives.py index b8cd9a75..d957b6c5 100644 --- a/kmip/core/primitives.py +++ b/kmip/core/primitives.py @@ -36,6 +36,7 @@ def __init__(self, tag=enums.Tags.DEFAULT, type=enums.Types.DEFAULT): self.tag = tag self.type = type self.length = None + self.logger = logging.getLogger('kmip.core.primitives') # TODO (peter-hamilton) Convert this into a classmethod, class name can be # obtained from cls parameter that replaces self @@ -47,7 +48,11 @@ def is_oversized(self, stream): def read_tag(self, istream): # Read in the bytes for the tag tts = istream.read(self.TAG_SIZE) - tag = unpack('!I', b'\x00' + tts[0:self.TAG_SIZE])[0] + try: + tag = unpack('!I', b'\x00' + tts[0:self.TAG_SIZE])[0] + except Exception: + self.logger.error("Error reading tag value from buffer") + return enum_tag = enums.Tags(tag) @@ -102,9 +107,12 @@ def read_value(self, istream): raise NotImplementedError() def read(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): - self.read_tag(istream) - self.read_type(istream) - self.read_length(istream) + try: + self.read_tag(istream) + self.read_type(istream) + self.read_length(istream) + except Exception as e: + self.logger.warning(f"Skipping malformed field during read: {str(e)}") def write_tag(self, ostream): # Write the tag to the output stream diff --git a/kmip/services/server/barbican.py b/kmip/services/server/barbican.py index 8b8341e1..5d8d8e3c 100644 --- a/kmip/services/server/barbican.py +++ b/kmip/services/server/barbican.py @@ -116,6 +116,8 @@ def __init__(self, project_name, project_domain_name): self.project_name = project_name self.os_client = OpenstackHelper(self.region, self.user_domain_name, self.project_domain_name, self.project_name) self.api = self.os_client.api.key_manager + + self.logger = logging.getLogger('kmip.server.engine') def create_secret(self, name, payload, algorithm=None, length=None): keymgr = self.api @@ -128,8 +130,22 @@ def create_secret(self, name, payload, algorithm=None, length=None): attrs['algorithm'] = algorithm if length: attrs['bit_length'] = length - secret_ref = keymgr.create_secret(**attrs) + secret_ref = keymgr.create_secret(**attrs) + return secret_ref.secret_ref + + #SECTION - Store metadata in barbican + def create_secret_metadata(self, secret_ref, metadata): + secret_id = secret_ref.rstrip('/').split('/')[-1] + barbican_endpoint = self.os_client.api.endpoint_for(service_type='key-manager') + url = f"{barbican_endpoint}/v1/secrets/{secret_id}/metadata" + + metadata_payload = {"metadata": metadata} + _ = self.os_client.api.session.put(url, json=metadata_payload) + + self.logger.debug(f'SAPCC: Metadata Created') + + return def retrive_secret(self, url): try: diff --git a/kmip/services/server/engine.py b/kmip/services/server/engine.py index 39aff0fa..d946e6c2 100644 --- a/kmip/services/server/engine.py +++ b/kmip/services/server/engine.py @@ -139,6 +139,7 @@ def __init__(self, policies=None, database_path=None): self.os_project_name = os.environ.get("OS_PROJECT_NAME") self.os_project_domain_name = os.environ.get("OS_PROJECT_DOMAIN_NAME") self.barbican = barbican.Barbicanstore(self.os_project_name, self.os_project_domain_name) + self.netapp_metadata = {} def _get_enum_string(self, e): return ''.join([x.capitalize() for x in e.name.split('_')]) @@ -568,7 +569,17 @@ def _process_template_attribute(self, template_attribute): for attribute in template_attribute.attributes: name = attribute.attribute_name.value + if name.startswith('x-NETAPP'): + if name == 'x-NETAPP-ClusterId': + self.netapp_metadata[name] = attribute.attribute_value.value + else: + self._logger.info(f"SAPCC: ignored attribute {name}" + f"({attribute.attribute_value})") + continue + + if not self._attribute_policy.is_attribute_supported(name): + self._logger.debug("SAPCC: 1") raise exceptions.InvalidField( "The {0} attribute is unsupported.".format(name) ) @@ -889,6 +900,9 @@ def _set_attribute_on_managed_object(self, managed_object, attribute): raise exceptions.InvalidField( "Cannot set duplicate name values." ) + elif attribute_name == "x-NETAPP-ClusterId": + for value in attribute_value: + managed_object.x_netapp_cluster_id = value.value elif attribute_name == "Application Specific Information": for value in attribute_value: managed_object.app_specific_info.append( @@ -905,6 +919,7 @@ def _set_attribute_on_managed_object(self, managed_object, attribute): objects.ObjectGroup(object_group=value.value) ) else: + self._logger.debug("SAPCC: 2") # TODO (peterhamilton) Remove when all attributes are supported raise exceptions.InvalidField( "The {0} attribute is unsupported.".format(attribute_name) @@ -940,6 +955,7 @@ def _set_attribute_on_managed_object(self, managed_object, attribute): else: setattr(managed_object, field, value) else: + self._logger.debug("SAPCC: 3") # TODO (peterhamilton) Remove when all attributes are supported raise exceptions.InvalidField( "The {0} attribute is unsupported.".format(attribute_name) @@ -2009,6 +2025,16 @@ def _process_register(self, payload): managed_object._owner = self._client_identity[0] managed_object.initial_date = int(time.time()) + name = "KMIP_REGISTERED" + algorithm = managed_object.cryptographic_algorithm + length = managed_object.cryptographic_length + bburl = self.barbican.create_secret(str(name), + managed_object.value, + str(algorithm), length) + _ = self.barbican.create_secret_metadata(bburl, self.netapp_metadata) + managed_object.value = bburl.encode('utf-8') + managed_object.names = [] + self._data_session.add(managed_object) # NOTE (peterhamilton) SQLAlchemy will *not* assign an ID until @@ -2026,8 +2052,12 @@ def _process_register(self, payload): unique_identifier=str(managed_object.unique_identifier) ) + self._logger.debug(f'SAPCC: response_payload.unique_identifier - {response_payload.unique_identifier}') + self._id_placeholder = str(managed_object.unique_identifier) + self._logger.debug(f'SAPCC: _id_placeholder - {self._id_placeholder}') + return response_payload @_kmip_version_supported('1.0') @@ -2705,11 +2735,14 @@ def _process_get_attribute_list(self, payload): def _process_activate(self, payload): self._logger.info("Processing operation: Activate") - if payload.unique_identifier: + if payload.unique_identifier and payload.unique_identifier.value: + self._logger.debug(f'SAPCC: Inside if') unique_identifier = payload.unique_identifier.value else: + self._logger.debug(f'SAPCC: Inside else') unique_identifier = self._id_placeholder + self._logger.debug(f'SAPCC: unique_identifier - {unique_identifier}') managed_object = self._get_object_with_access_controls( unique_identifier, enums.Operation.ACTIVATE diff --git a/kmip/services/server/policy.py b/kmip/services/server/policy.py index 400ffdfd..148ca066 100644 --- a/kmip/services/server/policy.py +++ b/kmip/services/server/policy.py @@ -131,6 +131,24 @@ def __init__(self, version): # TODO (peterhamilton) Alphabetize these self._attribute_rule_sets = { + 'x-NETAPP-ClusterId': AttributeRuleSet( + False, # Required? False + ('client',), # Who can supply it? client + True, # Readable + True, # Writable + True, # Can be used during Create + True, # Can be used during Register + ( + enums.Operation.CREATE, + enums.Operation.REGISTER, + ), # Allowed operations + ( + enums.ObjectType.SECRET_DATA, + enums.ObjectType.OPAQUE_DATA, + enums.ObjectType.SYMMETRIC_KEY + ), # Allowed object types + contents.ProtocolVersion(1, 4) # Minimum protocol version (1.4) + ), 'Unique Identifier': AttributeRuleSet( True, ('server', ),