Warning

This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.webapps.galaxy.api.cloudauthz

"""
API operations on defining cloud authorizations.

Through means of cloud authorization a user is able to grant a Galaxy server a secure access to his/her
cloud-based resources without sharing his/her long-lasting credentials.

User provides a provider-specific configuration, which Galaxy users to request temporary credentials
from the provider to access the user's resources.
"""

import logging

from galaxy.exceptions import (
    ActionInputError,
    InternalServerError,
    MalformedId,
    RequestParameterInvalidException,
    RequestParameterMissingException
)
from galaxy.managers import cloudauthzs
from galaxy.util import unicodify
from galaxy.web import (
    expose_api
)
from galaxy.webapps.base.controller import BaseAPIController

log = logging.getLogger(__name__)


[docs]class CloudAuthzController(BaseAPIController): """ RESTfull controller for defining cloud authorizations. """
[docs] def __init__(self, app): super(CloudAuthzController, self).__init__(app) self.cloudauthz_manager = cloudauthzs.CloudAuthzManager(app) self.cloudauthz_serializer = cloudauthzs.CloudAuthzsSerializer(app) self.cloudauthz_deserializer = cloudauthzs.CloudAuthzsDeserializer(app)
[docs] @expose_api def index(self, trans, **kwargs): """ * GET /api/cloud/authz Lists all the cloud authorizations user has defined. :type trans: galaxy.web.framework.webapp.GalaxyWebTransaction :param trans: Galaxy web transaction :param kwargs: empty dict :rtype: list of dict :return: a list of cloud authorizations (each represented in key-value pair format) defined for the user. """ rtv = [] for cloudauthz in trans.user.cloudauthz: rtv.append(self.cloudauthz_serializer.serialize_to_view( cloudauthz, user=trans.user, trans=trans, **self._parse_serialization_params(kwargs, 'summary'))) return rtv
[docs] @expose_api def create(self, trans, payload, **kwargs): """ * POST /api/cloud/authz Request to store the payload as a cloudauthz (cloud authorization) configuration for a user. :type trans: galaxy.web.framework.webapp.GalaxyWebTransaction :param trans: Galaxy web transaction :type payload: dict :param payload: A dictionary structure containing the following keys: * provider: the cloud-based resource provider to which this configuration belongs to. * config: a dictionary containing all the configuration required to request temporary credentials from the provider. See the following page for details: https://galaxyproject.org/cloud/authnz/ * authn_id: the (encoded) ID of a third-party authentication of a user. To have this ID, user must have logged-in to this Galaxy server using third-party identity (e.g., Google), or has associated his/her Galaxy account with a third-party OIDC-based identity. See this page: https://galaxyproject.org/admin/authentication/ * description: [Optional] a brief description for this configuration. :param kwargs: empty dict :rtype: dict :return: a dictionary with the following kvp: * status: HTTP response code * message: A message complementary to the response code. """ msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to create cloudauthz config because of {}." if not isinstance(payload, dict): raise ActionInputError('Invalid payload data type. The payload is expected to be a dictionary, but ' 'received data of type `{}`.'.format(str(type(payload)))) missing_arguments = [] provider = payload.get('provider', None) if provider is None: missing_arguments.append('provider') config = payload.get('config', None) if config is None: missing_arguments.append('config') authn_id = payload.get('authn_id', None) if authn_id is None: missing_arguments.append('authn_id') if len(missing_arguments) > 0: log.debug(msg_template.format("missing required config {}".format(missing_arguments))) raise RequestParameterMissingException('The following required arguments are missing in the payload: ' '{}'.format(missing_arguments)) description = payload.get("description", "") if not isinstance(config, dict): log.debug(msg_template.format("invalid config type `{}`, expect `dict`".format(type(config)))) raise RequestParameterInvalidException('Invalid type for the required `config` variable; expect `dict` ' 'but received `{}`.'.format(type(config))) try: authn_id = self.decode_id(authn_id) except Exception: log.debug(msg_template.format("cannot decode authn_id `" + str(authn_id) + "`")) raise MalformedId('Invalid `authn_id`!') try: trans.app.authnz_manager.can_user_assume_authn(trans, authn_id) except Exception as e: raise e # No two authorization configuration with # exact same key/value should exist. for ca in trans.user.cloudauthzs: if ca.equals(trans.user.id, provider, authn_id, config): log.debug("Rejected user `{}`'s request to create cloud authorization because a similar config " "already exists.".format(trans.user.id)) raise ActionInputError("A similar cloud authorization configuration is already defined.") try: new_cloudauthz = self.cloudauthz_manager.create( user_id=trans.user.id, provider=provider, config=config, authn_id=authn_id, description=description ) view = self.cloudauthz_serializer.serialize_to_view(new_cloudauthz, trans=trans, **self._parse_serialization_params(kwargs, 'summary')) log.debug('Created a new cloudauthz record for the user id `{}` '.format(str(trans.user.id))) trans.response.status = '200' return view except Exception as e: log.exception(msg_template.format("exception while creating the new cloudauthz record")) raise InternalServerError('An unexpected error has occurred while responding to the create request of the ' 'cloudauthz API.' + unicodify(e))
[docs] @expose_api def delete(self, trans, encoded_authz_id, **kwargs): """ * DELETE /api/cloud/authz/{encoded_authz_id} Deletes the CloudAuthz record with the given ``encoded_authz_id`` from database. :type trans: galaxy.web.framework.webapp.GalaxyWebTransaction :param trans: Galaxy web transaction :type encoded_authz_id: string :param encoded_authz_id: The encoded ID of the CloudAuthz record to be marked deleted. :rtype JSON :return The cloudauthz record marked as deleted, serialized as a JSON object. """ msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to delete cloudauthz config because of {}." try: authz_id = self.decode_id(encoded_authz_id) except Exception: log.debug(msg_template.format("cannot decode authz_id `" + str(encoded_authz_id) + "`")) raise MalformedId('Invalid `authz_id`!') try: cloudauthz = trans.app.authnz_manager.try_get_authz_config(trans.sa_session, trans.user.id, authz_id) trans.sa_session.delete(cloudauthz) trans.sa_session.flush() log.debug('Deleted a cloudauthz record with id `{}` for the user id `{}` '.format(authz_id, str(trans.user.id))) view = self.cloudauthz_serializer.serialize_to_view(cloudauthz, trans=trans, **self._parse_serialization_params(kwargs, 'summary')) trans.response.status = '200' return view except Exception as e: log.exception(msg_template.format("exception while deleting the cloudauthz record with " "ID: `{}`.".format(encoded_authz_id))) raise InternalServerError('An unexpected error has occurred while responding to the DELETE request of the ' 'cloudauthz API.' + unicodify(e))
[docs] @expose_api def update(self, trans, encoded_authz_id, payload, **kwargs): """ * PUT /api/cloud/authz/{encoded_authz_id} Updates the values for the cloudauthz configuration with the given ``encoded_authz_id``. With this API only the following attributes of a cloudauthz configuration can be updated: `authn_id`, `provider`, `config`, `deleted`. :type trans: galaxy.web.framework.webapp.GalaxyWebTransaction :param trans: Galaxy web transaction :type encoded_authz_id: string :param encoded_authz_id: The encoded ID of the CloudAuthz record to be updated. :type payload: dict :param payload: A dictionary structure containing the attributes to modified with their new values. It can contain any number of the following attributes: * provider: the cloud-based resource provider to which this configuration belongs to. * authn_id: the (encoded) ID of a third-party authentication of a user. To have this ID, user must have logged-in to this Galaxy server using third-party identity (e.g., Google), or has associated their Galaxy account with a third-party OIDC-based identity. See this page: https://galaxyproject.org/admin/authentication/ Note: A user can associate a cloudauthz record with their own authentications only. If the given authentication with authn_id belongs to a different user, Galaxy will throw the ItemAccessibilityException exception. * config: a dictionary containing all the configuration required to request temporary credentials from the provider. See the following page for details: https://galaxyproject.org/cloud/authnz/ * deleted: a boolean type marking the specified cloudauthz as (un)deleted. """ msg_template = "Rejected user `" + str(trans.user.id) + "`'s request to delete cloudauthz config because of {}." try: authz_id = self.decode_id(encoded_authz_id) except Exception: log.debug(msg_template.format("cannot decode authz_id `" + str(encoded_authz_id) + "`")) raise MalformedId('Invalid `authz_id`!') try: cloudauthz_to_update = trans.app.authnz_manager.try_get_authz_config(trans.sa_session, trans.user.id, authz_id) self.cloudauthz_deserializer.deserialize(cloudauthz_to_update, payload, trans=trans) self.cloudauthz_serializer.serialize_to_view(cloudauthz_to_update, view='summary') return self.cloudauthz_serializer.serialize_to_view(cloudauthz_to_update, view='summary') except MalformedId as e: raise e except Exception as e: log.exception(msg_template.format("exception while updating the cloudauthz record with " "ID: `{}`.".format(encoded_authz_id))) raise InternalServerError('An unexpected error has occurred while responding to the PUT request of the ' 'cloudauthz API.' + unicodify(e))