Changeset 6597 for TI12-security/trunk


Ignore:
Timestamp:
19/02/10 14:32:13 (10 years ago)
Author:
pjkersha
Message:

New Policy Information Point class ndg.security.common.authz.pip.esg.PIP for ESG Authorisation Service.

Location:
TI12-security/trunk/NDGSecurity/python
Files:
5 added
4 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/__init__.py

    r5165 r6597  
    1111__contact__ = "Philip.Kershaw@stfc.ac.uk" 
    1212__revision__ = "$Id: __init__.py 3755 2008-04-04 09:11:44Z pjkersha $" 
     13  
     14        
     15class _AttrDict(dict): 
     16    """Utility class for holding a constrained list of attributes governed 
     17    by a namespace list""" 
     18    namespaces = () 
     19    def __init__(self, **attributes): 
     20        invalidAttributes = [attr for attr in attributes 
     21                             if attr not in self.__class__.namespaces] 
     22        if len(invalidAttributes) > 0: 
     23            raise TypeError("The following attribute namespace(s) are not " 
     24                            "recognised: %s" % invalidAttributes) 
     25             
     26        self.update(attributes) 
     27 
     28    def __setitem__(self, key, val): 
     29        if key not in self.__class__.namespaces: 
     30            raise KeyError('Namespace "%s" not recognised.  Valid namespaces ' 
     31                           'are: %s' % self.__class__.namespaces) 
     32             
     33        dict.__setitem__(self, key, val) 
     34 
     35 
     36    def update(self, d, **kw):         
     37        for dictArg in (d, kw): 
     38            for k in dictArg: 
     39                if k not in self.__class__.namespaces: 
     40                    raise KeyError('Namespace "%s" not recognised.  Valid ' 
     41                                   'namespaces are: %s' %  
     42                                   self.__class__.namespaces) 
     43         
     44        dict.update(self, d, **kw) 
     45  
     46     
     47class SubjectRetrievalError(Exception): 
     48    """Generic exception class for errors related to information about the 
     49    subject"""        
     50        
     51         
     52class SubjectBase(object): 
     53    '''Base class Subject designator''' 
     54    namespaces = ("urn:ndg:security:authz:1.0:attr:subject:roles", ) 
     55    (ROLES_NS,) = namespaces 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_common/ndg/security/common/authz/msi.py

    r6586 r6597  
    2020from ndg.security.common.utils import TypedList 
    2121from ndg.security.common.utils.etree import QName 
     22from ndg.security.common.authz import _AttrDict, SubjectBase 
     23from ndg.security.common.authz.pip import (PIPBase, PIPAttributeQuery,  
     24                                           PIPAttributeResponse, 
     25                                           SubjectRetrievalError) 
    2226 
    2327 
     
    2529    """Error reading policy attributes from file""" 
    2630 
     31 
    2732class InvalidPolicyXmlNsError(Exception): 
    2833    """Invalid XML namespace for policy document""" 
     34 
    2935 
    3036class PolicyComponent(object): 
     
    338344        resource.parse(root) 
    339345        return resource 
    340   
    341         
    342 class _AttrDict(dict): 
    343     """Utility class for holding a constrained list of attributes governed 
    344     by a namespace list""" 
    345     namespaces = () 
    346     def __init__(self, **attributes): 
    347         invalidAttributes = [attr for attr in attributes 
    348                              if attr not in self.__class__.namespaces] 
    349         if len(invalidAttributes) > 0: 
    350             raise TypeError("The following attribute namespace(s) are not " 
    351                             "recognised: %s" % invalidAttributes) 
    352              
    353         self.update(attributes) 
    354  
    355     def __setitem__(self, key, val): 
    356         if key not in self.__class__.namespaces: 
    357             raise KeyError('Namespace "%s" not recognised.  Valid namespaces ' 
    358                            'are: %s' % self.__class__.namespaces) 
    359              
    360         dict.__setitem__(self, key, val) 
    361  
    362  
    363     def update(self, d, **kw):         
    364         for dictArg in (d, kw): 
    365             for k in dictArg: 
    366                 if k not in self.__class__.namespaces: 
    367                     raise KeyError('Namespace "%s" not recognised.  Valid ' 
    368                                    'namespaces are: %s' %  
    369                                    self.__class__.namespaces) 
    370          
    371         dict.update(self, d, **kw) 
    372  
    373  
    374 class Subject(_AttrDict): 
    375     '''Subject designator''' 
    376     namespaces = ( 
    377         "urn:ndg:security:authz:1.0:attr:subject:userId", 
    378         "urn:ndg:security:authz:1.0:attr:subject:sessionId", 
    379         "urn:ndg:security:authz:1.0:attr:subject:sessionManagerURI", 
    380         "urn:ndg:security:authz:1.0:attr:subject:roles"         
    381     ) 
    382     (USERID_NS, SESSIONID_NS, SESSIONMANAGERURI_NS, ROLES_NS) = namespaces 
     346 
     347 
     348class Subject(SubjectBase): 
     349    '''MSI Subject designator''' 
    383350 
    384351 
     
    471438                       fset=_setMessage, 
    472439                       doc="Optional message associated with response") 
    473          
    474          
    475 from ndg.security.common.AttCert import (AttCertInvalidSignature,  
    476     AttCertNotBeforeTimeError, AttCertExpired, AttCertError) 
    477        
    478 from ndg.security.common.sessionmanager import (SessionManagerClient,  
    479     SessionNotFound, SessionCertTimeError, SessionExpired, InvalidSession,  
    480     AttributeRequestDenied) 
    481  
    482 from ndg.security.common.attributeauthority import (AttributeAuthorityClient,  
    483     NoTrustedHosts, NoMatchingRoleInTrustedHosts,  
    484     InvalidAttributeAuthorityClientCtx) 
    485 from ndg.security.common.attributeauthority import AttributeRequestDenied as \ 
    486     AA_AttributeRequestDenied 
    487                     
    488 from ndg.security.common.authz.pdp import (PDPUserNotLoggedIn,  
    489     PDPUserAccessDenied) 
    490      
    491      
    492 class SubjectRetrievalError(Exception): 
    493     """Generic exception class for errors related to information about the 
    494     subject""" 
    495      
    496 class InvalidAttributeCertificate(SubjectRetrievalError): 
    497     "The certificate containing authorisation roles is invalid" 
    498     def __init__(self, msg=None): 
    499         SubjectRetrievalError.__init__(self, msg or  
    500                                        InvalidAttributeCertificate.__doc__) 
    501  
    502 class AttributeCertificateInvalidSignature(SubjectRetrievalError): 
    503     ("There is a problem with the signature of the certificate containing " 
    504      "authorisation roles") 
    505     def __init__(self, msg=None): 
    506         SubjectRetrievalError.__init__(self, msg or  
    507                                 AttributeCertificateInvalidSignature.__doc__) 
    508                
    509 class AttributeCertificateNotBeforeTimeError(SubjectRetrievalError): 
    510     ("There is a time issuing error with certificate containing authorisation " 
    511     "roles") 
    512     def __init__(self, msg=None): 
    513         SubjectRetrievalError.__init__(self, msg or  
    514                                 AttributeCertificateNotBeforeTimeError.__doc__) 
    515          
    516 class AttributeCertificateExpired(SubjectRetrievalError): 
    517     "The certificate containing authorisation roles has expired" 
    518     def __init__(self, msg=None): 
    519         SubjectRetrievalError.__init__(self, msg or  
    520                                        AttributeCertificateExpired.__doc__) 
    521              
    522 class SessionExpiredMsg(SubjectRetrievalError): 
    523     'Session has expired.  Please re-login at your home organisation' 
    524     def __init__(self, msg=None): 
    525         SubjectRetrievalError.__init__(self, msg or SessionExpiredMsg.__doc__) 
    526  
    527 class SessionNotFoundMsg(SubjectRetrievalError): 
    528     'No session was found.  Please try re-login with your home organisation' 
    529     def __init__(self, msg=None): 
    530         SubjectRetrievalError.__init__(self, msg or  
    531                                        SessionNotFoundMsg.__doc__) 
    532  
    533 class InvalidSessionMsg(SubjectRetrievalError): 
    534     'Session is invalid.  Please try re-login with your home organisation' 
    535     def __init__(self, msg=None): 
    536         SubjectRetrievalError.__init__(self, msg or  
    537                                        InvalidSessionMsg.__doc__) 
    538  
    539 class InitSessionCtxError(SubjectRetrievalError): 
    540     'A problem occurred initialising a session connection' 
    541     def __init__(self, msg=None): 
    542         SubjectRetrievalError.__init__(self, msg or  
    543                                        InitSessionCtxError.__doc__) 
    544  
    545 class AttributeCertificateRequestError(SubjectRetrievalError): 
    546     'A problem occurred requesting a certificate containing authorisation roles' 
    547     def __init__(self, msg=None): 
    548         SubjectRetrievalError.__init__(self, msg or  
    549                                     AttributeCertificateRequestError.__doc__) 
    550  
    551 class PIPAttributeQuery(_AttrDict): 
    552     '''Policy Information Point Query class.''' 
    553     namespaces = ( 
    554         "urn:ndg:security:authz:1.0:attr:subject", 
    555         "urn:ndg:security:authz:1.0:attr:attributeAuthorityURI", 
    556     )   
    557     (SUBJECT_NS, ATTRIBUTEAUTHORITY_NS) = namespaces     
    558  
    559 class PIPAttributeResponse(dict): 
    560     '''Policy Information Point Response class.''' 
    561     namespaces = ( 
    562         Subject.ROLES_NS, 
    563     ) 
    564  
    565  
    566 class PIPBase(object): 
    567     """Policy Information Point base class.  PIP enables PDP to get user  
    568     attribute information in order to make access control decisions  
    569     """ 
    570     def __init__(self, prefix='', **cfg): 
    571         '''Initialise settings for connection to an Attribute Authority''' 
    572         raise NotImplementedError(PIPBase.__init__.__doc__) 
    573      
    574     def attributeQuery(self, attributeQuery): 
    575         """Query the Attribute Authority specified in the request to retrieve 
    576         the attributes if any corresponding to the subject 
    577          
    578         @type attributeResponse: PIPAttributeQuery 
    579         @param attributeResponse:  
    580         @rtype: PIPAttributeResponse 
    581         @return: response containing the attributes retrieved from the 
    582         Attribute Authority""" 
    583         raise NotImplementedError(PIPBase.attributeQuery.__doc__) 
    584      
    585  
    586 from ndg.security.common.wssecurity import WSSecurityConfig 
    587  
    588 class NdgPIP(PIPBase): 
    589     """Policy Information Point - this implementation enables the PDP to  
    590     retrieve attributes about the Subject""" 
    591     wsseSectionName = 'wssecurity' 
    592      
    593     def __init__(self, prefix='', **cfg): 
    594         '''Set-up WS-Security and SSL settings for connection to an 
    595         Attribute Authority 
    596          
    597         @type **cfg: dict 
    598         @param **cfg: keywords including 'sslCACertFilePathList' used to set a 
    599         list of CA certificates for an SSL connection to the Attribute 
    600         Authority if used and also WS-Security settings as used by 
    601         ndg.security.common.wssecurity.WSSecurityConfig 
    602         ''' 
    603         self.wssecurityCfg = WSSecurityConfig() 
    604         wssePrefix = prefix + NdgPIP.wsseSectionName 
    605         self.wssecurityCfg.update(cfg, prefix=wssePrefix) 
    606                   
    607         # List of CA certificates used to verify peer certificate with SSL 
    608         # connections to Attribute Authority 
    609         self.sslCACertFilePathList = cfg.get(prefix+'sslCACertFilePathList', []) 
    610          
    611         # List of CA certificates used to verify the signatures of  
    612         # Attribute Certificates retrieved 
    613         self.caCertFilePathList = cfg.get(prefix + 'caCertFilePathList', []) 
    614  
    615     def attributeQuery(self, attributeQuery): 
    616         """Query the Attribute Authority specified in the request to retrieve 
    617         the attributes if any corresponding to the subject 
    618          
    619         @type attributeResponse: PIPAttributeQuery 
    620         @param attributeResponse:  
    621         @rtype: PIPAttributeResponse 
    622         @return: response containing the attributes retrieved from the 
    623         Attribute Authority""" 
    624          
    625         subject = attributeQuery[PIPAttributeQuery.SUBJECT_NS] 
    626         username = subject[Subject.USERID_NS] 
    627         sessionId = subject[Subject.SESSIONID_NS] 
    628         attributeAuthorityURI = attributeQuery[ 
    629                                     PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] 
    630          
    631         sessionId = subject[Subject.SESSIONID_NS] 
    632          
    633         log.debug("PIP: received attribute query: %r", attributeQuery) 
    634          
    635         attributeCertificate = self._getAttributeCertificate( 
    636                     attributeAuthorityURI, 
    637                     username=username, 
    638                     sessionId=sessionId, 
    639                     sessionManagerURI=subject[Subject.SESSIONMANAGERURI_NS]) 
    640  
    641         attributeResponse = PIPAttributeResponse() 
    642         attributeResponse[Subject.ROLES_NS] = attributeCertificate.roles 
    643          
    644         log.debug("PIP.attributeQuery response: %r", attributeResponse) 
    645          
    646         return attributeResponse 
    647      
    648     def _getAttributeCertificate(self, 
    649                                  attributeAuthorityURI, 
    650                                  username=None, 
    651                                  sessionId=None, 
    652                                  sessionManagerURI=None): 
    653         '''Retrieve an Attribute Certificate 
    654  
    655         @type attributeAuthorityURI: basestring 
    656         @param attributeAuthorityURI: URI to Attribute Authority service 
    657         @type username: basestring 
    658         @param username: subject user identifier - could be an OpenID         
    659         @type sessionId: basestring 
    660         @param sessionId: Session Manager session handle 
    661         @type sessionManagerURI: basestring 
    662         @param sessionManagerURI: URI to remote session manager service 
    663         @rtype: ndg.security.common.AttCert.AttCert 
    664         @return: Attribute Certificate containing user roles 
    665         ''' 
    666  
    667         if sessionId and sessionManagerURI: 
    668             attrCert = self._getAttributeCertificateFromSessionManager( 
    669                                                      attributeAuthorityURI, 
    670                                                      sessionId, 
    671                                                      sessionManagerURI) 
    672         else: 
    673             attrCert = self._getAttributeCertificateFromAttributeAuthority( 
    674                                                      attributeAuthorityURI, 
    675                                                      username) 
    676          
    677         try: 
    678             attrCert.certFilePathList = self.caCertFilePathList 
    679             attrCert.isValid(raiseExcep=True) 
    680          
    681         except AttCertInvalidSignature, e: 
    682             log.exception(e) 
    683             raise AttributeCertificateInvalidSignature() 
    684          
    685         except AttCertNotBeforeTimeError, e:    
    686             log.exception(e) 
    687             raise AttributeCertificateNotBeforeTimeError() 
    688          
    689         except AttCertExpired, e:    
    690             log.exception(e) 
    691             raise AttributeCertificateExpired() 
    692  
    693         except AttCertError, e: 
    694             log.exception(e) 
    695             raise InvalidAttributeCertificate() 
    696          
    697         return attrCert 
    698              
    699     def _getAttributeCertificateFromSessionManager(self, 
    700                                                    attributeAuthorityURI, 
    701                                                    sessionId, 
    702                                                    sessionManagerURI): 
    703         '''Retrieve an Attribute Certificate using the subject's Session 
    704         Manager 
    705          
    706         @type sessionId: basestring 
    707         @param sessionId: Session Manager session handle 
    708         @type sessionManagerURI: basestring 
    709         @param sessionManagerURI: URI to remote session manager service 
    710         @type attributeAuthorityURI: basestring 
    711         @param attributeAuthorityURI: URI to Attribute Authority service 
    712         @rtype: ndg.security.common.AttCert.AttCert 
    713         @return: Attribute Certificate containing user roles 
    714         ''' 
    715          
    716         log.debug("PIP._getAttributeCertificateFromSessionManager ...") 
    717          
    718         try: 
    719             # Create Session Manager client - if a file path was set, setting 
    720             # are read from a separate config file section otherwise, from the 
    721             # PDP config object 
    722             smClnt = SessionManagerClient( 
    723                             uri=sessionManagerURI, 
    724                             sslCACertFilePathList=self.sslCACertFilePathList, 
    725                             cfg=self.wssecurityCfg) 
    726         except Exception, e: 
    727             log.error("Creating Session Manager client: %s" % e) 
    728             raise InitSessionCtxError() 
    729               
    730         try: 
    731             # Make request for attribute certificate 
    732             return smClnt.getAttCert( 
    733                                 attributeAuthorityURI=attributeAuthorityURI, 
    734                                 sessID=sessionId) 
    735          
    736         except AttributeRequestDenied, e: 
    737             log.error("Request for attribute certificate denied: %s" % e) 
    738             raise PDPUserAccessDenied() 
    739          
    740         except SessionNotFound, e: 
    741             log.error("No session found: %s" % e) 
    742             raise SessionNotFoundMsg() 
    743  
    744         except SessionExpired, e: 
    745             log.error("Session expired: %s" % e) 
    746             raise SessionExpiredMsg() 
    747  
    748         except SessionCertTimeError, e: 
    749             log.error("Session cert. time error: %s" % e) 
    750             raise InvalidSessionMsg() 
    751              
    752         except InvalidSession, e: 
    753             log.error("Invalid user session: %s" % e) 
    754             raise InvalidSessionMsg() 
    755  
    756         except Exception, e: 
    757             log.error("Request from Session Manager [%s] to Attribute " 
    758                       "Authority [%s] for attribute certificate: %s: %s" %  
    759                       (sessionManagerURI, 
    760                        attributeAuthorityURI, 
    761                        e.__class__, e)) 
    762             raise AttributeCertificateRequestError() 
    763              
    764     def _getAttributeCertificateFromAttributeAuthority(self, 
    765                                                        attributeAuthorityURI, 
    766                                                        username): 
    767         '''Retrieve an Attribute Certificate direct from an Attribute 
    768         Authority.  This method is invoked if no session ID or Session  
    769         Manager endpoint where provided 
    770          
    771         @type username: basestring 
    772         @param username: user identifier - may be an OpenID URI 
    773         @type attributeAuthorityURI: basestring 
    774         @param attributeAuthorityURI: URI to Attribute Authority service 
    775         @rtype: ndg.security.common.AttCert.AttCert 
    776         @return: Attribute Certificate containing user roles 
    777         ''' 
    778          
    779         log.debug("PIP._getAttributeCertificateFromAttributeAuthority ...") 
    780         
    781         try: 
    782             # Create Attribute Authority client - if a file path was set,  
    783             # settingare read  from a separate config file section otherwise,  
    784             # from the PDP config object 
    785             aaClnt = AttributeAuthorityClient( 
    786                             uri=attributeAuthorityURI, 
    787                             sslCACertFilePathList=self.sslCACertFilePathList, 
    788                             cfg=self.wssecurityCfg) 
    789         except Exception: 
    790             log.error("Creating Attribute Authority client: %s", 
    791                       traceback.format_exc()) 
    792             raise InitSessionCtxError() 
    793          
    794           
    795         try: 
    796             # Make request for attribute certificate 
    797             return aaClnt.getAttCert(userId=username) 
    798          
    799          
    800         except AA_AttributeRequestDenied: 
    801             log.error("Request for attribute certificate denied: %s", 
    802                       traceback.format_exc()) 
    803             raise PDPUserAccessDenied() 
    804          
    805         # TODO: handle other specific Exception types here for more fine 
    806         # grained response info 
    807  
    808         except Exception, e: 
    809             log.error("Request to Attribute Authority [%s] for attribute " 
    810                       "certificate: %s: %s", attributeAuthorityURI, 
    811                       e.__class__, traceback.format_exc()) 
    812             raise AttributeCertificateRequestError() 
    813          
    814 # Backwards compatibility 
    815 PIP = NdgPIP 
    816440 
    817441             
  • TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/__init__.py

    r6575 r6597  
    548548        if not isinstance(attributeQuery, PIPAttributeQuery): 
    549549            raise TypeError('Expecting %r type for input "attributeQuery"; ' 
    550                             'got %r' % (AttributeQuery, type(attributeQuery))) 
     550                            'got %r' % (PIPAttributeQuery,  
     551                                        type(attributeQuery))) 
    551552                             
    552553        attributeAuthorityURI = attributeQuery[ 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authzservice.py

    r6593 r6597  
    1313 
    1414from ndg.security.common.utils.factory import importModuleObject 
    15 from ndg.security.common.authz.msi import Policy, PDP, PIP 
     15from ndg.security.common.authz.msi import Policy, PDP 
     16from ndg.security.common.authz.pip.esg import PIP 
    1617 
    1718 
     
    4041    POLICY_FILEPATH_OPTNAME = 'filePath' 
    4142    POLICY_CFG_PREFIX = 'policy.' 
     43    PIP_CFG_PREFIX = 'pip.' 
    4244     
    4345    __slots__ = ('__pdp', '__authzDecisionFunc', '__authzDecisionFuncKeyName') 
     
    8486         
    8587        # Initialise the Policy Information Point  
    86         pip = PIP() 
     88        pipCfgPrefix = prefix + cls.PIP_CFG_PREFIX 
     89        pip = PIP.fromConfig(prefix=pipCfgPrefix, **app_conf) 
    8790         
    8891        # Initialise the PDP reading in the policy         
     
    191194        @rtype: callable 
    192195        """ 
     196         
     197        # Nest function within AuthzServiceMiddleware method so that self is 
     198        # in its scope 
    193199        def getAuthzDecision(authzDecisionQuery): 
    194200            """Authorisation decision function accepts a SAML AuthzDecisionQuery 
     
    235241            elif pdpResponse.status == Response.DECISION_INDETERMINATE: 
    236242                log.info("AuthzServiceMiddleware.__call__: PDP returned a " 
    237                          "status of [%s] denying access for URI path [%s] using " 
    238                          "policy [%s]",  
     243                         "status of [%s] denying access for URI path [%s] " 
     244                         "using policy [%s]",  
    239245                         pdpResponse.decisionValue2String[response.status], 
    240246                         resourceURI, 
     
    245251            else: 
    246252                log.info("AuthzServiceMiddleware.__call__: PDP returned a " 
    247                          "status of [%s] denying access for URI path [%s] using " 
    248                          "policy [%s]",  
     253                         "status of [%s] denying access for URI path [%s] " 
     254                         "using policy [%s]",  
    249255                         pdpResponse.decisionValue2String[response.status], 
    250256                         resourceURI, 
     
    271277             
    272278            response.status.statusCode.value = StatusCode.SUCCESS_URI 
    273             response.status.statusMessage.value = "Response created successfully" 
     279            response.status.statusMessage.value = ("Response created " 
     280                                                   "successfully") 
    274281                
    275282            assertion = Assertion() 
Note: See TracChangeset for help on using the changeset viewer.