Beispiel #1
0
def require_auth():
    """
    Check if a request is authenticated.
    """
    check_user_credential()
    if not flask.g.user:
        raise AuthError('This endpoint requires authentication')
Beispiel #2
0
 def get_user_projects(self, user):
     if not user:
         raise AuthError('Please authenticate as a user')
     if not flask.g.user:
         flask.g.user = FederatedUser(user)
     results = (flask_sqlalchemy_session.current_session.query(
         userdatamodel.user.Project.auth_id,
         AccessPrivilege).join(AccessPrivilege.project).filter(
             AccessPrivilege.user_id == flask.g.user.id).all())
     return_res = {}
     if not results:
         raise AuthError('No project access')
     for item in results:
         dbgap_no, user_access = item
         return_res[dbgap_no] = user_access.privilege
     return return_res
Beispiel #3
0
 def authorize_and_call(program, project, *args, **kwargs):
     project_id = '{}-{}'.format(program, project)
     check_user_credential()
     # Get intersection of user's roles and requested roles
     if not set(flask.g.user.roles[project_id]) & set(roles):
         raise AuthError(
             role_error_msg(flask.g.user.username, roles, project_id))
     return func(program, project, *args, **kwargs)
Beispiel #4
0
def get_secret_key_and_user(access_key):
    hmac_keypair = (current_session.query(HMACKeyPair).filter(
        HMACKeyPair.access_key == access_key).first())
    if not hmac_keypair:
        raise AuthError(
            "Access key doesn't exist, or the key in use does not match any"
            " existing entries")
    if not hasattr(flask.g, 'user'):
        flask.g.user = FederatedUser(hmac_keypair=hmac_keypair)
    key = Fernet(bytes(flask.current_app.config['HMAC_ENCRYPTION_KEY']))
    return key.decrypt(bytes(hmac_keypair.secret_key))
Beispiel #5
0
def check_user_credential():
    try:
        username = cdis_oauth2client.get_username()
        get_user(username)
    except OAuth2Error as oauth2_error:
        try:
            verify_hmac(flask.request, 'submission', get_secret_key_and_user)
        except HMAC4Error as hmac_error:
            flask.current_app.logger.exception('Failed to verify OAuth')
            flask.current_app.logger.exception('Failed to verify hmac')
            raise AuthError(oauth2_error.message + '; ' + hmac_error.message)
Beispiel #6
0
 def check_nodes(self, nodes):
     """
     Check if user have access to all of the dids, return 403 if user
     doesn't have access on any of the file, 404 if any of the file
     is not in psqlgraph, 200 if user can access all dids
     """
     for node in nodes:
         node_acl = node.acl
         if node_acl == ['open']:
             continue
         elif node_acl == []:
             raise AuthError(
                 'Requested file %s does not allow read access' %
                 node.node_id,
                 code=403)
         else:
             if flask.g.user.token is None:
                 raise AuthError('Please specify a X-Auth-Token')
             else:
                 user_acl = (flask.g.user.get_phs_ids(self.get_role(node)))
                 if not (set(node_acl) & set(user_acl)):
                     raise AuthError("You don't have access to the data")
     return 200
Beispiel #7
0
 def get_role_by_dbgap(self, dbgap_no):
     project = (
         flask_sqlalchemy_session.current_session
         .query(userdatamodel.user.Project)
         .filter(userdatamodel.user.Project.auth_id == dbgap_no)
         .first()
     )
     if not project:
         raise InternalError("Don't have project with {0}".format(dbgap_no))
     roles = (
         flask_sqlalchemy_session.current_session
         .query(AccessPrivilege)
         .filter(AccessPrivilege.user_id == flask.g.user.id)
         .filter(AccessPrivilege.project_id == project.id)
         .first()
     )
     if not roles:
         raise AuthError("You don't have access to the data")
     return roles
Beispiel #8
0
    def file_operations(program, project, file_uuid):
        """
        Handle molecular file operations.  This will only be available once the
        user has created a file entity with GDC id ``uuid`` via the
        ``/<program>/<project>/`` endppoint.

        This endpoint is an S3 compatible endpoint as described here:
        http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectOps.html

        Supported operations:

        PUT /<program>/<project>/files/<uuid>
            Upload data using single PUT. The request body should contain
            binary data of the file

        PUT /internal/<program>/<project>/files/<uuid>/reassign
            Manually (re)assign the S3 url for a given node

        DELETE /<program>/<project>/files/<uuid>
            Delete molecular data from object storage.

        POST /<program>/<project>/files/<uuid>?uploads
            Initiate Multipart Upload.

        PUT /<program>/<project>/files/<uuid>?partNumber=PartNumber&uploadId=UploadId
            Upload Part.

        POST /<program>/<project>/files/<uuid>?uploadId=UploadId
            Complete Multipart Upload

        DELETE /<program>/<project>/files/<uuid>?uploadId=UploadId
            Abort Multipart Upload

        GET /<program>/<project>/files/<uuid>?uploadId=UploadId
            List Parts

        :param str program: |program_id|
        :param str project: |project_id|
        :param str uuid: The GDC id of the file to upload.
        :reqheader Content-Type: |reqheader_Content-Type|
        :reqheader Accept: |reqheader_Accept|
        :reqheader X-Auth-Token: |reqheader_X-Auth-Token|
        :resheader Content-Type: |resheader_Content-Type|
        :statuscode 200: Success.
        :statuscode 404: File not found.
        :statuscode 403: Unauthorized request.
        :statuscode 405: Method Not Allowed.
        :statuscode 400: Bad Request.
        """
        headers = {
            k: v
            for k, v in flask.request.headers.iteritems()
            if v and k != 'X-Auth-Token'
        }
        url = flask.request.url.split('?')
        args = url[-1] if len(url) > 1 else ''
        if flask.request.method == 'GET':
            if flask.request.args.get('uploadId'):
                action = 'list_parts'
            else:
                raise UserError('Method GET not allowed on file', code=405)
        elif flask.request.method == 'POST':
            if flask.request.args.get('uploadId'):
                action = 'complete_multipart'
            elif flask.request.args.get('uploads') is not None:
                action = 'initiate_multipart'
            else:
                action = 'upload'
        elif flask.request.method == 'PUT':
            if reassign:
                # admin only
                auth.admin_auth()
                action = 'reassign'
            elif flask.request.args.get('partNumber'):
                action = 'upload_part'
            else:
                action = 'upload'
        elif flask.request.method == 'DELETE':
            if flask.request.args.get('uploadId'):
                action = 'abort_multipart'
            else:
                action = 'delete'
        else:
            raise UserError('Unsupported file operation', code=405)


        project_id = program + '-' + project
        role = PERMISSIONS[action]
        if role not in flask.g.user.roles[project_id]:
            raise AuthError(
                "You don't have {} role to do '{}'".format(role, action)
            )

        resp = utils.proxy_request(
            project_id,
            file_uuid,
            flask.request.stream,
            args,
            headers,
            flask.request.method,
            action,
            dry_run,
        )


        if dry_run or action == 'reassign':
            return resp

        return flask.Response(
            resp.read(), status=resp.status, headers=resp.getheaders(),
            mimetype='text/xml'
        )
