Esempio n. 1
0
 def ValidateSignitureAndAdmin(token):
     signiture = AuthenticationHelper.ValidateSigniture(token)
     for admin in AgentUser.ListAllAdmin():
         ## TODO: which property should we use here
         if signiture["oid"].lower() == admin.ObjectId.lower():
             return "Admin"
     
     raise LunaUserException(HTTPStatus.FORBIDDEN, "Admin permission is required for this operation.")
Esempio n. 2
0
 def runProject(self,
                productName,
                deploymentName,
                apiVersion,
                operationVerb,
                userInput,
                predecessorOperationId,
                userId,
                subscriptionId,
                computeCluster="default",
                luna_config_file='luna_config.yml'):
     operationId = str('a' + uuid4().hex[1:])
     experimentName = subscriptionId
     entryPoint = self.GetOperationNameByVerb(operationVerb)
     if entryPoint:
         run_id = self._utils.RunProject(azureml_workspace=self._workspace,
                                         entry_point=entryPoint,
                                         experiment_name=experimentName,
                                         parameters={
                                             'operationId':
                                             operationId,
                                             'userId':
                                             userId,
                                             'userInput':
                                             userInput,
                                             'productName':
                                             productName,
                                             'deploymentName':
                                             deploymentName,
                                             'apiVersion':
                                             apiVersion,
                                             'subscriptionId':
                                             subscriptionId,
                                             'predecessorOperationId':
                                             predecessorOperationId
                                         },
                                         tags={
                                             'userId': userId,
                                             'productName': productName,
                                             'deploymentName':
                                             deploymentName,
                                             'apiVersion': apiVersion,
                                             'operationName': entryPoint,
                                             'subscriptionId':
                                             subscriptionId,
                                             'predecessorOperationId':
                                             predecessorOperationId,
                                             'operationId': operationId
                                         },
                                         compute_cluster=computeCluster)
     else:
         raise LunaUserException(
             HTTPStatus.NOT_FOUND,
             'Operation "{}" in not supported in current service.'.format(
                 operationVerb))
     return operationId
Esempio n. 3
0
 def ValidateSigniture(token):
     try:
         return jwt.decode(token,
             AuthenticationHelper.get_public_key(token),
             verify=True,
             algorithms=[AuthenticationHelper.get_alg(token)],
             audience=os.environ['AAD_VALID_AUDIENCES'].split(";"),
             issuer=os.environ['AAD_TOKEN_ISSUER'])
         
     except Exception as e:
         raise LunaUserException(HTTPStatus.FORBIDDEN, "The AAD token signiture is invalid.")
Esempio n. 4
0
def getInternalOffers():
    try:
        userId = request.args.get('userId')
        if not userId:
            raise LunaUserException(HTTPStatus.BAD_REQUEST,
                                    "Query parameter userId is required.")

        offers = Offer.ListInternalOffers(userId)
        return jsonify(offers), 200

    except Exception as e:
        return handleExceptions(e)
Esempio n. 5
0
def getOperationStatus(operationVerb, operationId, subscriptionId='default'):
    try:
        sub, version, workspace, apiVersion = getMetadata(subscriptionId)
        amlUtil = AzureMLUtils(workspace, version.ConfigFile)
        result = amlUtil.getOperationStatus(operationVerb, operationId,
                                            sub.Owner, sub.SubscriptionId)
        if result:
            return jsonify(result)
        else:
            raise LunaUserException(
                HTTPStatus.NOT_FOUND,
                'Object with id {} does not exist.'.format(operationId))
    except Exception as e:
        return handleExceptions(e)
Esempio n. 6
0
 def Update(subscription):
     session = Session()
     dbSubscription = session.query(APISubscription).filter_by(SubscriptionId = subscription.SubscriptionId).first()
     workspace = AMLWorkspace.Get(subscription.AMLWorkspaceName)
     if not workspace:
         raise LunaUserException(HTTPStatus.BAD_REQUEST, "The workspace {} doesn't exist or you don't have permission to access it.".format(subscription.AMLWorkspaceName))
     dbSubscription.AMLWorkspaceId = workspace.Id
     dbSubscription.AMLWorkspaceComputeClusterName = subscription.AMLWorkspaceComputeClusterName
     dbSubscription.AMLWorkspaceDeploymentTargetType = subscription.AMLWorkspaceDeploymentTargetType
     dbSubscription.AMLWorkspaceDeploymentClusterName = subscription.AMLWorkspaceDeploymentClusterName
     session.commit()
     session.close()
     # update
     return
