Changeset 6827 for TI12-security/trunk


Ignore:
Timestamp:
20/04/10 16:40:56 (10 years ago)
Author:
pjkersha
Message:

Testing with new getTrustRoots method added.

Location:
TI12-security/trunk/MyProxyClient
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/MyProxyClient/myproxy/client.py

    r6202 r6827  
    121121    http://grid.ncsa.uiuc.edu/myproxy/protocol/ 
    122122     
    123     @type getCmd: string 
    124     @cvar getCmd: get command string 
    125      
    126     @type infoCmd: string 
    127     @cvar infoCmd: info command string 
    128      
    129     @type destroyCmd: string 
    130     @cvar destroyCmd: destroy command string 
    131      
    132     @type changePassphraseCmd: string 
    133     @cvar changePassphraseCmd: command string to change cred pass-phrase 
    134      
    135     @type storeCmd: string 
    136     @cvar storeCmd: store command string 
     123    @type GET_CMD: string 
     124    @cvar GET_CMD: get command string 
     125     
     126    @type INFO_CMD: string 
     127    @cvar INFO_CMD: info command string 
     128     
     129    @type DESTROY_CMD: string 
     130    @cvar DESTROY_CMD: destroy command string 
     131     
     132    @type CHANGE_PASSPHRASE_CMD: string 
     133    @cvar CHANGE_PASSPHRASE_CMD: command string to change cred pass-phrase 
     134     
     135    @type STORE_CMD: string 
     136    @cvar STORE_CMD: store command string 
     137     
     138    @type GET_TRUST_ROOTS_CMD: string 
     139    @cvar GET_TRUST_ROOTS_CMD: get trust roots command string 
    137140     
    138141    @type _hostCertSubDirPath: string 
     
    141144    @type _hostKeySubDirPath: string 
    142145    @cvar _hostKeySubDirPath: sub-directory path to host key (as tuple) 
     146     
     147    @type PRIKEY_NBITS: int 
     148    @cvar PRIKEY_NBITS: default number of bits for private key generated 
     149     
     150    @type MESSAGE_DIGEST_TYPE: string 
     151    @cvar MESSAGE_DIGEST_TYPE: message digest type is MD5 
     152     
     153    @type SERVER_RESP_BLK_SIZE: int 
     154    @cvar SERVER_RESP_BLK_SIZE: block size for retrievals from server 
     155     
     156    @type MAX_RECV_TRIES: int 
     157    @cvar MAX_RECV_TRIES: maximum number of retrievals of size  
     158    SERVER_RESP_BLK_SIZE before this client gives up 
     159     
     160    @type DEF_PROXY_FILEPATH: string 
     161    @cvar DEF_PROXY_FILEPATH: default location for proxy file to be written to 
     162     
     163    @type PROXY_FILE_PERMISSIONS: int 
     164    @cvar PROXY_FILE_PERMISSIONS: file permissions returned proxy file is  
     165    created with 
    143166     
    144167    @type propertyDefaults: tuple 
     
    147170    """ 
    148171       
    149     getCmd="""VERSION=MYPROXYv2 
     172    GET_CMD="""VERSION=MYPROXYv2 
    150173COMMAND=0 
    151174USERNAME=%s 
     
    153176LIFETIME=%d""" 
    154177  
    155     infoCmd="""VERSION=MYPROXYv2 
     178    INFO_CMD="""VERSION=MYPROXYv2 
    156179COMMAND=2 
    157180USERNAME=%s 
     
    159182LIFETIME=0""" 
    160183  
    161     destroyCmd="""VERSION=MYPROXYv2 
     184    DESTROY_CMD="""VERSION=MYPROXYv2 
    162185COMMAND=3 
    163186USERNAME=%s 
     
    165188LIFETIME=0""" 
    166189 
    167     changePassphraseCmd="""VERSION=MYPROXYv2 
     190    CHANGE_PASSPHRASE_CMD="""VERSION=MYPROXYv2 
    168191 COMMAND=4 
    169192 USERNAME=%s 
     
    172195 LIFETIME=0""" 
    173196    
    174     storeCmd="""VERSION=MYPROXYv2 
     197    STORE_CMD="""VERSION=MYPROXYv2 
    175198COMMAND=5 
    176199USERNAME=%s 
     
    178201LIFETIME=%d""" 
    179202 
     203    GET_TRUST_ROOTS_CMD="""VERSION=MYPROXYv2 
     204COMMAND=7 
     205USERNAME=%s 
     206PASSPHRASE=%s 
     207LIFETIME=0 
     208TRUSTED_CERTS=1""" 
     209 
    180210    _hostCertSubDirPath = ('etc', 'hostcert.pem') 
    181211    _hostKeySubDirPath = ('etc', 'hostkey.pem') 
     
    183213    # Work out default location of proxy file if it exists.  This is set if a 
    184214    # call has been made previously to logon / get-delegation 
    185     defProxyFile = sys.platform == 'win32' and 'proxy' or \ 
    186     sys.platform in ('linux2', 'darwin') and '/tmp/x509up_u%s'%(os.getuid()) \ 
    187     or None      
    188      
    189     PRIKEY_NBITS = 2048 
     215    DEF_PROXY_FILEPATH = sys.platform == ('win32' and 'proxy' or  
     216                                    sys.platform in ('linux2', 'darwin') and  
     217                                    '/tmp/x509up_u%s' % (os.getuid())  
     218                                    or None)   
     219     
     220    PRIKEY_NBITS = 4096 
    190221    MESSAGE_DIGEST_TYPE = "md5" 
    191222    SERVER_RESP_BLK_SIZE = 8192 
     223    MAX_RECV_TRIES = 1024 
    192224     
    193225    # valid configuration property keywords 
     
    245277        self.serverDN = os.environ.get('MYPROXY_SERVER_DN', 
    246278                                    MyProxyClient.propertyDefaults['serverDN']) 
     279         
     280        # Environment variable may be quoted 
     281        if self.serverDN: 
     282            self.serverDN = self.serverDN.strip('"') 
    247283             
    248284        # keyword settings 
     
    554590                         
    555591        req.set_subject_name(x509Name) 
    556          
    557592        req.sign(pubKey, messageDigest) 
    558593 
    559594        return req.as_der() 
    560      
    561595     
    562596    def _deserializeResponse(self, msg, *fieldNames): 
     
    656690         
    657691        if filePath is None: 
    658             filePath = MyProxyClient.defProxyFile 
     692            filePath = MyProxyClient.DEF_PROXY_FILEPATH 
    659693             
    660694        if filePath is None: 
     
    663697         
    664698        outStr = proxyCert + proxyPriKey + userX509Cert        
    665         open(MyProxyClient.defProxyFile, 'w').write(outStr) 
     699        open(MyProxyClient.DEF_PROXY_FILEPATH, 'w').write(outStr) 
    666700        try: 
    667701            # Make sure permissions are set correctly 
    668             os.chmod(MyProxyClient.defProxyFile, 0600) 
     702            os.chmod(MyProxyClient.DEF_PROXY_FILEPATH,  
     703                     MyProxyClient.PROXY_FILE_PERMISSIONS) 
    669704        except Exception, e: 
    670705            # Don't leave the file lying around if couldn't change it's 
    671706            # permissions 
    672             os.unlink(MyProxyClient.defProxyFile) 
    673              
    674             log.error('Unable to set 0600 permissions for proxy file "%s": %s'%  
    675                       (MyProxyClient.defProxyFile, e)) 
     707            os.unlink(MyProxyClient.DEF_PROXY_FILEPATH) 
     708             
     709            log.error('Unable to set %o permissions for proxy file "%s": %s'%  
     710                      (MyProxyClient.PROXY_FILE_PERMISSIONS, 
     711                       MyProxyClient.DEF_PROXY_FILEPATH, e)) 
    676712            raise 
    677713 
     
    684720        @return: tuple containing proxy cert, private key, user cert""" 
    685721        if filePath is None: 
    686             filePath = MyProxyClient.defProxyFile 
     722            filePath = MyProxyClient.DEF_PROXY_FILEPATH 
    687723             
    688724        if filePath is None: 
     
    690726                                     "platform?") 
    691727                
    692         proxy = open(MyProxyClient.defProxyFile).read() 
     728        proxy = open(MyProxyClient.DEF_PROXY_FILEPATH).read() 
    693729         
    694730        # Split certs and key into separate tuple items 
     
    744780     
    745781        # send info command - ensure conversion from unicode before writing 
    746         cmd = MyProxyClient.infoCmd % username 
     782        cmd = MyProxyClient.INFO_CMD % username 
    747783        conn.write(str(cmd)) 
    748784     
     
    807843     
    808844        # send command - ensure conversion from unicode before writing 
    809         cmd = MyProxyClient.changePassphraseCmd % (username,  
    810                                                    passphrase, 
    811                                                    newPassphrase) 
     845        cmd = MyProxyClient.CHANGE_PASSPHRASE_CMD % (username,  
     846                                                     passphrase, 
     847                                                     newPassphrase) 
    812848        conn.write(str(cmd)) 
    813849     
     
    864900     
    865901        # send destroy command - ensure conversion from unicode before writing 
    866         cmd = MyProxyClient.destroyCmd % username 
     902        cmd = MyProxyClient.DESTROY_CMD % username 
    867903        conn.write(str(cmd)) 
    868904     
     
    963999     
    9641000        # send store command - ensure conversion from unicode before writing 
    965         cmd = MyProxyClient.storeCmd % (username, lifetime) 
     1001        cmd = MyProxyClient.STORE_CMD % (username, lifetime) 
    9661002        conn.write(str(cmd)) 
    9671003     
     
    10331069     
    10341070        # send get command - ensure conversion from unicode before writing 
    1035         cmd = MyProxyClient.getCmd % (username, passphrase, lifetime) 
     1071        cmd = MyProxyClient.GET_CMD % (username, passphrase, lifetime) 
    10361072        conn.write(str(cmd)) 
    10371073     
     
    10651101                                                    (nCerts, len(pemCerts))) 
    10661102     
    1067         if key is not None: 
     1103        if keys is not None: 
    10681104            # Return certs and private key 
    10691105            # - proxy or dynamically issued certificate (MyProxy CA mode) 
    10701106            # - private key 
    10711107            # - rest of cert chain if proxy cert issued 
    1072             pemKey = key.as_pem(cipher=None) 
     1108            pemKey = keys.as_pem(cipher=None) 
    10731109            creds = [pemCerts[0], pemKey] 
    10741110            creds.extend(pemCerts[1:]) 
     
    10831119        """Retrieve proxy cert for user - same as logon""" 
    10841120        return self.logon(*arg, **kw) 
     1121     
     1122    def getTrustRoots(self, username='', passphrase=''): 
     1123        """Get trust roots for the given MyProxy server 
     1124         
     1125        @type username: basestring 
     1126        @param username: username (optional) 
     1127         
     1128        @type passphrase: basestring 
     1129        @param passphrase: pass-phrase (optional) 
     1130        server 
     1131         
     1132        @return: trust root files as a dictionary keyed by file name with each  
     1133        item value set to the file contents 
     1134        @rtype: dict 
     1135        """ 
     1136        # Set-up SSL connection 
     1137        conn = self._initConnection() 
     1138        conn.connect((self.hostname, self.port)) 
     1139         
     1140        # send globus compatibility stuff 
     1141        conn.write('0') 
     1142     
     1143        # send get command - ensure conversion from unicode before writing 
     1144        cmd = MyProxyClient.GET_TRUST_ROOTS_CMD % (username, passphrase) 
     1145        conn.write(str(cmd)) 
     1146     
     1147        # process server response chunks until all consumed 
     1148        dat = '' 
     1149        try: 
     1150            for tries in range(MyProxyClient.MAX_RECV_TRIES): 
     1151                dat += conn.recv(MyProxyClient.SERVER_RESP_BLK_SIZE) 
     1152        except SSL.SSLError: 
     1153            # Expect this exception when response content exhausted 
     1154            pass 
     1155         
     1156        # Precaution 
     1157        if tries == MyProxyClient.MAX_RECV_TRIES: 
     1158            log.warning('Maximum %d tries reached for getTrustRoots response ' 
     1159                        'block retrieval with block size %d',  
     1160                        MyProxyClient.MAX_RECV_TRIES, 
     1161                        MyProxyClient.SERVER_RESP_BLK_SIZE) 
     1162             
     1163        respCode, errorTxt, fields = self._deserializeResponse(dat,  
     1164                                                               'TRUSTED_CERTS') 
     1165        if respCode: 
     1166            raise MyProxyClientGetError(errorTxt) 
     1167         
     1168        # Skip terminating line 
     1169        lines = dat.split('\n')[:-1] 
     1170        log.debug("Response = %r", lines) 
     1171 
     1172        fileNameKeys = fields['TRUSTED_CERTS'].split(',') 
     1173        respDict = dict([tuple(line.split('=', 1))  
     1174                         for line in lines if line.startswith('FILEDATA_')]) 
     1175         
     1176        filesDict = dict([(k, base64.b64decode(respDict['FILEDATA_' + k]))  
     1177                          for k in fileNameKeys]) 
     1178         
     1179        return filesDict 
     1180         
  • TI12-security/trunk/MyProxyClient/test/myProxyClient.cfg

    r6107 r6827  
    2121# CN is usually set to "host/<fqdn>".  Delete this element and set from  
    2222# MYPROXY_SERVER_DN environment variable if preferred 
    23 serverDN=/O=NDG/OU=Raphael/CN=raphael 
     23#serverDN=/O=NDG/OU=Raphael/CN=raphael 
    2424 
    2525# Set "host/" prefix to host cert CN as is default with globus 
     
    4444 
    4545#caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/ndg-test-ca.crt 
    46 caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/ndg-glue-ca.crt 
     46caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/test-ca.crt 
  • TI12-security/trunk/MyProxyClient/test/myProxyClientTest.cfg

    r5048 r6827  
    1515# terminal.  To set a null password, leave the field in place but set to 
    1616# blank 
    17 [test1Store] 
     17[test01Store] 
    1818username: testuser 
    1919passphrase: testpassword 
     
    2424ownerPassphrase: testpassword 
    2525 
    26 [test2GetDelegation] 
     26[test02GetDelegation] 
    2727username: testuser 
    2828passphrase: testpassword 
     
    3131proxyKeyFileOut: $MYPROXYCLIENT_UNITTEST_DIR/proxy.key 
    3232 
    33 [test3Info] 
     33[test03Info] 
    3434username: testuser 
    3535ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt 
     
    3737ownerPassphrase: testpassword 
    3838 
    39 [test4ChangePassphrase] 
     39[test04ChangePassphrase] 
    4040username: testuser 
    4141ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt 
     
    4545ownerPassphrase: testpassword 
    4646 
    47 [test5Destroy] 
     47[test05Destroy] 
    4848username: testuser 
    4949ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt 
  • TI12-security/trunk/MyProxyClient/test/test_myproxyclient.py

    r5048 r6827  
    1010__contact__ = "Philip.Kershaw@stfc.ac.uk" 
    1111__revision__ = '$Id$' 
     12import logging 
     13logging.basicConfig(level=logging.DEBUG) 
    1214 
    1315import unittest 
     
    1618import getpass 
    1719import traceback 
     20from os import path 
     21 
     22from M2Crypto import X509 
    1823 
    1924from myproxy.client import CaseSensitiveConfigParser, MyProxyClient 
    2025 
    21 xpdVars = os.path.expandvars 
    22 jnPath = os.path.join 
    23 mkPath = lambda file: jnPath(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], file) 
     26mkPath = lambda file: path.join(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], file) 
    2427 
    2528class _MyProxyClientTestCase(unittest.TestCase): 
     
    3134    if 'MYPROXYCLIENT_UNITTEST_DIR' not in os.environ: 
    3235        os.environ['MYPROXYCLIENT_UNITTEST_DIR'] = \ 
    33             os.path.abspath(os.path.dirname(__file__)) 
     36                                        path.abspath(path.dirname(__file__)) 
    3437 
    3538 
     
    3740    '''Tests require a connection to a real MyProxy service running on a host 
    3841    ''' 
     42    CONFIG_FILENAME = "myProxyClientTest.cfg" 
    3943     
    4044    def setUp(self): 
     
    4347         
    4448        configParser = CaseSensitiveConfigParser() 
    45         configFilePath = jnPath(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], 
    46                                 "myProxyClientTest.cfg") 
     49        configFilePath = path.join(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], 
     50                                   MyProxyClientLiveTestCase.CONFIG_FILENAME) 
    4751        configParser.read(configFilePath) 
    4852         
     
    5054        for section in configParser.sections(): 
    5155            self.cfg[section] = dict(configParser.items(section)) 
    52              
    53         self.clnt = MyProxyClient( 
    54                         cfgFilePath=xpdVars(self.cfg['setUp']['cfgFilePath'])) 
    55          
    56  
    57     def test1Store(self): 
    58         '''test1Store: upload X509 cert and private key to repository''' 
    59         thisSection = self.cfg['test1Store'] 
     56         
     57        configFilePath = path.expandvars(self.cfg['setUp']['cfgFilePath']) 
     58        self.clnt = MyProxyClient(cfgFilePath=configFilePath) 
     59         
     60    def test01Store(self): 
     61        # upload X509 cert and private key to repository 
     62        thisSection = self.cfg['test01Store'] 
    6063         
    6164        passphrase = thisSection.get('passphrase') 
     
    6972                                                     " owner pass-phrase: ") 
    7073 
    71         certFile = xpdVars(thisSection['signingCertFilePath']) 
    72         keyFile = xpdVars(thisSection['signingPriKeyFilePath']) 
    73         ownerCertFile = xpdVars(thisSection['ownerCertFile']) 
    74         ownerKeyFile = xpdVars(thisSection['ownerKeyFile']) 
     74        certFile = path.expandvars(thisSection['signingCertFilePath']) 
     75        keyFile = path.expandvars(thisSection['signingPriKeyFilePath']) 
     76        ownerCertFile = path.expandvars(thisSection['ownerCertFile']) 
     77        ownerKeyFile = path.expandvars(thisSection['ownerKeyFile']) 
    7578             
    7679        self.clnt.store(thisSection['username'], 
     
    8487        print("Store creds for user %s" % thisSection['username']) 
    8588     
    86      
    87     def test2GetDelegation(self): 
    88         '''test2GetDelegation: retrieve proxy cert./private key''' 
    89         thisSection = self.cfg['test2GetDelegation'] 
     89    def test02GetDelegation(self): 
     90        # retrieve proxy cert./private key 
     91        thisSection = self.cfg['test02GetDelegation'] 
    9092         
    9193        passphrase = thisSection.get('passphrase') 
     
    9496                                                "passphrase: ") 
    9597          
    96         proxyCertFile = xpdVars(thisSection['proxyCertFileOut']) 
    97         proxyKeyFile = xpdVars(thisSection['proxyKeyFileOut']) 
     98        proxyCertFile = path.expandvars(thisSection['proxyCertFileOut']) 
     99        proxyKeyFile = path.expandvars(thisSection['proxyKeyFileOut']) 
    98100 
    99101        creds = self.clnt.getDelegation(thisSection['username'],  
     
    104106        open(proxyKeyFile, 'w').write(creds[1]) 
    105107 
    106  
    107     def test3Info(self): 
    108         '''test3Info: Retrieve information about a given credential''' 
    109         thisSection = self.cfg['test3Info'] 
     108    def test03Info(self): 
     109        # Retrieve information about a given credential 
     110        thisSection = self.cfg['test03Info'] 
    110111         
    111112        # ownerPassphrase can be omitted from the congif file in which case 
     
    118119        credExists, errorTxt, fields = self.clnt.info( 
    119120                                     thisSection['username'], 
    120                                      xpdVars(thisSection['ownerCertFile']), 
    121                                      xpdVars(thisSection['ownerKeyFile']), 
     121                                     path.expandvars(thisSection['ownerCertFile']), 
     122                                     path.expandvars(thisSection['ownerKeyFile']), 
    122123                                     ownerPassphrase=ownerPassphrase) 
    123124        print "test3Info... " 
     
    126127        print "fields: %s" % fields 
    127128 
    128  
    129     def test4ChangePassphrase(self):         
    130         """test4ChangePassphrase: change pass-phrase protecting a given 
    131         credential""" 
    132         thisSection = self.cfg['test4ChangePassphrase'] 
     129    def test04ChangePassphrase(self):         
     130        # change pass-phrase protecting a given credential 
     131        thisSection = self.cfg['test04ChangePassphrase'] 
    133132         
    134133        passphrase = thisSection.get('passphrase') 
     
    153152 
    154153        self.clnt.changePassphrase(thisSection['username'], 
    155                                    passphrase, 
    156                                    newPassphrase,  
    157                                    xpdVars(thisSection['ownerCertFile']), 
    158                                    xpdVars(thisSection['ownerKeyFile']), 
    159                                    ownerPassphrase=ownerPassphrase) 
     154                               passphrase, 
     155                               newPassphrase,  
     156                               path.expandvars(thisSection['ownerCertFile']), 
     157                               path.expandvars(thisSection['ownerKeyFile']), 
     158                               ownerPassphrase=ownerPassphrase) 
    160159        print("Changed pass-phrase") 
    161160 
    162  
    163     def test5Destroy(self): 
    164         '''test5Destroy: destroy credentials for a given user''' 
    165         thisSection = self.cfg['test5Destroy'] 
     161    def test05Destroy(self): 
     162        # destroy credentials for a given user 
     163        thisSection = self.cfg['test05Destroy'] 
    166164         
    167165        ownerPassphrase = thisSection.get('ownerPassphrase') 
     
    171169 
    172170        self.clnt.destroy(thisSection['username'],  
    173                           ownerCertFile=xpdVars(thisSection['ownerCertFile']), 
    174                           ownerKeyFile=xpdVars(thisSection['ownerKeyFile']), 
    175                           ownerPassphrase=ownerPassphrase) 
     171                  ownerCertFile=path.expandvars(thisSection['ownerCertFile']), 
     172                  ownerKeyFile=path.expandvars(thisSection['ownerKeyFile']), 
     173                  ownerPassphrase=ownerPassphrase) 
    176174        print("Destroy creds for user %s" % thisSection['username']) 
    177175         
     176    def test06GetTrustRoots(self): 
     177        # Test get trust roots command 
     178        trustRoots = self.clnt.getTrustRoots() 
     179        self.assert_(trustRoots) 
     180        self.assert_(isinstance(trustRoots, dict)) 
     181        self.assert_(len(trustRoots) > 0) 
     182        for fileName, fileContents in trustRoots.items(): 
     183            if fileName.endswith('.0'): 
     184                # test parsing certificate 
     185                cert = X509.load_cert_string(fileContents, X509.FORMAT_PEM) 
     186                self.assert_(cert) 
     187                self.assert_(isinstance(cert, X509.X509)) 
     188                subj = cert.get_subject() 
     189                self.assert_(subj) 
     190                print("Trust root certificate retrieved with DN=%s" % subj) 
     191                 
    178192         
    179193from myproxy.utils.openssl import OpenSSLConfigError 
Note: See TracChangeset for help on using the changeset viewer.