Ejemplo n.º 1
0
    def get(self):
        '''
        This login uses parameters to generate auth token
        The alternative is to use the template tag inside "REST" that is called auth_token, that extracts an auth token from an user session
        We can use any of this forms due to the fact that the auth token is in fact a session key
        Parameters:
            mandatory:
                username:
                password:
                auth:
            optional:
                locale: (defaults to "en")
        Result:
            on success: { 'result': 'ok', 'auth': [auth_code] }
            on error: { 'result: 'error', 'error': [error string] }
        '''

        logger.debug('Params: {0}'.format(self._params))
        if len(self._args) == 0:
            return {}

        if len(self._args) != 1:
            raise RequestError('Invalid Request')

        uCache.purge()
        return 'done'
Ejemplo n.º 2
0
    def get(self):
        '''
        This login uses parameters to generate auth token
        The alternative is to use the template tag inside "REST" that is called auth_token, that extracts an auth token from an user session
        We can use any of this forms due to the fact that the auth token is in fact a session key
        Parameters:
            mandatory:
                username:
                password:
                auth:
            optional:
                locale: (defaults to "en")
        Result:
            on success: { 'result': 'ok', 'auth': [auth_code] }
            on error: { 'result: 'error', 'error': [error string] }
        '''

        logger.debug('Params: {0}'.format(self._params))
        if len(self._args) == 0:
            return {}

        if len(self._args) != 1:
            raise RequestError('Invalid Request')

        uCache.purge()
        return 'done'
Ejemplo n.º 3
0
 def clearRelatedData(self):
     """
     Removes all related information from database for this environment.
     """
     Cache.delete(self._key)
     Storage.delete(self._key)
     for _, v in self._idGenerators.items():
         v.release()
Ejemplo n.º 4
0
 def clearRelatedData(self):
     '''
     Removes all related information from database for this environment.
     '''
     from uds.core.util.Cache import Cache
     from uds.core.util.Storage import Storage
     Cache.delete(self._key)
     Storage.delete(self._key)
     for __, v in self._idGenerators.iteritems():
         v.release()
Ejemplo n.º 5
0
    def handle(self, *args, **options):
        sys.stdout.write("Cleaning up UDS\n")
        GlobalConfig.initialize()

        # UDSs cache
        Cache.cleanUp()
        # Django caches
        cache.clear()

        sys.stdout.write("UDS Cleaned UP\n")
Ejemplo n.º 6
0
 def __init__(self, key=None, data=None):
     self.uuidGenerator = lambda: (cryptoManager().uuid() + cryptoManager().
                                   uuid()).replace('-', '')
     self.cache = Cache(TICKET_OWNER)
     self.data = data
     self.key = key
     if key is not None:
         self.load()
     else:
         self.key = self.uuidGenerator()
Ejemplo n.º 7
0
 def clearRelatedData(self):
     """
     Removes all related information from database for this environment.
     """
     from uds.core.util.Cache import Cache
     from uds.core.util.Storage import Storage
     Cache.delete(self._key)
     Storage.delete(self._key)
     for __, v in six.iteritems(self._idGenerators):
         v.release()
Ejemplo n.º 8
0
    def get(self):
        """
        Processes get method. Basically, clears & purges the cache, no matter what params
        """
        logger.debug('Params: %s', self._params)
        if not self._args:
            return {}

        if len(self._args) != 1:
            raise RequestError('Invalid Request')

        uCache.purge()
        djCache.clear()
        return 'done'
Ejemplo n.º 9
0
    def handle(self, *args, **options):
        sys.stdout.write("Cleaning up UDS\n")
        GlobalConfig.initialize()

        sys.stdout.write("Cache...\n")
        # UDSs cache
        Cache.cleanUp()
        # Django caches
        cache.clear()

        sys.stdout.write("Releasing schedulers...\n")
        # Release all Schedulers
        Scheduler.objects.all().update(owner_server='', state=State.FOR_EXECUTE)

        sys.stdout.write("UDS Cleaned UP\n")
Ejemplo n.º 10
0
 def __init__(self, key=None, data=None):
     self.uuidGenerator = lambda: (cryptoManager().uuid() + cryptoManager().uuid()).replace('-', '')
     self.cache = Cache(TICKET_OWNER)
     self.data = data
     self.key = key
     if key is not None:
         self.load()
     else:
         self.key = self.uuidGenerator()
Ejemplo n.º 11
0
    def handle(self, *args, **options):
        sys.stdout.write("Cleaning up UDS\n")
        GlobalConfig.initialize()

        sys.stdout.write("Cache...\n")
        # UDSs cache
        Cache.cleanUp()
        # Django caches
        cache.clear()

        sys.stdout.write("Releasing schedulers...\n")
        # Release all Schedulers
        Scheduler.objects.all().update(owner_server='', state=State.FOR_EXECUTE)

        sys.stdout.write("Reseting UDS Theme (setting to html5)...\n")
        # Reset theme to html5
        GlobalConfig.UDS_THEME.set('html5')

        sys.stdout.write("UDS Cleaned UP\n")
