Changeset 5656


Ignore:
Timestamp:
21/08/09 17:05:45 (10 years ago)
Author:
pjkersha
Message:
  • Added factory methods to ndg.security.server.attributeauthority.AttributeAuthority? in order to create getAttCert and samlAttributeQuery wrapper functions. These can then be added to the WSGI environ to be referenced by other middleware.
  • ndg.security.test.unit.saml.test_soapattributeinterface: started work on unit tests for SAML 2.0 SOAP binding to attribute query interface.
Location:
TI12-security/trunk/python
Files:
4 added
4 edited

Legend:

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

    r5648 r5656  
    2727from uuid import uuid4 
    2828from datetime import datetime, timedelta 
     29from saml.utils import SAMLDateTime 
    2930from saml.saml2.core import Response, Assertion, Attribute, AttributeValue, \ 
    3031    AttributeStatement, SAMLVersion, Subject, NameID, Issuer, AttributeQuery, \ 
     
    11081109        try: 
    11091110            # Return a dictionary of name, value pairs 
    1110             attributes = self.getAttributes(attributeQuery.subject.nameID.value, 
    1111                                             requestedAttributeNames, 
    1112                                             attributeQuery.subject.nameID.value) 
     1111            attributes = self.attributeInterface.getAttributes( 
     1112                                        attributeQuery.subject.nameID.value, 
     1113                                        requestedAttributeNames, 
     1114                                        attributeQuery.subject.nameID.value) 
    11131115        except Exception, e: 
    11141116            # TODO: exception handling for requested attributes not allowed  
     
    14741476        return localRoles 
    14751477 
     1478    def getAttCertFactory(self): 
     1479        """Factory method to create SAML Attribute Qeury wrapper function 
     1480        @rtype: function 
     1481        @return getAttCert method function wrapper 
     1482        """ 
     1483        def getAttCertWrapper(*arg, **kw): 
     1484            """ 
     1485            @type *arg: tuple 
     1486            @param *arg: getAttCert arguments 
     1487            @type **kw: dict 
     1488            @param **kw: getAttCert keyword arguments 
     1489            @rtype: ndg.security.common.AttCert.AttCert 
     1490            @return: new attribute certificate 
     1491            """ 
     1492            return self.getAttCert(*arg, **kw) 
     1493         
     1494        return getAttCertWrapper 
     1495 
     1496    def samlAttributeQueryFactory(self): 
     1497        """Factory method to create SAML Attribute Qeury wrapper function 
     1498        @rtype: function 
     1499        @return: samlAttributeQuery method function wrapper 
     1500        """ 
     1501        def samlAttributeQueryWrapper(attributeQuery): 
     1502            """ 
     1503            @type attributeQuery: saml.saml2.core.AttributeQuery 
     1504            @param attributeQuery: SAML Attribute Query 
     1505            @rtype: saml.saml2.core.Response 
     1506            @return: SAML response 
     1507            """ 
     1508            return self.samlAttributeQuery(attributeQuery) 
     1509         
     1510        return samlAttributeQueryWrapper 
     1511     
    14761512 
    14771513from logging.handlers import RotatingFileHandler 
  • TI12-security/trunk/python/ndg_security_server/ndg/security/server/wsgi/saml.py

    r5637 r5656  
    3030class SOAPAttributeInterfaceMiddlewareError(Exception): 
    3131    """Base class for WSGI SAML 2.0 SOAP Attribute Interface Errors""" 
    32      
     32 
     33 
     34class SOAPAttributeInterfaceMiddlewareConfigError(Exception): 
     35    """WSGI SAML 2.0 SOAP Attribute Interface Configuration problem""" 
     36 
     37   
    3338class SOAPAttributeInterfaceMiddleware(SOAPMiddleware): 
    3439    """Implementation of SAML 2.0 SOAP Binding for Assertion Query/Request 
    3540    Profile""" 
     41    log = logging.getLogger('SOAPAttributeInterfaceMiddleware') 
     42    QUERY_INTERFACE_KEYNAME_OPTNAME = "queryInterfaceKeyName" 
     43    DEFAULT_QUERY_INTERFACE_KEYNAME = ("ndg.security.server.wsgi.saml." 
     44                            "SOAPAttributeInterfaceMiddleware.queryInterface") 
    3645     
    3746    def __init__(self, app, global_conf, prefix='', **app_conf): 
     
    4857        ''' 
    4958        self._app = app 
    50         self.__assertionLifetime = None 
    51         self.__issuerName = None 
     59        self.__queryInterfaceKeyName = None 
     60         
     61        self.queryInterfaceKeyName = app_conf.get(prefix + \ 
     62            SOAPAttributeInterfaceMiddleware.QUERY_INTERFACE_KEYNAME_OPTNAME, 
     63            prefix + \ 
     64            SOAPAttributeInterfaceMiddleware.DEFAULT_QUERY_INTERFACE_KEYNAME) 
    5265 
    53     def _getAssertionLifetime(self): 
    54         return self.__assertionLifetime 
     66    def _getQueryInterfaceKeyName(self): 
     67        return self.__queryInterfaceKeyName 
    5568 
    56     def _setAssertionLifetime(self, value): 
    57         self.__assertionLifetime = value 
     69    def _setQueryInterfaceKeyName(self, value): 
     70        if not isinstance(value, basestring): 
     71            raise TypeError('Expecting string type for "queryInterfaceKeyName"' 
     72                            ' got %r' % value) 
     73             
     74        self.__queryInterfaceKeyName = value 
    5875 
    59     assertionLifetime = property(fget=_getAssertionLifetime,  
    60                                  fset=_setAssertionLifetime,  
    61                                  doc="Validity lifetime (seconds) for " 
    62                                      "assertion issued in a response") 
     76    queryInterfaceKeyName = property(fget=_getQueryInterfaceKeyName,  
     77                                     fset=_setQueryInterfaceKeyName,  
     78                                     doc="environ keyname for Attribute Query " 
     79                                         "interface") 
    6380 
    6481    def _getIssuerName(self): 
     
    8198        @param start_response: standard WSGI start response function 
    8299        """ 
    83          
     100             
    84101        # Ignore non-SOAP requests 
    85102        if not self.isSOAPMessage(environ): 
     
    114131        log.debug("SOAPAttributeInterfaceMiddleware.__call__: received SAML " 
    115132                  "SOAP AttributeQuery ...") 
    116          
     133        
    117134        attributeQueryElem = soapRequest.body.elem[0] 
    118135        attributeQuery = AttributeQueryElementTree.fromXML(attributeQueryElem) 
    119                  
    120         samlResponse = Response() 
    121136         
    122         samlResponse.issueInstant = datetime.utcnow() 
    123         samlResponse.id = str(uuid4()) 
    124         samlResponse.issuer = Issuer() 
     137        # Check for Query Interface in environ 
     138        queryInterface = environ.get(self.queryInterfaceKeyName) 
     139        if queryInterface is None: 
     140            raise SOAPAttributeInterfaceMiddlewareConfigError( 
     141                                'No query interface "%s" key found in environ'% 
     142                                self.queryInterfaceKeyName) 
    125143         
    126         # SAML 2.0 spec says fromat must be omitted 
    127         #samlResponse.issuer.format = Issuer.X509_SUBJECT 
    128         samlResponse.issuer.value = \ 
    129                         "/O=NDG/OU=BADC/CN=attributeauthority.badc.rl.ac.uk" 
    130          
    131         samlResponse.inResponseTo = attributeQuery.id 
    132          
    133         assertion = Assertion() 
    134          
    135         assertion.version = SAMLVersion(SAMLVersion.VERSION_20) 
    136         assertion.id = str(uuid4()) 
    137         assertion.issueInstant = samlResponse.issueInstant 
    138          
    139         assertion.conditions = Conditions() 
    140         assertion.conditions.notBefore = assertion.issueInstant 
    141         assertion.conditions.notOnOrAfter = assertion.conditions.notBefore + \ 
    142             timedelta(seconds=60*60*8) 
    143          
    144         assertion.subject = Subject()   
    145         assertion.subject.nameID = NameID() 
    146         assertion.subject.nameID.format = attributeQuery.subject.nameID.format 
    147         assertion.subject.nameID.value = attributeQuery.subject.nameID.value 
    148  
    149         assertion.attributeStatements.append(AttributeStatement()) 
    150          
    151         for attribute in attributeQuery.attributes: 
    152             if attribute.name == "urn:esg:first:name": 
    153                 # special case handling for 'FirstName' attribute 
    154                 fnAttribute = Attribute() 
    155                 fnAttribute.name = attribute.name 
    156                 fnAttribute.nameFormat = attribute.nameFormat 
    157                 fnAttribute.friendlyName = attribute.friendlyName 
    158      
    159                 firstName = XSStringAttributeValue() 
    160                 firstName.value = self.firstName 
    161                 fnAttribute.attributeValues.append(firstName) 
    162      
    163                 assertion.attributeStatements[0].attributes.append(fnAttribute) 
    164              
    165             elif attribute.name == "urn:esg:last:name": 
    166                 lnAttribute = Attribute() 
    167                 lnAttribute.name = attribute.name 
    168                 lnAttribute.nameFormat = attribute.nameFormat 
    169                 lnAttribute.friendlyName = attribute.friendlyName 
    170      
    171                 lastName = XSStringAttributeValue() 
    172                 lastName.value = self.lastName 
    173                 lnAttribute.attributeValues.append(lastName) 
    174      
    175                 assertion.attributeStatements[0].attributes.append(lnAttribute) 
    176                 
    177             elif attribute.name == "urn:esg:email:address": 
    178                 emailAddressAttribute = Attribute() 
    179                 emailAddressAttribute.name = attribute.name 
    180                 emailAddressAttribute.nameFormat = attribute.nameFormat 
    181                 emailAddressAttribute.friendlyName = attribute.friendlyName 
    182      
    183                 emailAddress = XSStringAttributeValue() 
    184                 emailAddress.value = self.emailAddress 
    185                 emailAddressAttribute.attributeValues.append(emailAddress) 
    186      
    187                 assertion.attributeStatements[0].attributes.append( 
    188                                                         emailAddressAttribute) 
    189          
    190         samlResponse.assertions.append(assertion) 
    191          
    192         # Add mapping for ESG Group/Role Attribute Value to enable ElementTree 
    193         # Attribute Value factory to render the XML output 
    194         toXMLTypeMap = { 
    195             XSGroupRoleAttributeValue: XSGroupRoleAttributeValueElementTree 
    196         } 
    197  
    198          
    199         samlResponse.status = Status() 
    200         samlResponse.status.statusCode = StatusCode() 
    201         samlResponse.status.statusCode.value = StatusCode.SUCCESS_URI         
    202  
     144        # Call query interface         
     145        samlResponse = queryInterface(attributeQuery) 
    203146         
    204147        # Convert to ElementTree representation to enable attachment to SOAP 
  • TI12-security/trunk/python/ndg_security_test/ndg/security/test/integration/combinedservices/services.ini

    r5648 r5656  
    190190authkit.openid.store.config=%(here)s/data/openid 
    191191authkit.openid.session.key = authkit_openid 
    192 authkit.openid.sess-ion.secret = random string 
     192authkit.openid.session.secret = random string 
    193193 
    194194authkit.openid.baseurl = http://localhost 
  • TI12-security/trunk/python/ndg_security_test/ndg/security/test/integration/openidrelyingparty/securityservices.ini

    r5655 r5656  
    102102#authkit.openid.urltouser =  
    103103 
    104 #[app:OpenIDRelyingPartyApp] 
    105 #paste.app_factory =  
    106 #       ndg.security.server.wsgi.openid.relyingparty:OpenIDRelyingPartyMiddleware.app_factory 
    107 # 
    108 #openid.relyingparty.baseURL = %(authkit.openid.baseurl)s 
    109 #openid.relyingparty.certFilePath = %(testConfigDir)s/pki/localhost.crt 
    110 #openid.relyingparty.priKeyFilePath = %(testConfigDir)s/pki/localhost.key 
    111 #openid.relyingparty.priKeyPwd =  
    112 #openid.relyingparty.caCertDirPath = %(testConfigDir)s/ca 
    113 #openid.relyingparty.signinInterfaceMiddlewareClass = ndg.security.server.wsgi.openid.relyingparty.signin_interface.buffet.BuffetSigninTemplate 
    114 #openid.relyingparty.signinInterface.templatePackage = ndg.security.server.wsgi.openid.relyingparty.signin_interface.buffet.templates 
    115 #openid.relyingparty.signinInterface.staticContentRootDir = %(here)s/openidrelyingparty/public 
    116 #openid.relyingparty.signinInterface.baseURL = %(openid.relyingparty.baseURL)s 
    117 #openid.relyingparty.signinInterface.leftLogo = %(openid.relyingparty.signinInterface.baseURL)s/layout/NERC_Logo.gif 
    118 #openid.relyingparty.signinInterface.leftAlt = Natural Environment Research Council 
    119 #openid.relyingparty.signinInterface.ndgLink = http://ndg.nerc.ac.uk/ 
    120 #openid.relyingparty.signinInterface.ndgImage = %(openid.relyingparty.signinInterface.baseURL)s/layout/ndg_logo_circle.gif 
    121 #openid.relyingparty.signinInterface.disclaimer = This site is for test purposes only and is under active development. 
    122 #openid.relyingparty.signinInterface.stfcLink = http://www.stfc.ac.uk/ 
    123 #openid.relyingparty.signinInterface.stfcImage = %(openid.relyingparty.signinInterface.baseURL)s/layout/stfc-circle-sm.gif 
    124 #openid.relyingparty.signinInterface.helpIcon = %(openid.relyingparty.signinInterface.baseURL)s/layout/icons/help.png 
    125 # 
    126 #cache_dir = %(here)s/data 
    127 # 
    128 ## AuthKit Set-up 
    129 #authkit.setup.method=openid, cookie 
    130 # 
    131 ## This cookie name and secret MUST agree with the name used by the  
    132 ## Authentication Filter used to secure a given app 
    133 #authkit.cookie.name=ndg.security.auth 
    134 #authkit.cookie.secret=9wvZObs9anUEhSIAnJNoY2iJq59FfYZr 
    135 # 
    136 #authkit.cookie.signoutpath = /logout 
    137 #authkit.openid.path.signedin=/ 
    138 #authkit.openid.store.type=file 
    139 #authkit.openid.store.config=%(here)s/data/openid 
    140 #authkit.openid.session.key = authkit_openid 
    141 #authkit.openid.session.secret = random string 
    142 # 
    143 #authkit.openid.baseurl = http://localhost:6443 
    144 # 
    145 ## Key name for dereferencing beaker.session object held in environ 
    146 #authkit.openid.session.middleware = %(beakerSessionKeyName)s 
    147  
    148104 
    149105# Logging configuration 
Note: See TracChangeset for help on using the changeset viewer.