Exemple #1
0
def _determine_generation_type(algorithm):
    """Determines the type based on algorithm."""
    if not algorithm:
        raise sstore.SecretAlgorithmNotSupportedException(algorithm)

    symmetric_algs = crypto.PluginSupportTypes.SYMMETRIC_ALGORITHMS
    asymmetric_algs = crypto.PluginSupportTypes.ASYMMETRIC_ALGORITHMS
    if algorithm.lower() in symmetric_algs:
        return crypto.PluginSupportTypes.SYMMETRIC_KEY_GENERATION
    elif algorithm.lower() in asymmetric_algs:
        return crypto.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION
    else:
        raise sstore.SecretAlgorithmNotSupportedException(algorithm)
    def generate_asymmetric_key(self, key_spec):
        """Generate an asymmetric key pair.

        Creates KMIP attribute objects based on the given KeySpec to send to
        the server. The KMIP Secret Store currently does not support
        protecting the private key with a passphrase.

        :param key_spec: KeySpec with asymmetric algorithm and bit_length
        :returns: AsymmetricKeyMetadataDTO with the key UUIDs
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
                 KMIPSecretStoreActionNotSupported
        """
        LOG.debug("Starting asymmetric key generation with KMIP plugin")
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(key_spec.alg)

        if key_spec.alg.lower() not in ss.KeyAlgorithm.ASYMMETRIC_ALGORITHMS:
            raise ss.SecretAlgorithmNotSupportedException(key_spec.alg)

        if key_spec.passphrase:
            raise KMIPSecretStoreActionNotSupported(
                u._('KMIP plugin does not currently support protecting the '
                    'private key with a passphrase'))

        algorithm = self._get_kmip_algorithm(key_spec.alg.lower())
        length = key_spec.bit_length

        try:
            with self.client:
                LOG.debug("Opened connection to KMIP client for "
                          "asymmetric secret generation")
                public_uuid, private_uuid = self.client.create_key_pair(
                    algorithm, length)
                LOG.debug("SUCCESS: Asymmetric key pair generated with "
                          "public key uuid: %(public_uuid)s and "
                          "private key uuid: %(private_uuid)s" % {
                              'public_uuid': public_uuid,
                              'private_uuid': private_uuid
                          })
                private_key_metadata = {KMIPSecretStore.KEY_UUID: private_uuid}
                public_key_metadata = {KMIPSecretStore.KEY_UUID: public_uuid}
                passphrase_metadata = None
                return ss.AsymmetricKeyMetadataDTO(private_key_metadata,
                                                   public_key_metadata,
                                                   passphrase_metadata)
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(e)
Exemple #3
0
    def store_secret(self, secret_dto):
        """Stores a secret

        To store a secret in KMIP, the attributes must be known.

        :param secret_dto: SecretDTO of the secret to be stored
        :returns: Dictionary holding the key_uuid assigned by KMIP
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting secret storage with KMIP plugin")
        if not self.store_secret_supports(secret_dto.key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                secret_dto.key_spec.alg)

        secret_type = secret_dto.type
        object_type, key_format_type = (self._map_type_ss_to_kmip(secret_type))
        if object_type is None:
            raise KMIPSecretStoreError(
                u._('Secret object type {object_type} is '
                    'not supported').format(object_type=object_type))

        secret = self._get_kmip_secret(secret_dto)

        try:
            with self.client:
                LOG.debug("Opened connection to KMIP client")
                uuid = self.client.register(secret)
                LOG.debug("SUCCESS: Key stored with uuid: %s", uuid)
                return {KMIPSecretStore.KEY_UUID: uuid}
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
Exemple #4
0
    def generate_symmetric_key(self, key_spec):
        """Generate a symmetric key.

        Creates KMIP attribute objects based on the given KeySpec to send to
        the server.

        :param key_spec: KeySpec with symmetric algorithm and bit_length
        :returns: dictionary holding key_id returned by server
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting symmetric key generation with KMIP plugin")
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(key_spec.alg)

        if key_spec.alg.lower() not in ss.KeyAlgorithm.SYMMETRIC_ALGORITHMS:
            raise KMIPSecretStoreError(
                u._("An unsupported algorithm {algorithm} was passed to the "
                    "'generate_symmetric_key' method").format(
                        algorithm=key_spec.alg))

        algorithm = self._get_kmip_algorithm(key_spec.alg)
        try:
            with self.client:
                LOG.debug("Opened connection to KMIP client for secret " +
                          "generation")
                uuid = self.client.create(algorithm, key_spec.bit_length)
                LOG.debug("SUCCESS: Symmetric key generated with "
                          "uuid: %s", uuid)
                return {KMIPSecretStore.KEY_UUID: uuid}
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
    def generate_asymmetric_key(self, key_spec):
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                key_spec.alg)

        if key_spec.passphrase:
            raise ss.GeneratePassphraseNotSupportedException()

        try:
            private_id, public_id = self.key_manager.create_key_pair(
                self.context,
                key_spec.alg,
                key_spec.bit_length
            )

            private_key_metadata = self._meta_dict(
                private_id, key_spec.bit_length, key_spec.alg
            )

            public_key_metadata = self._meta_dict(
                public_id, key_spec.bit_length, key_spec.alg
            )

            return ss.AsymmetricKeyMetadataDTO(
                private_key_metadata,
                public_key_metadata,
                None
            )
        except Exception as e:
            LOG.exception("Error generating asymmetric key: {}".format(
                six.text_type(e)))
            raise ss.SecretGeneralException(e)