Ejemplo n.º 12
0
    def renderForHtml(self, userService, transport, ip, os, user, password):

        prefs = user.prefs('nx')

        username = user.getUsernameForAuth()
        proc = username.split('@')
        username = proc[0]
        if self._fixedName is not '':
            username = self._fixedName
        if self._fixedPassword is not '':
            password = self._fixedPassword
        if self._useEmptyCreds is True:
            username, password = '', ''

        width, height = CommonPrefs.getWidthHeight(prefs)
        cache = Cache('pam')

        tunuser = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) + ("%f" % time.time()).split('.')[1]
        tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12))
        cache.put(tunuser, tunpass, 60 * 10)  # Credential valid for ten minutes, and for 1 use only

        sshHost, sshPort = self._tunnelServer.split(':')

        logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
        tun = "{0} {1} {2} {3} {4} {5} {6}".format(tunuser, tunpass, sshHost, sshPort, ip, self._listenPort, '9')

        # Extra data
        extra = {
            'width': width,
            'height': height,
            'connection': self._connection,
            'session': self._session,
            'cacheDisk': self._cacheDisk,
            'cacheMem': self._cacheMem,
            'tun': tun
        }

        # Fix username/password acording to os manager
        username, password = userService.processUserPassword(username, password)

        return generateHtmlForNX(self, userService.uuid, transport.uuid, os, username, password, extra)
Ejemplo n.º 13
0
class Ticket(object):
    '''
    Manages tickets & ticketing save/loading
    Right now, uses cache as backend
    '''

    def __init__(self, key=None, data=None):
        self.uuidGenerator = lambda: (cryptoManager().uuid() + cryptoManager().uuid()).replace('-', '')
        self.cache = Cache(TICKET_OWNER)
        self.data = data
        self.key = key
        if key is not None:
            self.load()
        else:
            self.key = self.uuidGenerator()

    def save(self, data=None, validity=Cache.DEFAULT_VALIDITY):
        '''
        Stores data inside ticket, and make data persistent (store in db)
        '''
        if data is not None:
            self.data = data
        self.cache.put(self.key, self.data, validity)
        return self.key

    def load(self):
        '''
        Load data (if still valid) for a ticket
        '''
        self.data = self.cache.get(self.key, None)
        return self.data

    def delete(self):
        '''
        Removes a ticket from storage (db)
        '''
        self.cache.remove(self.key)

    def __unicode__(self):
        return "Ticket: {}, {}".format(self.key, self.data)
Ejemplo n.º 14
0
class Ticket(object):
    '''
    Manages tickets & ticketing save/loading
    Right now, uses cache as backend
    '''
    def __init__(self, key=None, data=None):
        self.uuidGenerator = lambda: (cryptoManager().uuid() + cryptoManager().
                                      uuid()).replace('-', '')
        self.cache = Cache(TICKET_OWNER)
        self.data = data
        self.key = key
        if key is not None:
            self.load()
        else:
            self.key = self.uuidGenerator()

    def save(self, data=None, validity=Cache.DEFAULT_VALIDITY):
        '''
        Stores data inside ticket, and make data persistent (store in db)
        '''
        if data is not None:
            self.data = data
        self.cache.put(self.key, self.data, validity)
        return self.key

    def load(self):
        '''
        Load data (if still valid) for a ticket
        '''
        self.data = self.cache.get(self.key, None)
        return self.data

    def delete(self):
        '''
        Removes a ticket from storage (db)
        '''
        self.cache.remove(self.key)

    def __unicode__(self):
        return "Ticket: {}, {}".format(self.key, self.data)
Ejemplo n.º 15
0
 def __init__(self, uniqueKey, idGenerators=None):
     """
     Initialized the Environment for the specified id
     @param uniqueKey: Key for this environment
     @param idGenerators: Hash of generators of ids for this environment. This "generators of ids" feature
         is used basically at User Services to auto-create ids for macs or names, using
         {'mac' : UniqueMacGenerator, 'name' : UniqueNameGenerator } as argument.
     """
     if idGenerators is None:
         idGenerators = dict()
     self._key = uniqueKey
     self._cache = Cache(uniqueKey)
     self._storage = Storage(uniqueKey)
     self._idGenerators = idGenerators
