def _forceGenerateProxyForDN(self, dn, time, group=None): """ An additional helper method for creating a proxy without any substantial validation, it can be used for a specific case(such as testing) where just need to generate a proxy with specific DN on the fly. :param str dn: requested proxy DN :param int time: expired time in a seconds :param str group: if need to add DIRAC group :return: S_OK(tuple)/S_ERROR() -- contain proxy as chain and as string """ self.__X509Name = X509.X509_Name() result = self.__parseDN(dn) if not result['OK']: return result dnInfoDict = result['Value'] for field, values in dnInfoDict.items(): result = self.__fillX509Name(field, values) if not result['OK']: return result result = self.__createCertM2Crypto() if result['OK']: certStr, keyStr = result['Value'] chain = X509Chain() if chain.loadChainFromString(certStr)['OK'] and chain.loadKeyFromString(keyStr)['OK']: result = chain.generateProxyToString(time, rfc=True, diracGroup=group) if not result['OK']: return result chain = X509Chain() chain.loadProxyFromString(result['Value']) return S_OK((chain, result['Value']))
def uploadProxy(params): DIRAC.gLogger.info("Loading user proxy") proxyLoc = params.proxyLoc if not proxyLoc: proxyLoc = Locations.getDefaultProxyLocation() if not proxyLoc: return S_ERROR("Can't find any proxy") if params.onTheFly: DIRAC.gLogger.info("Uploading proxy on-the-fly") certLoc = params.certLoc keyLoc = params.keyLoc if not certLoc or not keyLoc: cakLoc = Locations.getCertificateAndKeyLocation() if not cakLoc: return S_ERROR("Can't find user certificate and key") if not certLoc: certLoc = cakLoc[0] if not keyLoc: keyLoc = cakLoc[1] DIRAC.gLogger.info("Cert file %s" % certLoc) DIRAC.gLogger.info("Key file %s" % keyLoc) testChain = X509Chain() retVal = testChain.loadKeyFromFile(keyLoc, password=params.userPasswd) if not retVal['OK']: passwdPrompt = "Enter Certificate password:"******"\n") else: userPasswd = getpass.getpass(passwdPrompt) params.userPasswd = userPasswd DIRAC.gLogger.info("Loading cert and key") chain = X509Chain() # Load user cert and key retVal = chain.loadChainFromFile(certLoc) if not retVal['OK']: return S_ERROR("Can't load %s" % certLoc) retVal = chain.loadKeyFromFile(keyLoc, password=params.userPasswd) if not retVal['OK']: return S_ERROR("Can't load %s" % keyLoc) DIRAC.gLogger.info("User credentials loaded") restrictLifeTime = params.proxyLifeTime else: proxyChain = X509Chain() retVal = proxyChain.loadProxyFromFile(proxyLoc) if not retVal['OK']: return S_ERROR("Can't load proxy file %s: %s" % (params.proxyLoc, retVal['Message'])) chain = proxyChain restrictLifeTime = 0 DIRAC.gLogger.info(" Uploading...") return gProxyManager.uploadProxy(proxy=chain, restrictLifeTime=restrictLifeTime, rfcIfPossible=params.rfcIfPossible)
def createProxy(self, userName, group, time, rfc=True, limit=False, vo=None, role=None, path=None): """ Create user proxy """ userCertFile = os.path.join(self.userDir, userName + '.cert.pem') userKeyFile = os.path.join(self.userDir, userName + '.key.pem') self.proxyPath = path or os.path.join(self.userDir, userName + '.pem') if not vo: chain = X509Chain() # Load user cert and key retVal = chain.loadChainFromFile(userCertFile) if not retVal['OK']: gLogger.warn(retVal['Message']) return S_ERROR("Can't load %s" % userCertFile) retVal = chain.loadKeyFromFile(userKeyFile) if not retVal['OK']: gLogger.warn(retVal['Message']) if 'bad decrypt' in retVal['Message']: return S_ERROR("Bad passphrase") return S_ERROR("Can't load %s" % userKeyFile) result = chain.generateProxyToFile(self.proxyPath, time * 3600, limited=limit, diracGroup=group, rfc=rfc) if not result['OK']: return result else: cmd = 'voms-proxy-fake --cert %s --key %s -q' % (userCertFile, userKeyFile) cmd += ' -hostcert %s -hostkey %s' % (self.hostCert, self.hostKey) cmd += ' -uri fakeserver.cern.ch:15000' cmd += ' -voms "%s%s"' % (vo, role and ':%s' % role or '') cmd += ' -fqan "/%s/Role=%s/Capability=NULL"' % (vo, role) cmd += ' -hours %s -out %s' % (time, self.proxyPath) if limit: cmd += ' -limited' if rfc: cmd += ' -rfc' status, output = commands.getstatusoutput(cmd) if status: return S_ERROR(output) chain = X509Chain() result = chain.loadProxyFromFile(self.proxyPath) if not result['OK']: return result result = chain.generateProxyToString(12 * 3600, diracGroup=group) if not result['OK']: return result return S_OK((chain, result['Value']))
def createProxy(self, userName, group, time, vo=None, role=None): """Create user proxy :param str userName: user name :param str group: group name :param int time: proxy expired time :param str vo: VOMS VO name :param str role: VOMS Role :return: S_OK(tuple)/S_ERROR() -- contain proxy as and as string """ userCertFile = os.path.join(self.userDir, userName + ".cert.pem") userKeyFile = os.path.join(self.userDir, userName + ".key.pem") self.proxyPath = os.path.join(self.userDir, userName + ".pem") if not vo: chain = X509Chain() # Load user cert and key retVal = chain.loadChainFromFile(userCertFile) if not retVal["OK"]: gLogger.warn(retVal["Message"]) return S_ERROR("Can't load %s" % userCertFile) retVal = chain.loadKeyFromFile(userKeyFile) if not retVal["OK"]: gLogger.warn(retVal["Message"]) if "bad decrypt" in retVal["Message"]: return S_ERROR("Bad passphrase") return S_ERROR("Can't load %s" % userKeyFile) result = chain.generateProxyToFile(self.proxyPath, time * 3600, diracGroup=group) if not result["OK"]: return result else: cmd = "voms-proxy-fake --cert %s --key %s -q" % (userCertFile, userKeyFile) cmd += " -hostcert %s -hostkey %s" % (self.hostCert, self.hostKey) cmd += " -uri fakeserver.cern.ch:15000" cmd += ' -voms "%s"' % vo cmd += ' -fqan "/%s/Role=%s/Capability=NULL"' % (vo, role) cmd += " -hours %s -out %s -rfc" % (time, self.proxyPath) status, output = commands.getstatusoutput(cmd) if status: return S_ERROR(output) chain = X509Chain() result = chain.loadProxyFromFile(self.proxyPath) if not result["OK"]: return result result = chain.generateProxyToString(12 * 3600, diracGroup=group) if not result["OK"]: return result return S_OK((chain, result["Value"]))
def __processCredentials(self): """ Extract the user credentials based on the certificate or what comes from the balancer """ self.__credDict = {} #NGINX if Conf.balancer() == "nginx": headers = self.request.headers if headers['X-Scheme'] == "https" and headers[ 'X-Ssl_client_verify'] == 'SUCCESS': DN = headers['X-Ssl_client_s_dn'] self.__credDict['subject'] = DN self.__credDict['issuer'] = headers['X-Ssl_client_i_dn'] result = Registry.getUsernameForDN(DN) if not result['OK']: self.__credDict['validDN'] = False else: self.__credDict['validDN'] = True self.__credDict['username'] = result['Value'] return #TORNADO if not self.request.protocol == "https": return derCert = self.request.get_ssl_certificate(binary_form=True) if not derCert: return pemCert = ssl.DER_cert_to_PEM_cert(derCert) chain = X509Chain() chain.loadChainFromString(pemCert) result = chain.getCredentials() if not result['OK']: self.log.error("Could not get client credentials %s" % result['Message']) return self.__credDict = result['Value']
def getProxy(self, userDict=None, sessionDict=None): """ Generate user proxy :param dict userDict: user description dictionary with possible fields: FullName, UserName, DN, EMail, DiracGroup :param dict sessionDict: session dictionary :return: S_OK(dict)/S_ERROR() -- dict contain 'proxy' field with is a proxy string """ result = self.getUserDN(userDict, sessionDict, userDN=userDict.get('DN')) if not result['OK']: return result result = self.__createCertM2Crypto() if not result['OK']: return result certStr, keyStr = result['Value'] chain = X509Chain() result = chain.loadChainFromString(certStr) if not result['OK']: return result result = chain.loadKeyFromString(keyStr) if not result['OK']: return result result = chain.generateProxyToString(365 * 24 * 3600, rfc=True) if not result['OK']: return result return S_OK({'proxy': result['Value']})
def _gatherPeerCredentials(self): """ Load client certchain in DIRAC and extract informations. The dictionary returned is designed to work with the AuthManager, already written for DISET and re-used for HTTPS. :returns: a dict containing the return of :py:meth:`DIRAC.Core.Security.X509Chain.X509Chain.getCredentials` (not a DIRAC structure !) """ chainAsText = self.request.get_ssl_certificate().as_pem() peerChain = X509Chain() # Here we read all certificate chain cert_chain = self.request.get_ssl_certificate_chain() for cert in cert_chain: chainAsText += cert.as_pem() peerChain.loadChainFromString(chainAsText) # Retrieve the credentials res = peerChain.getCredentials(withRegistryInfo=False) if not res['OK']: raise Exception(res['Message']) credDict = res['Value'] # We check if client sends extra credentials... if "extraCredentials" in self.request.arguments: extraCred = self.get_argument("extraCredentials") if extraCred: credDict['extraCredentials'] = decode(extraCred)[0] return credDict
def getProxy(self, userDN, userGroup, requiredLifeTime=False): """ Get proxy string from the Proxy Repository for use with userDN in the userGroup """ retVal = self.__getPemAndTimeLeft(userDN, userGroup) if not retVal['OK']: return retVal pemData = retVal['Value'][0] timeLeft = retVal['Value'][1] chain = X509Chain() retVal = chain.loadProxyFromString(pemData) if not retVal['OK']: return retVal if requiredLifeTime: if timeLeft < requiredLifeTime: retVal = self.renewFromMyProxy(userDN, userGroup, lifeTime=requiredLifeTime, chain=chain) if not retVal['OK']: return S_ERROR("Can't get a proxy for %s seconds: %s" % (requiredLifeTime, retVal['Message'])) chain = retVal['Value'] #Proxy is invalid for some reason, let's delete it if not chain.isValidProxy()['Value']: self.deleteProxy(userDN, userGroup) return S_ERROR("%s@%s has no proxy registered" % (userDN, userGroup)) return S_OK((chain, timeLeft))
def test_generateProxyDN(ppf): result = ppf.getProxyProvider("DIRAC_TEST_CA") assert result["OK"], result["Message"] pp = result["Value"] userDict = { "FullName": "John Doe", "Email": "*****@*****.**", "O": "DIRAC", "OU": "DIRAC TEST", "C": "FR" } result = pp.generateDN(**userDict) assert result["OK"], "\n%s" % result.get( "Message") or "Error message is absent." result = pp.getProxy(result["Value"]) assert result["OK"], "\n%s" % result.get( "Message") or "Error message is absent." chain = X509Chain() chain.loadChainFromString(result["Value"]) result = chain.getCredentials() assert result["OK"], "\n%s" % result.get( "Message") or "Error message is absent." issuer = result["Value"]["issuer"] assert issuer == "/C=FR/O=DIRAC/OU=DIRAC TEST/CN=John Doe/[email protected]"
def test_generateProxyDN(self): userDict = { "FullName": "John Doe", "Email": "*****@*****.**", "O": 'DIRAC', 'OU': 'DIRAC TEST', 'C': 'FR' } result = self.pp.generateDN(**userDict) self.assertTrue( result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') result = self.pp.getProxy(result['Value']) self.assertTrue( result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') chain = X509Chain() chain.loadChainFromString(result['Value']) result = chain.getCredentials() self.assertTrue( result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') issuer = result['Value']['issuer'] self.assertEqual( issuer, '/C=FR/O=DIRAC/OU=DIRAC TEST/CN=John Doe/[email protected]' )
def downloadVOMSProxy( self, userDN, userGroup, limited = False, requiredTimeLeft = 1200, cacheTime = 43200, requiredVOMSAttribute = False, proxyToConnect = False, token = False ): """ Download a proxy if needed and transform it into a VOMS one """ cacheKey = ( userDN, userGroup, requiredVOMSAttribute, limited ) if self.__vomsProxiesCache.exists( cacheKey, requiredTimeLeft ): return S_OK( self.__vomsProxiesCache.get( cacheKey ) ) req = X509Request() req.generateProxyRequest( limited = limited ) if proxyToConnect: rpcClient = RPCClient( "Framework/ProxyManager", proxyChain = proxyToConnect, timeout = 120 ) else: rpcClient = RPCClient( "Framework/ProxyManager", timeout = 120 ) if token: retVal = rpcClient.getVOMSProxyWithToken( userDN, userGroup, req.dumpRequest()['Value'], long( cacheTime + requiredTimeLeft ), token, requiredVOMSAttribute ) else: retVal = rpcClient.getVOMSProxy( userDN, userGroup, req.dumpRequest()['Value'], long( cacheTime + requiredTimeLeft ), requiredVOMSAttribute ) if not retVal[ 'OK' ]: return retVal chain = X509Chain( keyObj = req.getPKey() ) retVal = chain.loadChainFromString( retVal[ 'Value' ] ) if not retVal[ 'OK' ]: return retVal self.__vomsProxiesCache.add( cacheKey, chain.getRemainingSecs()['Value'], chain ) return S_OK( chain )
def gatherPeerCredentials( self ): certList = self.sslSocket.get_peer_certificate_chain() #Servers don't receive the whole chain, the last cert comes alone if not self.infoDict[ 'clientMode' ]: certList.insert( 0, self.sslSocket.get_peer_certificate() ) peerChain = X509Chain( certList = certList ) isProxyChain = peerChain.isProxy()['Value'] isLimitedProxyChain = peerChain.isLimitedProxy()['Value'] if isProxyChain: if peerChain.isPUSP()['Value']: identitySubject = peerChain.getCertInChain( -2 )['Value'].getSubjectNameObject()[ 'Value' ] else: identitySubject = peerChain.getIssuerCert()['Value'].getSubjectNameObject()[ 'Value' ] else: identitySubject = peerChain.getCertInChain( 0 )['Value'].getSubjectNameObject()[ 'Value' ] credDict = { 'DN' : identitySubject.one_line(), 'CN' : identitySubject.commonName, 'x509Chain' : peerChain, 'isProxy' : isProxyChain, 'isLimitedProxy' : isLimitedProxyChain } diracGroup = peerChain.getDIRACGroup() if diracGroup[ 'OK' ] and diracGroup[ 'Value' ]: credDict[ 'group' ] = diracGroup[ 'Value' ] self.infoDict[ 'peerCredentials' ] = credDict return credDict
def completeDelegation(self, requestId, userDN, delegatedPem): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest(requestId, userDN) if not retVal['OK']: return retVal request = retVal['Value'] chain = X509Chain(keyObj=request.getPKey()) retVal = chain.loadChainFromString(delegatedPem) if not retVal['OK']: return retVal retVal = chain.isValidProxy(ignoreDefault=True) noGroupFlag = False if not retVal['OK']: if retVal['Message'] == "Proxy does not have an explicit group": noGroupFlag = True else: return retVal result = chain.isVOMS() if result['OK'] and result['Value']: return S_ERROR( "Proxies with VOMS extensions are not allowed to be uploaded") retVal = request.checkChain(chain) if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Received chain does not match request: %s" % retVal['Message']) retVal = chain.getDIRACGroup() if not retVal['OK']: return retVal userGroup = retVal['Value'] if not userGroup: userGroup = Registry.getDefaultUserGroup() retVal = Registry.getGroupsForDN(userDN) if not retVal['OK']: return retVal if not userGroup in retVal['Value']: return S_ERROR("%s group is not valid for %s" % (userGroup, userDN)) # For proxies without embedded DIRAC group only one default is allowed # Cleaning all the proxies for this DN if any before uploading the new one. if noGroupFlag: retVal = self.deleteProxy(userDN) if not retVal['OK']: return retVal retVal = self.storeProxy(userDN, userGroup, chain) if not retVal['OK']: return retVal retVal = self.deleteRequest(requestId) if not retVal['OK']: return retVal return S_OK()
def getProxy(self, userDN): """ Generate user proxy :param str userDN: user DN :return: S_OK(str)/S_ERROR() -- contain a proxy string """ result = self.checkStatus(userDN) if not result['OK']: return result puspURL = self.parameters['ServiceURL'] puspURL += "?proxy-renewal=false&disable-voms-proxy=true&rfc-proxy=true" puspURL += "&cn-label=user:%s" % userDN.split(":")[-1] try: proxy = urlopen(puspURL).read() except Exception: return S_ERROR('Failed to get proxy from the PUSP server') chain = X509Chain() chain.loadChainFromString(proxy) chain.loadKeyFromString(proxy) result = chain.getCredentials() if not result['OK']: return S_ERROR('Failed to get a valid PUSP proxy') credDict = result['Value'] if credDict['identity'] != userDN: return S_ERROR( 'Requested DN does not match the obtained one in the PUSP proxy' ) return chain.generateProxyToString(lifeTime=credDict['secondsLeft'])
def uploadProxy(self, proxy=None, restrictLifeTime: int = 0, rfcIfPossible=None): """Upload a proxy to the proxy management service using delegation :param X509Chain proxy: proxy as a chain :param restrictLifeTime: proxy live time in a seconds :return: S_OK(dict)/S_ERROR() -- dict contain proxies """ if rfcIfPossible is not None: if os.environ.get("DIRAC_DEPRECATED_FAIL", None): raise NotImplementedError( "'rfcIfPossible' argument is deprecated.") gLogger.warn("'rfcIfPossible' argument is deprecated.") # Discover proxy location if isinstance(proxy, X509Chain): chain = proxy proxyLocation = "" else: if not proxy: proxyLocation = Locations.getProxyLocation() if not proxyLocation: return S_ERROR("Can't find a valid proxy") elif isinstance(proxy, str): proxyLocation = proxy else: return S_ERROR("Can't find a valid proxy") chain = X509Chain() result = chain.loadProxyFromFile(proxyLocation) if not result["OK"]: return S_ERROR( f"Can't load {proxyLocation}: {result['Message']}") # Make sure it's valid if chain.hasExpired().get("Value"): return S_ERROR(f"Proxy {proxyLocation} has expired") if chain.getDIRACGroup(ignoreDefault=True).get( "Value") or chain.isVOMS().get("Value"): return S_ERROR( "Cannot upload proxy with DIRAC group or VOMS extensions") rpcClient = Client(url="Framework/ProxyManager", timeout=120) # Get a delegation request result = rpcClient.requestDelegationUpload() if not result["OK"]: return result reqDict = result["Value"] # Generate delegated chain chainLifeTime = chain.getRemainingSecs()["Value"] - 60 if restrictLifeTime and restrictLifeTime < chainLifeTime: chainLifeTime = restrictLifeTime result = chain.generateChainFromRequestString(reqDict["request"], lifetime=chainLifeTime) if result["OK"]: result = rpcClient.completeDelegationUpload( reqDict["id"], pemChain := result["Value"]) return result
def downloadProxy( self, userDN, userGroup, limited = False, requiredTimeLeft = 1200, cacheTime = 43200, proxyToConnect = False, token = False ): """ Get a proxy Chain from the proxy management """ cacheKey = ( userDN, userGroup ) if self.__proxiesCache.exists( cacheKey, requiredTimeLeft ): return S_OK( self.__proxiesCache.get( cacheKey ) ) req = X509Request() req.generateProxyRequest( limited = limited ) if proxyToConnect: rpcClient = RPCClient( "Framework/ProxyManager", proxyChain = proxyToConnect, timeout = 120 ) else: rpcClient = RPCClient( "Framework/ProxyManager", timeout = 120 ) if token: retVal = rpcClient.getProxyWithToken( userDN, userGroup, req.dumpRequest()['Value'], long( cacheTime + requiredTimeLeft ), token ) else: retVal = rpcClient.getProxy( userDN, userGroup, req.dumpRequest()['Value'], long( cacheTime + requiredTimeLeft ) ) if not retVal[ 'OK' ]: return retVal chain = X509Chain( keyObj = req.getPKey() ) retVal = chain.loadChainFromString( retVal[ 'Value' ] ) if not retVal[ 'OK' ]: return retVal self.__proxiesCache.add( cacheKey, chain.getRemainingSecs()['Value'], chain ) return S_OK( chain )
def check(proxyStr, proxyProvider, name): """Check proxy :param str proxyStr: proxy as string :param str proxyProvider: proxy provider name :param str name: proxy name """ proxyFile = os.path.join( testCAPath, proxyProvider + name.replace(" ", "") + ".pem") gLogger.info("Check proxy..") chain = X509Chain() result = chain.loadProxyFromString(proxyStr) self.assertTrue( result["OK"], "\n" + result.get("Message", "Error message is absent.")) for result in [ chain.getRemainingSecs(), chain.getIssuerCert(), chain.getPKeyObj(), chain.getCertList(), chain.getNumCertsInChain(), chain.generateProxyToString(3600), chain.generateProxyToFile(proxyFile, 3600), chain.isProxy(), chain.isLimitedProxy(), chain.isValidProxy(), chain.isVOMS(), chain.isRFC(), ]: self.assertTrue( result["OK"], "\n" + result.get("Message", "Error message is absent."))
def multiProxyArgument(proxy=False): """ Load a proxy: proxyChain param can be: : Default -> use current proxy : string -> upload file specified as proxy : X509Chain -> use chain returns: S_OK( { 'file' : <string with file location>, 'chain' : X509Chain object, 'tempFile' : <True if file is temporal> } S_ERROR """ tempFile = False #Set env if type(proxy) == g_X509ChainType: tempFile = True retVal = writeChainToTemporaryFile(proxy) if not retVal['OK']: return retVal proxyLoc = retVal['Value'] else: if not proxy: proxyLoc = getProxyLocation() if not proxyLoc: return S_ERROR("Can't find proxy") if type(proxy) == types.StringType: proxyLoc = proxy #Load proxy proxy = X509Chain() retVal = proxy.loadProxyFromFile(proxyLoc) if not retVal['OK']: return S_ERROR("Can't load proxy at %s" % proxyLoc) return S_OK({'file': proxyLoc, 'chain': proxy, 'tempFile': tempFile})
def test_getProxy(self): for dn, res in [ ('/C=FR/O=DIRAC/OU=DIRAC TEST/CN=DIRAC test user/[email protected]', True), ('/C=FR/OU=DIRAC TEST/[email protected]', False), ('/C=FR/OU=DIRAC/O=DIRAC TEST/[email protected]', False), ('/C=FR/O=DIRAC/BADFIELD=DIRAC TEST/CN=DIRAC test user', False) ]: result = self.pp.getProxy(dn) text = 'Must be ended %s%s' % ( 'successful' if res else 'with error', ': %s' % result.get('Message', 'Error message is absent.')) self.assertEqual(result['OK'], res, text) if res: chain = X509Chain() chain.loadChainFromString(result['Value']) result = chain.getCredentials() self.assertTrue( result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') credDict = result['Value'] self.assertEqual( credDict['username'], 'testuser', '%s, expected %s' % (credDict['username'], 'testuser'))
def downloadVOMSProxy( self, userDN, userGroup, limited=False, requiredTimeLeft=1200, cacheTime=14400, requiredVOMSAttribute=None, proxyToConnect=None, token=None, ): """Download a proxy if needed and transform it into a VOMS one :param str userDN: user DN :param str userGroup: user group :param boolean limited: if need limited proxy :param int requiredTimeLeft: required proxy live time in a seconds :param int cacheTime: store in a cache time in a seconds :param str requiredVOMSAttribute: VOMS attr to add to the proxy :param X509Chain proxyToConnect: proxy as a chain :param str token: valid token to get a proxy :return: S_OK(X509Chain)/S_ERROR() """ cacheKey = (userDN, userGroup, requiredVOMSAttribute, limited) if self.__vomsProxiesCache.exists(cacheKey, requiredTimeLeft): return S_OK(self.__vomsProxiesCache.get(cacheKey)) req = X509Request() req.generateProxyRequest(limited=limited) if proxyToConnect: rpcClient = Client(url="Framework/ProxyManager", proxyChain=proxyToConnect, timeout=120) else: rpcClient = Client(url="Framework/ProxyManager", timeout=120) if token: retVal = rpcClient.getVOMSProxyWithToken( userDN, userGroup, req.dumpRequest()["Value"], int(cacheTime + requiredTimeLeft), token, requiredVOMSAttribute, ) else: retVal = rpcClient.getVOMSProxy(userDN, userGroup, req.dumpRequest()["Value"], int(cacheTime + requiredTimeLeft), requiredVOMSAttribute) if not retVal["OK"]: return retVal chain = X509Chain(keyObj=req.getPKey()) retVal = chain.loadChainFromString(retVal["Value"]) if not retVal["OK"]: return retVal self.__vomsProxiesCache.add(cacheKey, chain.getRemainingSecs()["Value"], chain) return S_OK(chain)
def __getPUSProxy(self, userDN, userGroup, requiredLifetime, requestedVOMSAttr=None): result = Registry.getGroupsForDN(userDN) if not result['OK']: return result validGroups = result['Value'] if not userGroup in validGroups: return S_ERROR('Invalid group %s for user' % userGroup) voName = Registry.getVOForGroup(userGroup) if not voName: return S_ERROR('Can not determine VO for group %s' % userGroup) retVal = self.__getVOMSAttribute(userGroup, requestedVOMSAttr) if not retVal['OK']: return retVal vomsAttribute = retVal['Value']['attribute'] vomsVO = retVal['Value']['VOMSVO'] puspServiceURL = Registry.getVOOption(voName, 'PUSPServiceURL') if not puspServiceURL: return S_ERROR('Can not determine PUSP service URL for VO %s' % voName) user = userDN.split(":")[-1] puspURL = "%s?voms=%s:%s&proxy-renewal=false&disable-voms-proxy=false" \ "&rfc-proxy=true&cn-label=user:%s" % ( puspServiceURL, vomsVO, vomsAttribute, user ) try: proxy = urllib.urlopen(puspURL).read() except Exception as e: return S_ERROR('Failed to get proxy from the PUSP server') chain = X509Chain() chain.loadChainFromString(proxy) chain.loadKeyFromString(proxy) result = chain.getCredentials() if not result['OK']: return S_ERROR('Failed to get a valid PUSP proxy') credDict = result['Value'] if credDict['identity'] != userDN: return S_ERROR( 'Requested DN does not match the obtained one in the PUSP proxy' ) timeLeft = credDict['secondsLeft'] result = chain.generateProxyToString(lifeTime=timeLeft, diracGroup=userGroup) if not result['OK']: return result proxyString = result['Value'] return S_OK((proxyString, timeLeft))
def uploadProxy(self, proxy=None, restrictLifeTime=0, rfcIfPossible=False): """ Upload a proxy to the proxy management service using delegation :param X509Chain proxy: proxy as a chain :param int restrictLifeTime: proxy live time in a seconds :param boolean rfcIfPossible: make rfc proxy if possible :return: S_OK(dict)/S_ERROR() -- dict contain proxies """ # Discover proxy location if isinstance(proxy, X509Chain): chain = proxy proxyLocation = "" else: if not proxy: proxyLocation = Locations.getProxyLocation() if not proxyLocation: return S_ERROR("Can't find a valid proxy") elif isinstance(proxy, six.string_types): proxyLocation = proxy else: return S_ERROR("Can't find a valid proxy") chain = X509Chain() result = chain.loadProxyFromFile(proxyLocation) if not result['OK']: return S_ERROR("Can't load %s: %s " % (proxyLocation, result['Message'])) # Make sure it's valid if chain.hasExpired().get('Value'): return S_ERROR("Proxy %s has expired" % proxyLocation) if chain.getDIRACGroup().get('Value') or chain.isVOMS().get('Value'): return S_ERROR( "Cannot upload proxy with DIRAC group or VOMS extensions") rpcClient = RPCClient("Framework/ProxyManager", timeout=120) # Get a delegation request # WARN: Since v7r1 requestDelegationUpload method use only first argument! # WARN: Second argument for compatibility with older versions result = rpcClient.requestDelegationUpload( chain.getRemainingSecs()['Value'], None) if not result['OK']: return result reqDict = result['Value'] # Generate delegated chain chainLifeTime = chain.getRemainingSecs()['Value'] - 60 if restrictLifeTime and restrictLifeTime < chainLifeTime: chainLifeTime = restrictLifeTime retVal = chain.generateChainFromRequestString(reqDict['request'], lifetime=chainLifeTime, rfc=rfcIfPossible) if not retVal['OK']: return retVal # Upload! result = rpcClient.completeDelegationUpload(reqDict['id'], retVal['Value']) if not result['OK']: return result return S_OK(result.get('proxies') or result['Value'])
def uploadProxy( self, proxy = False, diracGroup = False, chainToConnect = False, restrictLifeTime = 0 ): """ Upload a proxy to the proxy management service using delgation """ #Discover proxy location if type( proxy ) == g_X509ChainType: chain = proxy proxyLocation = "" else: if not proxy: proxyLocation = Locations.getProxyLocation() if not proxyLocation: return S_ERROR( "Can't find a valid proxy" ) elif type( proxy ) in ( types.StringType, types.UnicodeType ): proxyLocation = proxy else: return S_ERROR( "Can't find a valid proxy" ) chain = X509Chain() result = chain.loadProxyFromFile( proxyLocation ) if not result[ 'OK' ]: return S_ERROR( "Can't load %s: %s " % ( proxyLocation, result[ 'Message' ] ) ) if not chainToConnect: chainToConnect = chain #Make sure it's valid if chain.hasExpired()[ 'Value' ]: return S_ERROR( "Proxy %s has expired" % proxyLocation ) #rpcClient = RPCClient( "Framework/ProxyManager", proxyChain = chainToConnect ) rpcClient = RPCClient( "Framework/ProxyManager", timeout = 120 ) #Get a delegation request result = rpcClient.requestDelegationUpload( chain.getRemainingSecs()['Value'], diracGroup ) if not result[ 'OK' ]: return result #Check if the delegation has been granted if 'Value' not in result or not result[ 'Value' ]: if 'proxies' in result: return S_OK( result[ 'proxies' ] ) else: return S_OK() reqDict = result[ 'Value' ] #Generate delegated chain chainLifeTime = chain.getRemainingSecs()[ 'Value' ] - 60 if restrictLifeTime and restrictLifeTime < chainLifeTime: chainLifeTime = restrictLifeTime retVal = chain.generateChainFromRequestString( reqDict[ 'request' ], lifetime = chainLifeTime, diracGroup = diracGroup ) if not retVal[ 'OK' ]: return retVal #Upload! result = rpcClient.completeDelegationUpload( reqDict[ 'id' ], retVal[ 'Value' ] ) if not result[ 'OK' ]: return result if 'proxies' in result: return S_OK( result[ 'proxies' ] ) return S_OK()
def getProxyInfo(proxy=False, disableVOMS=False): """ :Returns: a dict with all the proxy info: * values that will be there always * 'chain' : chain object containing the proxy * 'subject' : subject of the proxy * 'issuer' : issuer of the proxy * 'isProxy' : bool * 'isLimitedProxy' : bool * 'validDN' : Valid DN in DIRAC * 'validGroup' : Valid Group in DIRAC * 'secondsLeft' : Seconds left * values that can be there * 'path' : path to the file, * 'group' : DIRAC group * 'groupProperties' : Properties that apply to the DIRAC Group * 'username' : DIRAC username * 'identity' : DN that generated the proxy * 'hostname' : DIRAC host nickname * 'VOMS' """ # Discover proxy location proxyLocation = False if isinstance(proxy, X509Chain): chain = proxy else: if not proxy: proxyLocation = Locations.getProxyLocation() elif isinstance(proxy, basestring): proxyLocation = proxy if not proxyLocation: return S_ERROR(DErrno.EPROXYFIND) chain = X509Chain() retVal = chain.loadProxyFromFile(proxyLocation) if not retVal['OK']: return S_ERROR(DErrno.EPROXYREAD, "%s: %s " % (proxyLocation, retVal['Message'])) retVal = chain.getCredentials() if not retVal['OK']: return retVal infoDict = retVal['Value'] infoDict['chain'] = chain if proxyLocation: infoDict['path'] = proxyLocation if not disableVOMS and chain.isVOMS()['Value']: infoDict['hasVOMS'] = True retVal = VOMS().getVOMSAttributes(chain) if retVal['OK']: infoDict['VOMS'] = retVal['Value'] else: infoDict['VOMSError'] = retVal['Message'].strip() return S_OK(infoDict)
def uploadProxy(self, proxy=None, restrictLifeTime=0, rfcIfPossible=False): """Upload a proxy to the proxy management service using delegation :param X509Chain proxy: proxy as a chain :param int restrictLifeTime: proxy live time in a seconds :param boolean rfcIfPossible: make rfc proxy if possible :return: S_OK(dict)/S_ERROR() -- dict contain proxies """ # Discover proxy location if isinstance(proxy, X509Chain): chain = proxy proxyLocation = "" else: if not proxy: proxyLocation = Locations.getProxyLocation() if not proxyLocation: return S_ERROR("Can't find a valid proxy") elif isinstance(proxy, six.string_types): proxyLocation = proxy else: return S_ERROR("Can't find a valid proxy") chain = X509Chain() result = chain.loadProxyFromFile(proxyLocation) if not result["OK"]: return S_ERROR("Can't load %s: %s " % (proxyLocation, result["Message"])) # Make sure it's valid if chain.hasExpired().get("Value"): return S_ERROR("Proxy %s has expired" % proxyLocation) if chain.getDIRACGroup(ignoreDefault=True).get( "Value") or chain.isVOMS().get("Value"): return S_ERROR( "Cannot upload proxy with DIRAC group or VOMS extensions") rpcClient = Client(url="Framework/ProxyManager", timeout=120) # Get a delegation request result = rpcClient.requestDelegationUpload( chain.getRemainingSecs()["Value"]) if not result["OK"]: return result reqDict = result["Value"] # Generate delegated chain chainLifeTime = chain.getRemainingSecs()["Value"] - 60 if restrictLifeTime and restrictLifeTime < chainLifeTime: chainLifeTime = restrictLifeTime retVal = chain.generateChainFromRequestString(reqDict["request"], lifetime=chainLifeTime, rfc=rfcIfPossible) if not retVal["OK"]: return retVal # Upload! result = rpcClient.completeDelegationUpload(reqDict["id"], retVal["Value"]) if not result["OK"]: return result return S_OK(result.get("proxies") or result["Value"])
def getProxyInfo(proxy=False, disableVOMS=False): """ Returns a dict with all the proxy info * values that will be there always 'chain' : chain object containing the proxy 'subject' : subject of the proxy 'issuer' : issuer of the proxy 'isProxy' : bool 'isLimitedProxy' : bool 'validDN' : Valid DN in DIRAC 'validGroup' : Valid Group in DIRAC 'secondsLeft' : Seconds left * values that can be there 'path' : path to the file, 'group' : DIRAC group 'groupProperties' : Properties that apply to the DIRAC Group 'username' : DIRAC username 'identity' : DN that generated the proxy 'hostname' : DIRAC host nickname 'VOMS' """ #Discover proxy location proxyLocation = False if type(proxy) == g_X509ChainType: chain = proxy else: if not proxy: proxyLocation = Locations.getProxyLocation() elif type(proxy) in (types.StringType, types.UnicodeType): proxyLocation = proxy if not proxyLocation: return S_ERROR("Can't find a valid proxy") chain = X509Chain() retVal = chain.loadProxyFromFile(proxyLocation) if not retVal['OK']: return S_ERROR("Can't load %s: %s " % (proxyLocation, retVal['Message'])) retVal = chain.getCredentials() if not retVal['OK']: return retVal infoDict = retVal['Value'] infoDict['chain'] = chain if proxyLocation: infoDict['path'] = proxyLocation if not disableVOMS and chain.isVOMS()['Value']: infoDict['hasVOMS'] = True retVal = VOMS().getVOMSAttributes(chain) if retVal['OK']: infoDict['VOMS'] = retVal['Value'] else: infoDict['VOMSError'] = retVal['Message'].strip() return S_OK(infoDict)
def getProxy(self, userDN, userGroup, requiredLifeTime=False): """ Get proxy string from the Proxy Repository for use with userDN in the userGroup """ # Get the Per User SubProxy if one is requested if isPUSPdn(userDN): result = self.__getPUSProxy(userDN, userGroup, requiredLifeTime) if not result['OK']: return result pemData = result['Value'][0] timeLeft = result['Value'][1] chain = X509Chain() result = chain.loadProxyFromString(pemData) if not result['OK']: return result return S_OK((chain, timeLeft)) # Standard proxy is requested retVal = self.__getPemAndTimeLeft(userDN, userGroup) if not retVal['OK']: return retVal pemData = retVal['Value'][0] timeLeft = retVal['Value'][1] chain = X509Chain() retVal = chain.loadProxyFromString(pemData) if not retVal['OK']: return retVal if requiredLifeTime: if timeLeft < requiredLifeTime: if self.__useMyProxy: retVal = self.renewFromMyProxy(userDN, userGroup, lifeTime=requiredLifeTime, chain=chain) if not retVal['OK']: return S_ERROR("Can't get a proxy for %s seconds: %s" % (requiredLifeTime, retVal['Message'])) chain = retVal['Value'] else: return S_ERROR("Can't get a proxy: the required lifetime is less than the time left in the proxy") # Proxy is invalid for some reason, let's delete it if not chain.isValidProxy()['Value']: self.deleteProxy(userDN, userGroup) return S_ERROR("%s@%s has no proxy registered" % (userDN, userGroup)) return S_OK((chain, timeLeft))
def delegate(delegationRequest, kwargs): """ Check delegate! """ if kwargs.get("useCertificates"): chain = X509Chain() certTuple = Locations.getHostCertificateAndKeyLocation() chain.loadChainFromFile(certTuple[0]) chain.loadKeyFromFile(certTuple[1]) elif "proxyObject" in kwargs: chain = kwargs["proxyObject"] else: if "proxyLocation" in kwargs: procLoc = kwargs["proxyLocation"] else: procLoc = Locations.getProxyLocation() chain = X509Chain() chain.loadChainFromFile(procLoc) chain.loadKeyFromFile(procLoc) return chain.generateChainFromRequestString(delegationRequest)
def test_getProxyGroup(self): result = self.pp.getProxy(self.userDictGroup) self.assertTrue(result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') chain = X509Chain() chain.loadChainFromString(result['Value']) result = chain.getCredentials() self.assertTrue(result['OK'], '\n%s' % result.get('Message') or 'Error message is absent.') credDict = result['Value'] self.assertEqual(credDict['username'], 'testuser', '%s, expected %s' % (credDict['username'], 'testuser')) self.assertEqual(credDict['group'], 'dirac_user', '%s, expected %s' % (credDict['group'], 'dirac_user'))
def completeDelegation(self, requestId, userDN, delegatedPem): """ Complete a delegation and store it in the db """ retVal = self.retrieveDelegationRequest(requestId, userDN) if not retVal['OK']: return retVal request = retVal['Value'] chain = X509Chain(keyObj=request.getPKey()) retVal = chain.loadChainFromString(delegatedPem) if not retVal['OK']: return retVal retVal = chain.isValidProxy() if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Chain received is not a valid proxy: %s" % retVal['Message']) retVal = request.checkChain(chain) if not retVal['OK']: return retVal if not retVal['Value']: return S_ERROR("Received chain does not match request: %s" % retVal['Message']) retVal = chain.getDIRACGroup() if not retVal['OK']: return retVal userGroup = retVal['Value'] if not userGroup: userGroup = CS.getDefaultUserGroup() retVal = CS.getGroupsForDN(userDN) if not retVal['OK']: return retVal if not userGroup in retVal['Value']: return S_ERROR("%s group is not valid for %s" % (userGroup, userDN)) retVal = self.__checkVOMSisAlignedWithGroup(userGroup, chain) if not retVal['OK']: return retVal retVal = self.storeProxy(userDN, userGroup, chain) if not retVal['OK']: return retVal retVal = self.deleteRequest(requestId) if not retVal['OK']: return retVal return S_OK()