def __init__(self): config = self.get_component_config() groupttl = config.get('group_ttl', 60 * 60 * 24 * 14) groupsize = config.get('group_size', 50) userttl = config.get('user_ttl', 5 * 60) usersize = config.get('user_size', 500) self.groupcache = SimpleCache(lifetime=groupttl, killtime=groupttl, maxsize=groupsize) self.usercache = SimpleCache(lifetime=userttl, killtime=userttl, maxsize=usersize) self.usernamemap = {}
class MemorySubjectCache(Component): """Caches subjects in memory """ implements(ISubjectCache) def __init__(self): config = self.get_component_config() groupttl = config.get('group_ttl', 60 * 60 * 24 * 14) groupsize = config.get('group_size', 50) userttl = config.get('user_ttl', 5 * 60) usersize = config.get('user_size', 500) self.groupcache = SimpleCache( lifetime=groupttl, killtime=groupttl, maxsize=groupsize) self.usercache = SimpleCache( lifetime=userttl, killtime=userttl, maxsize=usersize) self.usernamemap = {} def get_user(self, userid): return self.usercache.get(userid) def get_user_by_name(self, username): if username in self.usernamemap: return self.get_user(self.usernamemap[username]) def get_users(self, userids): res = {} for userid in userids: res[userid] = self.get_user(userid) return res def add_users(self, users): for user in users: self.usercache.set(user.userid, user) self.usernamemap[user.username] = user.userid def get_group(self, groupid): return self.groupcache.get(groupid) def get_groups(self, groupids): res = {} for groupid in groupids: res[groupid] = self.get_group(groupid) return res def add_groups(self, groups): for group in groups: self.groupcache.set(group.groupid, group)
class MemorySubjectCache(Component): """Caches subjects in memory """ implements(ISubjectCache) def __init__(self): config = self.get_component_config() groupttl = config.get('group_ttl', 60 * 60 * 24 * 14) groupsize = config.get('group_size', 50) userttl = config.get('user_ttl', 5 * 60) usersize = config.get('user_size', 500) self.groupcache = SimpleCache(lifetime=groupttl, killtime=groupttl, maxsize=groupsize) self.usercache = SimpleCache(lifetime=userttl, killtime=userttl, maxsize=usersize) self.usernamemap = {} def get_user(self, userid): return self.usercache.get(userid) def get_user_by_name(self, username): if username in self.usernamemap: return self.get_user(self.usernamemap[username]) def get_users(self, userids): res = {} for userid in userids: res[userid] = self.get_user(userid) return res def add_users(self, users): for user in users: self.usercache.set(user.userid, user) self.usernamemap[user.username] = user.userid def get_group(self, groupid): return self.groupcache.get(groupid) def get_groups(self, groupids): res = {} for groupid in groupids: res[groupid] = self.get_group(groupid) return res def add_groups(self, groups): for group in groups: self.groupcache.set(group.groupid, group)
def __init__(self, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.cache = SimpleCache()
class HTTPBasicAuthenticator(object): translator = ExtensionPoint(IUserTranslator) authenticator = ExtensionPoint(IUserAuthenticator) def __init__(self, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.cache = SimpleCache() def __call__(self, environ): # default to guest environ['cydra_user'] = self.cydra.get_user(userid='*') # consult the REMOTE_USER variable. If this is set, apache or some other part # already did the authetication. We will trust that judgement userid = environ.get('REMOTE_USER', None) logger.debug('Remote user: "******"', str(userid)) if userid is None: # Nothing already set. Perform HTTP auth ourselves author = environ.get('HTTP_AUTHORIZATION', None) logger.debug( "No remote user supplied, trying Authorization header") if author is None: logger.debug("No Authorization header supplied") return self.cydra.get_user(userid='*') if author.strip().lower()[:5] != 'basic': # atm only basic is supported logging.warning( "User tried to use a different auth method (not basic): %s" ) return self.cydra.get_user(userid='*') userpw_base64 = author.strip()[5:].strip() if userpw_base64 in self.cache: # login cached as successful, we can now set REMOTE_USER for further use user = self.cache.get(userpw_base64) logger.debug('Author header found in cache, user: %s (%s)', user.full_name, user.userid) environ['REMOTE_USER'] = user.userid environ['cydra_user'] = user return user userid, pw = userpw_base64.decode('base64').split(':', 1) # yes, you probably don't want to leak information about a password # such as its length into the log. The length helps to debug issues with extra # whitespace though logger.debug('Got user "%s" with passwordlen %d. Agent: %s', userid, len(pw), environ.get('HTTP_USER_AGENT', 'None')) if is_urldecode_necessary(environ.get('HTTP_USER_AGENT', '')): logger.info('Client is broken w.r.t. url encoding: %s', environ.get('HTTP_USER_AGENT', 'None')) userid = urllib.unquote(userid) pw = urllib.unquote(pw) user = self.translator.username_to_user(userid) if user is None: logger.debug('Lookup for %s failed', userid) user = self.cydra.get_user(userid='*') logger.debug('User lookup gave %s (%s)', user.full_name, user.userid) if user.is_guest: logger.info('User %s resolved to guest', userid) return user elif self.authenticator.user_password(user, pw): # login successful, we can now set REMOTE_USER for further use environ['REMOTE_USER'] = user.userid environ['cydra_user'] = user # and cache logger.debug('Caching login data for %s (%s)', user.full_name, user.userid) self.cache.set(userpw_base64, user) return user else: logger.info('User %s (%s) supplied a wrong password', user.full_name, user.userid) return self.cydra.get_user(userid='*') else: logger.debug("Got REMOTE_USER=%s", userid) if userid in self.cache: user = self.cache.get(userid) environ['cydra_user'] = user else: user = self.translator.username_to_user(userid) if user is None: logger.debug('Lookup for %s failed', userid) user = self.cydra.get_user(userid='*') if not user.is_guest: self.cache.set(userid, user) environ['cydra_user'] = user return user
class HTTPBasicAuthenticator(object): translator = ExtensionPoint(IUserTranslator) authenticator = ExtensionPoint(IUserAuthenticator) def __init__(self, cyd=None): if cyd is None: cyd = cydra.Cydra() self.cydra = self.compmgr = cyd self.cache = SimpleCache() def __call__(self, environ): # default to guest environ['cydra_user'] = self.cydra.get_user(userid='*') # consult the REMOTE_USER variable. If this is set, apache or some other part # already did the authetication. We will trust that judgement userid = environ.get('REMOTE_USER', None) logger.debug('Remote user: "******"', str(userid)) if userid is None: # Nothing already set. Perform HTTP auth ourselves author = environ.get('HTTP_AUTHORIZATION', None) logger.debug("No remote user supplied, trying Authorization header") if author is None: logger.debug("No Authorization header supplied") return self.cydra.get_user(userid='*') if author.strip().lower()[:5] != 'basic': # atm only basic is supported logging.warning("User tried to use a different auth method (not basic): %s") return self.cydra.get_user(userid='*') userpw_base64 = author.strip()[5:].strip() if userpw_base64 in self.cache: # login cached as successful, we can now set REMOTE_USER for further use user = self.cache.get(userpw_base64) logger.debug('Author header found in cache, user: %s (%s)', user.full_name, user.userid) environ['REMOTE_USER'] = user.userid environ['cydra_user'] = user return user userid, pw = userpw_base64.decode('base64').split(':', 1) # yes, you probably don't want to leak information about a password # such as its length into the log. The length helps to debug issues with extra # whitespace though logger.debug('Got user "%s" with passwordlen %d. Agent: %s', userid, len(pw), environ.get('HTTP_USER_AGENT', 'None')) if is_urldecode_necessary(environ.get('HTTP_USER_AGENT', '')): logger.info('Client is broken w.r.t. url encoding: %s', environ.get('HTTP_USER_AGENT', 'None')) userid = urllib.unquote(userid) pw = urllib.unquote(pw) user = self.translator.username_to_user(userid) if user is None: logger.debug('Lookup for %s failed', userid) user = self.cydra.get_user(userid='*') logger.debug('User lookup gave %s (%s)', user.full_name, user.userid) if user.is_guest: logger.info('User %s resolved to guest', userid) return user elif self.authenticator.user_password(user, pw): # login successful, we can now set REMOTE_USER for further use environ['REMOTE_USER'] = user.userid environ['cydra_user'] = user # and cache logger.debug('Caching login data for %s (%s)', user.full_name, user.userid) self.cache.set(userpw_base64, user) return user else: logger.info('User %s (%s) supplied a wrong password', user.full_name, user.userid) return self.cydra.get_user(userid='*') else: logger.debug("Got REMOTE_USER=%s", userid) if userid in self.cache: return self.cache.get(userid) else: user = self.translator.username_to_user(userid) if user is None: logger.debug('Lookup for %s failed', userid) user = self.cydra.get_user(userid='*') if not user.is_guest: self.cache.set(userid, user) return user