Esempio n. 7
0
def removeAdmin(userId):
    try:
        AuthenticationHelper.ValidateSignitureAndAdmin(getToken())
        objectId = AuthenticationHelper.GetUserObjectId(getToken())
        admin = AgentUser.GetAdmin(userId)
        if not admin:
            return "The admin with user id {userId} doesn't exist.".format(
                userId=userId), 404
        if admin.ObjectId.lower() == objectId:
            raise LunaUserException(
                HTTPStatus.CONFLICT,
                "Admin cannot remove themselves from Admin list.")
        AgentUser.DeleteAdmin(userId)
        return jsonify({}), 204

    except Exception as e:
        return handleExceptions(e)
Esempio n. 8
0
    def ValidateSignitureAndUser(token, subscriptionId=None):
        signiture = AuthenticationHelper.ValidateSigniture(token)
        objectId = signiture["oid"].lower()
        for user in AgentUser.ListAllAdmin():
            ## TODO: which property should we use here
            if objectId == user.ObjectId.lower():
                return "Admin"

        ## If the subscription id is specified, validate the user permission. Otherwise, return user name directly
        if subscriptionId:
            for user in AgentUser.ListAllBySubscriptionId(subscriptionId):
                if objectId == user.ObjectId.lower():
                    return objectId

            raise LunaUserException(HTTPStatus.FORBIDDEN, "The resource doesn't exist or you don't have permission to access it.")
        else:
            return objectId
Esempio n. 9
0
    def Get(subscriptionId, objectId="Admin"):
        """ the function will should only be called in local mode, otherwise, the keys might be out of date! """
        if objectId != "Admin":
            # validate the userId
            users = AgentUser.ListAllBySubscriptionId(subscriptionId)
            if not any(user.ObjectId == objectId for user in users):
                raise LunaUserException(HTTPStatus.FORBIDDEN, "The subscription {} doesn't exist or you don't have permission to access it.".format(subscriptionId))

        session = Session()
        subscription = session.query(APISubscription).filter_by(SubscriptionId = subscriptionId).first()
        session.close()
        if not subscription:
            return None
        subscription.PrimaryKey = key_vault_helper.get_secret(subscription.PrimaryKeySecretName)
        subscription.SecondaryKey = key_vault_helper.get_secret(subscription.SecondaryKeySecretName)
        if os.environ["AGENT_MODE"] == "LOCAL" and objectId == "Admin":
            subscription.Admins = AgentUser.ListAllAdmin()
            subscription.Users = AgentUser.ListAllBySubscriptionId(subscriptionId)
            subscription.AvailablePlans = ["Basic", "Premium"]
        return subscription
Esempio n. 10
0
def addAdmin(userId):
    try:
        AuthenticationHelper.ValidateSignitureAndAdmin(getToken())
        if AgentUser.GetAdmin(userId):
            return "The admin with user id {userId} already exists.".format(
                userId=userId), 409

        if "ObjectId" not in request.json:
            raise LunaUserException(HTTPStatus.BAD_REQUEST,
                                    "The object id is required")
        user = AgentUser(**request.json)

        if user.Role != "Admin":
            return "The role of the admin user must be Admin.", 400
        if userId != user.AADUserId:
            return "The user id in request body doesn't match the user id in request url.", 400
        AgentUser.Create(user)
        return jsonify(request.json), 202

    except Exception as e:
        return handleExceptions(e)
Esempio n. 11
0
def addSubscriptionUser(subscriptionId, userId):
    try:
        AuthenticationHelper.ValidateSignitureAndAdmin(getToken())
        if AgentUser.GetUser(subscriptionId, userId):
            return "The user with user id {userId} already exists in subscription {subscriptionId}".format(
                userId=userId, subscriptionId=subscriptionId), 409

        if "ObjectId" not in request.json:
            raise LunaUserException(HTTPStatus.BAD_REQUEST,
                                    "The object id is required")

        user = AgentUser(**request.json)
        if subscriptionId != user.SubscriptionId:
            return "The subscription id in request body doesn't match the subscription id in request url.", 400
        if userId != user.AADUserId:
            return "The user id in request body doesn't match the user id in request url.", 400
        AgentUser.Create(user)
        return jsonify(request.json), 202

    except Exception as e:
        return handleExceptions(e)
Esempio n. 12
0
def getOperationOutput(operationNoun, operationId, subscriptionId='default'):

    try:
        sub, version, workspace, apiVersion = getMetadata(subscriptionId)
        amlUtil = AzureMLUtils(workspace, version.ConfigFile)
        result, outputType = amlUtil.getOperationOutput(
            operationNoun, operationId, sub.Owner, sub.SubscriptionId)
        if not result:
            raise LunaUserException(
                HTTP_Status.NOT_FOUND,
                "The specified operation didn't generate any output.")
        if outputType == "file":
            with open(result, 'rb') as bites:
                return send_file(
                    io.BytesIO(bites.read()),
                    attachment_filename='outputs_{}.zip'.format(operationId),
                    mimetype='application/zip')
        return jsonify(result)

    except Exception as e:
        return handleExceptions(e)
