def toxml(self): return xmlrpclib.dumps(xmlrpclib.Fault(int(self.errno), str(self)), "", True)
def test_repr(self): f = xmlrpclib.Fault(42, 'Test Fault') self.assertEqual(repr(f), "<Fault 42: 'Test Fault'>") self.assertEqual(repr(f), str(f))
def boom(self, code, string): """ Raise a Fault exception with the specified code and string """ raise xmlrpclib.Fault(code, string)
if method == "RPC2": # prevent recursion raise AssertionError("method cannot be 'RPC2'") response = self.process_rpc(method,params) response = xmlrpclib.dumps((response,), methodresponse=1, allow_none=True) except identity.IdentityFailure, e: session.rollback() response = xmlrpclib.dumps(xmlrpclib.Fault(1,"%s: %s" % (e.__class__, str(e)))) except xmlrpclib.Fault, fault: session.rollback() log.exception('Error handling XML-RPC method') # Can't marshal the result response = xmlrpclib.dumps(fault) except XMLRPCMethodDoesNotExist as e: session.rollback() response = xmlrpclib.dumps(xmlrpclib.Fault(1, 'XML-RPC method %s not implemented by this server' % e.args[0])) except Invalid, e: session.rollback() response = xmlrpclib.dumps(xmlrpclib.Fault(1, str(e))) except Exception: session.rollback() log.exception('Error handling XML-RPC method') # Some other error; send back some error info response = xmlrpclib.dumps( xmlrpclib.Fault(1, "%s:%s" % sys.exc_info()[:2]) ) if str(method).startswith('auth.'): log.debug('Time: %s %s', datetime.utcnow() - start, str(method)) else: log.debug('Time: %s %s %s', datetime.utcnow() - start, str(method), str(params)[0:50])
def getorraise(self, dlhash, key): try: d = self.downloads[dlhash] return d[key] except KeyError as e: raise xmlrpclib.Fault(-501, '')
def raiser(*args, **kw): raise xmlrpclib.Fault(100, 'error')
""" try: params, method = xmlrpclib.loads(data) response = xmlrpclib.dumps( (self._wrap_obj(self._dispatch(method, params)), ), methodresponse=True, allow_none=True, encoding=self.charset) except xmlrpclib.Fault, fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.charset) except: exc_type, exc_value, tb = exc_info = sys.exc_info() log.exception('Exception in XMLRPC request:', 'xmlrpc', exc_info) response = xmlrpclib.dumps(xmlrpclib.Fault( 1, '%s:%s' % (exc_type, exc_value)), encoding=self.charset, allow_none=self.allow_none) return response def handle_request(self, request): if request.method == 'POST': response = self._marshaled_dispatch(request.data) return BaseResponse(response, mimetype='application/xml') return BaseResponse( '\n'.join( ('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">', '<title>XMLRPC Interface</title>', '<h1>XMLRPC Interface</h1>', '<p>This URL provides an XMLRPC interface. You have to '
def __addToCollection(self, uid, request, pwd): """This is called after successful login to add an items to a certain collection, e.g. a new res.partner.""" hello() if not self.desc: raise xmlrpclib.Fault("warning -- Object Error", "no such collection") # check whether we got well-formed XML parser = etree.XMLParser(remove_comments=True) try: doc = etree.fromstring(request.content.read(), parser=parser) except Exception as e: request.setResponseCode(400) request.write("malformed XML: " + str(e)) request.finish() return # check whether we got valid XML with the given schema ns = str(request.URLPath()) + "/schema" schemaxml = self.__desc2relaxNG(str(request.URLPath()), self.desc) schema = etree.fromstring(schemaxml) relaxng = etree.RelaxNG(schema) # to validate doc, we need to set "id" to a numeric value try: doc.find("{%s}id" % ns).text = "-1" except: pass if not relaxng.validate(doc): request.setResponseCode(400) err = relaxng.error_log request.write("invalid XML:\n" + str(err)) request.finish() return # get default values for this model defaultDocRoot = etree.fromstring(self.__mkDefaultXml( str(request.URLPath()), self.desc, self.defaults[uid]), parser=parser) defaultDoc = defaultDocRoot.find( "{http://www.w3.org/2005/Atom}content").find( "{%s}%s" % (ns, self.model.replace(".", "_"))) stripNsRe = re.compile(r'^{%s}(.+)$' % ns) whitespaceRe = re.compile(r'\s+') # collect all fields with non-default values fields = {} for c in doc.getchildren(): if c.tag == "{%s}id" % ns or c.tag == "{%s}create_date" % ns: # will not update id or create_date continue elif whitespaceRe.sub( " ", etree.tostring( c, pretty_print=True).strip()) == whitespaceRe.sub( " ", etree.tostring(defaultDoc.find(c.tag), pretty_print=True).strip()): # c has default value continue # we can assume the regex will match due to validation beforehand tagname = stripNsRe.search(c.tag).group(1) if c.attrib["type"] in ("char", "selection", "text", "datetime"): fields[tagname] = c.text elif c.attrib["type"] == "float": fields[tagname] = float(c.text) elif c.attrib["type"] == "integer": fields[tagname] = int(c.text) elif c.attrib["type"] == "boolean": fields[tagname] = (c.text == "True") elif c.attrib["type"] == "many2one": assert c.attrib['relation'] == defaultDoc.find( c.tag).attrib['relation'] uris = [link.attrib['href'] for link in c.getchildren()] ids = [ int(u[u.rfind('/') + 1:]) for u in uris if u.startswith(c.attrib['relation']) ] if ids: fields[tagname] = ids[0] elif c.attrib["type"] in ("many2many", "one2many"): assert c.attrib['relation'] == defaultDoc.find( c.tag).attrib['relation'] uris = [link.attrib['href'] for link in c.getchildren()] ids = [ int(u[u.rfind('/') + 1:]) for u in uris if u.startswith(c.attrib['relation']) ] if ids: fields[tagname] = [(6, 0, ids)] else: # TODO: date, many2one (we can't really set many2many and one2many here, can we?) raise NotImplementedError("don't know how to handle element " + c.tag + " of type " + c.attrib["type"]) # compose the XML-RPC call from them proxy = quietProxy(self.openerpUrl + 'object') d = proxy.callRemote('execute', self.dbname, uid, pwd, self.model, 'create', fields) d.addCallback(self.__handleAddCollectionAnswer, request) return d
def __updateItem(self, old, uid, pwd, request, lastModified): """This is called after successful login to add an items to a certain collection, e.g. a new res.partner.""" hello() if not self.desc: raise xmlrpclib.Fault("warning -- Object Error", "no such collection") # check whether we got well-formed XML parser = etree.XMLParser(remove_comments=True) try: doc = etree.fromstring(request.content.read(), parser=parser) except Exception as e: request.setResponseCode(400) request.write("malformed XML: " + str(e)) request.finish() return # check whether we got valid XML with the given schema ns = str(request.URLPath()) + "/schema" schemaxml = self.__desc2relaxNG(str(request.URLPath()), self.desc) schema = etree.fromstring(schemaxml) relaxng = etree.RelaxNG(schema) # try to validate object if not relaxng.validate(doc): request.setResponseCode(400) err = relaxng.error_log request.write("invalid XML:\n" + str(err)) request.finish() return # compose old values for this object xmlns = "".join([word[0] for word in self.model.split('.')]) basepath = str(request.URLPath()) path = basepath + "/" + str(old[0]['id']) s = self.__mkItemXml(xmlns, basepath + "/schema", basepath, path, lastModified, old[0]) oldDocRoot = etree.fromstring(s, parser=parser) oldDoc = oldDocRoot.find("{http://www.w3.org/2005/Atom}content").find( "{%s}%s" % (ns, self.model.replace(".", "_"))) stripNsRe = re.compile(r'^{%s}(.+)$' % ns) whitespaceRe = re.compile(r'\s+') def isEquivalentXml(a, b): wsNormalizedA = whitespaceRe.sub( " ", etree.tostring(a, pretty_print=True).strip()) wsNormalizedB = whitespaceRe.sub( " ", etree.tostring(b, pretty_print=True).strip()) if wsNormalizedA == wsNormalizedB: return True elif a.attrib["type"] in ( "char", "selection", "text", "datetime", "float", "integer", "boolean") and a.attrib["type"] == b.attrib["type"]: return a.text == b.text else: return False # collect all fields with new values fields = {} for c in doc.getchildren(): if c.tag == "{%s}id" % ns or c.tag == "{%s}create_date" % ns: # will not update id or create_date continue elif isEquivalentXml(c, oldDoc.find(c.tag)): # c has old value continue # we can assume the regex will match due to validation beforehand tagname = stripNsRe.search(c.tag).group(1) if c.attrib["type"] in ("char", "selection", "text", "datetime"): fields[tagname] = c.text or "" elif c.attrib["type"] == "float": fields[tagname] = float(c.text) elif c.attrib["type"] == "integer": fields[tagname] = int(c.text) elif c.attrib["type"] == "boolean": fields[tagname] = (c.text == "True") elif c.attrib["type"] == "many2one": assert c.attrib['relation'] == oldDoc.find( c.tag).attrib['relation'] oldUris = [ link.attrib['href'] for link in oldDoc.find(c.tag).getchildren() ] uris = [link.attrib['href'] for link in c.getchildren()] ids = [ int(u[u.rfind('/') + 1:]) for u in uris if u.startswith(c.attrib['relation']) ] if ids and oldUris != uris: fields[tagname] = ids[0] elif c.attrib["type"] in ("many2many", "one2many"): assert c.attrib['relation'] == oldDoc.find( c.tag).attrib['relation'] oldUris = [ link.attrib['href'] for link in oldDoc.find(c.tag).getchildren() ] uris = [link.attrib['href'] for link in c.getchildren()] ids = [ int(u[u.rfind('/') + 1:]) for u in uris if u.startswith(c.attrib['relation']) ] if ids and oldUris != uris: fields[tagname] = [(6, 0, ids)] else: # TODO: date raise NotImplementedError("don't know how to handle element " + c.tag + " of type " + c.attrib["type"]) # compose the XML-RPC call from them proxy = quietProxy(self.openerpUrl + 'object') d = proxy.callRemote('execute', self.dbname, uid, pwd, self.model, 'write', [old[0]['id']], fields) d.addCallback(self.__handleUpdateItemAnswer, request) return d
def return_fault(self, code, msg): return xmlrpclib.Fault(code, msg)
if getattr(e, "log", True): self.logger.error(e, exc_info=True) raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) need_to_lock = not getattr(method_func, 'locking', False) if need_to_lock: lock_start = time.time() self.lock.acquire() lock_done = time.time() try: method_start = time.time() result = method_func(*args) except Exception, e: if getattr(e, "log", True): self.logger.error(e, exc_info=True) raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e)) finally: method_done = time.time() if need_to_lock: self.lock.release() self.statistics.add_value('component_lock', lock_done - lock_start) self.statistics.add_value(method, method_done - method_start) if getattr(method_func, "query", False): if not getattr(method_func, "query_all_methods", False): margs = args[:1] else: margs = [] result = marshal_query_result(result, *margs) return result
if method == "RPC2": # prevent recursion raise AssertionError("method cannot be 'RPC2'") response = self.process_rpc(method,params) response = xmlrpclib.dumps((response,), methodresponse=1, allow_none=True) except identity.IdentityFailure, e: session.rollback() response = xmlrpclib.dumps(xmlrpclib.Fault(1,"%s: %s" % (e.__class__, str(e)))) except xmlrpclib.Fault, fault: session.rollback() log.exception('Error handling XML-RPC method') # Can't marshal the result response = xmlrpclib.dumps(fault) except Invalid, e: session.rollback() response = xmlrpclib.dumps(xmlrpclib.Fault(1, str(e))) except Exception: session.rollback() log.exception('Error handling XML-RPC method') # Some other error; send back some error info response = xmlrpclib.dumps( xmlrpclib.Fault(1, "%s:%s" % sys.exc_info()[:2]) ) if str(method).startswith('auth.'): log.debug('Time: %s %s', datetime.utcnow() - start, str(method)) else: log.debug('Time: %s %s %s', datetime.utcnow() - start, str(method), str(params)[0:50]) cherrypy.response.headers["Content-Type"] = "text/xml" return response
def __call__(self): return xmlrpclib.Fault( premarshal(self.data.faultCode), premarshal(self.data.faultString), )
#!/usr/bin/env python2 # -*- coding:utf-8 -*- import sys import xmlrpclib import traceback import ssl server = xmlrpclib.ServerProxy('https://116.196.104.11:1337',context=ssl.SSLContext(ssl.PROTOCOL_TLSv1)) try: if not server.echo('try echo') == 'try echo': raise xmlrpclib.Fault(-1,'Try echo method failed, server invalid.') except xmlrpclib.Fault,e: traceback.print_exc() print('__________________') print(e.faultString) sys.exit() except Exception: traceback.print_exc() print('-------------NOT GOOD----------') sys.exit() print('Available methods:'+str(server.system.listMethods()))
def _dispatch(self, method, args): """ We provide a _dispatch function (which SimpleXMLRPCServer looks for and uses) so that we can log exceptions due to our programming errors within seattlegeni as well to detect incorrect usage by clients. """ try: # Get the requested function (making sure it exists). try: func = getattr(self, method) except AttributeError: raise InvalidRequestError("The requested method '" + method + "' doesn't exist.") # Call the requested function. return func(*args) except InvalidRequestError: log.error("The xmlrpc server was used incorrectly: " + traceback.format_exc()) raise except xmlrpclib.Fault: # A xmlrpc Fault was intentionally raised by the code in this module. raise except Exception, e: # We assume all other exceptions are bugs in our code. # We use the log message as the basis for the email message, as well. logmessage = "Internal error while handling an xmlrpc request: " + traceback.format_exc( ) log.critical(logmessage) # Normally django will send an email to the ADMINS defined in settings.py # when an exception occurs. However, our xmlrpc dispatcher will turn this # into a Fault that is returned to the client. So, django won't see it as # an uncaught exception. Therefore, we have to send it ourselves. if not settings.DEBUG: subject = "Error handling xmlrpc request '" + method + "': " + str( type(e)) + " " + str(e) emailmessage = logmessage + "\n\n" emailmessage += "XMLRPC method called: " + method + "\n" # If the first argument looks like auth info, don't include the # api_key in the email we send. Otherwise, include all the args. # We wrap this in a try block just in case we screw this up we want to # be sure we get an email still. try: if len(args) > 0 and isinstance( args[0], dict) and "username" in args[0]: emailmessage += "Username: "******"username"]) + "\n" if len(args) > 1: emailmessage += "Non-auth arguments: " + str( args[1:]) + "\n" else: emailmessage += "There were no non-auth arguments." + "\n" else: emailmessage += "Arguments: " + str(args) + "\n" except: pass # Send an email to the addresses listed in settings.ADMINS django.core.mail.mail_admins(subject, emailmessage) # It's not unlikely that the user ends up seeing this message, so we # are careful about what the content of the message is. We don't # include the exception trace. raise xmlrpclib.Fault( FAULTCODE_INTERNALERROR, "Internal error while handling the xmlrpc request.")
def __handleLoginAnswer(self, uid): hello() if not uid: raise xmlrpclib.Fault("AccessDenied", "login failed") else: return uid
def make_custom_query(self, entity, conditions, limit=200): """ Name ---- `make_custom_query` (`entity`, `conditions`, `limit`) Description ----------- Construct and run a custom query and return the results. Arguments --------- `entity`: string The entity you want to query `conditions`: string The conditions of the query `limit`: integer Add a limit to the number of results returned. Defaults to 200. Return value ------------ A list of dictionaries containing the query results. The user should be authenticated with a username and token. Example ------- # Get all test jobs submitted by the user 'kernel-ci', and which ended # as 'Incomplete': server.results.make_custom_query("testjob", "testjob__submitter__exact__kernel-ci," "testjob__health__exact__Incomplete") [{ jobXX }, { jobXY }, ...] # Get all test cases in a test suite named 'custom-tests', that failed, # and for whom the job ended after '2017-04-26 00:00:00'. server.results.make_custom_query("testcase", "testsuite__name__exact__1_custom-tests," "testcase__result__exact__Test failed," "testjob__end_time__gt__2017-04-26 00:00:00") [{ testcaseXX }, { testcaseXY }, ...] """ self._authenticate() try: content_type = Query.get_content_type(entity) except InvalidContentTypeError: raise xmlrpclib.Fault( 400, "Wrong table name in entity parameter. " "Please refer to query docs.") if content_type.model_class() not in QueryCondition.RELATION_MAP: raise xmlrpclib.Fault( 400, "Wrong table name in entity parameter. " "Please refer to query docs.") conditions = Query.parse_conditions(content_type, conditions) try: results = Query.get_queryset(content_type, conditions).visible_by_user(self.user) except FieldDoesNotExist: raise xmlrpclib.Fault(400, "Conditions URL incorrect: Field does not exist. " "Please refer to query docs.") return list(results[:limit])
def no_such_slice(self, slice_urn): """Raise a no such slice exception.""" fault_code = 'No such slice.' fault_string = 'The slice named by %s does not exist' % (slice_urn) self.logger.warning(fault_string) raise xmlrpclib.Fault(fault_code, fault_string)
response = (handler.run(),) # note that we wrap response in a singleton tuple response = xmlrpclib.dumps(response, methodresponse=1, allow_none=1) self.logger.info("RESPONSE: %r" % response) self.session.host.closeTask(handler.id, response) return except xmlrpclib.Fault, fault: response = xmlrpclib.dumps(fault) tb = ''.join(traceback.format_exception(*sys.exc_info())).replace(r"\n", "\n") self.logger.warn("FAULT:\n%s" % tb) except (SystemExit, koji.tasks.ServerExit, KeyboardInterrupt): #we do not trap these raise except koji.tasks.ServerRestart: #freeing this task will allow the pending restart to take effect self.session.host.freeTasks([handler.id]) return except: tb = ''.join(traceback.format_exception(*sys.exc_info())) self.logger.warn("TRACEBACK: %s" % tb) # report exception back to server e_class, e = sys.exc_info()[:2] faultCode = getattr(e_class, 'faultCode', 1) if issubclass(e_class, koji.GenericError): #just pass it through tb = str(e) response = xmlrpclib.dumps(xmlrpclib.Fault(faultCode, tb)) # if we get here, then we're handling an exception, so fail the task self.session.host.failTask(handler.id, response)
class CredentialVerifier(object): """Utilities to verify signed credentials from a given set of root certificates. Will compare target and source URNs, and privileges. See verify and verify_from_strings methods in particular.""" CATEDCERTSFNAME = 'CATedCACerts.pem' # root_cert_file is a trusted root file file or directory of # trusted roots for verifying credentials def __init__(self, root_cert_fileordir): self.logger = logging.getLogger('cred-verifier') if root_cert_fileordir is None: raise Exception("Missing Root certs argument") elif os.path.isdir(root_cert_fileordir): files = os.listdir(root_cert_fileordir) self.root_cert_files = [] for file in files: # FIXME: exclude files that aren't cert files? The combo cert file? if file == CredentialVerifier.CATEDCERTSFNAME: continue self.root_cert_files.append( os.path.expanduser(os.path.join(root_cert_fileordir, file))) self.logger.info( 'Will accept credentials signed by any of %d root certs found in %s: %r' % (len(self.root_cert_files), root_cert_fileordir, self.root_cert_files)) elif os.path.isfile(root_cert_fileordir): self.logger.info( 'Will accept credentials signed by the single root cert %s' % root_cert_fileordir) self.root_cert_files = [root_cert_fileordir] else: raise Exception("Couldn't find Root certs in %s" % root_cert_fileordir) @classmethod def getCAsFileFromDir(cls, caCerts): '''Take a directory of CA certificates and concatenate them into a single file suitable for use by the Python SSL library to validate client credentials. Existing file is replaced.''' if caCerts is None: raise Exception('Missing caCerts argument') if os.path.isfile(os.path.expanduser(caCerts)): return caCerts if not os.path.isdir(os.path.expanduser(caCerts)): raise Exception('caCerts arg Not a file or a dir: %s' % caCerts) logger = logging.getLogger('cred-verifier') # Now we have a dir of caCerts files # For each file in the dir (isfile), concatenate them into a new file comboFullPath = os.path.join(caCerts, CredentialVerifier.CATEDCERTSFNAME) caFiles = os.listdir(caCerts) #logger.debug('Got %d potential caCert files in the dir', len(caFiles)) outfile = open(comboFullPath, "w") okFileCount = 0 for filename in caFiles: filepath = os.path.join(caCerts, filename) # Confirm it's a CA file? # if not file.endswith('.pem'): # continue if not os.path.isfile(os.path.expanduser(filepath)): logger.debug('Skipping non file %s', filepath) continue if filename == CredentialVerifier.CATEDCERTSFNAME: # logger.debug('Skipping previous cated certs file') continue okFileCount += 1 logger.info("Adding trusted cert file %s", filename) certfile = open(filepath) for line in certfile: outfile.write(line) certfile.close() outfile.close() if okFileCount == 0: sys.exit('Found NO trusted certs in %s!' % caCerts) else: logger.info( 'Combined dir of %d trusted certs %s into file %s for Python SSL support', okFileCount, caCerts, comboFullPath) return comboFullPath def verify_from_strings(self, gid_string, cred_strings, target_urn, privileges): '''Create Credential and GID objects from the given strings, and then verify the GID has the right privileges according to the given credentials on the given target.''' def make_cred(cred_string): return cred.Credential(string=cred_string) return self.verify(gid.GID(string=gid_string), map(make_cred, cred_strings), target_urn, privileges) def verify_source(self, source_gid, credential): '''Ensure the credential is giving privileges to the caller/client. Return True iff the given source (client) GID's URN is == the given credential's Caller (Owner) URN''' source_urn = source_gid.get_urn() cred_source_urn = credential.get_gid_caller().get_urn() #self.logger.debug('Verifying source %r against credential source %r (cred target %s)', # source_urn, cred_source_urn, credential.get_gid_object().get_urn()) result = (cred_source_urn == source_urn) if result: # self.logger.debug('Source URNs match') pass else: self.logger.debug( 'Source URNs do not match. Source URN %r != credential source URN %r', source_urn, cred_source_urn) return result def verify_target(self, target_urn, credential): '''Ensure the credential is giving privileges on the right subject/target. Return True if no target is specified, or the target URN matches the credential's Object's (target's) URN, else return False. No target is required, for example, to ListResources.''' if not target_urn: # self.logger.debug('No target specified, considering it a match.') return True else: cred_target_urn = credential.get_gid_object().get_urn() # self.logger.debug('Verifying target %r against credential target %r', # target_urn, cred_target_urn) result = target_urn == cred_target_urn if result: # self.logger.debug('Target URNs match.') pass else: self.logger.debug( 'Target URNs do NOT match. Target URN %r != Credential URN %r', target_urn, cred_target_urn) return result def verify_privileges(self, privileges, credential): ''' Return True iff the given credential gives the privilege to perform ALL of the privileges (actions) in the given list. In particular, the given list of 'privileges' is really a list of names of operations. The privileges in credentials are each turned in to Rights objects (see sfa/trust/rights.py). And the SFA rights table is used to map from names of privileges as specified in credentials, to names of operations.''' result = True privs = credential.get_privileges() for priv in privileges: if not privs.can_perform(priv): self.logger.debug( 'Privilege %s not found on credential %s of %s', priv, credential.get_gid_object().get_urn(), credential.get_gid_caller().get_urn()) result = False return result def verify(self, gid, credentials, target_urn, privileges): '''Verify that the given Source GID supplied at least one credential in the given list of credentials that has all the privileges required in the privileges list on the given target. IE if any of the supplied credentials has a caller that matches gid and a target that matches target_urn, and has all the privileges in the given list, then return the list of credentials that were ok. Throw an Exception if we fail to verify any credential.''' # Note that here we treat a list of credentials as being options # Alternatively could accumulate privileges for example # The semantics of the list of credentials is under specified. self.logger.debug('Verifying privileges') result = list() failure = "" tried_creds = "" for cred in credentials: if tried_creds != "": tried_creds = "%s, %s" % (tried_creds, cred.get_gid_caller().get_urn()) else: tried_creds = cred.get_gid_caller().get_urn() if not self.verify_source(gid, cred): failure = "Cred %s fails: Source URNs dont match" % cred.get_gid_caller( ).get_urn() continue if not self.verify_target(target_urn, cred): failure = "Cred %s on %s fails: Target URNs dont match" % ( cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn()) continue if not self.verify_privileges(privileges, cred): failure = "Cert %s doesn't have sufficient privileges" % cred.get_gid_caller( ).get_urn() continue print try: if not cred.verify(self.root_cert_files): failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs" % ( cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn(), len(self.root_cert_files)) continue except Exception, exc: failure = "Couldn't validate credential for caller %s with target %s with any of %d known root certs: %s" % ( cred.get_gid_caller().get_urn(), cred.get_gid_object().get_urn(), len( self.root_cert_files), exc) self.logger.info(failure) continue # If got here it verified result.append(cred) if result and result != list(): # At least one credential verified ok and was added to the list # return that list return result else: # We did not find any credential with sufficient privileges # Raise an exception. fault_code = 'Insufficient privileges' fault_string = 'No credential was found with appropriate privileges. Tried %s. Last failure: %s' % ( tried_creds, failure) self.logger.error(fault_string) raise xmlrpclib.Fault(fault_code, fault_string)
class XMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, threading.Thread): """ Stoppable XMLRPC Server with custom dispatch to send over complete traceback in case of exception. """ def __init__(self, *args, **kwargs): threading.Thread.__init__(self) SimpleXMLRPCServer.SimpleXMLRPCServer.__init__( self, requestHandler=CustomXMLRPCRequestHandler, allow_none=True, *args, **kwargs) self._stop = False # set timeout for handle_request. If we don't the server will hang self.timeout = 2 def run(self): self.serve_forever() api.devlog("serve_forever ended") return # overloaded method to be able to stop server def serve_forever(self): while not self._stop: self.handle_request() api.devlog("server forever stopped by flag") def stop_server(self): api.devlog("server stopping...") self._stop = True # The default dispatcher does not send across the whole stack trace. # Only type and value are passed back. The client has no way of knowing # the exact place where error occurred in the server (short of some # other means such as server logging). This dispatcher sends the whole # stack trace. def _dispatch(self, method, params): """Dispatches the XML-RPC method. XML-RPC calls are forwarded to a registered function that matches the called XML-RPC method name. If no such function exists then the call is forwarded to the registered instance, if available. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called. """ func = None try: # check to see if a matching function has been registered func = self.funcs[method] except KeyError: if self.instance is not None: # check for a _dispatch method if hasattr(self.instance, '_dispatch'): return self.instance._dispatch(method, params) else: # call instance method directly try: func = SimpleXMLRPCServer.resolve_dotted_attribute( self.instance, method, self.allow_dotted_names) except AttributeError: pass if func is not None: try: # since we are using a keyword xmlrpc proxy this is sending # the info comes in form of args and kwargs # so params has 2 items, the first being a list or tuple # and the second a dictionary if len(params) == 2 and isinstance(params[1],dict) and\ ( isinstance(params[0],list) or isinstance(params[0],tuple) ) : return func(*params[0], **params[1]) else: # this is the default way in case a normal xmlrpclib.ServerProxy is used return func(*params) except Exception: # extended functionality to let the client have the full traceback msg = traceback.format_exc() raise xmlrpclib.Fault(1, msg) else: raise Exception('method "%s" is not supported' % method) def _marshaled_dispatch(self, data, dispatch_method=None): """Dispatches an XML-RPC method from marshalled (XML) data. XML-RPC methods are dispatched from the marshalled (XML) data using the _dispatch method and the result is returned as marshalled data. For backwards compatibility, a dispatch function can be provided as an argument (see comment in SimpleXMLRPCRequestHandler.do_POST) but overriding the existing method through subclassing is the prefered means of changing method dispatch behavior. """ try: params, method = xmlrpclib.loads(data) # generate response if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params) # wrap response in a singleton tuple response = (response, ) response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) except Fault, fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except Exception: # report exception back to server exc_type, exc_value, exc_tb = sys.exc_info() response = xmlrpclib.dumps( xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), encoding=self.encoding, allow_none=self.allow_none, )
self._cbRender(f, request) else: instance_name = "cloudfactory" #modul_name = args[1] modul_name = "CloudFactory" instance = self.moduls.get(modul_name) if not instance: msg = "modul id not exists args [%s]" % str(args) print msg function = None else: function = getattr(instance, functionName, None) if function is None: f = xmlrpclib.Fault( self.FAILURE, "The Resource didn't implement the %s method" % functionName) self._cbRender(f, request) else: function = packageResult(function) responseFailed = [] request.notifyFinish().addErrback(responseFailed.append) d = threads.deferToThread(function, *args) d.addErrback(self._ebRender) d.addCallback(self._cbRender, request, responseFailed) return server.NOT_DONE_YET def initResource():
def _error(self, code, message): fault = xmlrpclib.Fault(code, message) return xmlrpclib.dumps(fault, encoding=self.encoding, allow_none=True)
def make_fault(self): """Returns an xmlrpc fault.""" return xmlrpclib.Fault(666, "Yoghurt and spanners.")
else: response = self._dispatch(method, params) # wrap response in a singleton tuple response = (response, ) response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) except Fault, fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except: # report exception back to server response = xmlrpclib.dumps( xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), encoding=self.encoding, allow_none=self.allow_none, ) return response def system_listMethods(self): """system.listMethods() => ['add', 'subtract', 'multiple'] Returns a list of the methods supported by the server.""" methods = self.funcs.keys() if self.instance is not None: # Instance can implement _listMethod to return a list of # methods
# The interface.acquire_vessels() call expects 'rand' instead of 'random'. if resource_type == 'random': resource_type = 'rand' try: acquired_vessels = interface.acquire_vessels( geni_user, num_vessels, resource_type) except UnableToAcquireResourcesError, err: raise xmlrpclib.Fault( FAULTCODE_UNABLETOACQUIRE, "Unable to fulfill vessel acquire request at this given time. Details: " + str(err)) except InsufficientUserResourcesError, err: raise xmlrpclib.Fault( FAULTCODE_NOTENOUGHCREDITS, "You do not have enough vessel credits to acquire the number of vessels requested." ) # since acquire_vessels returns a list of Vessel objects, we # need to convert them into a list of 'info' dictionaries. return interface.get_vessel_infodict_list(acquired_vessels) @staticmethod @log_function_call def acquire_specific_vessels(auth, vesselhandle_list): """ <Purpose> Acquires specific vessels for a user. This will be best effort. Zero or more of the vessels may be acquired. The list, however, cannot include more vessels than the maximum number the user is allowed to acquire. <Arguments>
params, method = xmlrpclib.loads(data) # add request to params params = (request, ) + params # generate response try: if dispatch_method is not None: response = dispatch_method(method, params) else: response = self._dispatch(method, params) # wrap response in a singleton tuple response = (response, ) response = xmlrpclib.dumps(response, methodresponse=1, allow_none=self.allow_none, encoding=self.encoding) except xmlrpclib.Fault, fault: response = xmlrpclib.dumps(fault, allow_none=self.allow_none, encoding=self.encoding) except: response = xmlrpclib.dumps(xmlrpclib.Fault( 1, "%s: %s" % (sys.exc_type.__name__, sys.exc_value)), allow_none=self.allow_none, encoding=self.encoding) return response
def get_encrypted_api_key(username): """ <Purpose> Retrieve the account's API key encrypted with the account's public key. This provides the holder of an account's private key a means of obtaining the SeattleGENI API key for the account. A side effect is that this also provide a means of determining whether an account exists on seattlegeni. However, we do not protect against such querying here because the same can be determined in a handful of other ways through the html interface. This approach of obtaining the encrypted api key can be removed later if we implement a way to sign requests. <Arguments> username The username of the account whose encrypted API key we want. <Exceptions> Raises xmlrpclib Fault objects with fault codes: FAULTCODE_INVALIDREQUEST if a the provided username is not a string specifying a valid (existing) account username. <Returns> An string that represents DATA encrypted by (seattlelib) rsa.r2py's rsa_encrypt() function. DATA is a string that is the concatenation of a random string of 0-9a-fA-F of fixed length, an exclamation mark, and the API key. For example, DATA may be the following string: l28yDKLQGqhqdfDquDq0433!AD98OF2308Q9RYFHDHKJAC where AD98OF2308Q9RYFHDHKJAC is the API key. Note that this random data being prepended is just a dirty workaround for the lack of random padding being used by the encryption format offered by rsa.r2py or other repy libraries. This should be changed after a repy implementation of PKCS#1 is available. """ try: assertions.assert_str(username) except AssertionError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username must be a string.") try: geniuser = interface.get_user_without_password(username) except DoesNotExistError: raise xmlrpclib.Fault(FAULTCODE_INVALIDREQUEST, "Username does not exist.") # Don't change the number of bytes of random data without changing the API # spec and the xmlrpc client. randstring = ''.join( random.sample(string.letters + string.digits, ENCRYPTED_API_KEY_PADDING_BYTES)) data = randstring + "!" + geniuser.api_key data = str( data ) # make sure it's type str, not unicode, as required by rsa_encrypt user_pubkey_dict = rsa_string_to_publickey(geniuser.user_pubkey) encrypted_data = rsa_encrypt(data, user_pubkey_dict) # rsa_encrypt returns returns a string with an extra space in the front. encrypted_data = encrypted_data.strip() # If the encrypted_data is more than one "block" long, something odd is # going on and there may be no padding applied to one or more encrypted # blocks. if ' ' in encrypted_data: raise InternalError( "The encrypted_data to be returned by get_encrypted_api_key() " + "was more than one block long. user: "******" encrypted_data: " + encrypted_data) return encrypted_data
def boom(self): raise xmlrpclib.Fault(1, "boom")
"""Simple XML-RPC Server.