Example #1
0
    def loggedIn(self, userService, userName=None):
        """
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        """
        uniqueId = userService.unique_id
        userService.setInUse(True)
        si = userService.getInstance()
        si.userLoggedIn(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        if userName is None:
            userName = '******'

        addEvent(userService.deployed_service, ET_LOGIN, fld1=userName, fld2=knownUserIP, fld3=serviceIp, fld4=fullUserName)

        log.doLog(userService, log.INFO, "User {0} has logged in".format(userName), log.OSMANAGER)

        log.useLog('login', uniqueId, serviceIp, userName, knownUserIP, fullUserName, userService.friendly_name, userService.deployed_service.name)

        counter = int(userService.getProperty('loginsCounter', '0')) + 1
        userService.setProperty('loginsCounter', six.text_type(counter))
Example #2
0
def webLogout(request: HttpRequest,
              exit_url: typing.Optional[str] = None) -> HttpResponse:
    """
    Helper function to clear user related data from session. If this method is not used, the session we be cleaned anyway
    by django in regular basis.
    """

    if request.user:
        authenticator = request.user.manager.getInstance()
        username = request.user.name
        exit_url = authenticator.logout(username) or exit_url
        if request.user.id != ROOT_ID:
            # Try yo invoke logout of auth
            events.addEvent(request.user.manager,
                            events.ET_LOGOUT,
                            username=request.user.name,
                            srcip=request.ip)
    else:  # No user, redirect to /
        return HttpResponseRedirect(reverse('page.login'))

    request.session.clear()
    if exit_url is None:
        exit_url = GlobalConfig.LOGIN_URL.get()
        if GlobalConfig.REDIRECT_TO_HTTPS.getBool() is True:
            exit_url = exit_url.replace('http://', 'https://')

    # Try to delete session
    response = HttpResponseRedirect(request.build_absolute_uri(exit_url))
    if authenticator:
        authenticator.webLogoutHook(username, request, response)
    return response
Example #3
0
def __registerUser(authenticator: Authenticator,
                   authInstance: AuthenticatorInstance,
                   username: str) -> typing.Optional[User]:
    """
    Check if this user already exists on database with this authenticator, if don't, create it with defaults
    This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
    authenticate will return false, if external and return true, will create a reference in database
    """
    from uds.core.util.request import getRequest

    username = authInstance.transformUsername(username)
    logger.debug('Transformed username: %s', username)

    request = getRequest()

    usr = authenticator.getOrCreateUser(username, username)
    usr.real_name = authInstance.getRealName(username)
    usr.save()
    if usr is not None and State.isActive(usr.state):
        # Now we update database groups for this user
        usr.getManager().recreateGroups(usr)
        # And add an login event
        events.addEvent(authenticator,
                        events.ET_LOGIN,
                        username=username,
                        srcip=request.ip)  # pylint: disable=maybe-no-member
        events.addEvent(authenticator,
                        events.ET_PLATFORM,
                        platform=request.os.OS,
                        browser=request.os.Browser,
                        version=request.os.Version)  # pylint: disable=maybe-no-member
        return usr

    return None
Example #4
0
    def loggedOut(self, userService, userName=None, save=True):
        '''
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        '''
        uniqueId = userService.unique_id
        userService.setInUse(False)
        si = userService.getInstance()
        si.userLoggedOut(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        addEvent(userService.deployed_service, ET_LOGOUT, fld1=userName, fld2=knownUserIP, fld3=serviceIp, fld4=fullUserName)

        log.doLog(userService, log.INFO, "User {0} has logged out", log.OSMANAGER)

        log.useLog('logout', uniqueId, serviceIp, userName, knownUserIP, fullUserName)

        if save:
            userService.save()
Example #5
0
def __registerUser(authenticator, authInstance, username):
    """
    Check if this user already exists on database with this authenticator, if don't, create it with defaults
    This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
    authenticate will return false, if external and return true, will create a reference in database
    """
    from uds.core.util.request import getRequest

    username = authInstance.transformUsername(username)
    logger.debug('Transformed username: {0}'.format(username))

    request = getRequest()

    usr = authenticator.getOrCreateUser(username, username)
    usr.real_name = authInstance.getRealName(username)
    usr.save()
    if usr is not None and State.isActive(usr.state):
        # Now we update database groups for this user
        usr.getManager().recreateGroups(usr)
        # And add an login event
        events.addEvent(authenticator, events.ET_LOGIN, username=username, srcip=request.ip)  # pylint: disable=maybe-no-member
        events.addEvent(authenticator, events.ET_PLATFORM, platform=request.os.OS, browser=request.os.Browser, version=request.os.Version)  # pylint: disable=maybe-no-member
        return usr

    return None
Example #6
0
def webLogout(request, exit_url=None):
    """
    Helper function to clear user related data from session. If this method is not used, the session we be cleaned anyway
    by django in regular basis.
    """

    authenticator = request.user and request.user.manager.getInstance() or None
    username = request.user and request.user.name or None
    exit_url = authenticator.logout(username) or exit_url

    if request.user is not None and request.user.id != ROOT_ID:
        # Try yo invoke logout of auth
        events.addEvent(request.user.manager, events.ET_LOGOUT, username=request.user.name, srcip=request.ip)

    request.session.clear()
    if exit_url is None:
        exit_url = GlobalConfig.LOGIN_URL.get()
        if GlobalConfig.REDIRECT_TO_HTTPS.getBool() is True:
            exit_url = exit_url.replace('http://', 'https://')

    # Try to delete session
    response = HttpResponseRedirect(request.build_absolute_uri(exit_url))
    if authenticator:
        authenticator.webLogoutHook(username, request, response)
    return response
Example #7
0
def getService(request, idService, idTransport, doTest=True):
    kind, idService = idService[0], idService[1:]

    logger.debug('Kind of service: {0}, idService: {1}'.format(kind, idService))
    if kind == 'A':  # This is an assigned service
        logger.debug('Getting A service {}'.format(idService))
        ads = UserService.objects.get(uuid=idService)
        ads.deployed_service.validateUser(request.user)
    else:
        ds = DeployedService.objects.get(uuid=idService)
        # We first do a sanity check for this, if the user has access to this service
        # If it fails, will raise an exception
        ds.validateUser(request.user)
        # Now we have to locate an instance of the service, so we can assign it to user.
        ads = UserServiceManager.manager().getAssignationForUser(ds, request.user)

    if ads.isInMaintenance() is True:
        raise ServiceInMaintenanceMode()

    logger.debug('Found service: {0}'.format(ads))
    trans = Transport.objects.get(uuid=idTransport)

    # Ensures that the transport is allowed for this service
    if trans not in ads.deployed_service.transports.all():
        raise InvalidServiceException()

    # If transport is not available for the request IP...
    if trans.validForIp(request.ip) is False:
        raise InvalidServiceException()

    if doTest is False:
        return (None, ads, None, trans, None)

    # Test if the service is ready
    if ads.isReady():
        log.doLog(ads, log.INFO, "User {0} from {1} has initiated access".format(request.user.name, request.ip), log.WEB)
        # If ready, show transport for this service, if also ready ofc
        iads = ads.getInstance()
        ip = iads.getIp()
        events.addEvent(ads.deployed_service, events.ET_ACCESS, username=request.user.name, srcip=request.ip, dstip=ip, uniqueid=ads.unique_id)
        if ip is not None:
            itrans = trans.getInstance()
            if itrans.isAvailableFor(ip):
                ads.setConnectionSource(request.ip, 'unknown')
                log.doLog(ads, log.INFO, "User service ready", log.WEB)
                UserServiceManager.manager().notifyPreconnect(ads, itrans.processedUser(ads, request.user), itrans.protocol)
                return (ip, ads, iads, trans, itrans)
            else:
                log.doLog(ads, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
                logger.debug('Transport is not ready for user service {0}'.format(ads))
        else:
            logger.debug('Ip not available from user service {0}'.format(ads))
    else:
        log.doLog(ads, log.WARN, "User {0} from {1} tried to access, but machine was not ready".format(request.user.name, request.ip), log.WEB)

    return None
Example #8
0
    def loggedOut(self, userService, userName=None, save=True):
        """
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        """
        counter = int(userService.getProperty('loginsCounter', '0'))
        if counter > 0:
            counter -= 1
        userService.setProperty('loginsCounter', six.text_type(counter))

        if GlobalConfig.EXCLUSIVE_LOGOUT.getBool(True) is True:
            if counter > 0:
                return

        uniqueId = userService.unique_id
        userService.setInUse(False)
        si = userService.getInstance()
        si.userLoggedOut(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        if userName is None:
            userName = '******'

        addEvent(userService.deployed_service,
                 ET_LOGOUT,
                 fld1=userName,
                 fld2=knownUserIP,
                 fld3=serviceIp,
                 fld4=fullUserName)

        log.doLog(userService, log.INFO,
                  "User {0} has logged out".format(userName), log.OSMANAGER)

        log.useLog('logout', uniqueId, serviceIp, userName, knownUserIP,
                   fullUserName, userService.friendly_name,
                   userService.deployed_service.name)

        if save:
            userService.save()
Example #9
0
    def loggedOut(self,
                  userService: 'UserService',
                  userName: typing.Optional[str] = None) -> None:
        """
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        """
        counter = int(
            typing.cast(str, userService.getProperty('loginsCounter', '0')))
        if counter > 0:
            counter -= 1
        userService.setProperty('loginsCounter', str(counter))

        if GlobalConfig.EXCLUSIVE_LOGOUT.getBool(True) and counter > 0:
            return

        uniqueId = userService.unique_id
        userService.setInUse(False)
        userServiceInstance = userService.getInstance()
        userServiceInstance.userLoggedOut(userName or 'unknown')
        userService.updateData(userServiceInstance)

        serviceIp = userServiceInstance.getIp()

        fullUserName = '******'
        if userService.user:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        userName = userName or 'unknown'

        addEvent(userService.deployed_service,
                 ET_LOGOUT,
                 fld1=userName,
                 fld2=knownUserIP,
                 fld3=serviceIp,
                 fld4=fullUserName)

        log.doLog(userService, log.INFO,
                  "User {0} has logged out".format(userName), log.OSMANAGER)

        log.useLog('logout', uniqueId, serviceIp, userName, knownUserIP,
                   fullUserName, userService.friendly_name,
                   userService.deployed_service.name)
Example #10
0
def webLogout(request, exit_url=None):
    '''
    Helper function to clear user related data from session. If this method is not used, the session we be cleaned anyway
    by django in regular basis.
    '''
    # Invoke exit for authenticator

    if request.user is not None and request.user.id != ROOT_ID:
        events.addEvent(request.user.manager, events.ET_LOGOUT, username=request.user.name, srcip=request.ip)

    request.session.clear()
    if exit_url is None:
        exit_url = GlobalConfig.LOGIN_URL.get()
        if GlobalConfig.REDIRECT_TO_HTTPS.getBool() is True:
            exit_url = exit_url.replace('http://', 'https://')

    # Try to delete session
    return HttpResponseRedirect(request.build_absolute_uri(exit_url))
Example #11
0
def webLogout(request, exit_url=None):
    '''
    Helper function to clear user related data from session. If this method is not used, the session we be cleaned anyway
    by django in regular basis.
    '''
    # Invoke exit for authenticator

    if request.user.id != ROOT_ID:
        events.addEvent(request.user.manager, events.ET_LOGOUT, username=request.user.name, srcip=request.ip)

    request.session.clear()
    if exit_url is None:
        exit_url = GlobalConfig.LOGIN_URL.get()
        if GlobalConfig.REDIRECT_TO_HTTPS.getBool() is True:
            exit_url = exit_url.replace('http://', 'https://')

    # Try to delete session
    return HttpResponseRedirect(request.build_absolute_uri(exit_url))
Example #12
0
    def loggedIn(self, userService, userName=None, save=True):
        '''
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        '''
        uniqueId = userService.unique_id
        userService.setInUse(True)
        si = userService.getInstance()
        si.userLoggedIn(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        if userName is None:
            userName = '******'

        addEvent(userService.deployed_service,
                 ET_LOGIN,
                 fld1=userName,
                 fld2=knownUserIP,
                 fld3=serviceIp,
                 fld4=fullUserName)

        log.doLog(userService, log.INFO,
                  "User {0} has logged in".format(userName), log.OSMANAGER)

        log.useLog('login', uniqueId, serviceIp, userName, knownUserIP,
                   fullUserName)

        counter = int(userService.getProperty('loginsCounter', '0')) + 1
        userService.setProperty('loginsCounter', six.text_type(counter))

        if save:
            userService.save()
Example #13
0
    def loggedOut(self, userService, userName=None, save=True):
        """
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        """
        counter = int(userService.getProperty('loginsCounter', '0'))
        if counter > 0:
            counter -= 1
        userService.setProperty('loginsCounter', six.text_type(counter))

        if GlobalConfig.EXCLUSIVE_LOGOUT.getBool(True) is True:
            if counter > 0:
                return

        uniqueId = userService.unique_id
        userService.setInUse(False)
        si = userService.getInstance()
        si.userLoggedOut(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        if userName is None:
            userName = '******'

        addEvent(userService.deployed_service, ET_LOGOUT, fld1=userName, fld2=knownUserIP, fld3=serviceIp, fld4=fullUserName)

        log.doLog(userService, log.INFO, "User {0} has logged out".format(userName), log.OSMANAGER)

        log.useLog('logout', uniqueId, serviceIp, userName, knownUserIP, fullUserName, userService.friendly_name, userService.deployed_service.name)

        if save:
            userService.save()
Example #14
0
    def loggedIn(self,
                 userService: 'UserService',
                 userName: typing.Optional[str] = None) -> None:
        """
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        """
        uniqueId = userService.unique_id
        userService.setInUse(True)
        userServiceInstance = userService.getInstance()
        userServiceInstance.userLoggedIn(userName or 'unknown')
        userService.updateData(userServiceInstance)

        serviceIp = userServiceInstance.getIp()

        fullUserName = userService.user.manager.name + '\\' + userService.user.name if userService.user else 'unknown'

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        userName = userName or 'unknown'

        addEvent(userService.deployed_service,
                 ET_LOGIN,
                 fld1=userName,
                 fld2=knownUserIP,
                 fld3=serviceIp,
                 fld4=fullUserName)

        log.doLog(userService, log.INFO,
                  "User {0} has logged in".format(userName), log.OSMANAGER)

        log.useLog('login', uniqueId, serviceIp, userName, knownUserIP,
                   fullUserName, userService.friendly_name,
                   userService.deployed_service.name)

        counter = int(
            typing.cast(str, userService.getProperty('loginsCounter',
                                                     '0'))) + 1
        userService.setProperty('loginsCounter', str(counter))
Example #15
0
def __registerUser(authenticator, authInstance, username):
    '''
    Check if this user already exists on database with this authenticator, if don't, create it with defaults
    This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
    authenticate will return false, if external and return true, will create a reference in database
    '''
    from uds.core.util.request import getRequest

    username = authInstance.transformUsername(username)
    logger.debug('Transformed username: {0}'.format(username))

    usr = authenticator.getOrCreateUser(username, authInstance.getRealName(username))
    if usr is not None and State.isActive(usr.state):
        # Now we update database groups for this user
        usr.getManager().recreateGroups(usr)
        # And add an login event
        events.addEvent(authenticator, events.ET_LOGIN, username=username, srcip=getRequest().ip)  # pylint: disable=maybe-no-member
        return usr

    return None
    def getAssignationForUser(self, ds, user):
        assignedUserService = self.getExistingAssignationForUser(ds, user)
        # If has an assigned user service, returns this without any more work
        if assignedUserService is not None:
            return assignedUserService

        # Now try to locate 1 from cache already "ready" (must be usable and at level 1)
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.USABLE)[:1]
            if len(cache) > 0:
                cache = cache[0]
                cache.assignToUser(user)
                cache.save()  # Store assigned ASAP, we do not know how long assignToUser method of instance will take
            else:
                cache = None

        # Out of atomic transaction
        if cache is not None:
            logger.debug('Found a cached-ready service from {0} for user {1}, item {2}'.format(ds, user, cache))
            addEvent(ds, ET_CACHE_HIT, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.USABLE).count())
            ci = cache.getInstance()  # User Deployment instance
            ci.assignToUser(user)
            cache.updateData(ci)
            cache.save()
            return cache

        # Cache missed

        # Now find if there is a preparing one
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.PREPARING)[:1]
            if len(cache) > 0:
                cache = cache[0]
                cache.assignToUser(user)
                cache.save()
            else:
                cache = None

        # Out of atomic transaction
        if cache is not None:
            logger.debug('Found a cached-preparing service from {0} for user {1}, item {2}'.format(ds, user, cache))
            addEvent(ds, ET_CACHE_MISS, fld1=ds.cachedUserServices().filter(cache_level=services.UserDeployment.L1_CACHE, state=State.PREPARING).count())
            ci = cache.getInstance()  # User Deployment instance
            ci.assignToUser(user)
            cache.updateData(ci)
            cache.save()
            return cache

        # Can't assign directly from L2 cache... so we check if we can create e new service in the limits requested
        ty = ds.service.getType()
        if ty.usesCache is True:
            # inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
            inAssigned = ds.assignedUserServices().filter(UserServiceManager.getStateFilter()).count()
            # totalL1Assigned = inCacheL1 + inAssigned
            if inAssigned >= ds.max_srvs:  # cacheUpdater will drop necesary L1 machines, so it's not neccesary to check against inCacheL1
                raise MaxServicesReachedException()
        # Can create new service, create it
        addEvent(ds, ET_CACHE_MISS, fld1=0)
        return self.createAssignedFor(ds, user)
Example #17
0
    def loggedOut(self, userService, userName=None, save=True):
        '''
        This method:
          - Add log in event to stats
          - Sets service in use
          - Invokes userLoggedIn for user service instance
        '''
        uniqueId = userService.unique_id
        userService.setInUse(False)
        si = userService.getInstance()
        si.userLoggedOut(userName)
        userService.updateData(si)

        serviceIp = si.getIp()

        fullUserName = '******'
        if userService.user is not None:
            fullUserName = userService.user.manager.name + '\\' + userService.user.name

        knownUserIP = userService.src_ip + ':' + userService.src_hostname
        knownUserIP = knownUserIP if knownUserIP != ':' else 'unknown'

        addEvent(userService.deployed_service,
                 ET_LOGOUT,
                 fld1=userName,
                 fld2=knownUserIP,
                 fld3=serviceIp,
                 fld4=fullUserName)

        log.doLog(userService, log.INFO, "User {0} has logged out",
                  log.OSMANAGER)

        log.useLog('logout', uniqueId, serviceIp, userName, knownUserIP,
                   fullUserName)

        if save:
            userService.save()
Example #18
0
    def get(self) -> typing.MutableMapping[str, typing.Any]:
        """
        Processes get requests, currently none
        """
        logger.debug(
            'Tunnel parameters for GET: %s (%s) from %s', self._args, self._params, self._request.ip
        )

        if (
            not isTrustedSource(self._request.ip)
            or len(self._args) != 2
            or len(self._args[0]) != 48
        ):
            # Invalid requests
            raise AccessDenied()

        # Try to get ticket from DB
        try:
            user, userService, host, port, extra = models.TicketStore.get_for_tunnel(
                self._args[0]
            )
            data = {}
            if self._args[1][:4] == 'stop':
                sent, recv = self._params['sent'], self._params['recv']
                # Ensures extra exists...
                extra = extra or {}
                now = models.getSqlDatetimeAsUnix()
                totalTime = now - extra.get('b', now-1)               
                msg = f'User {user.name} stopped tunnel {extra.get("t", "")[:8]}... to {host}:{port}: u:{sent}/d:{recv}/t:{totalTime}.'
                log.doLog(user.manager, log.INFO, msg)
                log.doLog(userService, log.INFO, msg)
            else:
                if net.ipToLong(self._args[1][:32]) == 0:
                    raise Exception('Invalid from IP')
                events.addEvent(
                    userService.deployed_service,
                    events.ET_TUNNEL_ACCESS,
                    username=user.pretty_name,
                    srcip=self._args[1],
                    dstip=host,
                    uniqueid=userService.unique_id,
                )
                msg = f'User {user.name} started tunnel {self._args[0][:8]}... to {host}:{port} from {self._args[1]}.'
                log.doLog(user.manager, log.INFO, msg)
                log.doLog(userService, log.INFO, msg)
                # Generate new, notify only, ticket
                rstr = managers.cryptoManager().randomString(length=8)
                notifyTicket = models.TicketStore.create_for_tunnel(
                    userService=userService,
                    port=port,
                    host=host,
                    extra={'t': self._args[0], 'b': models.getSqlDatetimeAsUnix()},
                    validity=MAX_SESSION_LENGTH)
                data = {
                    'host': host,
                    'port': port,
                    'notify': notifyTicket
                }

            return data
        except Exception as e:
            logger.info('Ticket ignored: %s', e)
            raise AccessDenied()
Example #19
0
    def getService(  # pylint: disable=too-many-locals, too-many-branches, too-many-statements
        self,
        user: User,
        os: typing.MutableMapping,
        srcIp: str,
        idService: str,
        idTransport: str,
        doTest: bool = True,
        clientHostname: typing.Optional[str] = None
    ) -> typing.Tuple[typing.Optional[str], UserService,
                      typing.Optional['services.UserDeployment'], Transport,
                      typing.Optional[transports.Transport]]:
        """
        Get service info from user service
        """
        if idService[0] == 'M':  # Meta pool
            return self.getMeta(user, srcIp, os, idService[1:])

        userService = self.locateUserService(user, idService, create=True)

        if not userService:
            raise InvalidServiceException(
                _('Invalid service. The service is not available at this moment. Please, try later'
                  ))

        # Early log of "access try" so we can imagine what is going on
        userService.setConnectionSource(srcIp, clientHostname or srcIp)

        if userService.isInMaintenance():
            raise ServiceInMaintenanceMode()

        if not userService.deployed_service.isAccessAllowed():
            raise ServiceAccessDeniedByCalendar()

        if not idTransport:  # Find a suitable transport
            t: Transport
            for t in userService.deployed_service.transports.order_by(
                    'priority'):
                typeTrans = t.getType()
                if t.validForIp(srcIp) and typeTrans.supportsOs(
                        os['OS']) and t.validForOs(os['OS']):
                    idTransport = t.uuid
                    break

        try:
            transport: Transport = Transport.objects.get(uuid=idTransport)
        except Exception:
            raise InvalidServiceException()

        # Ensures that the transport is allowed for this service
        if userService.deployed_service.transports.filter(
                id=transport.id).count() == 0:
            raise InvalidServiceException()

        # If transport is not available for the request IP...
        if not transport.validForIp(srcIp):
            msg = _('The requested transport {} is not valid for {}').format(
                transport.name, srcIp)
            logger.error(msg)
            raise InvalidServiceException(msg)

        userName = user.name if user else 'unknown'

        if not doTest:
            # traceLogger.info('GOT service "{}" for user "{}" with transport "{}" (NOT TESTED)'.format(userService.name, userName, trans.name))
            return None, userService, None, transport, None

        serviceNotReadyCode = 0x0001
        ip = 'unknown'
        # Test if the service is ready
        if userService.isReady():
            serviceNotReadyCode = 0x0002
            log.doLog(
                userService, log.INFO,
                "User {0} from {1} has initiated access".format(
                    user.name, srcIp), log.WEB)
            # If ready, show transport for this service, if also ready ofc
            userServiceInstance = userService.getInstance()
            ip = userServiceInstance.getIp()
            userService.logIP(ip)  # Update known ip
            logger.debug('IP: %s', ip)

            if self.checkUuid(
                    userService
            ) is False:  # The service is not the expected one
                serviceNotReadyCode = 0x0004
                log.doLog(
                    userService, log.WARN,
                    "User service is not accessible due to invalid UUID (ip {0})"
                    .format(ip), log.TRANSPORT)
                logger.debug('UUID check failed for user service %s',
                             userService)
            else:
                events.addEvent(userService.deployed_service,
                                events.ET_ACCESS,
                                username=userName,
                                srcip=srcIp,
                                dstip=ip,
                                uniqueid=userService.unique_id)
                if ip:
                    serviceNotReadyCode = 0x0003
                    transportInstance = transport.getInstance()
                    if transportInstance.isAvailableFor(userService, ip):
                        # userService.setConnectionSource(srcIp, 'unknown')
                        log.doLog(userService, log.INFO, "User service ready",
                                  log.WEB)
                        self.notifyPreconnect(
                            userService,
                            transportInstance.processedUser(userService, user),
                            transportInstance.protocol)
                        traceLogger.info(
                            'READY on service "%s" for user "%s" with transport "%s" (ip:%s)',
                            userService.name, userName, transport.name, ip)
                        return ip, userService, userServiceInstance, transport, transportInstance

                    message = transportInstance.getCustomAvailableErrorMsg(
                        userService, ip)
                    log.doLog(userService, log.WARN, message, log.TRANSPORT)
                    logger.debug(
                        'Transport is not ready for user service %s: %s',
                        userService, message)
                else:
                    logger.debug('Ip not available from user service %s',
                                 userService)
        else:
            log.doLog(
                userService, log.WARN,
                "User {} from {} tried to access, but service was not ready".
                format(user.name, srcIp), log.WEB)

        traceLogger.error(
            'ERROR %s on service "%s" for user "%s" with transport "%s" (ip:%s)',
            serviceNotReadyCode, userService.name, userName, transport.name,
            ip)
        raise ServiceNotReadyError(code=serviceNotReadyCode,
                                   service=userService,
                                   transport=transport)
Example #20
0
    def getAssignationForUser(
        self, servicePool: ServicePool, user: User
    ) -> typing.Optional[UserService]:  # pylint: disable=too-many-branches
        if servicePool.service.getInstance().spawnsNew is False:
            assignedUserService = self.getExistingAssignationForUser(
                servicePool, user)
        else:
            assignedUserService = None

        # If has an assigned user service, returns this without any more work
        if assignedUserService:
            return assignedUserService

        if servicePool.isRestrained():
            raise InvalidServiceException(
                _('The requested service is restrained'))

        cache: typing.Optional[UserService] = None
        # Now try to locate 1 from cache already "ready" (must be usable and at level 1)
        with transaction.atomic():
            caches = typing.cast(
                typing.List[UserService],
                servicePool.cachedUserServices().select_for_update().filter(
                    cache_level=services.UserDeployment.L1_CACHE,
                    state=State.USABLE,
                    os_state=State.USABLE)[:1])
            if caches:
                cache = caches[0]
                # Ensure element is reserved correctly on DB
                if servicePool.cachedUserServices().select_for_update().filter(
                        user=None, uuid=typing.cast(
                            UserService, cache).uuid).update(
                                user=user, cache_level=0) != 1:
                    cache = None
            else:
                cache = None

        # Out of previous atomic
        if not cache:
            with transaction.atomic():
                caches = typing.cast(
                    typing.List[UserService],
                    servicePool.cachedUserServices().select_for_update().
                    filter(cache_level=services.UserDeployment.L1_CACHE,
                           state=State.USABLE)[:1])
                if cache:
                    cache = caches[0]
                    if servicePool.cachedUserServices().select_for_update(
                    ).filter(user=None,
                             uuid=typing.cast(UserService, cache).uuid).update(
                                 user=user, cache_level=0) != 1:
                        cache = None
                else:
                    cache = None

        # Out of atomic transaction
        if cache:
            # Early assign
            cache.assignToUser(user)

            logger.debug(
                'Found a cached-ready service from %s for user %s, item %s',
                servicePool, user, cache)
            events.addEvent(servicePool,
                            events.ET_CACHE_HIT,
                            fld1=servicePool.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.USABLE).count())
            return cache

        # Cache missed

        # Now find if there is a preparing one
        with transaction.atomic():
            caches = servicePool.cachedUserServices().select_for_update(
            ).filter(cache_level=services.UserDeployment.L1_CACHE,
                     state=State.PREPARING)[:1]
            if caches:
                cache = caches[0]
                if servicePool.cachedUserServices().select_for_update().filter(
                        user=None, uuid=typing.cast(
                            UserService, cache).uuid).update(
                                user=user, cache_level=0) != 1:
                    cache = None
            else:
                cache = None

        # Out of atomic transaction
        if cache:
            cache.assignToUser(user)

            logger.debug(
                'Found a cached-preparing service from %s for user %s, item %s',
                servicePool, user, cache)
            events.addEvent(servicePool,
                            events.ET_CACHE_MISS,
                            fld1=servicePool.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.PREPARING).count())
            return cache

        # Can't assign directly from L2 cache... so we check if we can create e new service in the limits requested
        serviceType = servicePool.service.getType()
        if serviceType.usesCache:
            # inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
            inAssigned = servicePool.assignedUserServices().filter(
                UserServiceManager.getStateFilter()).count()
            # totalL1Assigned = inCacheL1 + inAssigned
            if inAssigned >= servicePool.max_srvs:  # cacheUpdater will drop unnecesary L1 machines, so it's not neccesary to check against inCacheL1
                log.doLog(
                    servicePool, log.WARN,
                    'Max number of services reached: {}'.format(
                        servicePool.max_srvs), log.INTERNAL)
                raise MaxServicesReachedError()

        # Can create new service, create it
        events.addEvent(servicePool, events.ET_CACHE_MISS, fld1=0)
        return self.createAssignedFor(servicePool, user)
Example #21
0
    def getService(self, user, srcIp, idService, idTransport, doTest=True):
        """
        Get service info from
        """
        userService = self.locateUserService(user, idService, create=True)

        # Early log of "access try" so we can imagine what is going on
        userService.setConnectionSource(srcIp, 'unknown')

        if userService.isInMaintenance() is True:
            raise ServiceInMaintenanceMode()

        if userService.deployed_service.isAccessAllowed() is False:
            raise ServiceAccessDeniedByCalendar()

        if idTransport is None or idTransport == '':  # Find a suitable transport
            for v in userService.deployed_service.transports.order_by(
                    'priority'):
                if v.validForIp(srcIp):
                    idTransport = v.uuid
                    break

        try:
            trans = Transport.objects.get(uuid=idTransport)
        except Exception:
            raise InvalidServiceException()

        # Ensures that the transport is allowed for this service
        if trans not in userService.deployed_service.transports.all():
            raise InvalidServiceException()

        # If transport is not available for the request IP...
        if trans.validForIp(srcIp) is False:
            msg = 'The requested transport {} is not valid for {}'.format(
                trans.name, srcIp)
            logger.error(msg)
            raise InvalidServiceException(msg)

        if user is not None:
            userName = user.name
        else:
            userName = '******'

        if doTest is False:
            # traceLogger.info('GOT service "{}" for user "{}" with transport "{}" (NOT TESTED)'.format(userService.name, userName, trans.name))
            return None, userService, None, trans, None

        serviceNotReadyCode = 0x0001
        ip = 'unknown'
        # Test if the service is ready
        if userService.isReady():
            serviceNotReadyCode = 0x0002
            log.doLog(
                userService, log.INFO,
                "User {0} from {1} has initiated access".format(
                    user.name, srcIp), log.WEB)
            # If ready, show transport for this service, if also ready ofc
            iads = userService.getInstance()
            ip = iads.getIp()
            userService.logIP(ip)  # Update known ip

            if self.checkUuid(
                    userService) is False:  # Machine is not what is expected
                serviceNotReadyCode = 0x0004
                log.doLog(userService, log.WARN,
                          "User service is not accessible (ip {0})".format(ip),
                          log.TRANSPORT)
                logger.debug(
                    'Transport is not ready for user service {0}'.format(
                        userService))
            else:
                events.addEvent(userService.deployed_service,
                                events.ET_ACCESS,
                                username=userName,
                                srcip=srcIp,
                                dstip=ip,
                                uniqueid=userService.unique_id)
                if ip is not None:
                    serviceNotReadyCode = 0x0003
                    itrans = trans.getInstance()
                    if itrans.isAvailableFor(userService, ip):
                        # userService.setConnectionSource(srcIp, 'unknown')
                        log.doLog(userService, log.INFO, "User service ready",
                                  log.WEB)
                        self.notifyPreconnect(
                            userService,
                            itrans.processedUser(userService,
                                                 user), itrans.protocol)
                        traceLogger.info(
                            'READY on service "{}" for user "{}" with transport "{}" (ip:{})'
                            .format(userService.name, userName, trans.name,
                                    ip))
                        return ip, userService, iads, trans, itrans
                    else:
                        message = itrans.getCustomAvailableErrorMsg(
                            userService, ip)
                        log.doLog(userService, log.WARN, message,
                                  log.TRANSPORT)
                        logger.debug(
                            'Transport is not ready for user service {}:  {}'.
                            format(userService, message))
                else:
                    logger.debug(
                        'Ip not available from user service {0}'.format(
                            userService))
        else:
            log.doLog(
                userService, log.WARN,
                "User {0} from {1} tried to access, but service was not ready".
                format(user.name, srcIp), log.WEB)

        traceLogger.error(
            'ERROR {} on service "{}" for user "{}" with transport "{}" (ip:{})'
            .format(serviceNotReadyCode, userService.name, userName,
                    trans.name, ip))
        raise ServiceNotReadyError(code=serviceNotReadyCode,
                                   service=userService,
                                   transport=trans)
Example #22
0
    def getAssignationForUser(self, ds, user):

        if ds.service.getInstance().spawnsNew is False:
            assignedUserService = self.getExistingAssignationForUser(ds, user)
        else:
            assignedUserService = None

        # If has an assigned user service, returns this without any more work
        if assignedUserService is not None:
            return assignedUserService

        # Now try to locate 1 from cache already "ready" (must be usable and at level 1)
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(
                cache_level=services.UserDeployment.L1_CACHE,
                state=State.USABLE,
                os_state=State.USABLE)[:1]
            if len(cache) == 0:
                cache = ds.cachedUserServices().select_for_update().filter(
                    cache_level=services.UserDeployment.L1_CACHE,
                    state=State.USABLE)[:1]
            if len(cache) > 0:
                cache = cache[0]
                cache.assignToUser(user)
                cache.save(
                )  # Store assigned ASAP, we do not know how long assignToUser method of instance will take
            else:
                cache = None

        # Out of atomic transaction
        if cache is not None:
            logger.debug(
                'Found a cached-ready service from {0} for user {1}, item {2}'.
                format(ds, user, cache))
            events.addEvent(ds,
                            events.ET_CACHE_HIT,
                            fld1=ds.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.USABLE).count())
            ci = cache.getInstance()  # User Deployment instance
            ci.assignToUser(user)
            cache.updateData(ci)
            cache.save()
            return cache

        # Cache missed

        # Now find if there is a preparing one
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(
                cache_level=services.UserDeployment.L1_CACHE,
                state=State.PREPARING)[:1]
            if len(cache) > 0:
                cache = cache[0]
                cache.assignToUser(user)
                cache.save()
            else:
                cache = None

        # Out of atomic transaction
        if cache is not None:
            logger.debug(
                'Found a cached-preparing service from {0} for user {1}, item {2}'
                .format(ds, user, cache))
            events.addEvent(ds,
                            events.ET_CACHE_MISS,
                            fld1=ds.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.PREPARING).count())
            ci = cache.getInstance()  # User Deployment instance
            ci.assignToUser(user)
            cache.updateData(ci)
            cache.save()
            return cache

        # Can't assign directly from L2 cache... so we check if we can create e new service in the limits requested
        ty = ds.service.getType()
        if ty.usesCache is True:
            # inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
            inAssigned = ds.assignedUserServices().filter(
                UserServiceManager.getStateFilter()).count()
            # totalL1Assigned = inCacheL1 + inAssigned
            if inAssigned >= ds.max_srvs:  # cacheUpdater will drop necesary L1 machines, so it's not neccesary to check against inCacheL1
                raise MaxServicesReachedError()
        # Can create new service, create it
        events.addEvent(ds, events.ET_CACHE_MISS, fld1=0)
        return self.createAssignedFor(ds, user)
