Changeset 6827
- Timestamp:
- 20/04/10 16:40:56 (11 years ago)
- Location:
- TI12-security/trunk/MyProxyClient
- Files:
-
- 3 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/MyProxyClient/myproxy/client.py
r6202 r6827 121 121 http://grid.ncsa.uiuc.edu/myproxy/protocol/ 122 122 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 137 140 138 141 @type _hostCertSubDirPath: string … … 141 144 @type _hostKeySubDirPath: string 142 145 @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 143 166 144 167 @type propertyDefaults: tuple … … 147 170 """ 148 171 149 getCmd="""VERSION=MYPROXYv2172 GET_CMD="""VERSION=MYPROXYv2 150 173 COMMAND=0 151 174 USERNAME=%s … … 153 176 LIFETIME=%d""" 154 177 155 infoCmd="""VERSION=MYPROXYv2178 INFO_CMD="""VERSION=MYPROXYv2 156 179 COMMAND=2 157 180 USERNAME=%s … … 159 182 LIFETIME=0""" 160 183 161 destroyCmd="""VERSION=MYPROXYv2184 DESTROY_CMD="""VERSION=MYPROXYv2 162 185 COMMAND=3 163 186 USERNAME=%s … … 165 188 LIFETIME=0""" 166 189 167 changePassphraseCmd="""VERSION=MYPROXYv2190 CHANGE_PASSPHRASE_CMD="""VERSION=MYPROXYv2 168 191 COMMAND=4 169 192 USERNAME=%s … … 172 195 LIFETIME=0""" 173 196 174 storeCmd="""VERSION=MYPROXYv2197 STORE_CMD="""VERSION=MYPROXYv2 175 198 COMMAND=5 176 199 USERNAME=%s … … 178 201 LIFETIME=%d""" 179 202 203 GET_TRUST_ROOTS_CMD="""VERSION=MYPROXYv2 204 COMMAND=7 205 USERNAME=%s 206 PASSPHRASE=%s 207 LIFETIME=0 208 TRUSTED_CERTS=1""" 209 180 210 _hostCertSubDirPath = ('etc', 'hostcert.pem') 181 211 _hostKeySubDirPath = ('etc', 'hostkey.pem') … … 183 213 # Work out default location of proxy file if it exists. This is set if a 184 214 # 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 190 221 MESSAGE_DIGEST_TYPE = "md5" 191 222 SERVER_RESP_BLK_SIZE = 8192 223 MAX_RECV_TRIES = 1024 192 224 193 225 # valid configuration property keywords … … 245 277 self.serverDN = os.environ.get('MYPROXY_SERVER_DN', 246 278 MyProxyClient.propertyDefaults['serverDN']) 279 280 # Environment variable may be quoted 281 if self.serverDN: 282 self.serverDN = self.serverDN.strip('"') 247 283 248 284 # keyword settings … … 554 590 555 591 req.set_subject_name(x509Name) 556 557 592 req.sign(pubKey, messageDigest) 558 593 559 594 return req.as_der() 560 561 595 562 596 def _deserializeResponse(self, msg, *fieldNames): … … 656 690 657 691 if filePath is None: 658 filePath = MyProxyClient. defProxyFile692 filePath = MyProxyClient.DEF_PROXY_FILEPATH 659 693 660 694 if filePath is None: … … 663 697 664 698 outStr = proxyCert + proxyPriKey + userX509Cert 665 open(MyProxyClient. defProxyFile, 'w').write(outStr)699 open(MyProxyClient.DEF_PROXY_FILEPATH, 'w').write(outStr) 666 700 try: 667 701 # Make sure permissions are set correctly 668 os.chmod(MyProxyClient.defProxyFile, 0600) 702 os.chmod(MyProxyClient.DEF_PROXY_FILEPATH, 703 MyProxyClient.PROXY_FILE_PERMISSIONS) 669 704 except Exception, e: 670 705 # Don't leave the file lying around if couldn't change it's 671 706 # 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)) 676 712 raise 677 713 … … 684 720 @return: tuple containing proxy cert, private key, user cert""" 685 721 if filePath is None: 686 filePath = MyProxyClient. defProxyFile722 filePath = MyProxyClient.DEF_PROXY_FILEPATH 687 723 688 724 if filePath is None: … … 690 726 "platform?") 691 727 692 proxy = open(MyProxyClient. defProxyFile).read()728 proxy = open(MyProxyClient.DEF_PROXY_FILEPATH).read() 693 729 694 730 # Split certs and key into separate tuple items … … 744 780 745 781 # send info command - ensure conversion from unicode before writing 746 cmd = MyProxyClient. infoCmd% username782 cmd = MyProxyClient.INFO_CMD % username 747 783 conn.write(str(cmd)) 748 784 … … 807 843 808 844 # 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) 812 848 conn.write(str(cmd)) 813 849 … … 864 900 865 901 # send destroy command - ensure conversion from unicode before writing 866 cmd = MyProxyClient. destroyCmd% username902 cmd = MyProxyClient.DESTROY_CMD % username 867 903 conn.write(str(cmd)) 868 904 … … 963 999 964 1000 # send store command - ensure conversion from unicode before writing 965 cmd = MyProxyClient. storeCmd% (username, lifetime)1001 cmd = MyProxyClient.STORE_CMD % (username, lifetime) 966 1002 conn.write(str(cmd)) 967 1003 … … 1033 1069 1034 1070 # send get command - ensure conversion from unicode before writing 1035 cmd = MyProxyClient. getCmd% (username, passphrase, lifetime)1071 cmd = MyProxyClient.GET_CMD % (username, passphrase, lifetime) 1036 1072 conn.write(str(cmd)) 1037 1073 … … 1065 1101 (nCerts, len(pemCerts))) 1066 1102 1067 if key is not None:1103 if keys is not None: 1068 1104 # Return certs and private key 1069 1105 # - proxy or dynamically issued certificate (MyProxy CA mode) 1070 1106 # - private key 1071 1107 # - rest of cert chain if proxy cert issued 1072 pemKey = key .as_pem(cipher=None)1108 pemKey = keys.as_pem(cipher=None) 1073 1109 creds = [pemCerts[0], pemKey] 1074 1110 creds.extend(pemCerts[1:]) … … 1083 1119 """Retrieve proxy cert for user - same as logon""" 1084 1120 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 21 21 # CN is usually set to "host/<fqdn>". Delete this element and set from 22 22 # MYPROXY_SERVER_DN environment variable if preferred 23 serverDN=/O=NDG/OU=Raphael/CN=raphael23 #serverDN=/O=NDG/OU=Raphael/CN=raphael 24 24 25 25 # Set "host/" prefix to host cert CN as is default with globus … … 44 44 45 45 #caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/ndg-test-ca.crt 46 caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/ ndg-glue-ca.crt46 caCertFilePath=$MYPROXYCLIENT_UNITTEST_DIR/test-ca.crt -
TI12-security/trunk/MyProxyClient/test/myProxyClientTest.cfg
r5048 r6827 15 15 # terminal. To set a null password, leave the field in place but set to 16 16 # blank 17 [test 1Store]17 [test01Store] 18 18 username: testuser 19 19 passphrase: testpassword … … 24 24 ownerPassphrase: testpassword 25 25 26 [test 2GetDelegation]26 [test02GetDelegation] 27 27 username: testuser 28 28 passphrase: testpassword … … 31 31 proxyKeyFileOut: $MYPROXYCLIENT_UNITTEST_DIR/proxy.key 32 32 33 [test 3Info]33 [test03Info] 34 34 username: testuser 35 35 ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt … … 37 37 ownerPassphrase: testpassword 38 38 39 [test 4ChangePassphrase]39 [test04ChangePassphrase] 40 40 username: testuser 41 41 ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt … … 45 45 ownerPassphrase: testpassword 46 46 47 [test 5Destroy]47 [test05Destroy] 48 48 username: testuser 49 49 ownerCertFile: $MYPROXYCLIENT_UNITTEST_DIR/proxy.crt -
TI12-security/trunk/MyProxyClient/test/test_myproxyclient.py
r5048 r6827 10 10 __contact__ = "Philip.Kershaw@stfc.ac.uk" 11 11 __revision__ = '$Id$' 12 import logging 13 logging.basicConfig(level=logging.DEBUG) 12 14 13 15 import unittest … … 16 18 import getpass 17 19 import traceback 20 from os import path 21 22 from M2Crypto import X509 18 23 19 24 from myproxy.client import CaseSensitiveConfigParser, MyProxyClient 20 25 21 xpdVars = os.path.expandvars 22 jnPath = os.path.join 23 mkPath = lambda file: jnPath(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], file) 26 mkPath = lambda file: path.join(os.environ['MYPROXYCLIENT_UNITTEST_DIR'], file) 24 27 25 28 class _MyProxyClientTestCase(unittest.TestCase): … … 31 34 if 'MYPROXYCLIENT_UNITTEST_DIR' not in os.environ: 32 35 os.environ['MYPROXYCLIENT_UNITTEST_DIR'] = \ 33 os.path.abspath(os.path.dirname(__file__))36 path.abspath(path.dirname(__file__)) 34 37 35 38 … … 37 40 '''Tests require a connection to a real MyProxy service running on a host 38 41 ''' 42 CONFIG_FILENAME = "myProxyClientTest.cfg" 39 43 40 44 def setUp(self): … … 43 47 44 48 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) 47 51 configParser.read(configFilePath) 48 52 … … 50 54 for section in configParser.sections(): 51 55 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'] 60 63 61 64 passphrase = thisSection.get('passphrase') … … 69 72 " owner pass-phrase: ") 70 73 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']) 75 78 76 79 self.clnt.store(thisSection['username'], … … 84 87 print("Store creds for user %s" % thisSection['username']) 85 88 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'] 90 92 91 93 passphrase = thisSection.get('passphrase') … … 94 96 "passphrase: ") 95 97 96 proxyCertFile = xpdVars(thisSection['proxyCertFileOut'])97 proxyKeyFile = xpdVars(thisSection['proxyKeyFileOut'])98 proxyCertFile = path.expandvars(thisSection['proxyCertFileOut']) 99 proxyKeyFile = path.expandvars(thisSection['proxyKeyFileOut']) 98 100 99 101 creds = self.clnt.getDelegation(thisSection['username'], … … 104 106 open(proxyKeyFile, 'w').write(creds[1]) 105 107 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'] 110 111 111 112 # ownerPassphrase can be omitted from the congif file in which case … … 118 119 credExists, errorTxt, fields = self.clnt.info( 119 120 thisSection['username'], 120 xpdVars(thisSection['ownerCertFile']),121 xpdVars(thisSection['ownerKeyFile']),121 path.expandvars(thisSection['ownerCertFile']), 122 path.expandvars(thisSection['ownerKeyFile']), 122 123 ownerPassphrase=ownerPassphrase) 123 124 print "test3Info... " … … 126 127 print "fields: %s" % fields 127 128 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'] 133 132 134 133 passphrase = thisSection.get('passphrase') … … 153 152 154 153 self.clnt.changePassphrase(thisSection['username'], 155 156 157 xpdVars(thisSection['ownerCertFile']),158 xpdVars(thisSection['ownerKeyFile']),159 154 passphrase, 155 newPassphrase, 156 path.expandvars(thisSection['ownerCertFile']), 157 path.expandvars(thisSection['ownerKeyFile']), 158 ownerPassphrase=ownerPassphrase) 160 159 print("Changed pass-phrase") 161 160 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'] 166 164 167 165 ownerPassphrase = thisSection.get('ownerPassphrase') … … 171 169 172 170 self.clnt.destroy(thisSection['username'], 173 ownerCertFile=xpdVars(thisSection['ownerCertFile']),174 ownerKeyFile=xpdVars(thisSection['ownerKeyFile']),175 171 ownerCertFile=path.expandvars(thisSection['ownerCertFile']), 172 ownerKeyFile=path.expandvars(thisSection['ownerKeyFile']), 173 ownerPassphrase=ownerPassphrase) 176 174 print("Destroy creds for user %s" % thisSection['username']) 177 175 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 178 192 179 193 from myproxy.utils.openssl import OpenSSLConfigError
Note: See TracChangeset
for help on using the changeset viewer.