Пример #1
0
 def validatePublication(self):
     """
     Ensures that, if this service has publications, that a publication is active
     raises an IvalidServiceException if check fails
     """
     if self.activePublication() is None and self.service.getType().publicationType is not None:
         raise InvalidServiceException()
Пример #2
0
 def validateTransport(self, transport):
     try:
         self.transports.get(id=transport.id)
     except:
         raise InvalidServiceException()
Пример #3
0
def ticketAuth(request, ticketId):
    '''
    Used to authenticate an user via a ticket
    '''
    ticket = Ticket(ticketId)

    logger.debug('Ticket: {}'.format(ticket))

    try:
        try:
            # Extract ticket.data from ticket.data storage, and remove it if success
            username = ticket.data['username']
            groups = ticket.data['groups']
            auth = ticket.data['auth']
            realname = ticket.data['realname']
            servicePool = ticket.data['servicePool']
            password = ticket.data['password']
            transport = ticket.data['transport']
        except:
            logger.error('Ticket stored is not valid')
            raise InvalidUserException()

        # Remove ticket
        ticket.delete()

        auth = Authenticator.objects.get(uuid=auth)
        # If user does not exists in DB, create it right now
        # Add user to groups, if they exists...
        grps = []
        for g in groups:
            try:
                grps.append(auth.groups.get(uuid=g))
            except Exception:
                logger.debug('Group list has changed since ticket assignement')

        if len(grps) == 0:
            logger.error('Ticket has no valid groups')
            raise Exception('Invalid ticket authentication')

        usr = auth.getOrCreateUser(username, realname)
        if usr is None or State.isActive(
                usr.state) is False:  # If user is inactive, raise an exception
            raise InvalidUserException()

        # Add groups to user (replace existing groups)
        usr.groups = grps

        # Right now, we assume that user supports java, let's see how this works
        # Force cookie generation
        webLogin(request, None, usr, password)

        request.user = usr  # Temporarily store this user as "authenticated" user, next requests will be done using session

        # Check if servicePool is part of the ticket
        if servicePool is not None:
            servicePool = DeployedService.objects.get(uuid=servicePool)
            # Check if service pool can't be accessed by groups
            servicePool.validateUser(usr)
            if servicePool.isInMaintenance():
                raise ServiceInMaintenanceMode()

            transport = Transport.objects.get(uuid=transport)

            response = service(
                request, 'F' + servicePool.uuid,
                transport.uuid)  # 'A' Indicates 'assigned service'
        else:
            response = HttpResponsePermanentRedirect(
                reverse('uds.web.views.index'))

        # Now ensure uds cookie is at response
        getUDSCookie(request, response, True)
        return response

    except Authenticator.DoesNotExist:
        logger.error('Ticket has an non existing authenticator')
        return errors.error(request, InvalidUserException())
    except DeployedService.DoesNotExist:
        logger.error('Ticket has an invalid Service Pool')
        return errors.error(request, InvalidServiceException())
    except Exception as e:
        logger.exception('Exception')
        return errors.exceptionView(request, e)
Пример #4
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)
Пример #5
0
def ticketAuth(request, ticketId):
    """
    Used to authenticate an user via a ticket
    """
    try:
        data = TicketStore.get(ticketId, invalidate=True)

        try:
            # Extract ticket.data from ticket.data storage, and remove it if success
            username = data['username']
            groups = data['groups']
            auth = data['auth']
            realname = data['realname']
            servicePool = data['servicePool']
            password = cryptoManager().decrypt(data['password'])
            transport = data['transport']
        except Exception:
            logger.error('Ticket stored is not valid')
            raise InvalidUserException()

        auth = Authenticator.objects.get(uuid=auth)
        # If user does not exists in DB, create it right now
        # Add user to groups, if they exists...
        grps = []
        for g in groups:
            try:
                grps.append(auth.groups.get(uuid=g))
            except Exception:
                logger.debug('Group list has changed since ticket assignment')

        if len(grps) == 0:
            logger.error('Ticket has no valid groups')
            raise Exception('Invalid ticket authentication')

        usr = auth.getOrCreateUser(username, realname)
        if usr is None or State.isActive(usr.state) is False:  # If user is inactive, raise an exception
            raise InvalidUserException()

        # Add groups to user (replace existing groups)
        usr.groups.set(grps)

        # Force cookie generation
        webLogin(request, None, usr, password)

        request.user = usr  # Temporarily store this user as "authenticated" user, next requests will be done using session
        request.session['ticket'] = '1'  # Store that user access is done using ticket

        logger.debug("Service & transport: {}, {}".format(servicePool, transport))
        for v in DeployedService.objects.all():
            logger.debug("{} {}".format(v.uuid, v.name))

        # Check if servicePool is part of the ticket
        if servicePool is not None:
            # If service pool is in there, also is transport
            res = userServiceManager().getService(request.user, request.ip, 'F' + servicePool, transport, False)
            _x, userService, _x, transport, _x = res

            transportInstance = transport.getInstance()
            if transportInstance.ownLink is True:
                link = reverse('TransportOwnLink', args=('A' + userService.uuid, transport.uuid))
            else:
                link = html.udsAccessLink(request, 'A' + userService.uuid, transport.uuid)

            response = render(
                request,
                theme.template('simpleLauncher.html'),
                {
                    'link': link
                }
            )
        else:
            response = HttpResponsePermanentRedirect(reverse('uds.web.views.index'))

        # Now ensure uds cookie is at response
        getUDSCookie(request, response, True)
        return response
    except ServiceNotReadyError as e:
        return render(
            request,
            theme.template('service_not_ready.html'),
            {
                'fromLauncher': True,
                'code': e.code
            }
        )

    except TicketStore.InvalidTicket:
        return render(
            request,
            theme.template('simpleLauncherAlreadyLaunched.html')
        )
    except Authenticator.DoesNotExist:
        logger.error('Ticket has an non existing authenticator')
        return errors.exceptionView(request, InvalidUserException())
    except DeployedService.DoesNotExist:
        logger.error('Ticket has an invalid Service Pool')
        return errors.exceptionView(request, InvalidServiceException())
    except Exception as e:
        logger.exception('Exception')
        return errors.exceptionView(request, e)
