Ignore:
Timestamp:
24/11/09 14:14:53 (10 years ago)
Author:
pjkersha
Message:

Unit tested MSI PDP with per attribute entry attribute authority addresses.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/authz.py

    r6039 r6043  
    1717from ndg.security.common.utils.classfactory import importClass 
    1818from ndg.security.common.X509 import X500DN 
    19 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 
    20     NDGSecurityMiddlewareConfigError 
    21  
    22 from ndg.security.server.wsgi import NDGSecurityMiddlewareBase, \ 
    23     NDGSecurityMiddlewareConfigError 
    24 from ndg.security.server.wsgi.authn import SessionMiddlewareBase 
    25  
    26 from ndg.security.common.authz.msi import Policy, PIP, PDP, Request, \ 
    27     Response, Resource, Subject 
     19from ndg.security.common.utils.m2crypto import SSLClientProxy 
     20 
     21from ndg.security.common.credentialwallet import (CredentialWallet, 
     22                                                  SamlCredentialWallet) 
     23from ndg.security.server.wsgi import (NDGSecurityMiddlewareBase,  
     24                                      NDGSecurityMiddlewareConfigError) 
     25 
     26from ndg.security.server.wsgi import (NDGSecurityMiddlewareBase,  
     27                                      NDGSecurityMiddlewareConfigError) 
     28from ndg.security.server.wsgi.authn import (SessionMiddlewareBase,  
     29                                            SessionHandlerMiddlewareBase) 
     30 
     31from ndg.security.common.authz.msi import (Policy, PIP, PIPBase,  
     32                                           PIPAttributeQuery,  
     33                                           PIPAttributeResponse, PDP, Request,  
     34                                           Response, Resource, Subject) 
     35 
    2836 
    2937class PEPResultHandlerMiddleware(SessionMiddlewareBase): 
     
    314322 
    315323    
    316 from ndg.security.common.authz.msi import PIP 
    317 from ndg.security.common.credentialwallet import CredentialWallet 
    318  
    319324class PIPMiddlewareError(Exception): 
    320325    """Base class for Policy Information Point WSGI middleware exception types 
     
    325330    """ 
    326331     
    327 class PIPMiddleware(PIP, NDGSecurityMiddlewareBase): 
     332class NdgPIPMiddleware(PIP, NDGSecurityMiddlewareBase): 
    328333    '''Extend Policy Information Point to enable caching of credentials in 
    329334    a CredentialWallet object held in beaker.session 
    330335    ''' 
    331     environKey = 'ndg.security.server.wsgi.authz.PIPMiddleware' 
     336    ENVIRON_KEYNAME = 'ndg.security.server.wsgi.authz.NdgPIPMiddleware' 
    332337        
    333338    propertyDefaults = { 
     
    387392        self.session = environ.get(self.sessionKey) 
    388393        if self.session is None: 
    389             raise PIPMiddlewareConfigError('No beaker session key "%s" found ' 
     394            raise NdgPIPMiddlewareConfigError('No beaker session key "%s" found ' 
    390395                                           'in environ' % self.sessionKey) 
    391         environ[PIPMiddleware.environKey] = self 
     396        environ[NdgPIPMiddleware.ENVIRON_KEYNAME] = self 
    392397         
    393398        return self._app(environ, start_response) 
     
    416421        # any other security keys when the user logs out 
    417422        if not 'credentialWallet' in self.session: 
    418             log.debug("PIPMiddleware._getAttributeCertificate: adding a " 
     423            log.debug("NdgPIPMiddleware._getAttributeCertificate: adding a " 
    419424                      "Credential Wallet to user session [%s] ...", 
    420425                      self.session['username']) 
     
    433438        attrCert = credentialItem.credential 
    434439        if attrCert is not None: 
    435             log.debug("PIPMiddleware._getAttributeCertificate: retrieved " 
     440            log.debug("NdgPIPMiddleware._getAttributeCertificate: retrieved " 
    436441                      "existing Attribute Certificate cached in Credential " 
    437442                      "Wallet for user session [%s]", 
     
    446451                                                    **kw) 
    447452             
    448             log.debug("PIPMiddleware._getAttributeCertificate: updating " 
     453            log.debug("NdgPIPMiddleware._getAttributeCertificate: updating " 
    449454                      "Credential Wallet with retrieved Attribute " 
    450455                      "Certificate for user session [%s]", 
     
    457462             
    458463            return attrCert 
    459  
     464     
     465 
     466class SamlPIPMiddleware(PIPBase, NDGSecurityMiddlewareBase): 
     467    '''Extend Policy Information Point to enable caching of SAML credentials in 
     468    a CredentialWallet object held in beaker.session 
     469    ''' 
     470    ENVIRON_KEYNAME = 'ndg.security.server.wsgi.authz.SamlPIPMiddleware' 
    460471        
     472    propertyDefaults = { 
     473        'sessionKey': 'beaker.session.ndg.security', 
     474    } 
     475    propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults) 
     476   
     477    CREDENTIAL_WALLET_SESSION_KEYNAME = \ 
     478        SessionHandlerMiddlewareBase.CREDENTIAL_WALLET_SESSION_KEYNAME 
     479    USERNAME_SESSION_KEYNAME = \ 
     480        SessionHandlerMiddlewareBase.USERNAME_SESSION_KEYNAME  
     481           
     482    def __init__(self, app, global_conf, prefix='', **local_conf): 
     483        ''' 
     484        @type app: callable following WSGI interface 
     485        @param app: next middleware application in the chain       
     486        @type global_conf: dict         
     487        @param global_conf: PasteDeploy global configuration dictionary 
     488        @type prefix: basestring 
     489        @param prefix: prefix for configuration items 
     490        @type local_conf: dict         
     491        @param local_conf: PasteDeploy application specific configuration  
     492        dictionary 
     493        ''' 
     494        # Hold SSL Attribute Authority connection settings in SSL Context Proxy 
     495        # object 
     496        self.__sslCtxProxy = SSLContextProxy() 
     497         
     498        nameOffset = len(prefix) 
     499        for k in local_conf.keys(): 
     500            if k.startswith(prefix): 
     501                val = local_conf.pop(k) 
     502                name = k[nameOffset:] 
     503                setattr(self.__sslCtxProxy, name, val) 
     504                 
     505        NDGSecurityMiddlewareBase.__init__(self, app, {}) 
     506      
     507    @property 
     508    def sslCtxProxy(self): 
     509        """SSL Context Proxy object used for setting up an SSL Context for 
     510        queries to the Attribute Authority 
     511        """ 
     512        return self.__sslCtxProxy 
     513     
     514             
     515    def __call__(self, environ, start_response): 
     516        """Take a copy of the session object so that it is in scope for 
     517        _getAttributeCertificate call and add this instance to the environ 
     518        so that the PEPFilter can retrieve it and pass on to the PDP 
     519         
     520        @type environ: dict 
     521        @param environ: WSGI environment variables dictionary 
     522        @type start_response: function 
     523        @param start_response: standard WSGI start response function 
     524        @rtype: iterable 
     525        @return: response 
     526        """ 
     527        self.session = environ.get(self.sessionKey) 
     528        if self.session is None: 
     529            raise SamlPIPMiddlewareConfigError('No beaker session key "%s" ' 
     530                                               'found in environ' %  
     531                                               self.sessionKey) 
     532        environ[SamlPIPMiddleware.ENVIRON_KEYNAME] = self 
     533         
     534        return self._app(environ, start_response) 
     535     
     536    def attributeQuery(self, attributeQuery): 
     537        """Query the Attribute Authority specified in the request to retrieve 
     538        the attributes if any corresponding to the subject 
     539         
     540        @type attributeResponse: PIPAttributeQuery 
     541        @param attributeResponse:  
     542        @rtype: PIPAttributeResponse 
     543        @return: response containing the attributes retrieved from the 
     544        Attribute Authority""" 
     545         
     546        attributeAuthorityURI = attributeQuery[ 
     547                                    PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] 
     548         
     549        log.debug("SamlPIPMiddleware: received attribute query: %r",  
     550                  attributeQuery) 
     551                
     552        # Check for a wallet in the current session - if not present, create 
     553        # one.  See ndg.security.server.wsgi.authn.SessionHandlerMiddleware 
     554        # for session keys.  The 'credentialWallet' key is deleted along with 
     555        # any other security keys when the user logs out 
     556        credentialWalletKeyName = \ 
     557            SamlPIPMiddleware.CREDENTIAL_WALLET_SESSION_KEYNAME 
     558        usernameKeyName = SamlPIPMiddleware.USERNAME_SESSION_KEYNAME 
     559             
     560        if not credentialWalletKeyName in self.session: 
     561            log.debug("SamlPIPMiddleware.attributeQuery: adding a " 
     562                      "Credential Wallet to user session [%s] ...", 
     563                      self.session[usernameKeyName]) 
     564             
     565            credentialWallet = SamlCredentialWallet() 
     566            credentialWallet.userId = self.session[usernameKeyName] 
     567            credentialWallet.sslCtxProxy.copy(self.sslCtxProxy) 
     568             
     569            self.session[credentialWalletKeyName] = credentialWallet 
     570            self.session.save() 
     571        else:     
     572            # Take reference to wallet for efficiency 
     573            credentialWallet = self.session[credentialWalletKeyName]     
     574         
     575        # Check for existing credentials cached in wallet             
     576        credentialItem = credentialWallet.credentialsKeyedByURI.get( 
     577                                                    attributeAuthorityURI) 
     578        if credentialItem is None: 
     579            # No assertion is cached - make a fresh query 
     580            credentialWallet.attributeAuthorityURI = attributeAuthorityURI 
     581            credentialWallet.attributeQuery() 
     582            credentialItem = credentialWallet.credentialsKeyedByURI.get( 
     583                                                    attributeAuthorityURI) 
     584             
     585            log.debug("SamlPIPMiddleware.attributeQuery: updating Credential " 
     586                      "Wallet with retrieved SAML Attribute Assertion " 
     587                      "for user session [%s]", 
     588                      self.session[usernameKeyName]) 
     589        else: 
     590            log.debug("SamlPIPMiddleware.attributeQuery: retrieved existing " 
     591                      "SAML Attribute Assertion cached in Credential Wallet " 
     592                      "for user session [%s]", 
     593                      self.session[usernameKeyName]) 
     594 
     595        attributeResponse = PIPAttributeResponse() 
     596        attributeResponse[Subject.ROLES_NS] = [ 
     597            attribute.value  
     598            for attribute in credentialItem.credential.attributes 
     599        ] 
     600         
     601        log.debug("SamlPIPMiddleware.attributeQuery response: %r",  
     602                  attributeResponse) 
     603         
     604        return attributeResponse 
     605     
     606            
    461607from authkit.authenticate.multi import MultiHandler 
    462608 
     
    505651        # ahead of the PDP's request to it for an Attribute Certificate 
    506652        pipPrefix = AuthorizationMiddleware.PIP_PARAM_PREFIX 
    507         pipFilter = PIPMiddleware(pepFilter, 
    508                                   global_conf, 
    509                                   prefix=pipPrefix, 
    510                                   **app_conf) 
     653        pipFilter = SamlPIPMiddleware(pepFilter, 
     654                                      global_conf, 
     655                                      prefix=pipPrefix, 
     656                                      **app_conf) 
    511657        pepFilter.pdp.pip = pipFilter 
    512658         
Note: See TracChangeset for help on using the changeset viewer.