Exemple #6
0
    def generate_symmetric_key(self, key_spec, context):
        """Generate a symmetric key.

        :param key_spec: KeySpec that contains details on the type of key to
        generate
        :param context: StoreCryptoContext for secret
        :returns: a dictionary that contains metadata about the key
        """

        # Find HSM-style 'crypto' plugin.
        plugin_type = _determine_generation_type(key_spec.alg)
        if crypto.PluginSupportTypes.SYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)
        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type, key_spec.alg, key_spec.bit_length, key_spec.mode)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        # Create an encrypted datum instance and add the created cypher text.
        generate_dto = crypto.GenerateDTO(key_spec.alg, key_spec.bit_length,
                                          key_spec.mode, None)
        # Create the encrypted meta.
        response_dto = generating_plugin.generate_symmetric(
            generate_dto, kek_meta_dto, context.project_model.external_id)

        # Convert binary data into a text-based format.
        _store_secret_and_datum(context, context.secret_model, kek_datum_model,
                                response_dto)

        return None
Exemple #7
0
    def generate_symmetric_key(self, key_spec):
        """Generate a symmetric key.

        Creates KMIP attribute objects based on the given KeySpec to send to
        the server.

        :param key_spec: KeySpec with symmetric algorithm and bit_length
        :returns: dictionary holding key_id returned by server
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting symmetric key generation with KMIP plugin")
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(key_spec.alg)

        if key_spec.alg.lower() not in ss.KeyAlgorithm.SYMMETRIC_ALGORITHMS:
            raise KMIPSecretStoreError(
                u._("An unsupported algorithm {algorithm} was passed to the "
                    "'generate_symmetric_key' method").format(
                        algorithm=key_spec.alg))

        object_type = enums.ObjectType.SYMMETRIC_KEY

        algorithm = self._create_cryptographic_algorithm_attribute(
            key_spec.alg)

        usage_mask = self._create_usage_mask_attribute(object_type)

        length = self._create_cryptographic_length_attribute(
            key_spec.bit_length)

        attribute_list = [algorithm, usage_mask, length]
        template_attribute = TemplateAttribute(attributes=attribute_list)

        try:
            self.client.open()
            LOG.debug("Opened connection to KMIP client for secret " +
                      "generation")
            result = self.client.create(object_type=object_type,
                                        template_attribute=template_attribute,
                                        credential=self.credential)
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
        else:
            if result.result_status.enum == enums.ResultStatus.SUCCESS:
                LOG.debug("SUCCESS: Symmetric key generated with "
                          "uuid: %s", result.uuid.value)
                return {KMIPSecretStore.KEY_UUID: result.uuid.value}
            else:
                self._raise_secret_general_exception(result)
        finally:
            self.client.close()
            LOG.debug("Closed connection to KMIP client for secret " +
                      "generation")
Exemple #8
0
    def generate_asymmetric_key(self, key_spec, context):
        """Generates an asymmetric key.

        Returns a AsymmetricKeyMetadataDTO object containing
        metadata(s) for asymmetric key components. The metadata
        can be used to retrieve individual components of
        asymmetric key pair.
        """

        plugin_type = _determine_generation_type(key_spec.alg)
        if crypto.PluginSupportTypes.ASYMMETRIC_KEY_GENERATION != plugin_type:
            raise sstore.SecretAlgorithmNotSupportedException(key_spec.alg)

        generating_plugin = manager.get_manager().get_plugin_store_generate(
            plugin_type, key_spec.alg, key_spec.bit_length,
            project_id=context.project_model.id)

        # Find or create a key encryption key metadata.
        kek_datum_model, kek_meta_dto = _find_or_create_kek_objects(
            generating_plugin, context.project_model)

        generate_dto = crypto.GenerateDTO(key_spec.alg,
                                          key_spec.bit_length,
                                          None, key_spec.passphrase)

        # Create the encrypted meta.
        private_key_dto, public_key_dto, passwd_dto = (
            generating_plugin.generate_asymmetric(
                generate_dto, kek_meta_dto, context.project_model.external_id
            )
        )

        _store_secret_and_datum(
            context,
            context.private_secret_model,
            kek_datum_model,
            private_key_dto)

        _store_secret_and_datum(
            context,
            context.public_secret_model,
            kek_datum_model,
            public_key_dto)

        if key_spec.passphrase and passwd_dto:
            _store_secret_and_datum(
                context,
                context.passphrase_secret_model,
                kek_datum_model,
                passwd_dto)

        return sstore.AsymmetricKeyMetadataDTO()
    def store_secret(self, secret_dto):
        if not self.store_secret_supports(secret_dto.key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                secret_dto.key_spec.alg)

        try:
            secret_ref = self.key_manager.store(
                self.context,
                opaque_data.OpaqueData(secret_dto.secret)
            )
            return {CastellanSecretStore.KEY_ID: secret_ref}
        except Exception as e:
            LOG.exception("Error storing secret: {}".format(
                six.text_type(e)))
            raise ss.SecretGeneralException(e)
 def generate_symmetric_key(self, key_spec):
     if not self.generate_supports(key_spec):
         raise ss.SecretAlgorithmNotSupportedException(
             key_spec.alg)
     try:
         secret_ref = self.key_manager.create_key(
             self.context,
             key_spec.alg,
             key_spec.bit_length
         )
         return {CastellanSecretStore.KEY_ID: secret_ref}
     except Exception as e:
         LOG.exception("Error generating symmetric key: {}".format(
             six.text_type(e)))
         raise ss.SecretGeneralException(e)
 def store_secret(self, secret_dto):
     if not self.store_secret_supports(secret_dto.key_spec):
         raise ss.SecretAlgorithmNotSupportedException(
             secret_dto.key_spec.alg)
     plaintext = base64.b64decode(secret_dto.secret)
     try:
         secret_id = self.key_manager.store(
             self.context,
             opaque_data.OpaqueData(plaintext)
         )
         return self._meta_dict(secret_id)
     except Exception as e:
         LOG.exception("Error storing secret: {}".format(
             six.text_type(e)))
         raise ss.SecretGeneralException(e)
Exemple #12
0
    def store_secret(self, secret_dto):
        """Stores a secret

        To store a secret in KMIP, the attributes must be known.

        :param secret_dto: SecretDTO of the secret to be stored
        :returns: Dictionary holding the key_uuid assigned by KMIP
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting secret storage with KMIP plugin")
        if not self.store_secret_supports(secret_dto.key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                secret_dto.key_spec.alg)

        secret_type = secret_dto.type
        object_type, key_format_type = (self._map_type_ss_to_kmip(secret_type))
        if object_type is None:
            raise KMIPSecretStoreError(
                u._('Secret object type {object_type} is '
                    'not supported').format(object_type=object_type))

        usage_mask = self._create_usage_mask_attribute(object_type)
        attribute_list = [usage_mask]
        template_attribute = TemplateAttribute(attributes=attribute_list)
        secret = self._get_kmip_secret(secret_dto)

        try:
            self.client.open()
            LOG.debug("Opened connection to KMIP client for secret storage")
            result = self.client.register(
                object_type=object_type,
                template_attribute=template_attribute,
                secret=secret,
                credential=self.credential)
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
        else:
            if result.result_status.enum == enums.ResultStatus.SUCCESS:
                LOG.debug("SUCCESS: Key stored with uuid: %s",
                          result.uuid.value)
                return {KMIPSecretStore.KEY_UUID: result.uuid.value}
            else:
                self._raise_secret_general_exception(result)
        finally:
            self.client.close()
            LOG.debug("Closed connection to KMIP client for secret storage")
    def generate_asymmetric_key(self, key_spec):
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                key_spec.alg)

        if key_spec.passphrase:
            raise ss.GeneratePassphraseNotSupportedException()

        try:
            private_ref, public_ref = self.key_manager.create_key_pair(
                self.context,
                key_spec.alg,
                key_spec.bit_length
            )

            private_key_metadata = {
                CastellanSecretStore.ALG: key_spec.alg,
                CastellanSecretStore.BIT_LENGTH: key_spec.bit_length,
                CastellanSecretStore.KEY_ID: private_ref
            }

            public_key_metadata = {
                CastellanSecretStore.ALG: key_spec.alg,
                CastellanSecretStore.BIT_LENGTH: key_spec.bit_length,
                CastellanSecretStore.KEY_ID: public_ref
            }

            return ss.AsymmetricKeyMetadataDTO(
                private_key_metadata,
                public_key_metadata,
                None
            )
        except Exception as e:
            LOG.exception("Error generating asymmetric key: {}".format(
                six.text_type(e)))
            raise ss.SecretGeneralException(e)