Beispiel #9
0
def get_user(username):
    user = (current_session.query(User).filter(
        User.username == username).first())
    if not user:
        raise AuthError("User doesn't exist.")
    flask.g.user = flask.g.get('user', FederatedUser(user=user))
Beispiel #10
0
def admin_auth():
    check_user_credential()
    if not flask.g.user.user.is_admin:
        raise AuthError("You don't have admin access to perform this action")
Beispiel #11
0
    def file_operations(program, project, file_uuid):
        """
        Handle molecular file operations.  This will only be available once the
        user has created a file entity with GDC id ``uuid`` via the
        ``/<program>/<project>/`` endppoint.

        This endpoint is an S3 compatible endpoint as described here:
        http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectOps.html

        Supported operations:

        PUT /<program>/<project>/files/<uuid>
            Upload data using single PUT. The request body should contain
            binary data of the file

        PUT /internal/<program>/<project>/files/<uuid>/reassign
            Manually (re)assign the S3 url for a given node

        DELETE /<program>/<project>/files/<uuid>
            Delete molecular data from object storage.

        POST /<program>/<project>/files/<uuid>?uploads
            Initiate Multipart Upload.

        PUT /<program>/<project>/files/<uuid>?partNumber=PartNumber&uploadId=UploadId
            Upload Part.

        POST /<program>/<project>/files/<uuid>?uploadId=UploadId
            Complete Multipart Upload

        DELETE /<program>/<project>/files/<uuid>?uploadId=UploadId
            Abort Multipart Upload

        GET /<program>/<project>/files/<uuid>?uploadId=UploadId
            List Parts

        Tags:
            file

        Args:
            program (str): |program_id|
            project (str): |project_id|
            uuid (str): The GDC id of the file to upload.

        Responses:
            200: Success.
            400: Bad Request
            404: File not found.
            405: Method Not Allowed.
            403: Unauthorized request.

        :reqheader Content-Type: |reqheader_Content-Type|
        :reqheader Accept: |reqheader_Accept|
        :reqheader X-Auth-Token: |reqheader_X-Auth-Token|
        :resheader Content-Type: |resheader_Content-Type|
        """
        headers = {
            k: v
            for k, v in flask.request.headers.iteritems()
            if v and k != "X-Auth-Token"
        }
        url = flask.request.url.split("?")
        args = url[-1] if len(url) > 1 else ""
        if flask.request.method == "GET":
            if flask.request.args.get("uploadId"):
                action = "list_parts"
            else:
                raise UserError("Method GET not allowed on file", code=405)
        elif flask.request.method == "POST":
            if flask.request.args.get("uploadId"):
                action = "complete_multipart"
            elif flask.request.args.get("uploads") is not None:
                action = "initiate_multipart"
            else:
                action = "upload"
        elif flask.request.method == "PUT":
            if reassign:
                # admin only
                auth.current_user.require_admin()
                action = "reassign"
            elif flask.request.args.get("partNumber"):
                action = "upload_part"
            else:
                action = "upload"
        elif flask.request.method == "DELETE":
            if flask.request.args.get("uploadId"):
                action = "abort_multipart"
            else:
                action = "delete"
        else:
            raise UserError("Unsupported file operation", code=405)

        project_id = program + "-" + project
        role = PERMISSIONS[action]
        roles = auth.get_program_project_roles(*project_id.split("-", 1))
        if role not in roles:
            raise AuthError("You don't have {} role to do '{}'".format(
                role, action))

        resp = utils.proxy_request(
            project_id,
            file_uuid,
            flask.request.stream,
            args,
            headers,
            flask.request.method,
            action,
            dry_run,
        )

        if dry_run or action == "reassign":
            return resp

        return flask.Response(
            resp.read(),
            status=resp.status,
            headers=resp.getheaders(),
            mimetype="text/xml",
        )