Example #23
0
    def getService(self, user, srcIp, idService, idTransport, doTest=True):
        '''
        Get service info from
        '''
        userService = self.locateUserService(user, idService, create=True)

        if userService.isInMaintenance() is True:
            raise ServiceInMaintenanceMode()

        if userService.deployed_service.isAccessAllowed() is False:
            raise ServiceAccessDeniedByCalendar()

        if idTransport is None or idTransport == '':  # Find a suitable transport
            for v in userService.deployed_service.transports.order_by('priority'):
                if v.validForIp(srcIp):
                    idTransport = v.uuid
                    break

        try:
            trans = Transport.objects.get(uuid=idTransport)
        except Exception:
            raise InvalidServiceException()

        # Ensures that the transport is allowed for this service
        if trans not in userService.deployed_service.transports.all():
            raise InvalidServiceException()

        # If transport is not available for the request IP...
        if trans.validForIp(srcIp) is False:
            msg = 'The requested transport {} is not valid for {}'.format(trans.name, srcIp)
            logger.error(msg)
            raise InvalidServiceException(msg)

        if user is not None:
            userName = user.name
        else:
            userName = '******'

        if doTest is False:
            # traceLogger.info('GOT service "{}" for user "{}" with transport "{}" (NOT TESTED)'.format(userService.name, userName, trans.name))
            return (None, userService, None, trans, None)

        serviceNotReadyCode = 0x0001
        ip = 'unknown'
        # Test if the service is ready
        if userService.isReady():
            serviceNotReadyCode = 0x0002
            log.doLog(userService, log.INFO, "User {0} from {1} has initiated access".format(user.name, srcIp), log.WEB)
            # If ready, show transport for this service, if also ready ofc
            iads = userService.getInstance()
            ip = iads.getIp()
            userService.logIP(ip)  # Update known ip

            if self.checkUuid(userService) is False:  # Machine is not what is expected
                serviceNotReadyCode = 0x0004
                log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
                logger.debug('Transport is not ready for user service {0}'.format(userService))
            else:
                events.addEvent(userService.deployed_service, events.ET_ACCESS, username=userName, srcip=srcIp, dstip=ip, uniqueid=userService.unique_id)
                if ip is not None:
                    serviceNotReadyCode = 0x0003
                    itrans = trans.getInstance()
                    if itrans.isAvailableFor(userService, ip):
                        userService.setConnectionSource(srcIp, 'unknown')
                        log.doLog(userService, log.INFO, "User service ready", log.WEB)
                        self.notifyPreconnect(userService, itrans.processedUser(userService, user), itrans.protocol)
                        traceLogger.info('READY on service "{}" for user "{}" with transport "{}" (ip:{})'.format(userService.name, userName, trans.name, ip))
                        return (ip, userService, iads, trans, itrans)
                    else:
                        message = itrans.getCustomAvailableErrorMsg(userService, ip)
                        log.doLog(userService, log.WARN, message, log.TRANSPORT)
                        logger.debug('Transport is not ready for user service {}:  {}'.format(userService, message))
                else:
                    logger.debug('Ip not available from user service {0}'.format(userService))
        else:
            log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but service was not ready".format(user.name, srcIp), log.WEB)

        traceLogger.error('ERROR {} on service "{}" for user "{}" with transport "{}" (ip:{})'.format(serviceNotReadyCode, userService.name, userName, trans.name, ip))
        raise ServiceNotReadyError(code=serviceNotReadyCode, service=userService, transport=trans)
