Changeset 6040


Ignore:
Timestamp:
24/11/09 10:18:09 (10 years ago)
Author:
pjkersha
Message:
  • Added capability to thread paste SSL service for unit tests
  • added SSL Client authn functionality to SamlCredentialWallet? using ndg.security.common.utils.m2crypto.SSLContextProxy
Location:
TI12-security/trunk/python
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg_security_common/ndg/security/common/X509.py

    r6018 r6040  
    105105         
    106106        self.isValidTime(warningStackLevel=warningStackLevel, **isValidTimeKw) 
    107  
    108107 
    109108    def parse(self,  
     
    145144         
    146145        self.isValidTime(warningStackLevel=warningStackLevel, **isValidTimeKw) 
    147  
    148146       
    149147    def __setM2CryptoX509(self, m2CryptoX509=None): 
     
    157155                     
    158156            self.__m2CryptoX509 = m2CryptoX509 
    159              
    160              
     157                    
    161158        # Get distinguished name 
    162159        m2CryptoX509Name = self.__m2CryptoX509.get_subject() 
     
    164161        # Instantiate X500 Distinguished name 
    165162        self.__dn = X500DN(m2CryptoX509Name=m2CryptoX509Name) 
    166  
    167  
     163         
    168164        # Get not before and not after validity times 
    169165        # 
     
    179175            raise X509CertError("Not Before time: %s" % e) 
    180176 
    181          
    182177        try: 
    183178            m2CryptoNotAfter = self.__m2CryptoX509.get_not_after() 
     
    187182            raise X509CertError("Not After time: %s" % e) 
    188183 
    189  
    190184    def __getM2CryptoX509(self, m2CryptoX509=None): 
    191185        "Return M2Crypto X.509 cert object" 
    192186        return self.__m2CryptoX509 
    193187     
    194      
    195188    m2CryptoX509 = property(fset=__setM2CryptoX509, 
    196189                            fget=__getM2CryptoX509, 
    197190                            doc="M2Crypto.X509.X509 type") 
    198  
    199191         
    200192    def toString(self, **kw): 
     
    214206        return self.__m2CryptoX509.as_pem() 
    215207 
    216          
    217208    def asDER(self): 
    218209        """Return certificate file content in DER format""" 
     
    222213        return self.__m2CryptoX509.as_der() 
    223214 
    224      
    225215    # Make some attributes accessible as read-only 
    226216    def __getDN(self): 
     
    229219 
    230220    dn = property(fget=__getDN, doc="X.509 Distinguished Name") 
    231  
    232  
     221     
    233222    def __getVersion(self): 
    234223        """Get X.509 Certificate version""" 
     
    239228 
    240229    version = property(fget=__getVersion, doc="X.509 Certificate version") 
    241          
    242230         
    243231    def __getSerialNumber(self): 
     
    250238    serialNumber = property(fget=__getSerialNumber,  
    251239                            doc="X.509 Certificate Serial Number") 
    252          
    253240 
    254241    def __getNotBefore(self): 
     
    261248    notBefore = property(fget=__getNotBefore,  
    262249                         doc="Not before validity time as datetime type") 
    263          
    264250         
    265251    def __getNotAfter(self): 
     
    273259                         doc="Not after validity time as datetime type") 
    274260         
    275          
    276261    def __getPubKey(self): 
    277262        """Get public key 
     
    284269        return self.__m2CryptoX509.get_pubkey() 
    285270 
    286     pubKey = property(fget=__getPubKey,  doc="Public Key") 
    287          
     271    pubKey = property(fget=__getPubKey, doc="Public Key") 
    288272         
    289273    def __getIssuer(self): 
     
    295279        return X500DN(m2CryptoX509Name=self.__m2CryptoX509.get_issuer()) 
    296280 
    297     issuer = property(fget=__getIssuer,  doc="Certificate Issuer") 
    298          
     281    issuer = property(fget=__getIssuer, doc="Certificate Issuer") 
    299282     
    300283    def __getSubject(self): 
     
    306289        return X500DN(m2CryptoX509Name=self.__m2CryptoX509.get_subject()) 
    307290     
    308     subject = property(fget=__getSubject,  doc="Certificate subject") 
    309  
     291    subject = property(fget=__getSubject, doc="Certificate subject") 
    310292 
    311293    def isValidTime(self,  
     
    457439         
    458440        return x509Cert 
    459          
     441 
     442    @classmethod 
     443    def fromM2Crypto(cls, m2CryptoX509): 
     444        """Convenience method to instantiate a new object from an M2Crypto 
     445        X.509 certificate object""" 
     446        x509Cert = cls(m2CryptoX509=m2CryptoX509) 
     447        return x509Cert 
     448     
    460449# Alternative AttCert constructors 
    461450def X509CertRead(filePath, warningStackLevel=4, **isValidTimeKw): 
  • TI12-security/trunk/python/ndg_security_common/ndg/security/common/credentialwallet.py

    r6039 r6040  
    6363    """Generic Exception class for CredentialWallet module.  Overrides  
    6464    Exception to enable writing to the log""" 
    65     def __init__(self, msg): 
    66         log.error(msg) 
    67         Exception.__init__(self, msg) 
     65    def __init__(self, *arg, **kw): 
     66        if len(arg) > 0: 
     67            log.error(arg[0]) 
     68             
     69        Exception.__init__(self, *arg, **kw) 
    6870 
    6971 
     
    256258    """Abstract base class for NDG and SAML Credential Wallet implementations 
    257259    """ 
     260     
     261    CONFIG_FILE_OPTNAMES = ("userId", "attributeAuthorityURI") 
     262         
    258263    __slots__ = ( 
    259         "userId", 
    260         "attributeAuthorityURI", 
    261264        "credentials", 
    262265        "credentialsKeyedByURI", 
    263266    ) 
     267    __slots__ += CONFIG_FILE_OPTNAMES 
    264268    __slots__ += tuple(["_CredentialWalletBase__%s" % name  
    265269                        for name in __slots__]) 
     
    17381742    """Attribute Authority returned a SAML Response error code""" 
    17391743    def __init__(self, *arg, **kw): 
    1740         SamlCredentialWalletError.__init__(self, *arg, **kw) 
     1744        CredentialWalletError.__init__(self, *arg, **kw) 
    17411745        self.__status = Status() 
    17421746        self.__status.statusCode = StatusCode() 
     
    17681772        else: 
    17691773            return '' 
    1770          
     1774 
     1775import re 
    17711776from uuid import uuid4 
    17721777try: # >= python 2.5 
     
    17741779except ImportError: 
    17751780    import ElementTree 
    1776   
     1781 
     1782from M2Crypto.m2urllib2 import HTTPSHandler 
     1783 
    17771784from saml.utils import SAMLDateTime 
    17781785from saml.common.xml import SAMLConstants 
     
    17931800from ndg.security.common.saml_utils.esg import EsgSamlNamespaces 
    17941801from ndg.security.common.X509 import X500DN 
     1802from ndg.security.common.utils import TypedList 
    17951803from ndg.security.common.utils.m2crypto import SSLContextProxy 
    17961804from ndg.security.common.utils.etree import prettyPrint 
     
    18031811    Queries 
    18041812     
    1805     @cvar DEFAULT_ATTR_DESCR: default attribute to query""" 
     1813    @cvar DEFAULT_QUERY_ATTRIBUTES: default attribute to query 
     1814    @type DEFAULT_QUERY_ATTRIBUTES: basestring 
     1815    @cvar QUERY_ATTRIBUTES_PAT: regular expression for parsing a query  
     1816    attribute definition from a single string as set in an ini file e.g. 
     1817    queryAttribute.0 = urn:esg:firstName, FirstName,  
     1818    sets the name, friendly name and format respectivelty for a SAML Attribute 
     1819    to be used in a query. 
     1820     
     1821    @type QUERY_ATTRIBUTES_PAT: basestring""" 
    18061822     
    18071823    XSSTRING_NS = "%s#%s" % ( 
     
    18091825        XSStringAttributeValue.TYPE_LOCAL_NAME 
    18101826    ) 
    1811     N_ATTR_DESCR_ELEM_ITEMS = 3 
    1812      
    1813     DEFAULT_ATTR_DESCR = ( 
    1814         (EsgSamlNamespaces.FIRSTNAME_ATTRNAME,  
    1815          EsgSamlNamespaces.FIRSTNAME_FRIENDLYNAME,  
    1816          XSSTRING_NS), 
    1817         (EsgSamlNamespaces.LASTNAME_ATTRNAME,  
    1818          EsgSamlNamespaces.LASTNAME_FRIENDLYNAME,  
    1819          XSSTRING_NS), 
    1820         (EsgSamlNamespaces.EMAILADDRESS_ATTRNAME,  
    1821          EsgSamlNamespaces.EMAILADDRESS_FRIENDLYNAME,  
    1822          XSSTRING_NS), 
    1823     ) 
     1827     
     1828    DEFAULT_QUERY_ATTRIBUTES = TypedList(Attribute) 
     1829    DEFAULT_QUERY_ATTRIBUTES += [Attribute(), Attribute(), Attribute()] 
     1830     
     1831    DEFAULT_QUERY_ATTRIBUTES[0].name = EsgSamlNamespaces.FIRSTNAME_ATTRNAME  
     1832    DEFAULT_QUERY_ATTRIBUTES[0].friendlyName = \ 
     1833                                    EsgSamlNamespaces.FIRSTNAME_FRIENDLYNAME 
     1834    DEFAULT_QUERY_ATTRIBUTES[0].format = XSSTRING_NS 
     1835 
     1836    DEFAULT_QUERY_ATTRIBUTES[1].name = EsgSamlNamespaces.LASTNAME_ATTRNAME  
     1837    DEFAULT_QUERY_ATTRIBUTES[1].friendlyName = \ 
     1838                                    EsgSamlNamespaces.LASTNAME_FRIENDLYNAME 
     1839    DEFAULT_QUERY_ATTRIBUTES[1].format = XSSTRING_NS 
     1840     
     1841    DEFAULT_QUERY_ATTRIBUTES[2].name = EsgSamlNamespaces.EMAILADDRESS_ATTRNAME 
     1842    DEFAULT_QUERY_ATTRIBUTES[2].friendlyName = \ 
     1843                                    EsgSamlNamespaces.EMAILADDRESS_FRIENDLYNAME 
     1844    DEFAULT_QUERY_ATTRIBUTES[2].format =  XSSTRING_NS 
     1845 
     1846    QUERY_ATTRIBUTES_ATTRNAME = 'queryAttributes' 
     1847    LEN_QUERY_ATTRIBUTES_ATTRNAME = len(QUERY_ATTRIBUTES_ATTRNAME) 
     1848 
     1849    QUERY_ATTRIBUTES_PAT = re.compile(',\s*') 
     1850     
    18241851    ESG_NAME_ID_FORMAT = EsgSamlNamespaces.NAMEID_FORMAT 
    18251852     
     
    18301857        ISSUER_DN_OPTNAME,                  
    18311858        CLOCK_SKEW_OPTNAME             
    1832     ) 
     1859    ) + CredentialWalletBase.CONFIG_FILE_OPTNAMES 
     1860     
    18331861    __slots__ = ( 
    1834        'sslCtx', 
    1835        'attributeDescr', 
     1862       'sslCtxProxy', 
     1863       QUERY_ATTRIBUTES_ATTRNAME, 
    18361864    ) 
    18371865    __slots__ += CONFIG_FILE_OPTNAMES 
     
    18411869     
    18421870    CREDENTIAL_REPOSITORY_NOT_SUPPORTED_MSG = ("SamlCredentialWallet doesn't " 
    1843                                                "support the CredentialRepository" 
    1844                                                " interface") 
     1871                                               "support the " 
     1872                                               "CredentialRepository " 
     1873                                               "interface") 
     1874 
    18451875    def __init__(self): 
    18461876        super(SamlCredentialWallet, self).__init__() 
     
    18481878        self.__issuerDN = None 
    18491879        self.__clockSkew = timedelta(seconds=0.) 
    1850                 
    1851         # Use property here as a safeguard in case DEFAULT_ATTR_DESCR has been 
    1852         # altered 
    1853         self.attributeDescr = SamlCredentialWallet.DEFAULT_ATTR_DESCR 
    1854         self.__sslCtx = SSLContextProxy() 
     1880        self.__queryAttributes = TypedList(Attribute) 
     1881        self.__sslCtxProxy = SSLContextProxy() 
    18551882 
    18561883    @classmethod 
     
    18761903        @param section: configuration file section from which to extract 
    18771904        parameters. 
    1878         ''' 
    1879          
     1905        '''   
    18801906        if isinstance(cfg, basestring): 
    18811907            cfgFilePath = os.path.expandvars(cfg) 
    18821908            _cfg = CaseSensitiveConfigParser() 
    1883             _cfg.read(configFilePath) 
     1909            _cfg.read(cfgFilePath) 
    18841910             
    18851911        elif isinstance(cfg, ConfigParser): 
     
    18871913        else: 
    18881914            raise AttributeError('Expecting basestring or ConfigParser type ' 
    1889                                  'for "cfg" attribute; got %r type' % type(cfg))      
    1890          
    1891         for optName in SamlCredentialWallet.CONFIG_FILE_OPTNAMES: 
    1892             val = _cfg.get(section, prefix+optName) 
     1915                                 'for "cfg" attribute; got %r type' % type(cfg))  
     1916         
     1917        prefixLen = len(prefix) 
     1918        for optName, val in _cfg.items(section): 
     1919            if prefix and optName.startswith(prefix): 
     1920                optName = optName[prefixLen:] 
     1921                 
    18931922            setattr(self, optName, val) 
    1894              
    1895     def _getAttributeDescr(self): 
    1896         return self.__attributeDescr 
    1897  
    1898     def _setAttributeDescr(self, value): 
    1899         if not isinstance(value, tuple): 
    1900             raise TypeError('Expecting tuple type for "attributeDescr";' 
    1901                             ' got %r instead' % type(value)) 
    1902              
    1903         for i in value: 
    1904             if not isinstance(value, tuple): 
    1905                 raise TypeError('Expecting tuple type for "attributeDescr" ' 
    1906                                 'tuple sub-elements; got %r instead' %  
    1907                                 type(value)) 
    1908             if len(i) != SamlCredentialWallet.N_ATTR_DESCR_ELEM_ITEMS: 
    1909                 raise TypeError('Expecting %d element tuple for ' 
    1910                                 '"attributeDescr" sub-elements; got %d ' 
    1911                                 'elements instead' %  
    1912                                 (SamlCredentialWallet.N_ATTR_DESCR_ELEM_ITEMS, 
    1913                                  len(i))) 
     1923 
     1924    def __setattr__(self, name, value): 
     1925        try: 
     1926            super(SamlCredentialWallet, self).__setattr__(name, value) 
     1927             
     1928        except AttributeError, e: 
     1929            if name.startswith(SamlCredentialWallet.QUERY_ATTRIBUTES_ATTRNAME): 
     1930                # Special handler for parsing string format settings 
     1931                if not isinstance(value, basestring): 
     1932                    raise TypeError('Expecting string format for special ' 
     1933                                    '%r attribute; got %r instead' % 
     1934                                    (name, type(value))) 
     1935                     
     1936                pat = SamlCredentialWallet.QUERY_ATTRIBUTES_PAT 
     1937                attribute = Attribute() 
    19141938                 
    1915         self.__attributeDescr = value 
    1916      
    1917     attributeDescr = property(_getAttributeDescr,  
    1918                               _setAttributeDescr,  
    1919                               doc="List of name, friendly name, format tuples " 
    1920                                   "determining attributes to query from the " 
    1921                                   "Attribute Authority") 
     1939                (attribute.name,  
     1940                 attribute.friendlyName,  
     1941                 attribute.format) = pat.split(value) 
     1942                  
     1943                self.queryAttributes.append(attribute) 
     1944            else: 
     1945                # Coerce into setting SSL Context Proxy attributes 
     1946                try: 
     1947                    setattr(self.sslCtxProxy, name, value) 
     1948                except: 
     1949                    raise e 
     1950      
     1951    @property 
     1952    def sslCtxProxy(self): 
     1953        """SSL Context Proxy object used for setting up an SSL Context for 
     1954        queries to the Attribute Authority 
     1955        """ 
     1956        return self.__sslCtxProxy 
     1957            
     1958    def _getQueryAttributes(self): 
     1959        """Returns a *COPY* of the attributes to avoid overwriting the  
     1960        member variable content 
     1961        """ 
     1962        return self.__queryAttributes 
     1963 
     1964    def _setQueryAttributes(self, value): 
     1965        if not isinstance(value, TypedList) and value.elementType != Attribute: 
     1966            raise TypeError('Expecting TypedList(Attribute) type for ' 
     1967                            '"queryAttributes"; got %r instead' % type(value))  
     1968         
     1969        self.__queryAttributes = value 
     1970     
     1971    queryAttributes = property(_getQueryAttributes,  
     1972                               _setQueryAttributes,  
     1973                               doc="List of attributes to query from the " 
     1974                                   "Attribute Authority") 
    19221975 
    19231976    def _getIssuerDN(self): 
     
    19662019        for attr, val in attrDict.items(): 
    19672020            setattr(self, attr, val) 
    1968      
    1969     @staticmethod 
    1970     def serialiseAssertion(assertion): 
    1971         """Convert SAML assertion object into a string""" 
    1972         samlAssertionElem = AssertionElementTree.toXML(assertion) 
    1973         return ElementTree.tostring(samlAssertionElem) 
    19742021         
    19752022    def attributeQuery(self): 
     
    19942041                   
    19952042        # Add list of attributes to query                       
    1996         for name, friendlyName, format in self.attributeDescr: 
    1997             attribute = Attribute() 
    1998             attribute.name = name 
    1999             attribute.nameFormat = format 
    2000             attribute.friendlyName = friendlyName 
    2001      
     2043        for attribute in self.queryAttributes: 
    20022044            attributeQuery.attributes.append(attribute) 
    20032045 
    20042046        # Make query over SOAP interface to remote service 
    2005         binding = SamlSoapBinding() 
     2047        binding = SamlSoapBinding(handlers=()) 
     2048        httpsHandler = HTTPSHandler(ssl_context=self.sslCtxProxy.createCtx()) 
     2049        binding.client.openerDirector.add_handler(httpsHandler) 
     2050         
    20062051        response = binding.attributeQuery(attributeQuery,  
    20072052                                          self.attributeAuthorityURI) 
     
    20622107            raise samlRespError 
    20632108 
    2064  
    20652109        # Add credential into wallet 
    20662110        # 
     
    20702114            self.addCredential(assertion,  
    20712115                               attributeAuthorityURI=self.attributeAuthorityURI) 
     2116             
     2117        return response 
    20722118 
    20732119    def addCredential(self,  
  • TI12-security/trunk/python/ndg_security_common/ndg/security/common/utils/m2crypto.py

    r6033 r6040  
    99__contact__ = "Philip.Kershaw@stfc.ac.uk" 
    1010__revision__ = '$Id: $' 
     11import logging 
     12log = logging.getLogger(__name__) 
    1113 
    1214import os 
    13 import traceback 
    14  
    15 from M2Crypto import SSL, X509, BIO, RSA 
     15import re 
     16 
     17from M2Crypto import SSL, X509 
    1618from M2Crypto.httpslib import HTTPSConnection as _HTTPSConnection 
    1719 
    1820from ndg.security.common.X509 import X509Cert, X509Stack, X500DN 
     21 
    1922 
    2023class InvalidCertSignature(SSL.Checker.SSLVerificationError): 
    2124    """Raise if verification against CA cert public key fails""" 
     25 
    2226 
    2327class InvalidCertDN(SSL.Checker.SSLVerificationError): 
     
    236240class SSLContextProxy(object): 
    237241    """Holder for M2Crypto.SSL.Context parameters""" 
    238      
    239     __slots__ = ( 
    240         "sslCertFilePath", 
    241         "sslPriKeyFilePath", 
    242         "sslPriKeyPwd", 
    243         "sslCACertFilePath", 
    244         "sslCACertDir" 
     242    PRE_VERIFY_FAIL, PRE_VERIFY_OK = range(2) 
     243     
     244    SSL_CERT_FILEPATH_OPTNAME = "sslCertFilePath" 
     245    SSL_PRIKEY_FILEPATH_OPTNAME = "sslPriKeyFilePath" 
     246    SSL_PRIKEY_PWD_OPTNAME = "sslPriKeyPwd" 
     247    SSL_CACERT_FILEPATH_OPTNAME = "sslCACertFilePath" 
     248    SSL_CACERT_DIRPATH_OPTNAME = "sslCACertDir" 
     249    SSL_VALID_DNS_OPTNAME = "sslValidDNs" 
     250     
     251    OPTNAMES = ( 
     252        SSL_CERT_FILEPATH_OPTNAME, 
     253        SSL_PRIKEY_FILEPATH_OPTNAME, 
     254        SSL_PRIKEY_PWD_OPTNAME, 
     255        SSL_CACERT_FILEPATH_OPTNAME, 
     256        SSL_CACERT_DIRPATH_OPTNAME, 
     257        SSL_VALID_DNS_OPTNAME 
    245258    ) 
     259     
     260    __slots__ = OPTNAMES 
    246261    __slots__ += tuple(["_SSLContextProxy__%s" % name for name in __slots__]) 
    247262    del name 
     263     
     264    VALID_DNS_PAT = re.compile(',\s*') 
    248265     
    249266    def __init__(self): 
     
    253270        self.__sslCACertFilePath = None 
    254271        self.__sslCACertDir = None 
    255  
    256     def createM2Ctx(self, **kw): 
     272        self.__sslValidDNs = [] 
     273 
     274    def createCtx(self, **kw): 
    257275        """Create an M2Crypto SSL Context from this objects properties 
    258276        @rtype: M2Crypto.SSL.Context 
     
    262280        if self.sslCertFilePath and self.sslPriKeyFilePath: 
    263281            ctx.load_cert(self.sslCertFilePath,  
    264                           self.sslPriKeyFilePath,  
     282                          self.__sslPriKeyFilePath,  
    265283                          lambda *arg, **kw: self.sslPriKeyPwd) 
    266284         
     
    269287                                      self.sslCACertDir) 
    270288             
     289        ctx.set_verify(SSL.verify_peer|SSL.verify_fail_if_no_peer_cert, 9, 
     290                       callback=self.createVerifySSLPeerCertCallback()) 
     291            
    271292        return ctx 
    272   
     293     
     294    def createVerifySSLPeerCertCallback(self): 
     295        """Create a callback function to enable the DN of the peer in an SSL 
     296        connection to be verified against a whitelist.   
     297         
     298        Nb. Making this function within the scope of a method of the class to 
     299        enables to access instance variables 
     300        """ 
     301         
     302        def _verifySSLPeerCertCallback(preVerifyOK, x509StoreCtx): 
     303            '''SSL verify callback function used to control the behaviour when  
     304            the SSL_VERIFY_PEER flag is set.  See: 
     305             
     306            http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html 
     307             
     308            This implementation applies verification in order to check the DN 
     309            of the peer certificate against a whitelist 
     310             
     311            @type preVerifyOK: int 
     312            @param preVerifyOK: If a verification error is found, this  
     313            parameter will be set to 0 
     314            @type x509StoreCtx: M2Crypto.X509.X509_Store_Context 
     315            @param x509StoreCtx: locate the certificate to be verified and  
     316            perform additional verification steps as needed 
     317            @rtype: int 
     318            @return: controls the strategy of the further verification process.  
     319            - If verify_callback returns 0, the verification process is  
     320            immediately stopped with "verification failed" state. If  
     321            SSL_VERIFY_PEER is set, a verification failure alert is sent to the 
     322            peer and the TLS/SSL handshake is terminated.  
     323            - If verify_callback returns 1, the verification process is  
     324            continued.  
     325            If verify_callback always returns 1, the TLS/SSL handshake will not 
     326            be terminated with respect to verification failures and the  
     327            connection  
     328            will be established. The calling process can however retrieve the  
     329            error code of the last verification error using  
     330            SSL_get_verify_result or by maintaining its own error storage  
     331            managed by verify_callback. 
     332            ''' 
     333            if preVerifyOK == 0: 
     334                # Something is wrong with the certificate don't bother  
     335                # proceeding any further 
     336                log.error("verifyCallback: pre-verify OK flagged an error " 
     337                          "with the peer certificate, returning error state " 
     338                          "to caller ...") 
     339                return preVerifyOK 
     340             
     341            x509CertChain = x509StoreCtx.get1_chain() 
     342            for cert in x509CertChain: 
     343                x509Cert = X509Cert.fromM2Crypto(cert) 
     344                if x509Cert.dn in self.sslValidDNs: 
     345                    return preVerifyOK 
     346                 
     347                subject = cert.get_subject() 
     348                dn = subject.as_text() 
     349                log.debug("verifyCallback: dn = %r", dn) 
     350                 
     351            # No match found so return fail status 
     352            return SSLContextProxy.PRE_VERIFY_FAIL 
     353         
     354        return _verifySSLPeerCertCallback 
     355 
     356    def _getSSLCertFilePath(self): 
     357        return self.__sslCertFilePath 
     358     
    273359    def _setSSLCertFilePath(self, filePath): 
    274360        "Set X.509 cert file path property method" 
     
    283369                 
    284370    sslCertFilePath = property(fset=_setSSLCertFilePath, 
     371                               fget=_getSSLCertFilePath, 
    285372                               doc="File path to X.509 cert.") 
    286373         
     
    304391                            "a valid string or None type: %r" % type(value))  
    305392         
    306         self.__sslCACertFilePath = value 
     393        self.__sslCACertFilePath = os.path.expandvars(value) 
    307394         
    308395    sslCACertFilePath = property(fget=_getSSLCACertFilePath, 
     
    334421                            "a valid string or None type: %r" % type(value))       
    335422         
    336         self.__sslCACertDir = value 
     423        self.__sslCACertDir = os.path.expandvars(value) 
    337424         
    338425    sslCACertDir = property(fget=_getSSLCACertDir, 
    339426                            fset=_setSSLCACertDir, 
    340                             doc="Path to directory containing concatenated PEM " 
    341                                 "encoded CA Certificates - used for " 
    342                                 "verification of peer certs in SSL connection." 
    343                                 "   File must be named with the form <hash>.0 " 
    344                                 "where hash can be obtained using openssl " 
    345                                 "x509 -in cert -hash -noout or using the " 
    346                                 "c_rehash OpenSSL script") 
    347  
     427                            doc="Path to directory containing PEM encoded CA " 
     428                                "Certificates used for verification of peer " 
     429                                "certs in SSL connection.   Files in the " 
     430                                "directory must be named with the form " 
     431                                "<hash>.0 where <hash> can be obtained using " 
     432                                "openssl x509 -in cert -hash -noout or using " 
     433                                "the c_rehash OpenSSL script") 
     434     
     435    def _getSslValidDNs(self): 
     436        return self.__sslValidDNs 
     437 
     438    def _setSslValidDNs(self, value): 
     439        if isinstance(value, basestring):   
     440            pat = SSLContextProxy.VALID_DNS_PAT 
     441            self.__sslValidDNs = [X500DN.fromString(dn)  
     442                                  for dn in pat.split(value)] 
     443             
     444        elif isinstance(value, (tuple, list)): 
     445            self.__sslValidDNs = [X500DN.fromString(dn) for dn in value] 
     446        else: 
     447            raise TypeError('Expecting list/tuple or basestring type for "%s" ' 
     448                            'attribute; got %r' % 
     449                            (SSLContextProxy.SSL_VALID_DNS_OPTNAME,  
     450                             type(value))) 
     451     
     452    sslValidDNs = property(_getSslValidDNs,  
     453                           _setSslValidDNs,  
     454                           doc="whitelist of acceptable certificate " 
     455                               "Distinguished Names for peer certificates in " 
     456                               "SSL requests") 
     457 
     458    def _getSSLPriKeyFilePath(self): 
     459        return self.__sslPriKeyFilePath 
     460     
    348461    def _setSSLPriKeyFilePath(self, filePath): 
    349462        "Set ssl private key file path property method" 
     
    358471        self.__sslPriKeyFilePath = filePath 
    359472         
    360     sslPriKeyFilePath = property(fset=_setSSLPriKeyFilePath, 
     473    sslPriKeyFilePath = property(fget=_getSSLPriKeyFilePath, 
     474                                 fset=_setSSLPriKeyFilePath, 
    361475                                 doc="File path to SSL private key") 
    362476  
  • TI12-security/trunk/python/ndg_security_server/ndg/security/server/attributeauthority.py

    r6039 r6040  
    21252125                                         "Attribute Authority via the SAML " 
    21262126                                         "Attribute Query interface") 
     2127     
    21272128    def _getConnectionString(self): 
    21282129        return self.__connectionString 
  • TI12-security/trunk/python/ndg_security_test/ndg/security/test/unit/__init__.py

    r6039 r6040  
    6868    SESSIONMANAGER_PORTNUM = 5500 
    6969     
    70     mkDataDirPath = staticmethod(mkDataDirPath) 
    71      
    7270    NDGSEC_UNITTESTS_DISABLE_THREAD_SERVICES_ENVVAR = \ 
    7371        'NDGSEC_UNITTESTS_DISABLE_THREAD_SERVICES' 
     
    116114                           "/O=Site B/CN=Authorisation Service") 
    117115     
     116    SSL_PEM_FILENAME = 'localhost.pem' 
     117    SSL_PEM_FILEPATH = mkDataDirPath(os.path.join('pki', SSL_PEM_FILENAME)) 
     118     
    118119    def __init__(self, *arg, **kw): 
    119120        if BaseTestCase.configDirEnvVarName not in os.environ: 
     
    135136            return 
    136137         
     138        withSSL = kw.pop('withSSL', False) 
     139        if withSSL: 
     140            from OpenSSL import SSL 
     141             
     142            certFilePath = mkDataDirPath(os.path.join('pki', 'localhost.crt')) 
     143            priKeyFilePath = mkDataDirPath(os.path.join('pki', 'localhost.key')) 
     144             
     145            kw['ssl_context'] = SSL.Context(SSL.SSLv23_METHOD) 
     146            kw['ssl_context'].set_options(SSL.OP_NO_SSLv2) 
     147         
     148            kw['ssl_context'].use_privatekey_file(priKeyFilePath) 
     149            kw['ssl_context'].use_certificate_file(certFilePath) 
     150             
    137151        try: 
    138152            self.services.append(PasteDeployAppServer(*arg, **kw)) 
     
    142156            pass 
    143157 
    144     def startAttributeAuthorities(self): 
     158    def startAttributeAuthorities(self, withSSL=False, port=None): 
    145159        """Serve test Attribute Authorities to test against""" 
    146         self.startSiteAAttributeAuthority() 
    147         self.startSiteBAttributeAuthority() 
    148          
    149     def startSiteAAttributeAuthority(self): 
     160        self.startSiteAAttributeAuthority(withSSL=withSSL, port=port) 
     161        self.startSiteBAttributeAuthority(withSSL=withSSL, port=port) 
     162         
     163    def startSiteAAttributeAuthority(self, withSSL=False, port=None): 
    150164        siteACfgFilePath = mkDataDirPath(join('attributeauthority',  
    151165                                              'sitea',  
    152166                                              'site-a.ini')) 
    153167        self.addService(cfgFilePath=siteACfgFilePath,  
    154                         port=BaseTestCase.SITEA_ATTRIBUTEAUTHORITY_PORTNUM) 
    155          
    156     def startSiteBAttributeAuthority(self): 
     168                        port=port or BaseTestCase.SITEA_ATTRIBUTEAUTHORITY_PORTNUM, 
     169                        withSSL=withSSL) 
     170         
     171    def startSiteBAttributeAuthority(self, withSSL=False, port=None): 
    157172        siteBCfgFilePath = mkDataDirPath(join('attributeauthority', 
    158173                                              'siteb',  
    159174                                              'site-b.ini')) 
    160175        self.addService(cfgFilePath=siteBCfgFilePath,  
    161                         port=BaseTestCase.SITEB_ATTRIBUTEAUTHORITY_PORTNUM)         
     176                        port=port or BaseTestCase.SITEB_ATTRIBUTEAUTHORITY_PORTNUM, 
     177                        withSSL=withSSL)         
    162178 
    163179    def startSessionManager(self): 
  • TI12-security/trunk/python/ndg_security_test/ndg/security/test/unit/credentialwallet/test_credentialwallet.py

    r6039 r6040  
    189189 
    190190class SamlCredentialWalletTestCase(BaseTestCase): 
     191    THIS_DIR = os.path.dirname(__file__) 
     192    CONFIG_FILENAME = 'test_samlcredentialwallet.cfg' 
     193    CONFIG_FILEPATH = os.path.join(THIS_DIR, CONFIG_FILENAME) 
     194     
    191195    def __init__(self, *arg, **kw): 
    192196        super(SamlCredentialWalletTestCase, self).__init__(*arg, **kw) 
    193         self.startSiteAAttributeAuthority() 
    194          
    195     def test01(self): 
     197        self.startSiteAAttributeAuthority(withSSL=True, port=5443) 
     198         
     199    def test01Query(self): 
    196200        wallet = SamlCredentialWallet() 
    197201         
     
    200204        wallet.attributeAuthorityURI = \ 
    201205            SamlCredentialWalletTestCase.SITEA_ATTRIBUTEAUTHORITY_SAML_URI 
     206         
     207        wallet.queryAttributes = SamlCredentialWallet.DEFAULT_QUERY_ATTRIBUTES 
    202208         
    203209        wallet.attributeQuery() 
     
    217223            SamlCredentialWalletTestCase.SITEA_SAML_ISSUER_NAME 
    218224        ].credential 
    219         samlAssertionElem = AssertionElementTree.toXML(assertion) 
    220         print("SAML Assertion:\n%s" % prettyPrint(samlAssertionElem)) 
    221                                                                  
     225         
     226        print("SAML Assertion:\n%s" %  
     227              prettyPrint(AssertionElementTree.toXML(assertion))) 
     228 
     229    def test02ReadCustomQueryAttributes(self): 
     230        wallet = SamlCredentialWallet.fromConfig( 
     231                                SamlCredentialWalletTestCase.CONFIG_FILEPATH) 
     232        wallet.attributeQuery() 
     233         
     234        self.assert_(SamlCredentialWalletTestCase.SITEA_SAML_ISSUER_NAME in \ 
     235                     wallet.credentials) 
     236         
     237        assertion = wallet.credentials[ 
     238            SamlCredentialWalletTestCase.SITEA_SAML_ISSUER_NAME 
     239        ].credential 
     240         
     241        print("SAML Assertion:\n%s" %  
     242              prettyPrint(AssertionElementTree.toXML(assertion))) 
     243         
     244         
    222245if __name__ == "__main__": 
    223246    unittest.main()         
  • TI12-security/trunk/python/ndg_security_test/ndg/security/test/unit/wsgi/__init__.py

    r5779 r6040  
    2121    """Wrapper to paste.httpserver to enable background threading""" 
    2222     
    23     def __init__(self, app=None, cfgFilePath=None, port=7443, host='0.0.0.0'): 
     23    def __init__(self, app=None, cfgFilePath=None, port=7443, host='0.0.0.0', 
     24                 ssl_context=None): 
    2425        """Load an application configuration from cfgFilePath ini file and  
    2526        instantiate Paste server object 
     
    3435            raise KeyError('Either the "cfgFilePath" or "app" keyword must be ' 
    3536                           'set') 
    36              
     37                        
    3738        self.__pasteServer = paste.httpserver.serve(app, host=host, port=port,  
    38                                                     start_loop=False) 
     39                                                    start_loop=False,  
     40                                                    ssl_context=ssl_context) 
    3941     
    4042    def _getPasteServer(self): 
Note: See TracChangeset for help on using the changeset viewer.