Changeset 1103 for trunk/rp/trac

Show
Ignore:
Timestamp:
11/21/07 18:59:33 (14 months ago)
Author:
dbuss
Message:

Added auth plugins for session intervetion during login/logout. Started moving group permissions to new structure. Moved /iinfo and tok_meta and tok_claims setting to new session intervention. Added session setter for email and full name if provided in sec token. Fixed: getAssertion not returning all values.

Location:
trunk/rp/trac/infocard_acct/0.11/infocard_acct
Files:
1 added
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/groups.py

    r1098 r1103  
    2323from trac.web.session import Session 
    2424 
    25 class SessionGroupProvider(Component): 
    26         """ 
    27         Provides permission groups by evaluating what is stored on the session 
    28         Note, this doesn't change from invocation to invocation so often a cache 
    29         may be used. 
    30         """ 
    31         implements(IPermissionGroupProvider) 
     25from session import SecTokenChangeListener 
     26 
     27session_var_name = 'sec_groups' 
     28 
     29class SecTokenGroups(Component): 
     30        """Using Policy to move items from the security token to the session as groups 
     31        evaluated once, then cleared from the cache on logout""" 
     32         
     33        implements(SecTokenChangeListener) 
    3234 
    3335        def __init__(self): 
     
    3537                self.enabled = self.config.getbool('infocard_acct', 'groups', True) 
    3638                if not self.enabled: 
    37                         self.env.log.debug('SessionGroupProvider disabled') 
     39                        self.env.log.debug('SecTokenGroups disabled') 
    3840                        return 
    3941                gDefSets =  self.config.getlist('infocard_acct', 'group_definitions') 
    4042                for gDef in gDefSets: 
    4143                        gDef = gDef.strip()  #remove any unsightly spaces 
    42                         self.env.log.debug('SessionGroupProvider processing group definition : ' + gDef) 
     44#                       self.env.log.debug('SecTokenGroups processing group definition : ' + gDef) 
    4345                        groupRules = {}                  
    4446                        groupRules['name'] = gDef 
     
    4951                                self.gDefs[gDef] = groupRules 
    5052 
     53        def login(self, req, secToken): 
     54                """ on login set the parse the token and setup the sec_groups on the session""" 
     55                req.session[session_var_name] = '' 
    5156 
    52         # IPermissionGroupProvider interface 
    53         def get_permission_groups(self, username): 
    54                 """Return a list of names of the groups that the user with the specified 
    55                 name is a member of.""" 
    56  
    57                 #since we don't have the session object we have to fake it 
    58                 session = {} 
    59                  
    60                 try: 
    61                         db = self.env.get_db_cnx() 
    62                         cursor = db.cursor() 
    63                         cursor.execute("SELECT name,value FROM session_attribute " 
    64                                 "WHERE sid=%s and authenticated=%s", (username, int(True))) 
    65                         for name, value in cursor: 
    66                                 session[name] = value 
    67                 except Exception: 
    68                         pass 
    69                          
    70                 # anonymous and authenticated groups are set with the default provider 
    7157                groups = [] 
    72                 if not self.enabled or not self.gDefs.items() or not session.items(): 
    73                         return groups 
     58                if not self.enabled or not self.gDefs.items() or not secToken: 
     59                        return 
    7460                 
    7561                for ruleName in self.gDefs.keys(): 
    7662                        rule = self.gDefs[ruleName] 
    77 #                       try: 
    78                         if self._does_rule_match(rule, session): 
    79                                 values = self._evalute_rule(rule, session) 
    80                                 if values: 
    81                                         self.env.log.debug('SessionGroupProvider rule adds : '\ 
    82                                                 + ','.join(values)) 
    83                                         groups.extend(values) 
    84                                 if rule['exclusive']: 
    85                                         self.env.log.debug('SessionGroupProvider exclusive rule fired: '+ ruleName) 
    86                                         break 
    87 #                       except Exception: 
    88 #                               self.env.log.debug('SessionGroupProvider error evaluating rule: %s' % (ruleName))  
     63                        try: 
     64                                if self._does_rule_match(rule, session): 
     65                                        values = self._evalute_rule(rule, session) 
     66                                        if values: 
     67                                                self.env.log.debug('SecTokenGroups rule adds : '\ 
     68                                                        + ','.join(values)) 
     69                                                groups.extend(values) 
     70                                        if rule['exclusive']: 
     71                                                self.env.log.debug('SecTokenGroups exclusive rule fired: '+ ruleName) 
     72                                                break 
     73                        except Exception: 
     74                                self.env.log.debug('SecTokenGroups error evaluating rule: %s' % (ruleName))  
    8975                         
    9076                if groups: 
    91                         self.env.log.debug('SessionGroupProvider groups: ' + ','.join(groups)) 
     77                        self.env.log.debug('SecTokenGroups groups: ' + ','.join(groups)) 
    9278 
    9379                return groups 
     80                 
     81        def logout(self, req): 
     82                """On logout we must cleanup the sec_groups variable""" 
     83                if req.session.has_key(session_var_name): 
     84                        del req.session[session_var_name] 
    9485 
    9586        def _does_rule_match(self, rule, session): 
     
    115106                return None 
    116107 
     108 
     109class SessionGroupProvider(Component): 
     110        """ 
     111        Provides permission groups by evaluating what is stored on the session 
     112        Note, this doesn't change from invocation to invocation so often a cache 
     113        may be used. 
     114        """ 
     115        implements(IPermissionGroupProvider) 
     116 
     117        # IPermissionGroupProvider interface 
     118        def get_permission_groups(self, username): 
     119                """Return a list of names of the groups that the user with the specified 
     120                name is a member of.""" 
     121 
     122                #since we don't have the session object we have to fake it 
     123                try: 
     124                        db = self.env.get_db_cnx() 
     125                        cursor = db.cursor() 
     126                        cursor.execute("SELECT name,value FROM session_attribute " 
     127                                "WHERE sid=%s and authenticated=%s and name=%s", (username, int(True), session_var_name)) 
     128                        for name, value in cursor: 
     129                                self.env.log.debug('SessionGroupProvider groups: ' + ','.join(value)) 
     130                                return value.split(' ') 
     131                except Exception: 
     132                        pass 
     133                         
     134                return [] 
     135 
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/infocard/infocardlib.py

    r1098 r1103  
    359359                                                                try: 
    360360                                                                        if nsDict[name]: 
     361#                                                                               self.eventLog.add_event("Ignoring multi-valued %s/%s : %s" \ 
     362#                                                                               % (ns, name, value),  
     363#                                                                               event.INFO, 'parse-assertions') 
    361364                                                                                #TODO multivalued check 
    362365                                                                                pass 
    363                                                                         else: 
    364                                                                                 nsDict[name] = value 
    365366                                                                except Exception: 
     367#                                                                       self.eventLog.add_event("Adding %s/%s : %s" \ 
     368#                                                                       % (ns, name, value),  
     369#                                                                       event.INFO, 'parse-assertions') 
    366370                                                                        nsDict[name] = value 
    367371                                                        except Exception: 
     372#                                                               self.eventLog.add_event("First NS, adding %s/%s : %s" \ 
     373#                                                               % (ns, name, value),  
     374#                                                               event.INFO, 'parse-assertions') 
    368375                                                                self.assertions[ns] = {name:value} 
    369376 
     
    375382                #is the identifier a URI or just a short name? 
    376383                ns = None 
    377                 claim =None 
     384                claim = None 
    378385                try: 
    379                         s = identifier.rsplit('/', 1) 
    380                         if s.items() > 1: 
    381                                 ns = s[0] 
    382                         claim = s[-1] 
     386                        if identifier: 
     387                                s = identifier.rsplit('/', 1) 
     388                                if len(s) > 1: 
     389                                        ns = s[0] 
     390                                claim = s[-1] 
    383391                except Exception: 
    384392                        claim = identifier 
     
    396404                                                else: 
    397405                                                        claims[key] = nsDict[key] 
    398                                                 break 
    399406                if claims.items(): 
    400407                        return claims 
     
    424431                        m = hashlib.md5() 
    425432                        signer = None 
     433#                       ppid = self.getAssertion('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier') 
    426434                        ppid = self.getAssertion('privatepersonalidentifier') 
    427435                        if ppid: 
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/templates/infocard-session-detail.html

    r1098 r1103  
    2424        </thead> 
    2525        <tbody> 
     26                        <tr py:if="session.get('name')"> 
     27                                <td><pre>Full Name</pre></td> 
     28                                <td><pre>${session.get('name')}</pre></td> 
     29                        </tr> 
     30                        <tr py:if="session.get('email')"> 
     31                                <td><pre>email</pre></td> 
     32                                <td><pre>${session.get('email')}</pre></td> 
     33                        </tr> 
    2634                        <div if="tok_meta is not None"> 
    2735                                <div py:for="key in tok_meta.rsplit(' ')"> 
  • trunk/rp/trac/infocard_acct/0.11/infocard_acct/web_ui.py

    r1098 r1103  
    5252 
    5353from association import AssociationManager 
     54from session import SecTokenSessionModule 
    5455 
    5556import infocard.xmlseclibs, infocard.infocardlib 
     
    6768 
    6869        implements(ITemplateProvider) 
    69          
     70 
    7071        privateKey = '/' 
    7172        privateKeyPassPhrase = '' 
     
    7374        mandatoryClaims = ('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier',) 
    7475        displayDebug = False 
    75          
     76 
    7677        def __init__(self): 
    7778                privateKey = PathOption('infocard_acct', 'private_key_path', '/') 
     
    8283                privacyPolicyVer = Option('infocard_acct', 'privacy_version', '') 
    8384                issuer = Option('infocard_acct', 'privacy_issuer', '') 
    84                  
     85 
    8586                self.privateKey = self.env.config['infocard_acct'].get('private_key_path') 
    8687                self.requiredClaims = self.env.config['infocard_acct'].get('required_claims') 
     
    9091                self.issuer = self.env.config['infocard_acct'].get('issuer') 
    9192                self.displayDebug = self.config.getbool('infocard_acct', 'debug', False) 
    92          
     93 
    9394                #append all hard coded mandatory claims to the required claims  
    9495                rClaims = None 
     
    9899                        if not rClaims or not (claim in rClaims):   
    99100                                self.requiredClaims = self.requiredClaims + ' ' + claim  
    100                                  
    101                                  
     101 
     102 
    102103        def authenticate(self, req): 
    103104                #self.log.debug('web_ui:LoginModule:authenticate' ) 
     
    121122                        return True 
    122123 
    123                 if re.match(r'/iinfo/?$', req.path_info) is not None: 
    124                         return True 
    125                          
    126124                return False 
    127125 
     
    130128                if req.path_info.startswith('/logout'): 
    131129                        self._cleanup_session(req) 
    132                 if req.path_info.startswith('/iinfo'): 
    133                         data = { 
    134                                 'title': 'Infocard Session Debug', 
    135                                 'session': req.session, 
    136                                 'tok_claims': req.session.get('tok_claims'), 
    137                                 'tok_meta': req.session.get('tok_meta') 
    138                         } 
    139                         return 'infocard-session-detail.html', data, None 
    140130                if req.path_info.startswith('/login'): 
    141131                        if req.authname == 'anonymous': 
     
    153143                                        'submit_text': 'Login' 
    154144                                } 
    155                                  
     145 
    156146                                if not req.args.get('xmlToken') and not req.args.get('cardkeyhash'): 
    157147                                        data['display_infocard'] = 'True' 
     
    173163                                                                data['events'] = secToken.eventLog.events 
    174164                                                        return 'infocard-detail.html', data, None 
    175                                                          
     165 
    176166                                        data['cardkeyhash'] = cardkeyhash 
    177167                                         
     
    194184                                        data['events'] = secToken.eventLog.events 
    195185                                return 'infocard-detail.html', data, None 
    196                                  
     186 
    197187                        self.log.debug("%s",  self.displayDebug) 
    198188                        self._setup_session(req) 
    199189                return auth.LoginModule.process_request(self, req) 
    200                  
     190 
    201191        def _cleanup_session(self, req): 
    202192                """We need to delete session attributes here 
    203193                """ 
    204                 pass 
     194                SecTokenSessionModule(self.env).logout(req) 
    205195 
    206196        def _setup_session(self, req): 
     
    208198                the infocard must be parsed and availible on this request 
    209199                """ 
    210                 secToken = self._get_token(req) 
    211                 if secToken: 
    212                         metaData = secToken.getMetaData() 
    213                         if metaData: 
    214                                 tok_meta='' 
    215                                 for key in metaData.keys(): 
    216                                         req.session['tok_meta_'+key] = metaData[key] 
    217                                         tok_meta += ' tok_meta_'+key 
    218                                 req.session['tok_meta'] = tok_meta 
    219                                 #self.log.debug("tok_meta : %s", tok_meta) 
    220                         claims = secToken.getAssertion() 
    221                         if claims and claims.keys(): 
    222                                 tok_claims='' 
    223                                 for key in claims.keys(): 
    224                                         req.session['tok_claim_'+key] = claims[key] 
    225                                         tok_claims += ' tok_claim_'+key 
    226                                 req.session['tok_claims'] = tok_claims 
    227                                 #self.log.debug("tok_claims : %s", tok_claims) 
     200                SecTokenSessionModule(self.env).login(req, self._get_token(req)) 
    228201 
    229202        def _do_debug_login(self, req): 
     
    233206                ignore_case = BoolOption('trac', 'ignore_auth_case', 'false', 
    234207                """Whether case should be ignored for login names (''since 0.9'').""") 
    235                  
     208 
    236209                remote_user = req.remote_user 
    237210                if self.ignore_case: 
     
    266239                                 
    267240                return processor 
    268                  
    269                  
     241 
     242 
    270243        def _get_token(self, req): 
    271244                """get the security token, cache it on the request so it isn't reparsed 
    272245                """ 
    273                  
     246 
    274247                secToken = None 
    275248                try: 
     
    336309 
    337310        # ITemplateProvider 
    338          
     311 
    339312        def get_htdocs_dirs(self): 
    340313                """Return the absolute path of a directory containing additional