Ejemplo n.º 16
0
 def __init__(self, uniqueKey, idGenerators={}):
     '''
     Initialized the Environment for the specified id
     @param uniqueId: Key for this environment
     @param idGenerators: Hash of generators of ids for this environment. This "generators of ids" feature
         is used basically at User Services to auto-create ids for macs or names, using
         {'mac' : UniqueMacGenerator, 'name' : UniqueNameGenerator } as argument.
     '''
     from uds.core.util.Cache import Cache
     from uds.core.util.Storage import Storage
     self._key = uniqueKey
     self._cache = Cache(uniqueKey)
     self._storage = Storage(uniqueKey)
     self._idGenerators = idGenerators
Ejemplo n.º 17
0
class CalendarChecker(object):
    calendar = None

    # For performance checking
    updates = 0
    cache_hit = 0
    hits = 0

    cache = Cache('calChecker')

    def __init__(self, calendar):
        self.calendar = calendar

    def _updateData(self, dtime):
        # Else, update the array
        CalendarChecker.updates += 1

        data = bitarray.bitarray(60 * 24)  # Granurality is minute
        data.setall(False)

        data_date = dtime.date()

        start = datetime.datetime.combine(data_date,
                                          datetime.datetime.min.time())
        end = datetime.datetime.combine(data_date,
                                        datetime.datetime.max.time())

        for rule in self.calendar.rules.all():
            rr = rule.as_rrule()

            r_end = datetime.datetime.combine(
                rule.end,
                datetime.datetime.max.time()) if rule.end is not None else None

            ruleDurationMinutes = rule.duration_as_minutes
            ruleFrequencyMinutes = rule.frequency_as_minutes

            # Skip "bogus" definitions
            if ruleDurationMinutes == 0 or ruleFrequencyMinutes == 0:
                continue

            # ruleDurationMinutes = ruleDurationMinutes
            # Relative start, rrule can "spawn" the days, so we get the start at least the ruleDurationMinutes of rule to see if it "matches"
            # This means, we need the previous matching day to be "executed" so we can get the "actives" correctly
            diff = ruleFrequencyMinutes if ruleFrequencyMinutes > ruleDurationMinutes else ruleDurationMinutes
            _start = (start if start > rule.start else
                      rule.start) - datetime.timedelta(minutes=diff)

            _end = end if r_end is None or end < r_end else r_end

            for val in rr.between(_start, _end, inc=True):
                if val.date() != data_date:
                    diff = int((start - val).total_seconds() / 60)
                    pos = 0
                    posdur = ruleDurationMinutes - diff
                    if posdur <= 0:
                        continue
                else:
                    pos = val.hour * 60 + val.minute
                    posdur = pos + ruleDurationMinutes
                if posdur > 60 * 24:
                    posdur = 60 * 24
                data[pos:posdur] = True

        return data

    def _updateEvents(self, checkFrom, startEvent=True):

        next_event = None
        for rule in self.calendar.rules.all():
            if rule.start > checkFrom or (rule.end is not None
                                          and rule.end < checkFrom.date()):
                continue

            if startEvent:
                event = rule.as_rrule().after(checkFrom)  # At start
            else:
                event = rule.as_rrule_end().after(checkFrom)  # At end

            if next_event is None or next_event > event:
                next_event = event

        return next_event

    def check(self, dtime=None):
        '''
        Checks if the given time is a valid event on calendar
        @param dtime: Datetime object to check
        TODO: We can improve performance of this by getting from a cache first if we can
        '''
        if dtime is None:
            dtime = getSqlDatetime()

        # First, try to get data from cache if it is valid
        cacheKey = six.text_type(hash(self.calendar.modified)) + six.text_type(
            dtime.date().toordinal()) + self.calendar.uuid + 'checker'
        cached = CalendarChecker.cache.get(cacheKey, None)

        if cached is not None:
            data = bitarray.bitarray()  # Empty bitarray
            data.frombytes(cached)
            CalendarChecker.cache_hit += 1
        else:
            data = self._updateData(dtime)

            # Now data can be accessed as an array of booleans.
            # Store data on persistent cache
            CalendarChecker.cache.put(cacheKey, data.tobytes(), 3600 * 24)

        return data[dtime.hour * 60 + dtime.minute]

    def nextEvent(self, checkFrom=None, startEvent=True, offset=None):
        '''
        Returns next event for this interval
        Returns a list of two elements. First is datetime of event begining, second is timedelta of duration
        '''
        logger.debug('Obtainint nextEvent')
        if checkFrom is None:
            checkFrom = getSqlDatetime()

        if offset is None:
            offset = datetime.timedelta(minutes=0)

        cacheKey = six.text_type(hash(
            self.calendar.modified)) + self.calendar.uuid + six.text_type(
                offset.seconds) + six.text_type(
                    int(time.mktime(checkFrom.timetuple()))) + 'event' + (
                        'x' if startEvent is True else '_')
        next_event = CalendarChecker.cache.get(cacheKey, None)
        if next_event is None:
            logger.debug('Regenerating cached nextEvent')
            next_event = self._updateEvents(
                checkFrom - offset, startEvent
            )  # We substract on checkin, so we can take into account for next execution the "offset" on start & end (just the inverse of current, so we substract it)
            if next_event is not None:
                next_event += offset
            CalendarChecker.cache.put(cacheKey, next_event, 3600)
        else:
            logger.debug('nextEvent cache hit')
            CalendarChecker.hits += 1

        return next_event

    def debug(self):

        return "Calendar checker for {}".format(self.calendar)