Example #24
0
    def connection(self, doNotCheck=False):
        kind, idService = self._args[0][0], self._args[0][1:]
        idTransport = self._args[1]

        logger.debug('Type: {}, Service: {}, Transport: {}'.format(kind, idService, idTransport))

        try:
            logger.debug('Kind of service: {0}, idService: {1}'.format(kind, idService))
            if kind == 'A':  # This is an assigned service
                ads = UserService.objects.get(uuid=processUuid(idService))
            else:
                ds = DeployedService.objects.get(uuid=processUuid(idService))
                # We first do a sanity check for this, if the user has access to this service
                # If it fails, will raise an exception
                ds.validateUser(self._user)
                # Now we have to locate an instance of the service, so we can assign it to user.
                ads = UserServiceManager.manager().getAssignationForUser(ds, self._user)

            if ads.isInMaintenance() is True:
                return Connection.result(error='Service in maintenance')

            logger.debug('Found service: {0}'.format(ads))
            trans = Transport.objects.get(uuid=processUuid(idTransport))

            if trans.validForIp(self._request.ip) is False:
                return Connection.result(error='Access denied')

            # Test if the service is ready
            if doNotCheck or ads.isReady():
                log.doLog(ads, log.INFO, "User {0} from {1} has initiated access".format(self._user.name, self._request.ip), log.WEB)
                # If ready, show transport for this service, if also ready ofc
                iads = ads.getInstance()
                ip = iads.getIp()
                logger.debug('IP: {}'.format(ip))
                events.addEvent(ads.deployed_service, events.ET_ACCESS, username=self._user.name, srcip=self._request.ip, dstip=ip, uniqueid=ads.unique_id)
                if ip is not None:
                    itrans = trans.getInstance()
                    if itrans.providesConnetionInfo() and (doNotCheck or itrans.isAvailableFor(ads, ip)):
                        ads.setConnectionSource(self._request.ip, 'unknown')
                        log.doLog(ads, log.INFO, "User service ready, rendering transport", log.WEB)

                        ci = {
                            'username': '',
                            'password': '',
                            'domain': '',
                            'protocol': 'unknown',
                            'ip': ip
                        }
                        ci.update(itrans.getConnectionInfo(ads, self._user, 'UNKNOWN'))

                        UserServiceManager.manager().notifyPreconnect(ads, itrans.processedUser(ads, self._user), itrans.protocol)

                        return Connection.result(result=ci)
                    else:
                        log.doLog(ads, log.WARN, "User service is not accessible by REST (ip {0})".format(ip), log.TRANSPORT)
                        logger.debug('Transport {} is not accesible for user service {} from {}'.format(trans, ads, self._request.ip))
                        logger.debug("{}, {}".format(itrans.providesConnetionInfo(), itrans.isAvailableFor(ads, ip)))
                else:
                    logger.debug('Ip not available from user service {0}'.format(ads))
            else:
                log.doLog(ads, log.WARN, "User {0} from {1} tried to access, but service was not ready".format(self._user.name, self._request.ip), log.WEB)
            # Not ready, show message and return to this page in a while
            return Connection.result(error='Service not ready')
        except Exception as e:
            return Connection.result(error=six.text_type(e))
