Ejemplo n.º 1
0
    def create_key(self, context, algorithm, length, expiration=None, name=None):
        """Creates a symmetric key.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param algorithm: the algorithm associated with the secret
        :param length: the bit length of the secret
        :param name: the name of the key
        :param expiration: the date the key will expire
        :return: the UUID of the new key
        :raises KeyManagerError: if key creation fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            key_order = barbican_client.orders.create_key(
                name=name, algorithm=algorithm, bit_length=length, expiration=expiration
            )
            order_ref = key_order.submit()
            order = self._get_active_order(barbican_client, order_ref)
            return self._retrieve_secret_uuid(order.secret_ref)
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            LOG.error(u._LE("Error creating key: %s"), e)
            raise exception.KeyManagerError(reason=e)
    def create_key(self,
                   context,
                   algorithm,
                   length,
                   expiration=None,
                   name=None):
        """Creates a symmetric key.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param algorithm: the algorithm associated with the secret
        :param length: the bit length of the secret
        :param name: the name of the key
        :param expiration: the date the key will expire
        :return: the UUID of the new key
        :raises KeyManagerError: if key creation fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            key_order = barbican_client.orders.create_key(
                name=name,
                algorithm=algorithm,
                bit_length=length,
                expiration=expiration)
            order_ref = key_order.submit()
            order = self._get_active_order(barbican_client, order_ref)
            return self._retrieve_secret_uuid(order.secret_ref)
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            LOG.error(u._LE("Error creating key: %s"), e)
            raise exception.KeyManagerError(reason=e)
Ejemplo n.º 3
0
    def store(self, context, managed_object, expiration=None):
        """Stores (i.e., registers) an object with the key manager.

        :param context: contains information of the user and the environment
            for the request (castellan/context.py)
        :param managed_object: a secret object with unencrypted payload.
            Known as "secret" to the barbicanclient api
        :param expiration: the expiration time of the secret in ISO 8601
            format
        :returns: the UUID of the stored object
        :raises KeyManagerError: if object store fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            secret = self._get_barbican_object(barbican_client, managed_object)
            secret.expiration = expiration
            secret_ref = secret.store()
            return self._retrieve_secret_uuid(secret_ref)
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            LOG.error(u._LE("Error storing object: %s"), e)
            raise exception.KeyManagerError(reason=e)
Ejemplo n.º 4
0
    def create_key_pair(self, context, algorithm, length, expiration=None, name=None):
        """Creates an asymmetric key pair.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param algorithm: the algorithm associated with the secret
        :param length: the bit length of the secret
        :param name: the name of the key
        :param expiration: the date the key will expire
        :return: the UUIDs of the new key, in the order (private, public)
        :raises NotImplementedError: until implemented
        :raises KeyManagerError: if key pair creation fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            key_pair_order = barbican_client.orders.create_asymmetric(
                algorithm=algorithm, bit_length=length, name=name, expiration=expiration
            )

            order_ref = key_pair_order.submit()
            order = self._get_active_order(barbican_client, order_ref)
            container = barbican_client.containers.get(order.container_ref)

            private_key_uuid = self._retrieve_secret_uuid(container.secret_refs["private_key"])
            public_key_uuid = self._retrieve_secret_uuid(container.secret_refs["public_key"])
            return private_key_uuid, public_key_uuid
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            LOG.error(u._LE("Error creating key pair: %s"), e)
            raise exception.KeyManagerError(reason=e)
Ejemplo n.º 5
0
    def get(self, context, managed_object_id):
        """Retrieves the specified managed object.

        Currently only supports retrieving symmetric keys.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param managed_object_id: the UUID of the object to retrieve
        :return: SymmetricKey representation of the key
        :raises KeyManagerError: if object retrieval fails
        :raises ManagedObjectNotFoundError: if object not found
        """
        try:
            secret = self._get_secret(context, managed_object_id)
            return self._get_castellan_object(secret)
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            LOG.error(u._LE("Error retrieving object: %s"), e)
            if self._is_secret_not_found_error(e):
                raise exception.ManagedObjectNotFoundError(uuid=managed_object_id)
            else:
                raise exception.KeyManagerError(reason=e)