Ejemplo n.º 18
0
def checkLogin(request, form, tag=None):
    host = request.META.get('HTTP_HOST') or request.META.get(
        'SERVER_NAME'
    ) or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by(
                        'priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    if 'uds' not in request.COOKIES:
        logger.debug('Request does not have uds cookie')
        return (None, errors.COOKIES_NEEDED)
    if form.is_valid():
        os = request.os
        try:
            authenticator = Authenticator.objects.get(
                uuid=processUuid(form.cleaned_data['authenticator']))
        except Exception:
            authenticator = Authenticator()
        userName = form.cleaned_data['user']
        if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
            userName = userName.lower()

        cache = Cache('auth')
        cacheKey = str(authenticator.id) + userName
        tries = cache.get(cacheKey)
        if tries is None:
            tries = 0
        if authenticator.getInstance(
        ).blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt(
        ):
            authLogLogin(request, authenticator, userName,
                         'Temporarily blocked')
            return (
                None,
                _('Too many authentication errrors. User temporarily blocked'))
        else:
            password = form.cleaned_data['password']
            user = None
            if password == '':
                password = '******'  # Random string, in fact, just a placeholder that will not be used :)
            user = authenticate(userName, password, authenticator)
            logger.debug('User: {}'.format(user))

            if user is None:
                logger.debug(
                    "Invalid user {0} (access denied)".format(userName))
                tries += 1
                cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                authLogLogin(request, authenticator, userName,
                             'Access denied (user not allowed by UDS)')
                return (None, _('Access denied'))
            else:
                request.session.cycle_key()

                logger.debug('User {} has logged in'.format(userName))
                cache.remove(cacheKey)  # Valid login, remove cached tries

                # Add the "java supported" flag to session
                request.session['OS'] = os
                if form.cleaned_data['logouturl'] != '':
                    logger.debug('The logoout url will be {}'.format(
                        form.cleaned_data['logouturl']))
                    request.session['logouturl'] = form.cleaned_data[
                        'logouturl']
                authLogLogin(request, authenticator, user.name)
                return (user, form.cleaned_data['password'])

    logger.info('Invalid form received')
    return (None, _('Invalid data'))
Ejemplo n.º 19
0
def login(request, tag=None):
    '''
    View responsible of logging in an user
    :param request:  http request
    :param tag: tag of login auth
    '''
    # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt())

    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(True) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    logger.debug(request.method)
    if request.method == 'POST':
        if 'uds' not in request.COOKIES:
            logger.debug('Request does not have uds cookie')
            return errors.errorView(request, errors.COOKIES_NEEDED)  # We need cookies to keep session data
        request.session.cycle_key()
        form = LoginForm(request.POST, tag=tag)
        if form.is_valid():
            os = OsDetector.getOsFromUA(request.META.get('HTTP_USER_AGENT'))
            try:
                authenticator = Authenticator.objects.get(pk=form.cleaned_data['authenticator'])
            except Exception:
                authenticator = Authenticator()
            userName = form.cleaned_data['user']

            cache = Cache('auth')
            cacheKey = str(authenticator.id) + userName
            tries = cache.get(cacheKey)
            if tries is None:
                tries = 0
            if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
                form.add_form_error('Too many authentication errors. User temporarily  blocked.')
                authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            else:
                user = authenticate(userName, form.cleaned_data['password'], authenticator)
                logger.debug('User: {}'.format(user))

                if user is None:
                    logger.debug("Invalid credentials for user {0}".format(userName))
                    tries += 1
                    cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                    form.add_form_error('Invalid credentials')
                    authLogLogin(request, authenticator, userName, 'Invalid credentials')
                else:
                    logger.debug('User {} has logged in'.format(userName))
                    cache.remove(cacheKey)  # Valid login, remove cached tries
                    response = HttpResponseRedirect(reverse('uds.web.views.index'))
                    webLogin(request, response, user, form.cleaned_data['password'])
                    # Add the "java supported" flag to session
                    request.session['OS'] = os
                    authLogLogin(request, authenticator, user.name)
                    return response
    else:
        form = LoginForm(tag=tag)

    response = render_to_response(theme.template('login.html'), {'form': form, 'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True)},
                                  context_instance=RequestContext(request))

    getUDSCookie(request, response)

    return response
Ejemplo n.º 20
0
 def run(self):
     logger.debug('Starting cache cleanup')
     Cache.cleanUp()
     logger.debug('Done cache cleanup')
Ejemplo n.º 21
0
def checkLogin(request, form, tag=None):
    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    if 'uds' not in request.COOKIES:
        logger.debug('Request does not have uds cookie')
        return (None, errors.COOKIES_NEEDED)
    if form.is_valid():
        os = request.os
        try:
            authenticator = Authenticator.objects.get(uuid=processUuid(form.cleaned_data['authenticator']))
        except Exception:
            authenticator = Authenticator()
        userName = form.cleaned_data['user']
        if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
            userName = userName.lower()

        cache = Cache('auth')
        cacheKey = str(authenticator.id) + userName
        tries = cache.get(cacheKey)
        if tries is None:
            tries = 0
        if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
            authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            return (None, _('Too many authentication errrors. User temporarily blocked'))
        else:
            password = form.cleaned_data['password']
            user = None
            if password == '':
                password = '******'  # Random string, in fact, just a placeholder that will not be used :)
            user = authenticate(userName, password, authenticator)
            logger.debug('User: {}'.format(user))

            if user is None:
                logger.debug("Invalid user {0} (access denied)".format(userName))
                tries += 1
                cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                authLogLogin(request, authenticator, userName, 'Access denied (user not allowed by UDS)')
                return (None, _('Access denied'))
            else:
                request.session.cycle_key()

                logger.debug('User {} has logged in'.format(userName))
                cache.remove(cacheKey)  # Valid login, remove cached tries

                # Add the "java supported" flag to session
                request.session['OS'] = os
                if form.cleaned_data['logouturl'] != '':
                    logger.debug('The logoout url will be {}'.format(form.cleaned_data['logouturl']))
                    request.session['logouturl'] = form.cleaned_data['logouturl']
                authLogLogin(request, authenticator, user.name)
                return (user, form.cleaned_data['password'])

    logger.info('Invalid form received')
    return (None, _('Invalid data'))
Ejemplo n.º 22
0
 def run(self):
     logger.debug('Starting cache cleanup')
     Cache.cleanUp()
     logger.debug('Done cache cleanup')
Ejemplo n.º 23
0
class Client(object):
    cache = Cache('uds-openstack')

    PUBLIC = 'public'
    PRIVATE = 'private'
    INTERNAL = 'url'

    def __init__(self, host, port, domain, username, password, useSSL=False, projectId=None, region=None, access=None):
        self._authenticated = False
        self._tokenId = None
        self._catalog = None

        self._access = Client.PUBLIC if access is None else access
        self._host, self._port = host, int(port)
        self._domain, self._username, self._password = domain, username, password
        self._userId = None
        self._projectId = projectId
        self._project = None
        self._region = region
        self._timeout = 10

        self._authUrl = 'http{}://{}:{}/'.format('s' if useSSL else '', host, port)

        # Generates a hash for auth + credentials
        h = hashlib.md5()
        h.update(six.binary_type(host))
        h.update(six.binary_type(port))
        h.update(six.binary_type(domain))
        h.update(six.binary_type(username))
        h.update(six.binary_type(password))
        h.update(six.binary_type(useSSL))
        h.update(six.binary_type(projectId))
        h.update(six.binary_type(region))
        self._cacheKey = h.hexdigest()

    def _getEndpointFor(self, type_):  # If no region is indicatad, first endpoint is returned
        for i in self._catalog:
            if i['type'] == type_:
                for j in i['endpoints']:
                    if j['interface'] == self._access and (self._region is None or j['region'] == self._region):
                        return j['url']

    def _requestHeaders(self):
        headers = {'content-type': 'application/json'}
        if self._tokenId is not None:
            headers['X-Auth-Token'] = self._tokenId

        return headers

    def _getFromCache(self):
        cached = self.cache.get(self._cacheKey)
        if cached is not None:
            self._authenticated = True
            self._tokenId = cached['tokenId']
            # Extract the token id
            self._userId = cached['userId']
            self._projectId = cached['projectId']
            self._catalog = cached['catalog']

            return True

        return False

    def _saveToCache(self, validity=600):
        self.cache.put(self._cacheKey,
                       {
                        'tokenId': self._tokenId,
                        'userId': self._userId,
                        'projectId': self._projectId,
                        'catalog': self._catalog
                       },
                       validity - 60)  # We substract some seconds to allow some time desynchronization

    def _clearCache(self):
        self.cache.remove(self._cacheKey)

    def authPassword(self):
        # If cached data exists, use it as auth
        if self._getFromCache() is True:
            return

        data = {
            'auth': {
                'identity': {
                    'methods': [
                        'password'
                    ],
                    'password': {
                        'user': {
                            'name': self._username,
                            'domain': {
                                'name': 'Default' if self._domain is None else self._domain
                            },
                            'password': self._password
                        }
                    }
                }
            }
        }

        if self._projectId is None:
            data['auth']['scope'] = 'unscoped'
        else:
            data['auth']['scope'] = {
                'project': {
                    'id': self._projectId
                }
            }

        r = requests.post(self._authUrl + 'v3/auth/tokens',
                          data=json.dumps(data),
                          headers={'content-type': 'application/json'},
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Invalid Credentials')

        self._authenticated = True
        self._tokenId = r.headers['X-Subject-Token']
        # Extract the token id
        token = r.json()['token']
        self._userId = token['user']['id']
        validity = (dateutil.parser.parse(token['expires_at']).replace(tzinfo=None) - dateutil.parser.parse(token['issued_at']).replace(tzinfo=None)).seconds - 60


        logger.debug('The token {} will be valid for {}'.format(self._tokenId, validity))

        # Now, if endpoints are present (only if tenant was specified), store & cache them
        if self._projectId is not None:
            self._catalog = token['catalog']

        self._saveToCache(validity)

    def ensureAuthenticated(self):
        if self._authenticated is False:
            self.authPassword()


    @authRequired
    def listProjects(self):
        return getRecurringUrlJson(self._authUrl + 'v3/users/{user_id}/projects'.format(user_id=self._userId),
                                     headers=self._requestHeaders(),
                                     key='projects',
                                     errMsg='List Projects',
                                     timeout=self._timeout)


    @authRequired
    def listRegions(self):
        return getRecurringUrlJson(self._authUrl + 'v3/regions/',
                                     headers=self._requestHeaders(),
                                     key='regions',
                                     errMsg='List Regions',
                                     timeout=self._timeout)


    @authProjectRequired
    def listServers(self, detail=False, params=None):
        path = '/servers/' + 'detail' if detail is True else ''
        return getRecurringUrlJson(self._getEndpointFor('compute') + path,
                                    headers=self._requestHeaders(),
                                    key='servers',
                                    params=params,
                                    errMsg='List Vms',
                                    timeout=self._timeout)


    @authProjectRequired
    def listImages(self):
        return getRecurringUrlJson(self._getEndpointFor('image') + '/v2/images?status=active',
                                     headers=self._requestHeaders(),
                                     key='images',
                                     errMsg='List Images',
                                     timeout=self._timeout)


    @authProjectRequired
    def listVolumeTypes(self):
        return getRecurringUrlJson(self._getEndpointFor('volumev2') + '/types',
                                     headers=self._requestHeaders(),
                                     key='volume_types',
                                     errMsg='List Volume Types',
                                     timeout=self._timeout)


    @authProjectRequired
    def listVolumes(self):
        # self._getEndpointFor('volumev2') + '/volumes'
        return getRecurringUrlJson(self._getEndpointFor('volumev2') + '/volumes/detail',
                                     headers=self._requestHeaders(),
                                     key='volumes',
                                     errMsg='List Volumes',
                                     timeout=self._timeout)


    @authProjectRequired
    def listVolumeSnapshots(self, volumeId=None):
        for s in getRecurringUrlJson(self._getEndpointFor('volumev2') + '/snapshots',
                                     headers=self._requestHeaders(),
                                     key='snapshots',
                                     errMsg='List snapshots',
                                     timeout=self._timeout):
            if volumeId is None or s['volume_id'] == volumeId:
                yield s


    @authProjectRequired
    def listAvailabilityZones(self):
        for az in getRecurringUrlJson(self._getEndpointFor('compute') + '/os-availability-zone',
                                     headers=self._requestHeaders(),
                                     key='availabilityZoneInfo',
                                     errMsg='List Availability Zones',
                                     timeout=self._timeout):
            if az['zoneState']['available'] is True:
                yield az['zoneName']


    @authProjectRequired
    def listFlavors(self):
        return getRecurringUrlJson(self._getEndpointFor('compute') + '/flavors',
                                     headers=self._requestHeaders(),
                                     key='flavors',
                                     errMsg='List Flavors',
                                     timeout=self._timeout)


    @authProjectRequired
    def listNetworks(self):
        return getRecurringUrlJson(self._getEndpointFor('network') + '/v2.0/networks',
                                     headers=self._requestHeaders(),
                                     key='networks',
                                     errMsg='List Networks',
                                     timeout=self._timeout)

    @authProjectRequired
    def listPorts(self, networkId=None, ownerId=None):
        params = {}
        if networkId is not None:
            params['network_id'] = networkId
        if ownerId is not None:
            params['device_owner'] = ownerId

        return getRecurringUrlJson(self._getEndpointFor('network') + '/v2.0/ports',
                                   headers=self._requestHeaders(),
                                   key='ports',
                                   params=params,
                                   errMsg='List ports',
                                     timeout=self._timeout)

    @authProjectRequired
    def listSecurityGroups(self):
        return getRecurringUrlJson(self._getEndpointFor('compute') + '/os-security-groups',
                                     headers=self._requestHeaders(),
                                     key='security_groups',
                                     errMsg='List security groups',
                                     timeout=self._timeout)


    @authProjectRequired
    def getServer(self, serverId):
        r = requests.get(self._getEndpointFor('compute') + '/servers/{server_id}'.format(server_id=serverId),
                                    headers=self._requestHeaders(),
                                    verify=VERIFY_SSL,
                                    timeout=self._timeout)

        ensureResponseIsValid(r, 'Get Server information')
        return r.json()['server']

    @authProjectRequired
    def getVolume(self, volumeId):
        r = requests.get(self._getEndpointFor('volumev2') + '/volumes/{volume_id}'.format(volume_id=volumeId),
                         headers=self._requestHeaders(),
                         verify=VERIFY_SSL,
                         timeout=self._timeout)

        ensureResponseIsValid(r, 'Get Volume information')

        v = r.json()['volume']

        return v


    @authProjectRequired
    def getSnapshot(self, snapshotId):
        '''
        States are:
            creating, available, deleting, error,  error_deleting
        '''
        r = requests.get(self._getEndpointFor('volumev2') + '/snapshots/{snapshot_id}'.format(snapshot_id=snapshotId),
                         headers=self._requestHeaders(),
                         verify=VERIFY_SSL,
                         timeout=self._timeout)

        ensureResponseIsValid(r, 'Get Snaphost information')

        v = r.json()['snapshot']

        return v


    @authProjectRequired
    def updateSnapshot(self, snapshotId, name=None, description=None):
        data = { 'snapshot': {} }
        if name is not None:
            data['snapshot']['name'] = name

        if description is not None:
            data['snapshot']['description'] = description

        r = requests.put(self._getEndpointFor('volumev2') + '/snapshots/{snapshot_id}'.format(snapshot_id=snapshotId),
                         data=json.dumps(data),
                         headers=self._requestHeaders(),
                         verify=VERIFY_SSL,
                         timeout=self._timeout)

        ensureResponseIsValid(r, 'Update Snaphost information')

        v = r.json()['snapshot']

        return v


    @authProjectRequired
    def createVolumeSnapshot(self, volumeId, name, description=None):
        description = 'UDS Snapshot' if description is None else description
        data = {
            'snapshot': {
                'name': name,
                'description': description,
                'volume_id': volumeId,
                'force': True
            }
        }

        # First, ensure volume is in state "available"

        r = requests.post(self._getEndpointFor('volumev2') + '/snapshots',
                          data=json.dumps(data),
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Cannot create snapshot. Ensure volume is in state "available"')

        return r.json()['snapshot']


    @authProjectRequired
    def createVolumeFromSnapshot(self, snapshotId, name, description=None):
        description = 'UDS Volume' if description is None else description
        data = {
                'volume': {
                        'name': name,
                        'description': description,
                        # 'volume_type': volType,  # This seems to be the volume type name, not the id
                        'snapshot_id': snapshotId
                }
        }

        r = requests.post(self._getEndpointFor('volumev2') + '/volumes',
                          data=json.dumps(data),
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Cannot create volume from snapshot.')

        return r.json()

    @authProjectRequired
    def createServerFromSnapshot(self, snapshotId, name, availabilityZone, flavorId, networkId, securityGroupsIdsList, count=1):
        data = {
            'server': {
                'name': name,
                'imageRef': '',
                # 'os-availability-zone': availabilityZone,
                'availability_zone': availabilityZone,
                'block_device_mapping_v2': [{
                    'boot_index': '0',
                    'uuid': snapshotId,
                    # 'volume_size': 1,
                    # 'device_name': 'vda',
                    'source_type': 'snapshot',
                    'destination_type': 'volume',
                    'delete_on_termination': True
                }],
                'flavorRef': flavorId,
                # 'OS-DCF:diskConfig': 'AUTO',
                'max_count': count,
                'min_count': count,
                'networks': [ { 'uuid': networkId } ],
                'security_groups': [{'name': sg} for sg in securityGroupsIdsList]
            }
        }

        r = requests.post(self._getEndpointFor('compute') + '/servers',
                          data=json.dumps(data),
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Cannot create instance from snapshot.')

        return r.json()['server']


    @authProjectRequired
    def deleteServer(self, serverId):
        r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
                          data='{"forceDelete": null}',
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Cannot start server (probably server does not exists).')

        # This does not returns anything


    @authProjectRequired
    def deleteSnapshot(self, snapshotId):
        r = requests.delete(self._getEndpointFor('volumev2') + '/snapshots/{snapshot_id}'.format(snapshot_id=snapshotId),
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Cannot remove snapshot.')

        # Does not returns a message body


    @authProjectRequired
    def startServer(self, serverId):
        r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
                          data='{"os-start": null}',
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Starting server')

        # This does not returns anything


    @authProjectRequired
    def stopServer(self, serverId):
        r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
                          data='{"os-stop": null}',
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Stoping server')

    @authProjectRequired
    def suspendServer(self, serverId):
        r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
                          data='{"suspend": null}',
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Suspending server')

    @authProjectRequired
    def resumeServer(self, serverId):
        r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId),
                          data='{"resume": null}',
                          headers=self._requestHeaders(),
                          verify=VERIFY_SSL,
                          timeout=self._timeout)

        ensureResponseIsValid(r, 'Resuming server')


    def testConnection(self):
        # First, ensure requested api is supported
        # We need api version 3.2 or greater
        try:
            r = requests.get(self._authUrl,
                             verify=VERIFY_SSL,
                             headers=self._requestHeaders())
        except Exception:
            raise Exception('Connection error')

        for v in r.json()['versions']['values']:
            if v['id'] >= 'v3.2':
                # Tries to authenticate
                try:
                    self.authPassword()
                    return True
                except Exception:
                    raise Exception(_('Authentication error'))

        raise Exception(_('Openstack does not support identity API 3.2 or newer. This OpenStack server is not compatible with UDS.'))
Ejemplo n.º 24
0
from uds.models import User, Service, UserService, DeployedService, getSqlDatetime

from uds.core.util.stats import counters
from uds.core.util.Cache import Cache
from uds.core.util.State import State
from uds.core.util import encoders
from uds.REST import Handler, RequestError, ResponseError
import pickle
from datetime import timedelta

import logging

logger = logging.getLogger(__name__)

cache = Cache('StatsDispatcher')

# Enclosed methods under /syatem path
POINTS = 365
SINCE = 365  # Days
USE_MAX = True


def getServicesPoolsCounters(servicePool, counter_type):
    # pylint: disable=no-value-for-parameter
    try:
        cacheKey = (servicePool and servicePool.id
                    or 'all') + str(counter_type) + str(POINTS) + str(SINCE)
        to = getSqlDatetime()
        since = to - timedelta(days=SINCE)
        val = cache.get(cacheKey)
Ejemplo n.º 25
0
def login(request, tag=None):
    '''
    View responsible of logging in an user
    :param request:  http request
    :param tag: tag of login auth
    '''
    # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt())

    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    logger.debug(request.method)
    if request.method == 'POST':
        if 'uds' not in request.COOKIES:
            logger.debug('Request does not have uds cookie')
            return errors.errorView(request, errors.COOKIES_NEEDED)  # We need cookies to keep session data
        request.session.cycle_key()
        form = LoginForm(request.POST, tag=tag)
        if form.is_valid():
            os = request.os
            try:
                authenticator = Authenticator.objects.get(pk=form.cleaned_data['authenticator'])
            except Exception:
                authenticator = Authenticator()
            userName = form.cleaned_data['user']
            if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
                userName = userName.lower()

            cache = Cache('auth')
            cacheKey = str(authenticator.id) + userName
            tries = cache.get(cacheKey)
            if tries is None:
                tries = 0
            if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
                form.add_error(None, 'Too many authentication errors. User temporarily  blocked.')
                authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            else:
                password = form.cleaned_data['password']
                user = None
                if password == '':
                    password = '******'
                user = authenticate(userName, password, authenticator)
                logger.debug('User: {}'.format(user))

                if user is None:
                    logger.debug("Invalid credentials for user {0}".format(userName))
                    tries += 1
                    cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                    form.add_error(None, ugettext('Invalid credentials'))
                    authLogLogin(request, authenticator, userName, 'Invalid credentials')
                else:
                    logger.debug('User {} has logged in'.format(userName))
                    cache.remove(cacheKey)  # Valid login, remove cached tries
                    response = HttpResponseRedirect(reverse('uds.web.views.index'))
                    webLogin(request, response, user, form.cleaned_data['password'])
                    # Add the "java supported" flag to session
                    request.session['OS'] = os
                    if form.cleaned_data['logouturl'] != '':
                        logger.debug('The logoout url will be {}'.format(form.cleaned_data['logouturl']))
                        request.session['logouturl'] = form.cleaned_data['logouturl']
                    authLogLogin(request, authenticator, user.name)
                    return response
        else:
            logger.info('Invalid form received')
    else:
        form = LoginForm(tag=tag)

    response = render_to_response(
        theme.template('login.html'),
        {
            'form': form,
            'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True),
            'version': VERSION

        },
        context_instance=RequestContext(request)
    )

    getUDSCookie(request, response)

    return response