Example #25
0
def getService(request, idService, idTransport, doTest=True):
    kind, idService = idService[0], idService[1:]

    logger.debug('Kind of service: {0}, idService: {1}'.format(
        kind, idService))
    if kind == 'A':  # This is an assigned service
        logger.debug('Getting A service {}'.format(idService))
        ads = UserService.objects.get(uuid=idService)
        ads.deployed_service.validateUser(request.user)
    else:
        ds = DeployedService.objects.get(uuid=idService)
        # We first do a sanity check for this, if the user has access to this service
        # If it fails, will raise an exception
        ds.validateUser(request.user)
        # Now we have to locate an instance of the service, so we can assign it to user.
        ads = UserServiceManager.manager().getAssignationForUser(
            ds, request.user)

    if ads.isInMaintenance() is True:
        raise ServiceInMaintenanceMode()

    logger.debug('Found service: {0}'.format(ads))
    trans = Transport.objects.get(uuid=idTransport)

    # Ensures that the transport is allowed for this service
    if trans not in ads.deployed_service.transports.all():
        raise InvalidServiceException()

    # If transport is not available for the request IP...
    if trans.validForIp(request.ip) is False:
        raise InvalidServiceException()

    if doTest is False:
        return (None, ads, None, trans, None)

    # Test if the service is ready
    if ads.isReady():
        log.doLog(
            ads, log.INFO, "User {0} from {1} has initiated access".format(
                request.user.name, request.ip), log.WEB)
        # If ready, show transport for this service, if also ready ofc
        iads = ads.getInstance()
        ip = iads.getIp()
        events.addEvent(ads.deployed_service,
                        events.ET_ACCESS,
                        username=request.user.name,
                        srcip=request.ip,
                        dstip=ip,
                        uniqueid=ads.unique_id)
        if ip is not None:
            itrans = trans.getInstance()
            if itrans.isAvailableFor(ip):
                ads.setConnectionSource(request.ip, 'unknown')
                log.doLog(ads, log.INFO, "User service ready", log.WEB)
                UserServiceManager.manager().notifyPreconnect(
                    ads, itrans.processedUser(ads, request.user),
                    itrans.protocol)
                return (ip, ads, iads, trans, itrans)
            else:
                log.doLog(ads, log.WARN,
                          "User service is not accessible (ip {0})".format(ip),
                          log.TRANSPORT)
                logger.debug(
                    'Transport is not ready for user service {0}'.format(ads))
        else:
            logger.debug('Ip not available from user service {0}'.format(ads))
    else:
        log.doLog(
            ads, log.WARN,
            "User {0} from {1} tried to access, but machine was not ready".
            format(request.user.name, request.ip), log.WEB)

    return None
