Changeset 6918 for TI12-security/trunk/MyProxyClient/myproxy/client.py
- Timestamp:
- 02/06/10 15:01:16 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/MyProxyClient/myproxy/client.py
r6847 r6918 243 243 environment variable name 244 244 245 @type GLOBUS_LOCATION_ENVVARNAME: string 246 @param GLOBUS_LOCATION_ENVVARNAME: 'GLOBUS_LOCATION' environment variable 247 name 248 245 249 @type GET_CMD: string 246 250 @cvar GET_CMD: get command string … … 261 265 @cvar GET_TRUST_ROOTS_CMD: get trust roots command string 262 266 263 @type _hostCertSubDirPath: string 264 @cvar _hostCertSubDirPath: sub-directory path host certificate (as tuple) 265 266 @type _hostKeySubDirPath: string 267 @cvar _hostKeySubDirPath: sub-directory path to host key (as tuple) 267 @type TRUSTED_CERTS_FIELDNAME: string 268 @param TRUSTED_CERTS_FIELDNAME: field name in get trust roots response for 269 trusted certificate file names 270 271 @type TRUSTED_CERTS_FILEDATA_FIELDNAME_PREFIX: string 272 @param TRUSTED_CERTS_FILEDATA_FIELDNAME_PREFIX: field name prefix in get 273 trust roots response for trusted certificate file contents 274 275 @type HOSTCERT_SUBDIRPATH: string 276 @cvar HOSTCERT_SUBDIRPATH: sub-directory path host certificate (as tuple) 277 278 @type HOSTKEY_SUBDIRPATH: string 279 @cvar HOSTKEY_SUBDIRPATH: sub-directory path to host key (as tuple) 268 280 269 281 @type PRIKEY_NBITS: int … … 290 302 @cvar PROPERTY_DEFAULTS: sets permissable element names for MyProxy config 291 303 file 304 305 @type ROOT_USERNAME: string 306 @cvar ROOT_USERNAME: root username - used to determine output directory 307 for trust roots 308 309 @type ROOT_TRUSTROOT_DIR: string 310 @param ROOT_TRUSTROOT_DIR: default trust root directory if running as root 311 user 312 313 @type USER_TRUSTROOT_DIR: string 314 @param USER_TRUSTROOT_DIR: default trust root directory for users other 315 than root 316 317 @type X509_CERT_DIR_ENVVARNAME: string 318 @param X509_CERT_DIR_ENVVARNAME: environment variable name 'X509_CERT_DIR', 319 which if set points to the location of the trust roots 292 320 """ 293 321 MYPROXY_SERVER_ENVVARNAME = 'MYPROXY_SERVER' 294 322 MYPROXY_SERVER_PORT_ENVVARNAME = 'MYPROXY_SERVER_PORT' 295 323 MYPROXY_SERVER_DN_ENVVARNAME = 'MYPROXY_SERVER_DN' 296 324 325 GLOBUS_LOCATION_ENVVARNAME = 'GLOBUS_LOCATION' 326 297 327 GET_CMD="""VERSION=MYPROXYv2 298 328 COMMAND=0 … … 339 369 TRUSTED_CERTS=1""" 340 370 341 _hostCertSubDirPath = ('etc', 'hostcert.pem') 342 _hostKeySubDirPath = ('etc', 'hostkey.pem') 371 TRUSTED_CERTS_FIELDNAME = 'TRUSTED_CERTS' 372 TRUSTED_CERTS_FILEDATA_FIELDNAME_PREFIX = 'FILEDATA_' 373 374 HOSTCERT_SUBDIRPATH = ('etc', 'hostcert.pem') 375 HOSTKEY_SUBDIRPATH = ('etc', 'hostkey.pem') 343 376 344 377 PROXY_FILE_PERMISSIONS = 0600 … … 360 393 'hostname': 'localhost', 361 394 'port': 7512, 395 'cnPrefix': MyProxyServerSSLCertVerification.SERVER_CN_PREFIX, 362 396 'serverDN': None, 363 397 'openSSLConfFilePath': '', 364 398 'proxyCertMaxLifetime': 43200, 365 399 'proxyCertLifetime': 43200, 366 'caCertFilePath': None,367 400 'caCertDir': None 368 401 } 402 403 ROOT_USERNAME = 'root' 404 ROOT_TRUSTROOT_DIR = '/etc/grid-security/certificates' 405 USER_TRUSTROOT_DIR = '~/.globus/certificates' 406 X509_CERT_DIR_ENVVARNAME = 'X509_CERT_DIR' 369 407 370 408 # Restrict attributes to the above properties, their equivalent … … 395 433 self.__proxyCertLifetime = MyProxyClient.PROPERTY_DEFAULTS[ 396 434 'proxyCertLifetime'] 397 self.__caCertFilePath = None398 435 self.__caCertDir = None 399 436 … … 419 456 self.serverDN = serverDN 420 457 458 # Set trust root - the directory containing the CA certificates for 459 # verifying the MyProxy server's SSL certificate 460 self.setDefaultCACertDir() 461 421 462 # Any keyword settings override the defaults above 422 463 for opt, val in prop.items(): … … 427 468 if cfgFilePath is not None: 428 469 self.parseConfig(cfg=cfgFilePath) 429 430 def _getServerSSLCertVerify(self): 431 return self.__serverSSLCertVerify 432 433 serverSSLCertVerify = property(_getServerSSLCertVerify, 434 doc="Server SSL Certificate Verification " 435 "callable") 436 470 471 def setDefaultCACertDir(self): 472 '''Make default trust root setting - the directory containing the CA 473 certificates for verifying the MyProxy server's SSL certificate. 474 475 The setting is made by using standard Globus defined locations and 476 environment variable settings 477 ''' 478 479 # Check for X509_CERT_DIR environment variable 480 x509CertDir = os.environ.get(MyProxyClient.X509_CERT_DIR_ENVVARNAME) 481 if x509CertDir is not None: 482 self.caCertDir = x509CertDir 483 484 # Check for running as root user 485 elif os.environ.get(MyProxyClient.ROOT_USERNAME) is not None: 486 self.caCertDir = MyProxyClient.ROOT_TRUSTROOT_DIR 487 488 # Default to non-root standard location 489 else: 490 self.caCertDir = os.path.expanduser( 491 MyProxyClient.USER_TRUSTROOT_DIR) 437 492 438 493 def _getServerSSLCertVerify(self): … … 582 637 doc="Default proxy cert. lifetime used in " 583 638 "logon request") 584 585 def _getCACertFilePath(self):586 return self.__caCertFilePath587 588 def _setCACertFilePath(self, val):589 '''@type val: basestring590 @param val: file path for CA certificate to be used to verify591 MyProxy server certificate'''592 593 if isinstance(val, basestring):594 if val == '':595 self.__caCertFilePath = None596 else:597 self.__caCertFilePath = os.path.expandvars(val)598 599 elif isinstance(val, None):600 raise TypeError("Expecting string type for caCertFilePath "601 "attribute")602 603 caCertFilePath = property(fget=_getCACertFilePath,604 fset=_setCACertFilePath,605 doc="CA certificate file path - MyProxy server "606 "certificate must validate against it and/"607 "or any present in caCertDir")608 639 609 640 def _getCACertDir(self): … … 634 665 caCertDir = property(fget=_getCACertDir, 635 666 fset=_setCACertDir, 636 doc=" directory containing PEM encoded CA "637 "certificates . Use along with caCertFilePath"638 " setting to validate MyProxy servercertificate")667 doc="trust roots directory containing PEM encoded CA " 668 "certificates to validate MyProxy server " 669 "certificate") 639 670 640 671 … … 648 679 certFile=None, 649 680 keyFile=None, 650 keyFilePassphrase=None): 681 keyFilePassphrase=None, 682 verifyPeerWithTrustRoots=True): 651 683 """Initialise connection setting up SSL context and client and 652 684 server side identity checks … … 661 693 @type keyFilePassphrase: basestring 662 694 @param keyFilePassphrase: pass-phrase protecting private key if set 695 @type verifyPeerWithTrustRoots: bool 696 @param verifyPeerWithTrustRoots: verify MyProxy server's SSL certificate 697 against a list of trusted CA certificates in the CA certificate 698 directory set by the "CaCertDir" attribute. This should always be set 699 to True for MyProxy client calls unless using the 'bootstrap' trust 700 roots mode available with logon and get trust roots calls 663 701 """ 664 702 # Must be version 3 for MyProxy 665 703 context = SSL.Context(SSL.SSLv3_METHOD) 666 704 667 if self.caCertFilePath or self.caCertDir: 668 context.load_verify_locations(self.caCertFilePath, self.caCertDir) 669 705 if verifyPeerWithTrustRoots: 706 context.load_verify_locations(None, self.caCertDir) 707 verifyMode = SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT 708 else: 709 log.warning("SSL Context verify mode set to SSL.VERIFY_NONE") 710 verifyMode = SSL.VERIFY_NONE 711 712 # Verify peer's (MyProxy server) certificate 713 context.set_verify(verifyMode, self.__serverSSLCertVerify) 714 670 715 if certFile: 671 716 try: … … 674 719 promptPassphraseTwice, 675 720 passphrase): 721 """Private key file password callback function""" 676 722 if len(passphrase) > passphraseMaxLen: 677 723 log.error('Passphrase length %d is greater than the ' … … 691 737 "connection [also check CA " 692 738 "certificate settings]: %s" % 693 traceback.format_exc()) 694 695 # Verify peer's (MyProxy server) certificate 696 context.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, 697 self.__serverSSLCertVerify) 698 739 traceback.format_exc()) 699 740 700 741 # Disable for compatibility with myproxy server (er, globus) … … 713 754 @param nBitsForKey: number of bits for private key generation - 714 755 default is 2048 715 @rtype: string756 @rtype: OpenSSL.crypto.PKey 716 757 @return: public/private key pair 717 758 """ … … 731 772 @type messageDigest: basestring 732 773 @param messageDigest: message digest type - default is MD5 733 @rtype: tuple774 @rtype: base string 734 775 @return certificate request PEM text and private key PEM text 735 776 """ … … 949 990 private key is not password protected. 950 991 """ 951 globusLoc = os.environ.get( 'GLOBUS_LOCATION')992 globusLoc = os.environ.get(MyProxyClient.GLOBUS_LOCATION_ENVVARNAME) 952 993 if not sslCertFile: 953 994 if globusLoc: 954 995 sslCertFile = os.path.join(globusLoc, 955 *MyProxyClient. _hostCertSubDirPath)996 *MyProxyClient.HOSTCERT_SUBDIRPATH) 956 997 sslKeyFile = os.path.join(globusLoc, 957 *MyProxyClient. _hostKeySubDirPath)998 *MyProxyClient.HOSTKEY_SUBDIRPATH) 958 999 else: 959 1000 raise MyProxyClientError( … … 1011 1052 @return none 1012 1053 """ 1013 globusLoc = os.environ.get( 'GLOBUS_LOCATION')1054 globusLoc = os.environ.get(MyProxyClient.GLOBUS_LOCATION_ENVVARNAME) 1014 1055 if not sslCertFile or not sslKeyFile: 1015 1056 if globusLoc: 1016 1057 sslCertFile = os.path.join(globusLoc, 1017 *MyProxyClient._hostCertSubDirPath)1058 *MyProxyClient.HOSTCERT_SUBDIRPATH) 1018 1059 sslKeyFile = os.path.join(globusLoc, 1019 *MyProxyClient._hostKeySubDirPath)1060 *MyProxyClient.HOSTKEY_SUBDIRPATH) 1020 1061 else: 1021 1062 raise MyProxyClientError( … … 1067 1108 @return none 1068 1109 """ 1069 globusLoc = os.environ.get( 'GLOBUS_LOCATION')1110 globusLoc = os.environ.get(MyProxyClient.GLOBUS_LOCATION_ENVVARNAME) 1070 1111 if not sslCertFile or not sslKeyFile: 1071 1112 if globusLoc: 1072 1113 sslCertFile = os.path.join(globusLoc, 1073 *MyProxyClient. _hostCertSubDirPath)1114 *MyProxyClient.HOSTCERT_SUBDIRPATH) 1074 1115 sslKeyFile = os.path.join(globusLoc, 1075 *MyProxyClient. _hostKeySubDirPath)1116 *MyProxyClient.HOSTKEY_SUBDIRPATH) 1076 1117 else: 1077 1118 raise MyProxyClientError( … … 1153 1194 passphrase = str(passphrase) 1154 1195 1155 globusLoc = os.environ.get( 'GLOBUS_LOCATION')1196 globusLoc = os.environ.get(MyProxyClient.GLOBUS_LOCATION_ENVVARNAME) 1156 1197 if not sslCertFile or not sslKeyFile: 1157 1198 if globusLoc: 1158 1199 sslCertFile = os.path.join(globusLoc, 1159 *MyProxyClient._hostCertSubDirPath)1200 *MyProxyClient.HOSTCERT_SUBDIRPATH) 1160 1201 sslKeyFile = os.path.join(globusLoc, 1161 *MyProxyClient._hostKeySubDirPath)1202 *MyProxyClient.HOSTKEY_SUBDIRPATH) 1162 1203 else: 1163 1204 # Default so that the owner is the same as the ID of the … … 1211 1252 1212 1253 def logon(self, username, passphrase, lifetime=None, keyPair=None, 1213 certReq=None, nBitsForKey=PRIKEY_NBITS): 1254 certReq=None, nBitsForKey=PRIKEY_NBITS, bootstrap=False, 1255 updateTrustRoots=False): 1214 1256 """Retrieve a proxy credential from a MyProxy server 1215 1257 … … 1225 1267 @type lifetime: int 1226 1268 @param lifetime: lifetime for generated certificate 1269 1270 @type keyPair: OpenSSL.crypto.PKey 1271 @param keyPair: Public/Private key pair. This is ignored if a 1272 certificate request is passed via the certReq keyword 1273 1274 @type certReq: string 1275 @param certReq: ASN1 format certificate request, if none set, one is 1276 created along with a key pair 1277 1278 @type nBitsForKey: int 1279 @param nBitsForKey: number of bits to use when generating key pair, 1280 defaults to the PRIKEY_NBITS class variable setting. This keyword is 1281 ignored if a key pair is passed in from an external source via the 1282 keyPair keyword 1227 1283 1228 1284 @rtype: tuple … … 1230 1286 user certificate, it's private key and the issuing certificate. The 1231 1287 issuing certificate is only set if the user certificate is a proxy 1288 1289 @type bootstrap: bool 1290 @param bootstrap: If set to True, bootstrap trust roots i.e. connect to 1291 MyProxy server without verification of the server's SSL certificate 1292 against any CA certificates. Set to False, for default behaviour: 1293 verify server SSL certificate against CA certificates held in location 1294 set by the "caCertDir" attribute. If bootstrap is set, updateTrustRoots 1295 will be forced to True also 1296 1297 @type updateTrustRoots: bool 1298 @param updateTrustRoots: set to True to update the trust roots 1232 1299 """ 1233 1300 if bootstrap: 1301 log.info('Bootstrapping MyProxy server root of trust.') 1302 1303 # Bootstrap implies update to trust roots 1304 updateTrustRoots = True 1305 1306 if updateTrustRoots: 1307 self.getTrustRoots(username, 1308 passphrase, 1309 writeToCACertDir=True, 1310 bootstrap=bootstrap) 1311 1234 1312 lifetime = lifetime or self.proxyCertLifetime 1235 1313 … … 1255 1333 # send get command - ensure conversion from unicode before writing 1256 1334 cmd = MyProxyClient.GET_CMD % (username, passphrase, lifetime) 1335 1257 1336 conn.write(str(cmd)) 1258 1337 1259 1338 # process server response 1260 1339 dat = conn.recv(MyProxyClient.SERVER_RESP_BLK_SIZE) 1340 1261 1341 respCode, errorTxt = self._deserializeResponse(dat) 1262 1342 if respCode: … … 1278 1358 respCode, errorTxt = self._deserializeResponse(resp) 1279 1359 if respCode: 1280 raise MyProxyClientRetrieveError(errorTxt) 1360 raise MyProxyClientRetrieveError(errorTxt) 1281 1361 1282 1362 # deserialize certs from received cert data … … 1304 1384 return self.logon(*arg, **kw) 1305 1385 1306 def getTrustRoots(self, username='', passphrase=''): 1386 def getTrustRoots(self, 1387 username='', 1388 passphrase='', 1389 writeToCACertDir=False, 1390 bootstrap=False): 1307 1391 """Get trust roots for the given MyProxy server 1308 1392 … … 1313 1397 @param passphrase: pass-phrase (optional) 1314 1398 server 1399 1400 @type writeToCACertDir: bool 1401 @param writeToCACertDir: if set to True, write the retrieved trust roots 1402 out to the directory specified by the "caCertDir" attribute 1403 1404 @type bootstrap: bool 1405 @param bootstrap: If set to True, bootstrap trust roots i.e. connect to 1406 MyProxy server without verification of the server's SSL certificate 1407 against any CA certificates. Set to False, for default behaviour: 1408 verify server SSL certificate against CA certificates held in location 1409 set by the "caCertDir" attribute. 1315 1410 1316 1411 @return: trust root files as a dictionary keyed by file name with each … … 1318 1413 @rtype: dict 1319 1414 """ 1415 if bootstrap: 1416 log.info('Bootstrapping MyProxy server root of trust.') 1417 1320 1418 # Set-up SSL connection 1321 conn = self._initConnection( )1419 conn = self._initConnection(verifyPeerWithTrustRoots=(not bootstrap)) 1322 1420 conn.connect((self.hostname, self.port)) 1323 1421 … … 1331 1429 # process server response chunks until all consumed 1332 1430 dat = '' 1431 tries = 0 1333 1432 try: 1334 1433 for tries in range(MyProxyClient.MAX_RECV_TRIES): … … 1344 1443 MyProxyClient.MAX_RECV_TRIES, 1345 1444 MyProxyClient.SERVER_RESP_BLK_SIZE) 1346 1445 1446 fieldName = MyProxyClient.TRUSTED_CERTS_FIELDNAME 1447 prefix = MyProxyClient.TRUSTED_CERTS_FILEDATA_FIELDNAME_PREFIX 1347 1448 respCode, errorTxt, fileData = self._deserializeResponse(dat, 1348 'TRUSTED_CERTS',1349 'FILEDATA_')1449 fieldName, 1450 prefix) 1350 1451 if respCode: 1351 1452 raise MyProxyClientGetTrustRootsError(errorTxt) 1352 1453 1353 filesDict = dict([(k, base64.b64decode(v)) 1354 for k, v in fileData.items() if k != 'TRUSTED_CERTS']) 1355 1454 filesDict = dict([(k.split(prefix, 1)[1], base64.b64decode(v)) 1455 for k, v in fileData.items() if k != fieldName]) 1456 1457 if writeToCACertDir: 1458 for fileName, fileContents in filesDict.items(): 1459 filePath = os.path.join(self.caCertDir, fileName) 1460 open(filePath, 'wb').write(fileContents) 1461 1356 1462 return filesDict 1357 1463
Note: See TracChangeset
for help on using the changeset viewer.