Пример #6
0
    def getMeta(self, user, srcIp, os, idMetaPool):
        logger.debug('This is meta')
        # We need to locate the service pool related to this meta, and also the transport
        # First, locate if there is a service in any pool associated with this metapool
        meta = MetaPool.objects.get(uuid=idMetaPool)

        # If access is denied by calendar...
        if meta.isAccessAllowed() is False:
            raise ServiceAccessDeniedByCalendar()

        # Sort pools based on meta selection
        if meta.policy == MetaPool.PRIORITY_POOL:
            pools = [(p.priority, p.pool) for p in meta.members.all()]
        elif meta.policy == MetaPool.MOST_AVAILABLE_BY_NUMBER:
            pools = [(p.usage(), p) for p in meta.pools.all()]
        else:
            pools = [(random.randint(0, 10000), p) for p in meta.pools.all()]

        # Sort pools related to policy now, and xtract only pools, not sort keys
        # Remove "full" pools (100%) from result and pools in maintenance mode, not ready pools, etc...
        pools = [
            p[1] for p in sorted(pools, key=lambda x: x[0])
            if p[1].usage() < 100 and p[1].isUsable()
        ]

        logger.debug('Pools: %s', pools)

        usable = None

        # Now, Lets find first if there is one assigned in ANY pool

        def ensureTransport(pool):
            usable = None
            for t in pool.transports.all().order_by('priority'):
                typeTrans = t.getType()
                if t.getType() and t.validForIp(
                        srcIp) and typeTrans.supportsOs(
                            os['OS']) and t.validForOs(os['OS']):
                    usable = (pool, t)
                    break
            return usable

        try:
            alreadyAssigned = UserService.objects.filter(
                deployed_service__in=pools,
                state__in=State.VALID_STATES,
                user=user,
                cache_level=0).order_by('deployed_service__name')[0]
            logger.debug('Already assigned %s', alreadyAssigned)

            # Ensure transport is available for the OS, and store it
            usable = ensureTransport(alreadyAssigned.deployed_service)
            # Found already assigned, ensure everythinf is fine
            if usable:
                self.getService(user,
                                os,
                                srcIp,
                                'F' + usable[0].uuid,
                                usable[1].uuid,
                                doTest=False)

        except Exception:  # No service already assigned, lets find a suitable one
            for pool in pools:  # Pools are already sorted, and "full" pools are filtered out
                # Ensure transport is available for the OS
                usable = ensureTransport(pool)

                # Stop if a pool-transport is found and can be assigned to user
                if usable:
                    try:
                        self.getService(user,
                                        os,
                                        srcIp,
                                        'F' + usable[0].uuid,
                                        usable[1].uuid,
                                        doTest=False)
                        break  # If all goes fine, stop here
                    except Exception as e:
                        logger.info(
                            'Meta service {}:{} could not be assigned, trying a new one'
                            .format(usable[0].name, e))
                        usable = None

        if not usable:
            log.doLog(
                meta, log.WARN,
                "No user service accessible from device (ip {}, os: {})".
                format(srcIp, os['OS']), log.SERVICE)
            raise InvalidServiceException(
                _('The service is not accessible from this device'))

        logger.debug('Found usable pair: %s', usable)
        usable[0].validateUser(user)
        # We have found an usable user service already assigned & can be accessed from this, so return it
        return None, usable[0], None, usable[1], None
Пример #7
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)
Пример #8
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
Пример #9
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)