Esempio n. 13
0
 def getOperationStatus(self, operationVerb, operationId, userId,
                        subscriptionId):
     experimentName = subscriptionId
     exp = Experiment(self._workspace, experimentName)
     operationName = self.GetOperationNameByVerb(operationVerb)
     tags = {
         'userId': userId,
         'operationId': operationId,
         'operationName': operationName,
         'subscriptionId': subscriptionId
     }
     runs = exp.get_runs(type='azureml.PipelineRun', tags=tags)
     try:
         run = next(runs)
         result = {'operationId': operationId, 'status': run.status}
         return result
     except StopIteration:
         raise LunaUserException(
             HTTPStatus.NOT_FOUND,
             'Operation "{}" with id {} does not exist.'.format(
                 operationVerb, operationId))
Esempio n. 14
0
def getMetadata(subscriptionId, isRealTimePredict=False):

    apiVersion = request.args.get('api-version')
    if not apiVersion:
        raise LunaUserException(
            HTTPStatus.BAD_REQUEST,
            'The api-version query parameter is not provided.')

    # Verify key first if api-key is provided. Otherwise, try AAD auth
    subscriptionKey = request.headers.get('api-key')
    if subscriptionKey:
        sub = APISubscription.GetByKey(subscriptionKey)
        if not sub:
            raise LunaUserException(HTTPStatus.UNAUTHORIZED,
                                    'The api key is invalid.')
        if subscriptionId != "default" and subscriptionId.lower(
        ) != sub.SubscriptionId.lower():
            raise LunaUserException(
                HTTPStatus.UNAUTHORIZED,
                "The subscription {} doesn't exist or api key is invalid.".
                format(subscriptionId))
    else:
        objectId = AuthenticationHelper.ValidateSignitureAndUser(
            getToken(), subscriptionId)
        sub = APISubscription.Get(subscriptionId, objectId)
        if not sub:
            raise LunaUserException(
                HTTPStatus.NOT_FOUND,
                'The subscription {} does not exist.'.format(subscriptionId))

    version = APIVersion.Get(sub.ProductName, sub.DeploymentName, apiVersion,
                             sub.PublisherId)
    if not version:
        raise LunaUserException(
            HTTPStatus.NOT_FOUND,
            'The api version {} does not exist.'.format(apiVersion))

    if isRealTimePredict:
        if os.environ["AGENT_MODE"] == "LOCAL":
            raise LunaUserException(
                HTTPStatus.BAD_REQUEST,
                'Cannot call SaaS service from local agent.')
        if version.AMLWorkspaceId and version.AMLWorkspaceId != 0:
            workspace = AMLWorkspace.GetByIdWithSecrets(version.AMLWorkspaceId)
        else:
            workspace = None
    else:
        if os.environ["AGENT_MODE"] == "SAAS":
            workspace = AMLWorkspace.GetByIdWithSecrets(version.AMLWorkspaceId)
        elif os.environ["AGENT_MODE"] == "LOCAL":
            if (not sub.AMLWorkspaceId) or sub.AMLWorkspaceId == 0:
                raise LunaUserException(
                    HTTPStatus.METHOD_NOT_ALLOWED,
                    'There is not an Azure Machine Learning workspace configured for this subscription. Please contact your admin to finish the configuration.'
                    .format(version.AMLWorkspaceId))
            workspace = AMLWorkspace.GetByIdWithSecrets(sub.AMLWorkspaceId)

        if not workspace:
            raise LunaServerException(
                'The workspace with id {} is not found.'.format(
                    version.AMLWorkspaceId))

        publisher = Publisher.Get(sub.PublisherId)
        if version.VersionSourceType == 'git':
            CodeUtils.getLocalCodeFolder(
                sub.SubscriptionId, sub.ProductName, sub.DeploymentName,
                version,
                pathlib.Path(__file__).parent.absolute(),
                publisher.ControlPlaneUrl)
    return sub, version, workspace, apiVersion
Esempio n. 15
0
def getToken():
    bearerToken = request.headers.get("Authorization")
    if not bearerToken or not bearerToken.startswith("Bearer "):
        raise LunaUserException(HTTPStatus.FORBIDDEN, "AAD token is required.")
    return bearerToken.replace("Bearer ", "")