Ignore:
Timestamp:
05/03/10 16:56:35 (11 years ago)
Author:
pjkersha
Message:

Refactoring Attribute Authority to remove NDG Attribute Certificate and role mapping code.

Location:
TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test
Files:
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/config/attributeauthority/sitea/site-a.ini

    r6615 r6686  
    2727[pipeline:main] 
    2828pipeline = AttributeAuthorityFilter  
    29                    wsseSignatureVerificationFilter  
    30                    AttributeAuthorityWsdlSoapBindingFilter 
    31                    wsseSignatureFilter  
    3229                   AttributeAuthoritySamlSoapBindingFilter 
    3330                   mainApp 
     
    6259attributeAuthority.clockSkew: 180.0 
    6360 
    64 # All Attribute Certificates issued are recorded in this dir 
    65 attributeAuthority.attCertDir: %(here)s/attributeCertificateLog 
    66  
    67 # Files in attCertDir are stored using a rotating file handler 
    68 # attCertFileLogCnt sets the max number of files created before the first is  
    69 # overwritten 
    70 attributeAuthority.attCertFileName: ac.xml 
    71 attributeAuthority.attCertFileLogCnt: 16 
    7261attributeAuthority.dnSeparator:/ 
    73  
    74 # Location of role mapping file 
    75 attributeAuthority.mapConfigFilePath: %(here)s/siteAMapConfig.xml 
    7662 
    7763# Settings for custom AttributeInterface derived class to get user roles for given  
     
    8066attributeAuthority.attributeInterface.modName: siteAUserRoles 
    8167attributeAuthority.attributeInterface.className: TestUserRoles 
    82  
    83 # Config for XML signature of Attribute Certificate 
    84 attributeAuthority.signingPriKeyFilePath: %(here)s/siteA-aa.key 
    85 attributeAuthority.signingCertFilePath: %(here)s/siteA-aa.crt 
    86 attributeAuthority.caCertFilePathList: $NDGSEC_TEST_CONFIG_DIR/ca/ndg-test-ca.crt 
    87  
    88  
    89 # SOAP WSDL Based Binding to the Attribute Authority 
    90 [filter:AttributeAuthorityWsdlSoapBindingFilter] 
    91 paste.filter_app_factory = ndg.security.server.wsgi.attributeauthority:AttributeAuthoritySOAPBindingMiddleware.filter_app_factory 
    92 prefix = service.soap.binding. 
    93 attributeAuthoritySOAPBindingPrefix = attributeauthority.service.soap.binding. 
    94  
    95 service.soap.binding.referencedFilters = wsseSignatureVerificationFilter01 
    96 service.soap.binding.path = %(attributeAuthoritySoapWsdlServicePath)s 
    97 service.soap.binding.enableWSDLQuery = True 
    98 service.soap.binding.charset = utf-8 
    99 service.soap.binding.serviceSOAPBindingEnvironKeyName = ndg.security.server.wsgi.attributeauthority.AttributeAuthoritySOAPBindingMiddleware 
    100  
    101 attributeauthority.service.soap.binding.attributeAuthorityEnvironKeyName = %(attributeAuthorityEnvironKeyName)s 
    102 attributeauthority.service.soap.binding.wsseSignatureVerificationFilterID = wsseSignatureVerificationFilter01 
    103  
    10468 
    10569# SAML SOAP Binding to the Attribute Authority 
     
    11579saml.soapbinding.pathMatchList = /AttributeAuthority/saml 
    11680saml.soapbinding.queryInterfaceKeyName = %(attributeQueryInterfaceEnvironKeyName)s 
    117  
    118  
    119 [filter:wsseSignatureVerificationFilter] 
    120 paste.filter_app_factory = ndg.security.server.wsgi.wssecurity:SignatureVerificationFilter.filter_app_factory 
    121 filterID = wsseSignatureVerificationFilter01 
    122 path = %(attributeAuthoritySoapWsdlServicePath)s 
    123  
    124 # Settings for WS-Security SignatureHandler class used by this filter 
    125 wsseCfgFilePrefix = wssecurity 
    126  
    127 # Verify against known CAs - Provide a space separated list of file paths 
    128 wssecurity.caCertFilePathList=$NDGSEC_TEST_CONFIG_DIR/ca/ndg-test-ca.crt 
    129  
    130 [filter:wsseSignatureFilter] 
    131 paste.filter_app_factory = ndg.security.server.wsgi.wssecurity:ApplySignatureFilter.filter_app_factory 
    132 path = %(attributeAuthoritySoapWsdlServicePath)s 
    133  
    134 # Reference the verification filter in order to be able to apply signature 
    135 # confirmation 
    136 referencedFilters = wsseSignatureVerificationFilter01 
    137 wsseSignatureVerificationFilterID = wsseSignatureVerificationFilter01 
    138  
    139 # Last filter in chain SOAP handlers writes the response 
    140 writeResponse = True 
    141  
    142 # Settings for WS-Security SignatureHandler class used by this filter 
    143 wsseCfgFilePrefix = wssecurity 
    144  
    145 # Certificate associated with private key used to sign a message.  The sign  
    146 # method will add this to the BinarySecurityToken element of the WSSE header.   
    147 wssecurity.signingCertFilePath=%(here)s/siteA-aa.crt 
    148  
    149 # PEM encoded private key file 
    150 wssecurity.signingPriKeyFilePath=%(here)s/siteA-aa.key 
    151  
    152 # Set the ValueType for the BinarySecurityToken added to the WSSE header for a 
    153 # signed message.  See __setReqBinSecTokValType method and binSecTokValType  
    154 # class variable for options - it may be one of X509, X509v3, X509PKIPathv1 or  
    155 # give full namespace to alternative - see  
    156 # ZSI.wstools.Namespaces.OASIS.X509TOKEN 
    157 # 
    158 # binSecTokValType determines whether signingCert or signingCertChain  
    159 # attributes will be used. 
    160 wssecurity.reqBinSecTokValType=X509v3 
    161  
    162 # Add a timestamp element to an outbound message 
    163 wssecurity.addTimestamp=True 
    164  
    165 # For WSSE 1.1 - service returns signature confirmation containing signature  
    166 # value sent by client 
    167 wssecurity.applySignatureConfirmation=True 
    16881 
    16982 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/attributeauthority/test_attributeauthority.cfg

    r5681 r6686  
    88 
    99[DEFAULT] 
    10 siteBPropFilePath=$NDGSEC_TEST_CONFIG_DIR/attributeauthority/siteb/siteBAttAuthority.cfg 
    11  
    12 [setUp] 
    13 # ! SiteBMapConfig.xml trusted site A aaURI setting must agree with this  
    14 # setting for test6GetMappedAttCert 
    15 propFilePath=$NDGSEC_TEST_CONFIG_DIR/attributeauthority/sitea/siteAAttributeAuthority.cfg 
    16  
    17 # For https connections only.  !Omit ssl* settings if using http! 
    18 # sslpeercertcn is the expected CommonName of peer cert.  Omit if it's the  
    19 # same as peer hostname.  
    20 sslPeerCertCN = AttributeAuthority 
    21 sslCACertFilePathList = $NDGSEC_TEST_CONFIG_DIR/ca/ndg-test-ca.crt 
    22  
    23 [test02GetTrustedHostInfo] 
    24 role = urn:siteA:security:authz:1.0:attr:postgrad 
    25  
    26 [test03GetTrustedHostInfoWithNoMatchingRoleFound] 
    27 # Set an alternative role to test no matching role found exception 
    28 role = blah 
    29   
    30 [test05GetAttCert] 
    31 issuingClntCertFilePath = $NDGSEC_TEST_CONFIG_DIR/pki/user.crt 
    32  
    33 # Setup for use by test08GetMappedAttCert test 
    34 attCertFilePath = $NDGSEC_AA_UNITTEST_DIR/ac-clnt.xml 
    35  
    36 [test06GetAttCertWithUserIdSet] 
    37 userId = system 
    38 attCertFilePath = $NDGSEC_AA_UNITTEST_DIR/ac-clnt-test6.xml 
    39  
    40 [test07GetMappedAttCert] 
    41 issuingClntCertFilePath = $NDGSEC_TEST_CONFIG_DIR/pki/user.crt 
    42 userAttCertFilePath = $NDGSEC_AA_UNITTEST_DIR/ac-clnt.xml 
    43 mappedAttCertFilePath = $NDGSEC_AA_UNITTEST_DIR/mapped-ac.xml 
    44  
    45 [test08GetMappedAttCertStressTest] 
    46 issuingClntCertFilePath = $NDGSEC_TEST_CONFIG_DIR/pki/user.crt 
    47 userAttCertFilePathList = $NDGSEC_AA_UNITTEST_DIR/ac-clnt.xml 
    48  
     10prefix='attribute-authority.' 
     11attribute-authority.assertionLifetime = 3600 
     12attribute-authority.issuerName = /O=My Organisation/OU=Centre/CN=Attribute Authority  
     13attribute-authority.attributeInterface.className = ndg.security.server.attributeauthority.AttributeInterface 
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/attributeauthority/test_attributeauthority.py

    r6615 r6686  
    1919logging.basicConfig(level=logging.DEBUG) 
    2020 
    21 from os.path import expandvars as xpdVars 
    22 from os.path import join as jnPath 
    23 mkPath = lambda file:jnPath(os.environ['NDGSEC_AA_UNITTEST_DIR'], file) 
     21from warnings import warn 
     22from uuid import uuid4 
     23from datetime import datetime 
     24from os import path 
    2425 
    2526from ndg.security.test.unit import BaseTestCase 
     
    2829    CaseSensitiveConfigParser) 
    2930from ndg.security.server.attributeauthority import (AttributeAuthority,  
    30     AttributeAuthorityNoMatchingRoleInTrustedHosts,  
    3131    SQLAlchemyAttributeInterface, InvalidAttributeFormat) 
    3232 
    33 from ndg.security.common.AttCert import AttCert 
    34  
    35  
    36 class AttributeAuthorityTestCase(BaseTestCase): 
    37     clntPriKeyPwd = None 
    38  
    39     def setUp(self): 
    40         super(AttributeAuthorityTestCase, self).setUp() 
    41          
    42         if 'NDGSEC_INT_DEBUG' in os.environ: 
    43             import pdb 
    44             pdb.set_trace() 
    45          
    46         if 'NDGSEC_AA_UNITTEST_DIR' not in os.environ: 
    47             os.environ['NDGSEC_AA_UNITTEST_DIR'] = \ 
    48                 os.path.abspath(os.path.dirname(__file__)) 
    49  
    50         self.cfgParser = CaseSensitiveConfigParser() 
    51         cfgFilePath = mkPath('test_attributeauthority.cfg') 
    52         self.cfgParser.read(cfgFilePath) 
    53          
    54         self.cfg = {} 
    55         for section in self.cfgParser.sections() + ['DEFAULT']: 
    56             self.cfg[section] = dict(self.cfgParser.items(section)) 
    57              
    58         self.aa = AttributeAuthority.fromPropertyFile( 
    59                                             self.cfg['setUp']['propFilePath']) 
    60  
    61     _mkSiteBAttributeAuthority = lambda self: \ 
    62         AttributeAuthority.fromPropertyFile( 
    63                         propFilePath=self.cfg['DEFAULT']['siteBPropFilePath']) 
    64      
    65     def test01GetHostInfo(self): 
    66         """test01GetHostInfo: retrieve info for AA host""" 
    67         hostInfo = self.aa.hostInfo 
    68         print("Host Info:\n %s" % hostInfo)      
    69  
    70     def test02GetTrustedHostInfo(self): 
    71         """test02GetTrustedHostInfo: retrieve trusted host info matching a 
    72         given role""" 
    73         thisSection = self.cfg['test02GetTrustedHostInfo'] 
    74          
    75         trustedHostInfo = self.aa.getTrustedHostInfo(thisSection['role']) 
    76         for hostname, hostInfo in trustedHostInfo.items(): 
    77             self.assert_(hostname, "Hostname not set") 
    78             for k, v in hostInfo.items(): 
    79                 self.assert_(k, "hostInfo value key unset") 
    80  
    81         print("Trusted Host Info:\n %s" % trustedHostInfo) 
    82  
    83     def test03GetTrustedHostInfoWithNoMatchingRoleFound(self): 
    84         """test03GetTrustedHostInfoWithNoMatchingRoleFound: test the case  
    85         where the input role doesn't match any roles in the target AA's map  
    86         config file""" 
    87         thisSection = self.cfg[ 
    88                             'test03GetTrustedHostInfoWithNoMatchingRoleFound'] 
    89         try: 
    90             trustedHostInfo = self.aa.getTrustedHostInfo(thisSection['role']) 
    91             self.fail("Expecting NoMatchingRoleInTrustedHosts exception") 
    92              
    93         except AttributeAuthorityNoMatchingRoleInTrustedHosts, e: 
    94             print('PASSED - no match for role "%s": %s' % (thisSection['role'], 
    95                                                            e)) 
    96  
    97  
    98     def test04GetTrustedHostInfoWithNoRole(self): 
    99         """test04GetTrustedHostInfoWithNoRole: retrieve trusted host info  
    100         irrespective of role""" 
    101         trustedHostInfo = self.aa.getTrustedHostInfo() 
    102         for hostname, hostInfo in trustedHostInfo.items(): 
    103             self.assert_(hostname, "Hostname not set") 
    104             for k, v in hostInfo.items(): 
    105                 self.assert_(k, "hostInfo value key unset") 
    106                     
    107         print("Trusted Host Info:\n %s" % trustedHostInfo) 
    108  
    109     def test05GetAttCert(self):         
    110         """test05GetAttCert: Request attribute certificate from NDG Attribute  
    111         Authority Web Service.""" 
    112         thisSection = self.cfg['test05GetAttCert'] 
    113          
    114         # Read user Certificate into a string ready for passing via WS 
    115         try: 
    116             userX509CertFilePath = xpdVars(thisSection.get( 
    117                                                     'issuingClntCertFilePath')) 
    118             userX509CertTxt = open(userX509CertFilePath, 'r').read() 
    119          
    120         except TypeError: 
    121             # No issuing cert set 
    122             userX509CertTxt = None 
    123                  
    124         except IOError, ioErr: 
    125             raise Exception("Error reading certificate file \"%s\": %s" % 
    126                                     (ioErr.filename, ioErr.strerror)) 
    127  
    128         # Make attribute certificate request 
    129         attCert = self.aa.getAttCert(holderX509Cert=userX509CertTxt) 
    130          
    131         print("Attribute Certificate: \n\n:" + str(attCert)) 
    132          
    133         attCert.filePath = xpdVars(thisSection['attCertFilePath']) 
    134         attCert.write() 
    135          
    136          
    137     def test06GetAttCertWithUserIdSet(self):         
    138         """test06GetAttCertWithUserIdSet: Request attribute certificate from  
    139         NDG Attribute Authority Web Service setting a specific user Id  
    140         independent of the signer of the SOAP request.""" 
    141         thisSection = self.cfg['test06GetAttCertWithUserIdSet'] 
    142          
    143         # Make attribute certificate request 
    144         userId = thisSection['userId'] 
    145         attCert = self.aa.getAttCert(userId=userId) 
    146          
    147         print("Attribute Certificate: \n\n:" + str(attCert)) 
    148          
    149         attCert.filePath = xpdVars(thisSection['attCertFilePath']) 
    150         attCert.write() 
    151  
    152  
    153     def test07GetMappedAttCert(self):         
    154         """test07GetMappedAttCert: Request mapped attribute certificate from  
    155         NDG Attribute Authority Web Service.""" 
    156         thisSection = self.cfg['test07GetMappedAttCert'] 
    157          
    158         # Read user Certificate into a string ready for passing via WS 
    159         try: 
    160             userX509CertFilePath = xpdVars(thisSection.get( 
    161                                                     'issuingClntCertFilePath')) 
    162             userX509CertTxt = open(userX509CertFilePath, 'r').read() 
    163          
    164         except TypeError: 
    165             # No issuing cert set 
    166             userX509CertTxt = None 
    167                  
    168         except IOError, ioErr: 
    169             raise Exception("Error reading certificate file \"%s\": %s" %  
    170                                     (ioErr.filename, ioErr.strerror)) 
    171      
    172         # Simlarly for Attribute Certificate  
    173         try: 
    174             userAttCert = AttCert.Read( 
    175                                 xpdVars(thisSection['userAttCertFilePath'])) 
    176              
    177         except IOError, ioErr: 
    178             raise Exception("Error reading attribute certificate file \"%s\": " 
    179                             "%s" % (ioErr.filename, ioErr.strerror)) 
    180          
    181         # Make client to site B Attribute Authority 
    182         siteBAA = self._mkSiteBAttributeAuthority() 
    183      
    184         # Make attribute certificate request 
    185         attCert = siteBAA.getAttCert(holderX509Cert=userX509CertTxt, 
    186                                      userAttCert=userAttCert) 
    187         print("Attribute Certificate: \n\n:" + str(attCert)) 
    188          
    189         attCert.filePath = xpdVars(thisSection['mappedAttCertFilePath']) 
    190         attCert.write() 
    191          
    192          
    193     def test08GetMappedAttCertStressTest(self):         
    194         """test08GetMappedAttCertStressTest: Request mapped attribute  
    195         certificate from NDG Attribute Authority Web Service.""" 
    196         thisSection = self.cfg['test08GetMappedAttCertStressTest'] 
    197          
    198         # Read user Certificate into a string ready for passing via WS 
    199         try: 
    200             userX509CertFilePath = xpdVars(thisSection.get( 
    201                                                     'issuingClntCertFilePath')) 
    202             userX509CertTxt = open(userX509CertFilePath, 'r').read() 
    203          
    204         except TypeError: 
    205             # No issuing cert set 
    206             userX509CertTxt = None 
    207                  
    208         except IOError, ioErr: 
    209             raise Exception("Error reading certificate file \"%s\": %s" %  
    210                                     (ioErr.filename, ioErr.strerror)) 
    211  
    212         # Make client to site B Attribute Authority 
    213         siteBAA = self._mkSiteBAttributeAuthority() 
    214  
    215         acFilePathList = [xpdVars(file) for file in \ 
    216                           thisSection['userAttCertFilePathList'].split()] 
    217  
    218         passed = True 
    219         for acFilePath in acFilePathList: 
    220             try: 
    221                 userAttCert = AttCert.Read(acFilePath) 
    222                  
    223             except IOError, ioErr: 
    224                 raise Exception("Error reading attribute certificate file " 
    225                                 '"%s": %s' % (ioErr.filename, ioErr.strerror)) 
    226          
    227             # Make attribute certificate request 
    228             try: 
    229                 attCert = siteBAA.getAttCert(holderX509Cert=userX509CertTxt, 
    230                                              userAttCert=userAttCert) 
    231             except Exception, e: 
    232                 passed = True 
    233                 outFilePfx = 'test08GetMappedAttCertStressTest-%s' % \ 
    234                         os.path.basename(acFilePath)     
    235                 msgFile = open(outFilePfx+".msg", 'w') 
    236                 msgFile.write('Failed for "%s": %s\n' % (acFilePath, e)) 
    237                  
    238         self.assert_(passed,  
    239                      "At least one Attribute Certificate request failed.  " 
    240                      "Check the .msg files in this directory") 
    241  
    242  
    243 from warnings import warn 
    244 from uuid import uuid4 
    245 from datetime import datetime 
    246 from ndg.saml.saml2.core import (Response, Attribute, SAMLVersion, Subject, NameID, 
    247                              Issuer, AttributeQuery, XSStringAttributeValue,  
    248                              Status, StatusMessage, StatusCode) 
     33from ndg.saml.saml2.core import (Response, Attribute, SAMLVersion, Subject,  
     34                                 NameID, Issuer, AttributeQuery,  
     35                                 XSStringAttributeValue, Status, StatusMessage,  
     36                                 StatusCode) 
    24937from ndg.saml.xml import XMLConstants 
    25038from ndg.security.common.saml_utils.esg import EsgSamlNamespaces 
    25139 
     40THIS_DIR = path.dirname(__file__) 
     41 
     42 
     43class AttributeAuthorityTestCase(BaseTestCase): 
     44    THIS_DIR = THIS_DIR 
     45    PROPERTIES_FILENAME = 'test_attributeauthority.cfg' 
     46    PROPERTIES_FILEPATH = path.join(THIS_DIR, PROPERTIES_FILENAME) 
     47    ISSUER_NAME = '/O=My Organisation/OU=Centre/CN=Attribute Authority' 
     48     
     49    def test01ParsePropertiesFile(self): 
     50        cls = AttributeAuthorityTestCase 
     51        aa = AttributeAuthority.fromPropertyFile(cls.PROPERTIES_FILEPATH) 
     52        self.assert_(aa) 
     53        self.assert_(aa.assertionLifetime == 3600) 
     54        self.assert_(aa.issuerName == cls.ISSUER_NAME) 
     55         
     56    def test02FromPropertis(self): 
     57         
     58        # Casts from string to float 
     59        assertionLifetime = "86400" 
     60        issuerName = 'My issuer' 
     61        aa = AttributeAuthority.fromProperties(issuerName=issuerName, 
     62                                            assertionLifetime=assertionLifetime) 
     63        self.assert_(aa) 
     64        self.assert_(aa.assertionLifetime == float(assertionLifetime)) 
     65        self.assert_(aa.issuerName == issuerName) 
     66 
    25267 
    25368class SQLAlchemyAttributeInterfaceTestCase(BaseTestCase): 
     69    THIS_DIR = THIS_DIR 
     70    PROPERTIES_FILENAME = 'test_sqlalchemyattributeinterface.cfg' 
     71    PROPERTIES_FILEPATH = path.join(THIS_DIR, PROPERTIES_FILENAME) 
     72     
    25473    SAML_SUBJECT_SQLQUERY = ("select count(*) from users where openid = " 
    25574                             "'${userId}'") 
     
    364183            return 
    365184        cfgParser = CaseSensitiveConfigParser() 
    366         cfgFilePath = mkPath('test_sqlalchemyattributeinterface.cfg') 
     185        cls = SQLAlchemyAttributeInterfaceTestCase 
     186        cfgFilePath = cls.PROPERTIES_FILEPATH 
    367187        cfgParser.read(cfgFilePath) 
    368188         
  • TI12-security/trunk/NDGSecurity/python/ndg_security_test/ndg/security/test/unit/saml/test_samlinterface.py

    r6615 r6686  
    2020from xml.etree import ElementTree 
    2121 
     22from ndg.saml.utils import SAMLDateTime 
    2223from ndg.saml.saml2.core import (Response, Assertion, Attribute,  
    2324                             AttributeStatement, SAMLVersion, Subject, NameID, 
     
    3132from ndg.security.common.soap.etree import SOAPEnvelope 
    3233from ndg.security.common.utils.etree import QName, prettyPrint 
     34from ndg.security.common.saml_utils.binding.soap.subjectquery import ( 
     35    SubjectQuerySOAPBinding, ResponseIssueInstantInvalid,  
     36    AssertionIssueInstantInvalid, AssertionConditionNotBeforeInvalid,  
     37    AssertionConditionNotOnOrAfterInvalid) 
     38     
    3339from ndg.security.common.saml_utils.esg import (EsgSamlNamespaces,  
    3440                                          XSGroupRoleAttributeValue) 
     
    160166    """TODO: test SAML Attribute Authority interface""" 
    161167    thisDir = os.path.dirname(os.path.abspath(__file__)) 
     168    RESPONSE = '''\ 
     169<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
     170   <SOAP-ENV:Body> 
     171      <samlp:Response ID="05680cb2-4973-443d-9d31-7bc99bea87c1" InResponseTo="e3183380-ae82-4285-8827-8c40613842de" IssueInstant="%(issueInstant)s" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> 
     172         <saml:Issuer Format="urn:esg:issuer" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">ESG-NCAR</saml:Issuer> 
     173         <samlp:Status> 
     174            <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> 
     175         </samlp:Status> 
     176         <saml:Assertion ID="192c67d9-f9cd-457a-9242-999e7b943166" IssueInstant="%(assertionIssueInstant)s" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> 
     177            <saml:Issuer Format="urn:esg:issuer">ESG-NCAR</saml:Issuer> 
     178            <saml:Subject> 
     179               <saml:NameID Format="urn:esg:openid">https://esg.prototype.ucar.edu/myopenid/testUser</saml:NameID> 
     180            </saml:Subject> 
     181            <saml:Conditions NotBefore="%(notBefore)s" NotOnOrAfter="%(notOnOrAfter)s" /> 
     182            <saml:AttributeStatement> 
     183               <saml:Attribute FriendlyName="FirstName" Name="urn:esg:first:name" NameFormat="http://www.w3.org/2001/XMLSchema#string"> 
     184                  <saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Test</saml:AttributeValue> 
     185               </saml:Attribute> 
     186               <saml:Attribute FriendlyName="LastName" Name="urn:esg:last:name" NameFormat="http://www.w3.org/2001/XMLSchema#string"> 
     187                  <saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">User</saml:AttributeValue> 
     188               </saml:Attribute> 
     189               <saml:Attribute FriendlyName="EmailAddress" Name="urn:esg:first:email:address" NameFormat="http://www.w3.org/2001/XMLSchema#string"> 
     190                  <saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">ejn@ucar.edu</saml:AttributeValue> 
     191               </saml:Attribute> 
     192               <saml:Attribute FriendlyName="GroupRole" Name="urn:esg:group:role" NameFormat="groupRole"> 
     193                  <saml:AttributeValue> 
     194                     <esg:groupRole group="CCSM" role="default" xmlns:esg="http://www.esg.org" /> 
     195                  </saml:AttributeValue> 
     196                  <saml:AttributeValue> 
     197                     <esg:groupRole group="Dynamical Core" role="default" xmlns:esg="http://www.esg.org" /> 
     198                  </saml:AttributeValue> 
     199                  <saml:AttributeValue> 
     200                     <esg:groupRole group="NARCCAP" role="default" xmlns:esg="http://www.esg.org" /> 
     201                  </saml:AttributeValue> 
     202               </saml:Attribute> 
     203            </saml:AttributeStatement> 
     204         </saml:Assertion> 
     205      </samlp:Response> 
     206   </SOAP-ENV:Body> 
     207</SOAP-ENV:Envelope> 
     208''' 
    162209 
    163210    def __init__(self, *args, **kwargs): 
     
    167214        BaseTestCase.__init__(self, *args, **kwargs) 
    168215         
    169  
    170216    def test01AttributeQuery(self): 
    171217        attributeQuery = AttributeQuery() 
     
    389435        self.assert_(response) 
    390436 
     437    def _parseResponse(self, responseStr): 
     438        """Helper to parse a response from a string""" 
     439        soapResponse = SOAPEnvelope() 
     440         
     441        responseStream = StringIO() 
     442        responseStream.write(responseStr) 
     443        responseStream.seek(0) 
     444         
     445        soapResponse.parse(responseStream) 
     446         
     447        print("Parsed response ...") 
     448        print(soapResponse.serialize()) 
     449         
     450        toSAMLTypeMap = [XSGroupRoleAttributeValueElementTree.factoryMatchFunc] 
     451        response = ResponseElementTree.fromXML(soapResponse.body.elem[0], 
     452                                            customToSAMLTypeMap=toSAMLTypeMap) 
     453        return response 
     454         
     455    def test03ParseResponse(self): 
     456        utcNow = datetime.utcnow() 
     457        respDict = { 
     458            'issueInstant': SAMLDateTime.toString(utcNow), 
     459            'assertionIssueInstant': SAMLDateTime.toString(utcNow), 
     460            'notBefore': SAMLDateTime.toString(utcNow), 
     461            'notOnOrAfter': SAMLDateTime.toString(utcNow + timedelta( 
     462                                                            seconds=60*60*8)) 
     463        } 
     464        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     465                                                                        respDict 
     466        response = self._parseResponse(responseStr) 
     467        self.assert_(response) 
     468 
     469    def test04AssertionConditionExpired(self): 
     470        # issued 9 hours ago 
     471        issueInstant = datetime.utcnow() - timedelta(seconds=60*60*9) 
     472        respDict = { 
     473            'issueInstant': SAMLDateTime.toString(issueInstant), 
     474            'assertionIssueInstant': SAMLDateTime.toString(issueInstant), 
     475            'notBefore': SAMLDateTime.toString(issueInstant), 
     476            # It lasts for 8 hours so it's expired by one hour 
     477            'notOnOrAfter': SAMLDateTime.toString(issueInstant + timedelta( 
     478                                                            seconds=60*60*8)) 
     479        } 
     480        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     481                                                                    respDict 
     482        response = self._parseResponse(responseStr) 
     483        binding = SubjectQuerySOAPBinding() 
     484        try: 
     485            binding._verifyTimeConditions(response) 
     486            self.fail("Expecting not on or after timestamp error") 
     487        except AssertionConditionNotOnOrAfterInvalid, e: 
     488            print("PASSED: %s" % e) 
     489 
     490    def test05ResponseIssueInstantInvalid(self): 
     491        utcNow = datetime.utcnow() 
     492        respDict = { 
     493            'issueInstant': SAMLDateTime.toString(utcNow + timedelta( 
     494                                                                    seconds=1)), 
     495            'assertionIssueInstant': SAMLDateTime.toString(utcNow), 
     496            'notBefore': SAMLDateTime.toString(utcNow), 
     497            'notOnOrAfter': SAMLDateTime.toString(utcNow + timedelta( 
     498                                                            seconds=60*60*8)) 
     499        } 
     500        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     501                                                                    respDict 
     502        response = self._parseResponse(responseStr) 
     503        binding = SubjectQuerySOAPBinding() 
     504        try: 
     505            binding._verifyTimeConditions(response) 
     506            self.fail("Expecting issue instant timestamp error") 
     507        except ResponseIssueInstantInvalid, e: 
     508            print("PASSED: %s" % e) 
     509 
     510    def test06NotBeforeConditionInvalid(self): 
     511        utcNow = datetime.utcnow() 
     512        respDict = { 
     513            'issueInstant': SAMLDateTime.toString(utcNow), 
     514            'assertionIssueInstant': SAMLDateTime.toString(utcNow), 
     515            'notBefore': SAMLDateTime.toString(utcNow + timedelta(seconds=1)), 
     516            'notOnOrAfter': SAMLDateTime.toString(utcNow + timedelta( 
     517                                                            seconds=60*60*8)) 
     518        } 
     519        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     520                                                                    respDict 
     521        response = self._parseResponse(responseStr) 
     522        binding = SubjectQuerySOAPBinding() 
     523        try: 
     524            binding._verifyTimeConditions(response) 
     525            self.fail("Expecting issue instant timestamp error") 
     526        except AssertionConditionNotBeforeInvalid, e: 
     527            print("PASSED: %s" % e) 
     528 
     529    def test07AssertionIssueInstantInvalid(self): 
     530        utcNow = datetime.utcnow() 
     531        respDict = { 
     532            'issueInstant': SAMLDateTime.toString(utcNow), 
     533            'assertionIssueInstant': SAMLDateTime.toString(utcNow + timedelta( 
     534                                                                    seconds=1)), 
     535            'notBefore': SAMLDateTime.toString(utcNow), 
     536            'notOnOrAfter': SAMLDateTime.toString(utcNow + timedelta( 
     537                                                            seconds=60*60*8)) 
     538        } 
     539        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     540                                                                    respDict 
     541        response = self._parseResponse(responseStr) 
     542        binding = SubjectQuerySOAPBinding() 
     543        try: 
     544            binding._verifyTimeConditions(response) 
     545            self.fail("Expecting issue instant timestamp error") 
     546        except AssertionIssueInstantInvalid, e: 
     547            print("PASSED: %s" % e) 
     548 
     549    def test07ClockSkewCorrectedAssertionIssueInstantInvalid(self): 
     550        utcNow = datetime.utcnow() 
     551        respDict = { 
     552            'issueInstant': SAMLDateTime.toString(utcNow), 
     553            'assertionIssueInstant': SAMLDateTime.toString(utcNow + timedelta( 
     554                                                                    seconds=1)), 
     555            'notBefore': SAMLDateTime.toString(utcNow), 
     556            'notOnOrAfter': SAMLDateTime.toString(utcNow + timedelta( 
     557                                                            seconds=60*60*8)) 
     558        } 
     559        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     560                                                                    respDict 
     561        response = self._parseResponse(responseStr) 
     562        binding = SubjectQuerySOAPBinding() 
     563         
     564        # Set a skew to correct the error 
     565        binding.clockSkewTolerance = 1 
     566         
     567        try: 
     568            binding._verifyTimeConditions(response) 
     569        except AssertionIssueInstantInvalid, e: 
     570            self.fail("issue instant timestamp error should be corrected for") 
     571 
     572    def test08ClockSkewCorrectedAssertionConditionExpired(self): 
     573        # Issued 9 hours ago 
     574        issueInstant = datetime.utcnow() - timedelta(seconds=60*60*9) 
     575        respDict = { 
     576            'issueInstant': SAMLDateTime.toString(issueInstant), 
     577            'assertionIssueInstant': SAMLDateTime.toString(issueInstant), 
     578            'notBefore': SAMLDateTime.toString(issueInstant), 
     579            # Assertion lasts 8 hours so it has expired by one hour 
     580            'notOnOrAfter': SAMLDateTime.toString(issueInstant + timedelta( 
     581                                                            seconds=60*60*8)) 
     582        } 
     583        responseStr = SamlAttributeAuthorityInterfaceTestCase.RESPONSE % \ 
     584                                                                    respDict 
     585        response = self._parseResponse(responseStr) 
     586        binding = SubjectQuerySOAPBinding() 
     587         
     588        # Set a skew of over one hour to correct for the assertion expiry 
     589        binding.clockSkewTolerance = 60*60 + 3 
     590         
     591        try: 
     592            binding._verifyTimeConditions(response) 
     593             
     594        except AssertionConditionNotOnOrAfterInvalid, e: 
     595            self.fail("Not on or after timestamp error should be corrected for") 
     596             
    391597             
    392598if __name__ == "__main__": 
Note: See TracChangeset for help on using the changeset viewer.