Example #26
0
    def getService(self, user, srcIp, idService, idTransport, doTest=True):
        '''
        Get service info from
        '''
        kind, idService = idService[0], idService[1:]

        logger.debug('Kind of service: {0}, idService: {1}'.format(
            kind, idService))
        if kind == 'A':  # This is an assigned service
            logger.debug('Getting A service {}'.format(idService))
            userService = UserService.objects.get(uuid=idService)
            userService.deployed_service.validateUser(user)
        else:
            ds = ServicePool.objects.get(uuid=idService)
            # We first do a sanity check for this, if the user has access to this service
            # If it fails, will raise an exception
            ds.validateUser(user)
            # Now we have to locate an instance of the service, so we can assign it to user.
            userService = self.getAssignationForUser(ds, user)

        logger.debug('Found service: {0}'.format(userService))

        if userService.isInMaintenance() is True:
            raise ServiceInMaintenanceMode()

        # If service is not visible, do not allow it to be used
        if userService.deployed_service.isVisible() is False:
            raise InvalidServiceException()

        if userService.deployed_service.isAccessAllowed() is False:
            raise ServiceAccessDeniedByCalendar()

        if idTransport is None or idTransport == '':  # Find a suitable transport
            for v in userService.deployed_service.transports.order_by(
                    'priority'):
                if v.validForIp(srcIp):
                    idTransport = v.uuid
                    break

        try:
            trans = Transport.objects.get(uuid=idTransport)
        except Exception:
            raise InvalidServiceException()

        # Ensures that the transport is allowed for this service
        if trans not in userService.deployed_service.transports.all():
            raise InvalidServiceException()

        # If transport is not available for the request IP...
        if trans.validForIp(srcIp) is False:
            raise InvalidServiceException()

        if user is not None:
            userName = user.name

        if doTest is False:
            # traceLogger.info('GOT service "{}" for user "{}" with transport "{}" (NOT TESTED)'.format(userService.name, userName, trans.name))
            return (None, userService, None, trans, None)

        serviceNotReadyCode = 0x0001
        ip = 'unknown'
        # Test if the service is ready
        if userService.isReady():
            serviceNotReadyCode = 0x0002
            log.doLog(
                userService, log.INFO,
                "User {0} from {1} has initiated access".format(
                    user.name, srcIp), log.WEB)
            # If ready, show transport for this service, if also ready ofc
            iads = userService.getInstance()
            ip = iads.getIp()

            if self.checkUuid(
                    userService) is False:  # Machine is not what is expected
                serviceNotReadyCode = 0x0004
                log.doLog(userService, log.WARN,
                          "User service is not accessible (ip {0})".format(ip),
                          log.TRANSPORT)
                logger.debug(
                    'Transport is not ready for user service {0}'.format(
                        userService))
            else:
                events.addEvent(userService.deployed_service,
                                events.ET_ACCESS,
                                username=userName,
                                srcip=srcIp,
                                dstip=ip,
                                uniqueid=userService.unique_id)
                if ip is not None:
                    serviceNotReadyCode = 0x0003
                    itrans = trans.getInstance()
                    if itrans.isAvailableFor(userService, ip):
                        userService.setConnectionSource(srcIp, 'unknown')
                        log.doLog(userService, log.INFO, "User service ready",
                                  log.WEB)
                        self.notifyPreconnect(
                            userService,
                            itrans.processedUser(userService,
                                                 user), itrans.protocol)
                        traceLogger.info(
                            'READY on service "{}" for user "{}" with transport "{}" (ip:{})'
                            .format(userService.name, userName, trans.name,
                                    ip))
                        return (ip, userService, iads, trans, itrans)
                    else:
                        log.doLog(
                            userService, log.WARN,
                            "User service is not accessible (ip {0})".format(
                                ip), log.TRANSPORT)
                        logger.debug(
                            'Transport is not ready for user service {0}'.
                            format(userService))
                else:
                    logger.debug(
                        'Ip not available from user service {0}'.format(
                            userService))
        else:
            log.doLog(
                userService, log.WARN,
                "User {0} from {1} tried to access, but service was not ready".
                format(user.name, srcIp), log.WEB)

        traceLogger.error(
            'ERROR {} on service "{}" for user "{}" with transport "{}" (ip:{})'
            .format(serviceNotReadyCode, userService.name, userName,
                    trans.name, ip))
        raise ServiceNotReadyError(code=serviceNotReadyCode,
                                   service=userService,
                                   transport=trans)
    def getService(self, user, srcIp, idService, idTransport, doTest=True):
        '''
        Get service info from
        '''
        kind, idService = idService[0], idService[1:]

        logger.debug('Kind of service: {0}, idService: {1}'.format(kind, idService))
        if kind == 'A':  # This is an assigned service
            logger.debug('Getting A service {}'.format(idService))
            userService = UserService.objects.get(uuid=idService)
            userService.deployed_service.validateUser(user)
        else:
            ds = ServicePool.objects.get(uuid=idService)
            # We first do a sanity check for this, if the user has access to this service
            # If it fails, will raise an exception
            ds.validateUser(user)
            # Now we have to locate an instance of the service, so we can assign it to user.
            userService = self.getAssignationForUser(ds, user)

        logger.debug('Found service: {0}'.format(userService))

        if userService.isInMaintenance() is True:
            raise ServiceInMaintenanceMode()

        # If service is not visible, do not allow it to be used
        if userService.deployed_service.isVisible() is False:
            raise InvalidServiceException()

        if userService.deployed_service.isAccessAllowed() is False:
            raise ServiceAccessDeniedByCalendar()

        if idTransport is None or idTransport == '':  # Find a suitable transport
            for v in userService.deployed_service.transports.order_by('priority'):
                if v.validForIp(srcIp):
                    idTransport = v.uuid
                    break

        try:
            trans = Transport.objects.get(uuid=idTransport)
        except Exception:
            raise InvalidServiceException()

        # Ensures that the transport is allowed for this service
        if trans not in userService.deployed_service.transports.all():
            raise InvalidServiceException()

        # If transport is not available for the request IP...
        if trans.validForIp(srcIp) is False:
            raise InvalidServiceException()

        if user is not None:
            userName = user.name


        if doTest is False:
            # traceLogger.info('GOT service "{}" for user "{}" with transport "{}" (NOT TESTED)'.format(userService.name, userName, trans.name))
            return (None, userService, None, trans, None)


        serviceNotReadyCode = 0x0001
        ip = 'unknown'
        # Test if the service is ready
        if userService.isReady():
            serviceNotReadyCode = 0x0002
            log.doLog(userService, log.INFO, "User {0} from {1} has initiated access".format(user.name, srcIp), log.WEB)
            # If ready, show transport for this service, if also ready ofc
            iads = userService.getInstance()
            ip = iads.getIp()

            if self.checkUuid(userService) is False:  # Machine is not what is expected
                serviceNotReadyCode = 0x0004
                log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
                logger.debug('Transport is not ready for user service {0}'.format(userService))
            else:
                events.addEvent(userService.deployed_service, events.ET_ACCESS, username=userName, srcip=srcIp, dstip=ip, uniqueid=userService.unique_id)
                if ip is not None:
                    serviceNotReadyCode = 0x0003
                    itrans = trans.getInstance()
                    if itrans.isAvailableFor(userService, ip):
                        userService.setConnectionSource(srcIp, 'unknown')
                        log.doLog(userService, log.INFO, "User service ready", log.WEB)
                        self.notifyPreconnect(userService, itrans.processedUser(userService, user), itrans.protocol)
                        traceLogger.info('READY on service "{}" for user "{}" with transport "{}" (ip:{})'.format(userService.name, userName, trans.name, ip))
                        return (ip, userService, iads, trans, itrans)
                    else:
                        log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT)
                        logger.debug('Transport is not ready for user service {0}'.format(userService))
                else:
                    logger.debug('Ip not available from user service {0}'.format(userService))
        else:
            log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but service was not ready".format(user.name, srcIp), log.WEB)

        traceLogger.error('ERROR {} on service "{}" for user "{}" with transport "{}" (ip:{})'.format(serviceNotReadyCode, userService.name, userName, trans.name, ip))
        raise ServiceNotReadyError(code=serviceNotReadyCode, service=userService, transport=trans)