Exemple #14
0
    def get_secret(self, secret_type, secret_metadata):
        """Retrieve a secret from the KRA

        The secret_metadata is simply the dict returned by a store_secret() or
        get_secret() call.  We will extract the key_id from this dict.

        Note: There are two ways to retrieve secrets from the KRA.

        The first method calls retrieve_key without a wrapping key.  This
        relies on the KRA client to generate a wrapping key (and wrap it with
        the KRA transport cert), and is completely transparent to the
        Barbican server.  What is returned to the caller is the
        unencrypted secret.

        The second way is to provide a wrapping key that would be generated
        on the barbican client.  That way only the client will be
        able to unwrap the secret.  This wrapping key is provided in the
        secret_metadata by Barbican core.

        Format/Type of the secret returned in the SecretDTO object.
        -----------------------------------------------------------
        The type of the secret returned is always dependent on the way it is
        stored using the store_secret method.

        In case of strings - like passphrase/PEM strings, the return will be a
        string.

        In case of binary data - the return will be the actual binary data.

        In case of retrieving an asymmetric key that is generated using the
        dogtag plugin, then the binary representation of, the asymmetric key in
        PEM format, is returned
        """
        key_id = secret_metadata[DogtagKRAPlugin.KEY_ID]

        key_spec = sstore.KeySpec(
            alg=secret_metadata.get(DogtagKRAPlugin.ALG, None),
            bit_length=secret_metadata.get(DogtagKRAPlugin.BIT_LENGTH, None),
            mode=secret_metadata.get(DogtagKRAPlugin.SECRET_MODE, None),
            passphrase=None)

        generated = secret_metadata.get(DogtagKRAPlugin.GENERATED, False)

        passphrase = self._get_passphrase_for_a_private_key(
            secret_type, secret_metadata, key_spec)

        recovered_key = None
        twsk = DogtagKRAPlugin._get_trans_wrapped_session_key(
            secret_type, secret_metadata)

        if DogtagKRAPlugin.CONVERT_TO_PEM in secret_metadata:
            # Case for returning the asymmetric keys generated in KRA.
            # Asymmetric keys generated in KRA are not generated in PEM format.
            # This marker DogtagKRAPlugin.CONVERT_TO_PEM is set in the
            # secret_metadata for asymmetric keys generated in KRA to
            # help convert the returned private/public keys to PEM format and
            # eventually return the binary data of the keys in PEM format.

            if secret_type == sstore.SecretType.PUBLIC:
                # Public key should be retrieved using the get_key_info method
                # as it is treated as an attribute of the asymmetric key pair
                # stored in the KRA database.

                if key_spec.alg is None:
                    raise sstore.SecretAlgorithmNotSupportedException('None')

                key_info = self.keyclient.get_key_info(key_id)
                if key_spec.alg.upper() == key.KeyClient.RSA_ALGORITHM:
                    recovered_key = (RSA.importKey(
                        key_info.public_key).publickey().exportKey('PEM')
                                     ).encode('utf-8')
                elif key_spec.alg.upper() == key.KeyClient.DSA_ALGORITHM:
                    pub_seq = asn1.DerSequence()
                    pub_seq[:] = key_info.public_key
                    recovered_key = (("%s\n%s%s" %
                                      (DogtagKRAPlugin.DSA_PUBLIC_KEY_HEADER,
                                       pub_seq.encode().encode("base64"),
                                       DogtagKRAPlugin.DSA_PUBLIC_KEY_FOOTER)
                                      ).encode('utf-8'))
                else:
                    raise sstore.SecretAlgorithmNotSupportedException(
                        key_spec.alg.upper())

            elif secret_type == sstore.SecretType.PRIVATE:
                key_data = self.keyclient.retrieve_key(key_id)
                if key_spec.alg.upper() == key.KeyClient.RSA_ALGORITHM:
                    recovered_key = ((RSA.importKey(key_data.data).exportKey(
                        'PEM', passphrase, 8)).encode('utf-8'))
                elif key_spec.alg.upper() == key.KeyClient.DSA_ALGORITHM:
                    pub_seq = asn1.DerSequence()
                    pub_seq[:] = key_data.data
                    recovered_key = (("%s\n%s%s" %
                                      (DogtagKRAPlugin.DSA_PRIVATE_KEY_HEADER,
                                       pub_seq.encode().encode("base64"),
                                       DogtagKRAPlugin.DSA_PRIVATE_KEY_FOOTER)
                                      ).encode('utf-8'))
                else:
                    raise sstore.SecretAlgorithmNotSupportedException(
                        key_spec.alg.upper())
        else:
            # TODO(alee-3) send transport key as well when dogtag client API
            # changes in case the transport key has changed.
            key_data = self.keyclient.retrieve_key(key_id, twsk)
            if twsk:
                # The data returned is a byte array.
                recovered_key = key_data.encrypted_data
            else:
                recovered_key = key_data.data

        # TODO(alee) remove final field when content_type is removed
        # from secret_dto

        if generated:
            recovered_key = base64.b64encode(recovered_key)

        ret = sstore.SecretDTO(type=secret_type,
                               secret=recovered_key,
                               key_spec=key_spec,
                               content_type=None,
                               transport_key=None)

        return ret
