Changeset 1861


Ignore:
Timestamp:
14/12/06 11:03:16 (13 years ago)
Author:
pjkersha
Message:

server/MyProxy.py:

  • getDelegation wrapper to logon fixed to *return* logon output
  • store command calls info first to check if credential already exists for

username given

  • logon method - create proxy cert request BEFORE connecting to server to

avoid confusing the latter if an error occurs in the request.

test/MyProxy/myProxyClientTest.cfg, test/MyProxy/MyProxyClientTest.py:
fixed store and logon tests. Tests now run in a configured order.

Location:
TI12-security/trunk/python
Files:
3 edited

Legend:

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

    r1858 r1861  
    5959    @cvar _hostCertSubDirPath: sub-directory path host certificate (as tuple) 
    6060    @cvar _hostKeySubDirPath: sub-directory path to host key (as tuple) 
    61     @cvar _certReqDNdefaultsName: names of parameters needed to generate a  
     61    @cvar _certReqDNparamName: names of parameters needed to generate a  
    6262    certificate request e.g. CN, OU etc. 
    6363    """ 
     
    9797    _hostKeySubDirPath = ('etc', 'hostkey.pem') 
    9898     
    99     _certReqDNdefaultsName = ('O', 'OU') 
     99    _certReqDNparamName = ('O', 'OU') 
    100100 
    101101    # valid configuration property keywords 
     
    129129 
    130130        # Set-up parameter names for certificate request 
    131         self.__certReqDNdefaults = {} 
     131        self.__certReqDNparam = {} 
    132132         
    133133        # Check for parameter names set from input 
    134         #self.certReqDNdefaults = None 
     134        #self.certReqDNparam = None 
    135135 
    136136        # settings dictionary 
    137137        self.__prop = {} 
    138138         
    139         # Defaults 
    140         self.__prop['port'] = 7512 
     139        # Server host name - take from environment variable if available 
     140        if 'MYPROXY_SERVER' in os.environ: 
     141            self.__prop['hostname'] = os.environ['MYPROXY_SERVER'] 
     142             
     143        # ... and port number 
     144        if 'MYPROXY_SERVER_PORT' in os.environ: 
     145            self.__prop['port'] = int(os.environ['MYPROXY_SERVER_PORT']) 
     146        else: 
     147            # Usual default is ... 
     148            self.__prop['port'] = 7512 
     149             
    141150        self.__prop['proxyCertLifetime'] = 43200 
    142151        self.__prop['proxyCertMaxLifetime'] = 43200 
     
    163172                            os.path.join(self.__prop['gridSecurityDir'], 
    164173                                         self.__prop['openSSLConfFileName']) 
    165  
    166         # Server host name - environment setting overrides 
    167         if 'MYPROXY_SERVER' in os.environ: 
    168             self.__prop['hostname'] = os.environ['MYPROXY_SERVER'] 
    169              
    170         # ... and port number 
    171         if 'MYPROXY_SERVER_PORT' in os.environ: 
    172             self.__prop['port'] = os.environ['MYPROXY_SERVER_PORT'] 
    173174 
    174175    #_________________________________________________________________________ 
     
    245246 
    246247    #_________________________________________________________________________         
    247     def __setCertReqParam(self, dict): 
    248         '''certReqDNdefaults property set method - forces setting of certificate  
     248    def __setCertReqDNparam(self, dict): 
     249        '''certReqDNparam property set method - forces setting of certificate  
    249250        request parameter names to valid values 
    250251         
     
    252253         
    253254        invalidKw = [k for k in dict \ 
    254                      if k not in MyProxyClient._certReqDNdefaultsName] 
     255                     if k not in MyProxyClient._certReqDNparamName] 
    255256        if invalidKw: 
    256257            raise MyProxyClientError, \ 
    257258    "Invalid certificate request keyword(s): %s.  Valid keywords are: %s" % \ 
    258     (', '.join(invalidKw), ', '.join(MyProxyClient._certReqDNdefaultsName)) 
    259      
    260         self.__certReqDNdefaults.update(dict) 
     259    (', '.join(invalidKw), ', '.join(MyProxyClient._certReqDNparamName)) 
     260     
     261        self.__certReqDNparam.update(dict) 
    261262 
    262263    #_________________________________________________________________________         
    263     def __getCertReqParam(self): 
    264         """certReqDNdefaults property set method - for Certificate request  
     264    def __getCertReqDNparam(self): 
     265        """certReqDNparam property set method - for Certificate request  
    265266        parameters dict""" 
    266         return self.__certReqDNdefaults 
    267      
    268      
    269     certReqDNdefaults = property(fset=__setCertReqParam, 
    270                             fget=__getCertReqParam, 
     267        return self.__certReqDNparam 
     268     
     269     
     270    certReqDNparam = property(fset=__setCertReqDNparam, 
     271                            fget=__getCertReqDNparam, 
    271272                            doc="Dictionary of parameters for cert. request") 
    272273     
     
    299300        req.set_pubkey(pubKey) 
    300301         
    301         if self.__certReqDNdefaults: 
    302             certReqDNdefaults = self.__certReqDNdefaults 
     302        if self.__certReqDNparam: 
     303            certReqDNparam = self.__certReqDNparam 
    303304        else: 
    304305            defaultReqDN = self.__openSSLConf.getReqDN() 
    305306             
    306             certReqDNdefaults['O'] = defaultReqDN['0.organizationName'] 
    307             certReqDNdefaults['OU'] = defaultReqDN['0.organizationUnitName'] 
    308              
    309         import pdb;pdb.set_trace() 
    310          
     307            certReqDNparam = {} 
     308            certReqDNparam['O'] = defaultReqDN['0.organizationName'] 
     309            certReqDNparam['OU'] = defaultReqDN['0.organizationalUnitName'] 
     310             
    311311        # Set DN 
    312312        x509Name = X509.X509_Name() 
    313313        x509Name.CN = CN 
    314         x509Name.OU = certReqDNdefaults['OU'] 
    315         x509Name.O = certReqDNdefaults['O'] 
     314        x509Name.OU = certReqDNparam['OU'] 
     315        x509Name.O = certReqDNparam['O'] 
    316316        req.set_subject_name(x509Name) 
    317317         
     
    423423        for ownerCertFile 
    424424        @param ownerPassphrase: passphrase for ownerKeyFile.  Omit if the 
    425         private key is not password protected.   
     425        private key is not password protected. 
    426426        @return none 
    427427        """ 
     
    436436                raise MyProxyClientError, \ 
    437437            "No client authentication cert. and private key file were given" 
    438          
    439438 
    440439        context = Context(protocol='sslv3') 
     
    622621              ownerKeyFile=None, 
    623622              ownerPassphrase=None, 
    624               lifetime=None): 
     623              lifetime=None, 
     624              force=True): 
    625625        """Upload credentials to the server 
    626626         
     
    642642        be passphrase protected as this will be the passphrase used for 
    643643        logon / getDelegation. 
     644        @param force: set to True to overwrite any existing creds with the 
     645        same username.  If, force=False a check is made with a call to info. 
     646        If creds already, exist exit without proceeding 
    644647        @return none 
    645648        """ 
     
    658661                ownerKeyFile = keyFile 
    659662         
    660  
     663         
     664        if not force: 
     665            # Check credentials don't already exist 
     666            if self.info(username, 
     667                         ownerCertFile=ownerCertFile, 
     668                         ownerKeyFile=ownerKeyFile, 
     669                         ownerPassphrase=ownerPassphrase)[0]: 
     670                raise MyProxyClientError, \ 
     671                        "Credentials already exist for user: %s" % username 
     672 
     673        # Set up SSL connection 
    661674        context = Context(protocol='sslv3') 
    662675        context.load_cert(ownerCertFile, 
     
    718731         
    719732        lifetime = lifetime or self.__prop['proxyCertLifetime'] 
    720          
     733 
     734        # Generate certificate request here - any errors will be thrown 
     735        # prior to making the connection and so not upsetting the server 
     736        # 
     737        # - The client will generate a public/private key pair and send a  
     738        #   NULL-terminated PKCS#10 certificate request to the server. 
     739        certReq, priKey = self._createCertReq(username) 
     740 
     741 
    721742        context = Context(protocol='sslv3') 
    722743         
     
    747768            raise GetError, errorTxt 
    748769         
    749         # generate and send certificate request 
    750         # - The client will generate a public/private key pair and send a  
    751         #   NULL-terminated PKCS#10 certificate request to the server. 
    752         certReq, priKey = self._createCertReq(username) 
     770        # Send certificate request 
    753771        conn.send(certReq) 
    754772     
    755773        # process certificates 
    756         # - 1 byte , number of certs 
     774        # - 1st byte , number of certs 
    757775        dat = conn.recv(1) 
    758776        nCerts = ord(dat[0]) 
     
    773791                                                    (nCerts, len(pemCerts)) 
    774792     
    775         # write certs and private key to file 
     793        # Return certs and private key 
    776794        # - proxy cert 
    777795        # - private key 
    778796        # - rest of cert chain 
    779         creds = pemCerts[0]+priKey+''.join([cert for cert in pemCerts[1:]]) 
    780          
    781         return creds 
     797        creds = [pemCerts[0], priKey] 
     798        creds.extend(pemCerts[1:]) 
     799         
     800        return tuple(creds) 
    782801         
    783802 
    784803    def getDelegation(self, *arg, **kw): 
    785804        """Retrieve proxy cert for user - same as logon""" 
    786         self.logon(*arg, **kw) 
     805        return self.logon(*arg, **kw) 
    787806 
    788807 
     
    807826         
    808827        @param filePath: path to OpenSSL configuration file""" 
     828         
     829        # Content of file 
     830        self.__fileTxt = None 
    809831        self.__setFilePath(filePath) 
    810832 
     
    839861                        doc="file path for configuration file") 
    840862     
     863    def __getFileTxt(self): 
     864        """Get content of file in call to getReqDN 
     865        @return string content of file""" 
     866        return self.__fileTxt 
     867     
     868    def __setFileTxt(self, input): 
     869        """Set content of file 
     870        @param input: string content of  file. - Set to None to re-read  
     871        file content in call to getReqDN""" 
     872        self.__fileTxt = input 
     873     
     874     
     875    fileTxt = property(fset=__setFileTxt, 
     876                       fget=__getFileTxt, 
     877                       doc="Content of SSL file") 
     878     
    841879    def _read(self): 
    842880        """Read OpenSSL configuration file and return as string 
     
    844882        @return fileTxt: content of the file""" 
    845883 
    846         fileTxt = open(self.__filePath).read() 
    847         return fileTxt 
     884        self.__fileTxt = self.__fileTxt or open(self.__filePath).read() 
     885        return self.__fileTxt 
    848886 
    849887 
     
    852890        them in a dictionary 
    853891         
    854         @return required Distinguished Name as a dictionary""" 
     892        @return Distinguished Name OU and O defaults in a dictionary""" 
    855893         
    856894        # Nb. Match over line boundaries 
    857         reqDnTxt = re.findall(self.__reqDnRE, self._read(), re.S)[0] 
    858  
    859         # Separate lines 
    860         reqDnLines = reqDnTxt.split(os.linesep) 
    861          
    862         # Match the '*_default' entries and make a dictionary 
    863         # 
    864         # Make sure comment lies are omitted - P J Kershaw 22/07/05 
    865         return dict([re.split('_default\s*=\s*', line) for line in reqDnLines\ 
    866                      if re.match('[^#].*_default\s*=', line)])  
     895        try: 
     896            reqDnTxt = re.findall(self.__reqDnRE, self._read(), re.S)[0] 
     897 
     898            # Separate lines 
     899            reqDnLines = reqDnTxt.split(os.linesep) 
     900             
     901            # Match the '*_default' entries and make a dictionary 
     902            # 
     903            # Make sure comment lies are omitted - P J Kershaw 22/07/05 
     904            return dict([re.split('_default\s*=\s*', line) \ 
     905                         for line in reqDnLines \ 
     906                         if re.match('[^#].*_default\s*=', line)])  
     907        except Exception, e: 
     908            raise "Error reading content of OpenSSL config file \"%s\: %s" % \ 
     909                                                    (self.__filePath, str(e)) 
    867910 
    868911 
     
    9871030                                  passphrase,  
    9881031                                  lifetime=options.lifetime) 
    989             open(outfile, 'w').write(creds) 
     1032            open(outfile, 'w').write(''.join(creds)) 
     1033            try: 
     1034                # Make sure permssions are set correctly 
     1035                os.chmod(outfile, 600) 
     1036            except Exception: 
     1037                # Don't leave the file lying around if couldn't change it's 
     1038                # permissions 
     1039                os.unlink(outfile) 
     1040                 
    9901041            print "A proxy has been received for user %s in %s." % \ 
    9911042                (username, outfile) 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/MyProxy/MyProxyClientTest.py

    r1858 r1861  
    1414import os 
    1515import sys 
     16import getpass 
     17import traceback 
    1618 
    1719from ConfigParser import SafeConfigParser 
     
    3133        self.clnt = MyProxyClient(\ 
    3234                          propFilePath=self.cfg['setUp']['propfilepath']) 
     35         
     36 
     37    def test1Store(self): 
     38        '''test1Store: upload X509 cert and private key to repository''' 
     39        ownerPassphrase = self.cfg['test1Store']['ownerpassphrase'] or \ 
     40            getpass.getpass(prompt="\ntest1Store cred. owner pass-phrase: ") 
     41             
     42        try: 
     43            self.clnt.store(self.cfg['test1Store']['username'], 
     44                        self.cfg['test1Store']['ownercertfile'], 
     45                        self.cfg['test1Store']['ownerkeyfile'], 
     46                        ownerCertFile=self.cfg['test1Store']['ownercertfile'], 
     47                        ownerKeyFile=self.cfg['test1Store']['ownerkeyfile'], 
     48                        ownerPassphrase=ownerPassphrase, 
     49                        force=False) 
     50            print "Store creds for user %s" % \ 
     51                    self.cfg['test1Store']['username'] 
     52        except: 
     53            self.fail(traceback.print_exc()) 
    3354     
    3455     
    35     def testGetDelegation(self): 
    36         '''testGetDelegation: retrieve proxy cert./private key''' 
    37         #import pdb;pdb.set_trace() 
    38         import getpass 
    39         passphrase = getpass.getpass() 
    40         proxyCert = self.clnt.getDelegation(\ 
    41                                   self.cfg['testGetDelegation']['username'],  
     56    def test2GetDelegation(self): 
     57        '''test2GetDelegation: retrieve proxy cert./private key''' 
     58        passphrase = self.cfg['test2GetDelegation']['passphrase'] or \ 
     59            getpass.getpass(prompt="\ntest2GetDelegation pass-phrase: ") 
     60          
     61        try:    
     62            creds = self.clnt.getDelegation(\ 
     63                                  self.cfg['test2GetDelegation']['username'],  
    4264                                  passphrase) 
    43         print "proxyCert:\n" + proxyCert 
    44          
     65            print "proxy credentials:"  
     66            print ''.join(creds) 
     67        except: 
     68            self.fail(traceback.print_exc()) 
    4569 
    46     def testStore(self): 
    47         '''testStore: upload X509 cert and private key to repository''' 
    48         self.clnt.store(self.cfg['testStore']['username'], 
    49                           options.certFile, 
    50                           options.keyFile, 
    51                           ownerCertFile=options.certFile, 
    52                           ownerKeyFile=options.keyFile, 
    53                           ownerPassphrase=open('../tmp2').read().strip()) 
    54         print "Store creds for user %s" % username 
    55          
    5670 
    57     def testDestroy(self): 
    58         '''testDestroy: destroy credentials for a given user''' 
    59         self.clnt.destroy(self.cfg['testDestroy']['username'],  
    60                             ownerCertFile=options.certFile, 
    61                             ownerKeyFile=options.keyFile, 
    62                             ownerPassphrase=open('../tmp2').read().strip()) 
    63         print "Destroy creds for user %s" % username 
     71    def test3Info(self): 
     72        '''test3Info: Retrieve information about a given credential''' 
     73        try: 
     74            credExists, errorTxt, fields = clnt.info( 
     75                                 self.cfg['test3Info']['username'], 
     76                                 self.cfg['test3Info']['ownercertfile'], 
     77                                 self.cfg['test3Info']['ownerkeyfile'], 
     78                                 ownerPassphrase=ownerpassphrase) 
     79            print "test3Info... " 
     80            print "credExists: " + credExists 
     81            print "errorTxt: " + errorTxt 
     82            print "fields: " + fields 
     83        except: 
     84            self.fail(traceback.print_exc()) 
    6485 
    65     def testInfo(self): 
    66         '''testInfo: Retrieve information about a given credential''' 
    67         credExists, errorTxt, fields = clnt.info( 
    68                              self.cfg['testInfo']['username'], 
    69                              options.certFile, 
    70                              options.keyFile, 
    71                              ownerPassphrase=open('../tmp2').read().strip()) 
    72         print "testInfo... " 
    73         print "credExists: " + credExists 
    74         print "errorTxt: " + errorTxt 
    75         print "fields: " + fields 
    76          
    7786 
    78     def testChangePassphrase(self):         
    79         """testChangePassphrase: change pass-phrase protecting a given 
     87    def test4ChangePassphrase(self):         
     88        """test4ChangePassphrase: change pass-phrase protecting a given 
    8089        credential""" 
    8190     
    82         self.clnt.changePassphrase( 
    83                              self.cfg['testChangePassphrase']['username'], 
    84                              passphrase, 
    85                              newPassphrase,  
    86                              options.certFile, 
    87                              options.keyFile, 
    88                              ownerPassphrase=open('../tmp2').read().strip()) 
    89         print "Change pass-phrase" 
     91        try: 
     92            self.clnt.changePassphrase( 
     93                         self.cfg['test4ChangePassphrase']['username'], 
     94                         passphrase, 
     95                         newPassphrase,  
     96                         self.cfg['test4ChangePassphrase']['ownercertfile'], 
     97                         self.cfg['test4ChangePassphrase']['ownerkeyfile'], 
     98                         ownerPassphrase=ownerpassphrase) 
     99            print "Change pass-phrase" 
     100        except: 
     101            self.fail(traceback.print_exc()) 
     102 
     103 
     104    def test5Destroy(self): 
     105        '''test5Destroy: destroy credentials for a given user''' 
     106 
     107        ownerPassphrase = self.cfg['test5Destroy']['ownerpassphrase'] or \ 
     108            getpass.getpass(prompt="\ntest5Destroy cred. owner pass-phrase: ") 
     109 
     110        try: 
     111            self.clnt.destroy(self.cfg['test5Destroy']['username'],  
     112                    ownerCertFile=self.cfg['test5Destroy']['ownercertfile'], 
     113                    ownerKeyFile=self.cfg['test5Destroy']['ownerkeyfile'], 
     114                    ownerPassphrase=ownerpassphrase) 
     115            print "Destroy creds for user %s" % username 
     116        except: 
     117            self.fail(traceback.print_exc()) 
    90118         
    91119  
     
    95123        map = map(MyProxyClientTestCase, 
    96124                  ( 
    97                     "testGetDelegation", 
    98                     "testStore", 
    99                     "testDestroy", 
    100                     "testInfo", 
    101                     "testChangePassphrase", 
     125                    "test1Store", 
     126                    "test2GetDelegation", 
     127                    "test3Info", 
     128                    "test4ChangePassphrase", 
     129                    "test5Destroy", 
    102130                  )) 
    103131        unittest.TestSuite.__init__(self, map) 
  • TI12-security/trunk/python/ndg.security.test/ndg/security/test/MyProxy/myProxyClientTest.cfg

    r1858 r1861  
    1010propFilePath: ./myProxyProperties.xml 
    1111 
    12 [testGetDelegation] 
     12[test1Store] 
    1313username: sstljakTestUser 
    14  
    15 [testStore] 
    16 username: sstljakTestUser 
    17 certFile: 
    18 keyFile: 
    19 ownerCertFile: 
    20 ownerKeyFile: 
     14certFile: ./userCert.pem 
     15keyFile: ./userKey.pem 
     16ownerCertFile: ./userCert.pem 
     17ownerKeyFile: ./userKey.pem 
    2118ownerPassphrase: 
    2219 
    23 [testDestroy] 
     20[test2GetDelegation] 
     21username: sstljakTestUser 
     22passphrase: 
     23 
     24[test3Info] 
    2425username: sstljakTestUser 
    2526ownerCertFile: 
     
    2728ownerPassphrase: 
    2829 
    29 [testInfo] 
     30[test4ChangePassphrase] 
    3031username: sstljakTestUser 
    3132ownerCertFile: 
     
    3334ownerPassphrase: 
    3435 
    35 [testChangePassphrase] 
     36[test5Destroy] 
    3637username: sstljakTestUser 
    3738ownerCertFile: 
Note: See TracChangeset for help on using the changeset viewer.