Example #28
0
    def connection(self, doNotCheck=False):
        kind, idService = self._args[0][0], self._args[0][1:]
        idTransport = self._args[1]

        logger.debug('Type: {}, Service: {}, Transport: {}'.format(
            kind, idService, idTransport))

        try:
            logger.debug('Kind of service: {0}, idService: {1}'.format(
                kind, idService))
            if kind == 'A':  # This is an assigned service
                ads = UserService.objects.get(uuid=processUuid(idService))
            else:
                ds = DeployedService.objects.get(uuid=processUuid(idService))
                # We first do a sanity check for this, if the user has access to this service
                # If it fails, will raise an exception
                ds.validateUser(self._user)
                # Now we have to locate an instance of the service, so we can assign it to user.
                ads = UserServiceManager.manager().getAssignationForUser(
                    ds, self._user)

            if ads.isInMaintenance() is True:
                return Connection.result(error='Service in maintenance')

            logger.debug('Found service: {0}'.format(ads))
            trans = Transport.objects.get(uuid=processUuid(idTransport))

            if trans.validForIp(self._request.ip) is False:
                return Connection.result(error='Access denied')

            # Test if the service is ready
            if doNotCheck or ads.isReady():
                log.doLog(
                    ads, log.INFO,
                    "User {0} from {1} has initiated access".format(
                        self._user.name, self._request.ip), log.WEB)
                # If ready, show transport for this service, if also ready ofc
                iads = ads.getInstance()
                ip = iads.getIp()
                logger.debug('IP: {}'.format(ip))
                events.addEvent(ads.deployed_service,
                                events.ET_ACCESS,
                                username=self._user.name,
                                srcip=self._request.ip,
                                dstip=ip,
                                uniqueid=ads.unique_id)
                if ip is not None:
                    itrans = trans.getInstance()
                    if itrans.providesConnetionInfo() and (
                            doNotCheck or itrans.isAvailableFor(ads, ip)):
                        ads.setConnectionSource(self._request.ip, 'unknown')
                        log.doLog(ads, log.INFO,
                                  "User service ready, rendering transport",
                                  log.WEB)

                        ci = {
                            'username': '',
                            'password': '',
                            'domain': '',
                            'protocol': 'unknown',
                            'ip': ip
                        }
                        ci.update(
                            itrans.getConnectionInfo(ads, self._user,
                                                     'UNKNOWN'))

                        UserServiceManager.manager().notifyPreconnect(
                            ads, itrans.processedUser(ads, self._user),
                            itrans.protocol)

                        return Connection.result(result=ci)
                    else:
                        log.doLog(
                            ads, log.WARN,
                            "User service is not accessible by REST (ip {0})".
                            format(ip), log.TRANSPORT)
                        logger.debug(
                            'Transport {} is not accesible for user service {} from {}'
                            .format(trans, ads, self._request.ip))
                        logger.debug("{}, {}".format(
                            itrans.providesConnetionInfo(),
                            itrans.isAvailableFor(ads, ip)))
                else:
                    logger.debug(
                        'Ip not available from user service {0}'.format(ads))
            else:
                log.doLog(
                    ads, log.WARN,
                    "User {0} from {1} tried to access, but service was not ready"
                    .format(self._user.name, self._request.ip), log.WEB)
            # Not ready, show message and return to this page in a while
            return Connection.result(error='Service not ready')
        except Exception as e:
            return Connection.result(error=six.text_type(e))