Exemple #15
0
    def generate_asymmetric_key(self, key_spec):
        """Generate an asymmetric key pair.

        Creates KMIP attribute objects based on the given KeySpec to send to
        the server. The KMIP Secret Store currently does not support
        protecting the private key with a passphrase.

        :param key_spec: KeySpec with asymmetric algorithm and bit_length
        :returns: AsymmetricKeyMetadataDTO with the key UUIDs
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting asymmetric key generation with KMIP plugin")
        if not self.generate_supports(key_spec):
            raise ss.SecretAlgorithmNotSupportedException(key_spec.alg)

        if key_spec.alg.lower() not in ss.KeyAlgorithm.ASYMMETRIC_ALGORITHMS:
            raise KMIPSecretStoreError(
                u._("An unsupported algorithm {algorithm} was passed to "
                    "the 'generate_asymmetric_key' method").format(
                        algorithm=key_spec.alg))

        if key_spec.passphrase:
            raise KMIPSecretStoreError(
                u._('KMIP plugin does not currently support protecting the '
                    'private key with a passphrase'))

        algorithm = self._create_cryptographic_algorithm_attribute(
            key_spec.alg)

        length = self._create_cryptographic_length_attribute(
            key_spec.bit_length)

        attributes = [algorithm, length]
        common = CommonTemplateAttribute(attributes=attributes)

        try:
            self.client.open()
            LOG.debug("Opened connection to KMIP client for asymmetric " +
                      "secret generation")
            result = self.client.create_key_pair(
                common_template_attribute=common, credential=self.credential)
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
        else:
            if result.result_status.enum == enums.ResultStatus.SUCCESS:
                LOG.debug(
                    "SUCCESS: Asymmetric key pair generated with "
                    "public key uuid: %s and private key uuid: %s",
                    result.public_key_uuid.value,
                    result.private_key_uuid.value)
                private_key_metadata = {
                    KMIPSecretStore.KEY_UUID: result.private_key_uuid.value
                }
                public_key_metadata = {
                    KMIPSecretStore.KEY_UUID: result.public_key_uuid.value
                }
                passphrase_metadata = None
                return ss.AsymmetricKeyMetadataDTO(private_key_metadata,
                                                   public_key_metadata,
                                                   passphrase_metadata)
            else:
                self._raise_secret_general_exception(result)
        finally:
            self.client.close()
            LOG.debug("Closed connection to KMIP client for asymmetric "
                      "secret generation")
Exemple #16
0
    def store_secret(self, secret_dto):
        """Stores a secret

        To store a secret in KMIP, the attributes must be known.

        :param secret_dto: SecretDTO of the secret to be stored
        :returns: Dictionary holding the key_uuid assigned by KMIP
        :raises: SecretGeneralException, SecretAlgorithmNotSupportedException
        """
        LOG.debug("Starting secret storage with KMIP plugin")
        if not self.store_secret_supports(secret_dto.key_spec):
            raise ss.SecretAlgorithmNotSupportedException(
                secret_dto.key_spec.alg)

        object_type = self._map_type_ss_to_kmip(secret_dto.type)

        algorithm_value = self._map_algorithm_ss_to_kmip(
            secret_dto.key_spec.alg)

        usage_mask = self._create_usage_mask_attribute()

        attribute_list = [usage_mask]
        template_attribute = kmip_objects.TemplateAttribute(
            attributes=attribute_list)

        secret_features = {
            'key_format_type': enums.KeyFormatType.RAW,
            'key_value': {
                'bytes': self._convert_base64_to_byte_array(secret_dto.secret)
            },
            'cryptographic_algorithm': algorithm_value,
            'cryptographic_length': secret_dto.key_spec.bit_length
        }

        secret = secrets.SecretFactory().create_secret(object_type,
                                                       secret_features)
        LOG.debug("Created secret object to be stored: %s, %s, %s",
                  secret_features.get('key_format_type'),
                  secret_features.get('cryptographic_algorithm'),
                  secret_features.get('cryptographic_length'))

        try:
            self.client.open()
            LOG.debug("Opened connection to KMIP client for secret storage")
            result = self.client.register(object_type,
                                          template_attribute,
                                          secret,
                                          self.credential)
        except Exception as e:
            LOG.exception(u._LE("Error opening or writing to client"))
            raise ss.SecretGeneralException(str(e))
        else:
            if result.result_status.enum == enums.ResultStatus.SUCCESS:
                LOG.debug("SUCCESS: Key stored with uuid: %s",
                          result.uuid.value)
                return {KMIPSecretStore.KEY_UUID: result.uuid.value}
            else:
                self._raise_secret_general_exception(result)
        finally:
            self.client.close()
            LOG.debug("Closed connection to KMIP client for secret storage")