Ejemplo n.º 6
0
    def _get_active_order(self, barbican_client, order_ref):
        """Returns the order when it is active.

        Barbican key creation is done asynchronously, so this loop continues
        checking until the order is active or a timeout occurs.
        """
        active_status = u'ACTIVE'
        error_status = u'ERROR'
        number_of_retries = self.conf.barbican.number_of_retries
        retry_delay = self.conf.barbican.retry_delay
        order = barbican_client.orders.get(order_ref)
        time.sleep(.25)
        for n in range(number_of_retries):
            if order.status == error_status:
                kwargs = {
                    "status": error_status,
                    "code": order.error_status_code,
                    "reason": order.error_reason
                }
                msg = u._LE("Order is in %(status)s status - status code: "
                            "%(code)s, status reason: %(reason)s") % kwargs
                LOG.error(msg)
                raise exception.KeyManagerError(reason=msg)
            if order.status != active_status:
                kwargs = {
                    'attempt': n,
                    'total': number_of_retries,
                    'status': order.status,
                    'active': active_status,
                    'delay': retry_delay
                }
                msg = u._LI("Retry attempt #%(attempt)i out of %(total)i: "
                            "Order status is '%(status)s'. Waiting for "
                            "'%(active)s', will retry in %(delay)s "
                            "seconds")
                LOG.info(msg, kwargs)
                time.sleep(retry_delay)
                order = barbican_client.orders.get(order_ref)
            else:
                return order
        msg = u._LE("Exceeded retries: Failed to find '%(active)s' status "
                    "within %(num_retries)i retries") % {
                        'active': active_status,
                        'num_retries': number_of_retries
                    }
        LOG.error(msg)
        raise exception.KeyManagerError(reason=msg)