Example #29
0
    def getAssignationForUser(self, ds, user):

        if ds.service.getInstance().spawnsNew is False:
            assignedUserService = self.getExistingAssignationForUser(ds, user)
        else:
            assignedUserService = None

        # If has an assigned user service, returns this without any more work
        if assignedUserService is not None:
            return assignedUserService

        if ds.isRestrained():
            raise InvalidServiceException(
                _('The requested service is restrained'))

        # Now try to locate 1 from cache already "ready" (must be usable and at level 1)
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(
                cache_level=services.UserDeployment.L1_CACHE,
                state=State.USABLE,
                os_state=State.USABLE)[:1]
            if len(cache) != 0:
                cache = cache[0]
                # Ensure element is reserved correctly on DB
                if ds.cachedUserServices().select_for_update().filter(
                        user=None, uuid=cache.uuid).update(user=user,
                                                           cache_level=0) != 1:
                    cache = None
            else:
                cache = None

        if cache == None:
            with transaction.atomic():
                cache = ds.cachedUserServices().select_for_update().filter(
                    cache_level=services.UserDeployment.L1_CACHE,
                    state=State.USABLE)[:1]
                if len(cache) > 0:
                    cache = cache[0]
                    if ds.cachedUserServices().select_for_update().filter(
                            user=None, uuid=cache.uuid).update(
                                user=user, cache_level=0) != 1:
                        cache = None
                else:
                    cache = None

        if cache:
            cache.assignToUser(user, save=True)

        # Out of atomic transaction
        if cache is not None:
            logger.debug(
                'Found a cached-ready service from {0} for user {1}, item {2}'.
                format(ds, user, cache))
            events.addEvent(ds,
                            events.ET_CACHE_HIT,
                            fld1=ds.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.USABLE).count())
            return cache

        # Cache missed

        # Now find if there is a preparing one
        with transaction.atomic():
            cache = ds.cachedUserServices().select_for_update().filter(
                cache_level=services.UserDeployment.L1_CACHE,
                state=State.PREPARING)[:1]
            if len(cache) > 0:
                cache = cache[0]
                if ds.cachedUserServices().select_for_update().filter(
                        user=None, uuid=cache.uuid).update(user=user,
                                                           cache_level=0) != 1:
                    cache = None
                else:
                    cache.assignToUser(user, save=True)
            else:
                cache = None

        # Out of atomic transaction
        if cache is not None:
            logger.debug(
                'Found a cached-preparing service from {0} for user {1}, item {2}'
                .format(ds, user, cache))
            events.addEvent(ds,
                            events.ET_CACHE_MISS,
                            fld1=ds.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.PREPARING).count())
            return cache

        # Can't assign directly from L2 cache... so we check if we can create e new service in the limits requested
        ty = ds.service.getType()
        if ty.usesCache is True:
            # inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
            inAssigned = ds.assignedUserServices().filter(
                UserServiceManager.getStateFilter()).count()
            # totalL1Assigned = inCacheL1 + inAssigned
            if inAssigned >= ds.max_srvs:  # cacheUpdater will drop necesary L1 machines, so it's not neccesary to check against inCacheL1
                log.doLog(
                    ds, log.WARN,
                    'Max number of services reached: {}'.format(ds.max_srvs),
                    log.INTERNAL)
                raise MaxServicesReachedError()
        # Can create new service, create it
        events.addEvent(ds, events.ET_CACHE_MISS, fld1=0)
        return self.createAssignedFor(ds, user)