Ejemplo n.º 7
0
    def _create_base_url(self, auth, sess, endpoint):
        if self.conf.barbican.barbican_api_version:
            api_version = self.conf.barbican.barbican_api_version
        else:
            discovery = auth.get_discovery(sess, url=endpoint)
            raw_data = discovery.raw_version_data()
            if len(raw_data) == 0:
                msg = u._LE("Could not find discovery information for %s") % endpoint
                LOG.error(msg)
                raise exception.KeyManagerError(reason=msg)
            latest_version = raw_data[-1]
            api_version = latest_version.get("id")

        base_url = urllib.parse.urljoin(endpoint, api_version)
        return base_url
    def _create_base_url(self, auth, sess, endpoint):
        if self.conf.barbican.barbican_api_version:
            api_version = self.conf.barbican.barbican_api_version
        else:
            discovery = auth.get_discovery(sess, url=endpoint)
            raw_data = discovery.raw_version_data()
            if len(raw_data) == 0:
                msg = u._LE(
                    "Could not find discovery information for %s") % endpoint
                LOG.error(msg)
                raise exception.KeyManagerError(reason=msg)
            latest_version = raw_data[-1]
            api_version = latest_version.get('id')

        base_url = urllib.parse.urljoin(endpoint, api_version)
        return base_url
    def _get_barbican_client(self, context):
        """Creates a client to connect to the Barbican service.

        :param context: the user context for authentication
        :return: a Barbican Client object
        :raises Forbidden: if the context is None
        :raises KeyManagerError: if context is missing tenant or tenant is
                                 None or error occurs while creating client
        """

        # Confirm context is provided, if not raise forbidden
        if not context:
            msg = u._("User is not authorized to use key manager.")
            LOG.error(msg)
            raise exception.Forbidden(msg)

        if not hasattr(context, 'tenant') or context.tenant is None:
            msg = u._("Unable to create Barbican Client without tenant "
                      "attribute in context object.")
            LOG.error(msg)
            raise exception.KeyManagerError(reason=msg)

        if self._barbican_client and self._current_context == context:
            return self._barbican_client

        try:
            self._current_context = context
            auth = self._get_keystone_auth(context)
            sess = session.Session(auth=auth)

            self._barbican_endpoint = self._get_barbican_endpoint(auth, sess)
            self._barbican_client = barbican_client.Client(
                session=sess, endpoint=self._barbican_endpoint)

        except Exception as e:
            LOG.error(u._LE("Error creating Barbican client: %s"), e)
            raise exception.KeyManagerError(reason=e)

        self._base_url = self._create_base_url(auth, sess,
                                               self._barbican_endpoint)

        return self._barbican_client
    def create_key_pair(self,
                        context,
                        algorithm,
                        length,
                        expiration=None,
                        name=None):
        """Creates an asymmetric key pair.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param algorithm: the algorithm associated with the secret
        :param length: the bit length of the secret
        :param name: the name of the key
        :param expiration: the date the key will expire
        :return: the UUIDs of the new key, in the order (private, public)
        :raises NotImplementedError: until implemented
        :raises KeyManagerError: if key pair creation fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            key_pair_order = barbican_client.orders.create_asymmetric(
                algorithm=algorithm,
                bit_length=length,
                name=name,
                expiration=expiration)

            order_ref = key_pair_order.submit()
            order = self._get_active_order(barbican_client, order_ref)
            container = barbican_client.containers.get(order.container_ref)

            private_key_uuid = self._retrieve_secret_uuid(
                container.secret_refs['private_key'])
            public_key_uuid = self._retrieve_secret_uuid(
                container.secret_refs['public_key'])
            return private_key_uuid, public_key_uuid
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            LOG.error(u._LE("Error creating key pair: %s"), e)
            raise exception.KeyManagerError(reason=e)
    def _get_secret(self, context, object_id):
        """Returns the metadata of the secret.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param object_id: UUID of the secret
        :return: the secret's metadata
        :raises HTTPAuthError: if object retrieval fails with 401
        :raises HTTPClientError: if object retrieval fails with 4xx
        :raises HTTPServerError: if object retrieval fails with 5xx
        """

        barbican_client = self._get_barbican_client(context)

        try:
            secret_ref = self._create_secret_ref(object_id)
            return barbican_client.secrets.get(secret_ref)
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            with excutils.save_and_reraise_exception():
                LOG.error(u._LE("Error getting secret metadata: %s"), e)
Ejemplo n.º 12
0
    def _get_barbican_client(self, context):
        """Creates a client to connect to the Barbican service.

        :param context: the user context for authentication
        :return: a Barbican Client object
        :raises Forbidden: if the context is None
        :raises KeyManagerError: if context is missing tenant or tenant is
                                 None or error occurs while creating client
        """

        # Confirm context is provided, if not raise forbidden
        if not context:
            msg = u._("User is not authorized to use key manager.")
            LOG.error(msg)
            raise exception.Forbidden(msg)

        if not hasattr(context, "tenant") or context.tenant is None:
            msg = u._("Unable to create Barbican Client without tenant " "attribute in context object.")
            LOG.error(msg)
            raise exception.KeyManagerError(reason=msg)

        if self._barbican_client and self._current_context == context:
            return self._barbican_client

        try:
            self._current_context = context
            auth = self._get_keystone_auth(context)
            sess = session.Session(auth=auth)

            self._barbican_endpoint = self._get_barbican_endpoint(auth, sess)
            self._barbican_client = barbican_client.Client(session=sess, endpoint=self._barbican_endpoint)

        except Exception as e:
            LOG.error(u._LE("Error creating Barbican client: %s"), e)
            raise exception.KeyManagerError(reason=e)

        self._base_url = self._create_base_url(auth, sess, self._barbican_endpoint)

        return self._barbican_client
    def delete(self, context, managed_object_id):
        """Deletes the specified managed object.

        :param context: contains information of the user and the environment
                     for the request (castellan/context.py)
        :param managed_object_id: the UUID of the object to delete
        :raises KeyManagerError: if key deletion fails
        :raises ManagedObjectNotFoundError: if the object could not be found
        """
        barbican_client = self._get_barbican_client(context)

        try:
            secret_ref = self._create_secret_ref(managed_object_id)
            barbican_client.secrets.delete(secret_ref)
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            LOG.error(u._LE("Error deleting object: %s"), e)
            if self._is_secret_not_found_error(e):
                raise exception.ManagedObjectNotFoundError(
                    uuid=managed_object_id)
            else:
                raise exception.KeyManagerError(reason=e)
Ejemplo n.º 14
0
    def _get_active_order(self, barbican_client, order_ref):
        """Returns the order when it is active.

        Barbican key creation is done asynchronously, so this loop continues
        checking until the order is active or a timeout occurs.
        """
        active = u"ACTIVE"
        number_of_retries = self.conf.barbican.number_of_retries
        retry_delay = self.conf.barbican.retry_delay
        order = barbican_client.orders.get(order_ref)
        time.sleep(0.25)
        for n in range(number_of_retries):
            if order.status != active:
                kwargs = {
                    "attempt": n,
                    "total": number_of_retries,
                    "status": order.status,
                    "active": active,
                    "delay": retry_delay,
                }
                msg = u._LI(
                    "Retry attempt #%(attempt)i out of %(total)i: "
                    "Order status is '%(status)s'. Waiting for "
                    "'%(active)s', will retry in %(delay)s "
                    "seconds"
                )
                LOG.info(msg, kwargs)
                time.sleep(retry_delay)
                order = barbican_client.orders.get(order_ref)
            else:
                return order
        msg = u._LE("Exceeded retries: Failed to find '%(active)s' status " "within %(num_retries)i retries") % {
            "active": active,
            "num_retries": number_of_retries,
        }
        LOG.error(msg)
        raise exception.KeyManagerError(reason=msg)
    def get(self, context, managed_object_id):
        """Retrieves the specified managed object.

        Currently only supports retrieving symmetric keys.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param managed_object_id: the UUID of the object to retrieve
        :return: SymmetricKey representation of the key
        :raises KeyManagerError: if object retrieval fails
        :raises ManagedObjectNotFoundError: if object not found
        """
        try:
            secret = self._get_secret(context, managed_object_id)
            return self._get_castellan_object(secret)
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            LOG.error(u._LE("Error retrieving object: %s"), e)
            if self._is_secret_not_found_error(e):
                raise exception.ManagedObjectNotFoundError(
                    uuid=managed_object_id)
            else:
                raise exception.KeyManagerError(reason=e)
    def store(self, context, managed_object, expiration=None):
        """Stores (i.e., registers) an object with the key manager.

        :param context: contains information of the user and the environment
            for the request (castellan/context.py)
        :param managed_object: a secret object with unencrypted payload.
            Known as "secret" to the barbicanclient api
        :param expiration: the expiration time of the secret in ISO 8601
            format
        :returns: the UUID of the stored object
        :raises KeyManagerError: if object store fails
        """
        barbican_client = self._get_barbican_client(context)

        try:
            secret = self._get_barbican_object(barbican_client, managed_object)
            secret.expiration = expiration
            secret_ref = secret.store()
            return self._retrieve_secret_uuid(secret_ref)
        except (barbican_exceptions.HTTPAuthError,
                barbican_exceptions.HTTPClientError,
                barbican_exceptions.HTTPServerError) as e:
            LOG.error(u._LE("Error storing object: %s"), e)
            raise exception.KeyManagerError(reason=e)
Ejemplo n.º 17
0
    def _get_secret(self, context, object_id):
        """Returns the metadata of the secret.

        :param context: contains information of the user and the environment
                        for the request (castellan/context.py)
        :param object_id: UUID of the secret
        :return: the secret's metadata
        :raises HTTPAuthError: if object retrieval fails with 401
        :raises HTTPClientError: if object retrieval fails with 4xx
        :raises HTTPServerError: if object retrieval fails with 5xx
        """

        barbican_client = self._get_barbican_client(context)

        try:
            secret_ref = self._create_secret_ref(object_id)
            return barbican_client.secrets.get(secret_ref)
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            with excutils.save_and_reraise_exception():
                LOG.error(u._LE("Error getting secret metadata: %s"), e)
Ejemplo n.º 18
0
    def delete(self, context, managed_object_id):
        """Deletes the specified managed object.

        :param context: contains information of the user and the environment
                     for the request (castellan/context.py)
        :param managed_object_id: the UUID of the object to delete
        :raises KeyManagerError: if key deletion fails
        :raises ManagedObjectNotFoundError: if the object could not be found
        """
        barbican_client = self._get_barbican_client(context)

        try:
            secret_ref = self._create_secret_ref(managed_object_id)
            barbican_client.secrets.delete(secret_ref)
        except (
            barbican_exceptions.HTTPAuthError,
            barbican_exceptions.HTTPClientError,
            barbican_exceptions.HTTPServerError,
        ) as e:
            LOG.error(u._LE("Error deleting object: %s"), e)
            if self._is_secret_not_found_error(e):
                raise exception.ManagedObjectNotFoundError(uuid=managed_object_id)
            else:
                raise exception.KeyManagerError(reason=e)