def test_dont_log_methods_without_system_id(self): # we need a method that doesn't have a system_id parameter def api_method(not_system_id): pass auditlog_xmlrpc(api_method, "method_name", "args", "request") self.assertFalse(self.auditlog_server.log.called)
def test_successful_logging_with_proxy(self): request = Mock() request.headers_in = {"SERVER_NAME": "server_name", "REMOTE_ADDR": "remote_addr", "SERVER_PORT": "server_port", "DOCUMENT_ROOT": "document_root", "SCRIPT_FILENAME": "script_filename", "SCRIPT_URI": "script_uri", "HTTP_X_RHN_PROXY_AUTH": "proxy_auth", "HTTP_X_RHN_PROXY_VERSION": "proxy_version", "HTTP_X_RHN_IP_PATH": "original_addr"} auditlog._get_server_id = Mock(return_value=("system_id", ("arg1", "arg2"))) def api_method(system_id): pass auditlog_xmlrpc(api_method, "api_method_name", ["args"], request) self.assertEqual(self.auditlog_server.audit.log.call_args, (('42(geeko)', "api_method_name('arg1', 'arg2')", 'server_name', {'EVT.SRC': 'BACKEND_API', 'REQ.SCRIPT_URI': 'script_uri', 'REQ.SCRIPT_FILENAME': 'script_filename', 'REQ.REMOTE_ADDR': 'remote_addr', 'REQ.DOCUMENT_ROOT': 'document_root', 'REQ.SERVER_PORT': 'server_port', 'REQ.PROXY': 'proxy_auth', 'REQ.PROXY_VERSION': 'proxy_version', 'REQ.ORIGINAL_ADDR': 'original_addr'}), {}))
def test_missing_header_values_in_proxy_sent_as_null_strings(self): request = Mock() request.headers_in = { "SERVER_NAME": "server_name", "HTTP_X_RHN_PROXY_AUTH": "proxy" } auditlog._get_server_id = Mock(return_value=("system_id", ("args", ))) def api_method(system_id): pass auditlog_xmlrpc(api_method, "method_name", ["args"], request) self.assertEqual( self.auditlog_server.audit.log.call_args, (('42(geeko)', "method_name('args',)", 'server_name', { 'EVT.SRC': 'BACKEND_API', 'REQ.SCRIPT_URI': '', 'REQ.SCRIPT_FILENAME': '', 'REQ.REMOTE_ADDR': '', 'REQ.DOCUMENT_ROOT': '', 'REQ.SERVER_PORT': '', 'REQ.PROXY': 'proxy', 'REQ.PROXY_VERSION': '', 'REQ.ORIGINAL_ADDR': '' }), {}))
def test_missing_header_values_sent_as_null_strings(self): request = Mock() request.headers_in = {"SERVER_NAME": "server_name"} auditlog._get_server_id = Mock(return_value=("system_id", ("args",))) def api_method(system_id): pass auditlog_xmlrpc(api_method, "method_name", ["args"], request) self.assertEqual(self.auditlog_server.audit.log.call_args, (('42(geeko)', "method_name('args',)", 'server_name', {'EVT.SRC': 'BACKEND_API', 'REQ.SCRIPT_URI': '', 'REQ.SCRIPT_FILENAME': '', 'REQ.REMOTE_ADDR': '', 'REQ.DOCUMENT_ROOT': '', 'REQ.SERVER_PORT': ''}), {}))
def test_logging_is_disabled(self): auditlog._read_config = Mock(return_value=(False, "")) auditlog_xmlrpc("method", "method_name", "args", "request") self.assertFalse(self.auditlog_server.log.called)
def call_function(self, method, params): # short-circuit everything if sending a system-wide message. if CFG.SEND_MESSAGE_TO_ALL: # Make sure the applet doesn't see the message if method == 'applet.poll_status': return self.response({ 'checkin_interval': 3600, 'server_status': 'normal' }) if method == 'applet.poll_packages': return self.response({'use_cached_copy': 1}) # Fetch global message being sent to clients if applicable. msg = open(CFG.MESSAGE_TO_ALL).read() log_debug(3, "Sending message to all clients: %s" % msg) # Send the message as a fault. response = xmlrpclib.Fault( -1, _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg) # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret # req: where the response is sent to log_debug(2, method) # Now we have the reference, call away force_rollback = 1 func = None try: # now get the function reference and call it func = self.method_ref(method) response = func(*params) except (TypeError, ValueError, KeyError, IndexError, UnknownXML): # report exception back to server fault = 1 if sys.version_info[0] == 3: exctype = sys.exc_info()[0] else: exctype = sys.exc_info()[0] if exctype == UnknownXML: fault = -1 e_type, e_value = sys.exc_info()[:2] response = xmlrpclib.Fault(fault, _( "While running '%s': caught\n%s : %s\n") % ( method, e_type, e_value)) Traceback(method, self.req, extra="Response sent back to the caller:\n%s\n" % ( response.faultString,), severity="notification") except rhnNotFound: e = sys.exc_info()[1] return apache.HTTP_NOT_FOUND # pkilambi:catch exception if redirect except redirectException: re = sys.exc_info()[1] log_debug(3, "redirect exception caught", re.path) response = re.path except rhnFault: f = sys.exc_info()[1] response = f.getxml() except rhnSQL.SQLSchemaError: e = sys.exc_info()[1] f = None if e.errno == 20200: log_debug(2, "User Group Membership EXCEEDED") f = rhnFault(43, e.errmsg) if not f: log_error("rhnSQL.SQLSchemaError caught", e) rhnSQL.rollback() # generate the traceback report Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR response = f.getxml() except rhnSQL.SQLError: e = sys.exc_info()[1] log_error("rhnSQL.SQLError caught", e) rhnSQL.rollback() Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: e = sys.exc_info()[1] log_error("Unhandled exception", e) rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR else: # if no exception, we don't need to rollback force_rollback = 0 if force_rollback: rhnSQL.rollback() # we only want to log successful actions at this time, that's # why we do it here. Note: "func" might be None, in this case # it will cause AuditLogException below. try: auditlog_xmlrpc(func, method, params, self.req) except AuditLogException as e: # if logging didn't succeed, cancel the whole action rhnSQL.rollback() Traceback(method, self.req, extra="AuditLogging error: %s" % e) return apache.HTTP_INTERNAL_SERVER_ERROR # and now send everything back ret = self.response(response) # we only want to log successful actions at this time, that's # why we do it here auditlog_xmlrpc(func, method, params, self.req) log_debug(4, "Leave with return value", ret) return ret
class apacheRequest: def __init__(self, client_version, req): self.client = client_version self.req = req # grab an Input object self.input = transports.Input(req.headers_in) # make sure we have a parser and a decoder available self.parser, self.decoder = xmlrpclib.getparser() # Make sure the decoder doesn't assume UTF-8 data, that would break if # non-UTF-8 chars are sent (bug 139370) self.decoder._encoding = None # extract the server we're talking to and the root directory # from the request configuration options req_config = req.get_options() # XXX: attempt to catch these KeyErrors sometime when there is # time to play nicely self.server = req_config["SERVER"] # Load the server classes # XXX: some day we're going to trust the timestamp stuff... self.servers = None self._setup_servers() def _setup_servers(self): self.servers = rhnImport.load("server/handlers", interface_signature='rpcClasses') # return a reference to a method name. The method in the base def method_ref(self, method): raise UnknownXML("Could not find reference definition" "for method '%s'" % method) # call a function with parameters def call_function(self, method, params): # short-circuit everything if sending a system-wide message. if CFG.SEND_MESSAGE_TO_ALL: # Make sure the applet doesn't see the message if method == 'applet.poll_status': return self.response({ 'checkin_interval': 3600, 'server_status': 'normal' }) if method == 'applet.poll_packages': return self.response({'use_cached_copy': 1}) # Fetch global message being sent to clients if applicable. msg = open(CFG.MESSAGE_TO_ALL).read() log_debug(3, "Sending message to all clients: %s" % msg) # Send the message as a fault. response = xmlrpclib.Fault( -1, _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg) # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret # req: where the response is sent to log_debug(2, method) # Now we have the reference, call away force_rollback = 1 func = None try: # now get the function reference and call it func = self.method_ref(method) response = func(*params) except (TypeError, ValueError, KeyError, IndexError, UnknownXML): # report exception back to server fault = 1 if sys.version_info[0] == 3: exctype = sys.exc_info()[0] else: exctype = sys.exc_type if exctype == UnknownXML: fault = -1 e_type, e_value = sys.exc_info()[:2] response = xmlrpclib.Fault( fault, _("While running '%s': caught\n%s : %s\n") % (method, e_type, e_value)) Traceback(method, self.req, extra="Response sent back to the caller:\n%s\n" % (response.faultString, ), severity="notification") except rhnNotFound: e = sys.exc_info()[1] return apache.HTTP_NOT_FOUND # pkilambi:catch exception if redirect except redirectException: re = sys.exc_info()[1] log_debug(3, "redirect exception caught", re.path) response = re.path except rhnFault: f = sys.exc_info()[1] response = f.getxml() except rhnSQL.SQLSchemaError: e = sys.exc_info()[1] f = None if e.errno == 20200: log_debug(2, "User Group Membership EXCEEDED") f = rhnFault(43, e.errmsg) if not f: log_error("rhnSQL.SQLSchemaError caught", e) rhnSQL.rollback() # generate the traceback report Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR response = f.getxml() except rhnSQL.SQLError: e = sys.exc_info()[1] log_error("rhnSQL.SQLError caught", e) rhnSQL.rollback() Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: e = sys.exc_info()[1] log_error("Unhandled exception", e) rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR else: # if no exception, we don't need to rollback force_rollback = 0 if force_rollback: rhnSQL.rollback() # we only want to log successful actions at this time, that's # why we do it here. Note: "func" might be None, in this case # it will cause AuditLogException below. try: auditlog_xmlrpc(func, method, params, self.req) except AuditLogException, e: # if logging didn't succeed, cancel the whole action rhnSQL.rollback() Traceback(method, self.req, extra="AuditLogging error: %s" % e) return apache.HTTP_INTERNAL_SERVER_ERROR # and now send everything back ret = self.response(response) # we only want to log successful actions at this time, that's # why we do it here auditlog_xmlrpc(func, method, params, self.req) log_debug(4, "Leave with return value", ret) return ret
def call_function(self, method, params): # short-circuit everything if sending a system-wide message. if CFG.SEND_MESSAGE_TO_ALL: # Make sure the applet doesn't see the message if method == 'applet.poll_status': return self.response({ 'checkin_interval': 3600, 'server_status': 'normal' }) if method == 'applet.poll_packages': return self.response({'use_cached_copy': 1}) # Fetch global message being sent to clients if applicable. msg = open(CFG.MESSAGE_TO_ALL).read() log_debug(3, "Sending message to all clients: %s" % msg) # Send the message as a fault. response = xmlrpclib.Fault( -1, _("IMPORTANT MESSAGE FOLLOWS:\n%s") % msg) # and now send everything back ret = self.response(response) log_debug(4, "Leave with return value", ret) return ret # req: where the response is sent to log_debug(2, method) # Now we have the reference, call away force_rollback = 1 func = None try: # now get the function reference and call it func = self.method_ref(method) response = func(*params) except (TypeError, ValueError, KeyError, IndexError, UnknownXML): # report exception back to server fault = 1 if sys.version_info[0] == 3: exctype = sys.exc_info()[0] else: exctype = sys.exc_type if exctype == UnknownXML: fault = -1 e_type, e_value = sys.exc_info()[:2] response = xmlrpclib.Fault(fault, _( "While running '%s': caught\n%s : %s\n") % ( method, e_type, e_value)) Traceback(method, self.req, extra="Response sent back to the caller:\n%s\n" % ( response.faultString,), severity="notification") except rhnNotFound: e = sys.exc_info()[1] return apache.HTTP_NOT_FOUND # pkilambi:catch exception if redirect except redirectException: re = sys.exc_info()[1] log_debug(3, "redirect exception caught", re.path) response = re.path except rhnFault: f = sys.exc_info()[1] response = f.getxml() except rhnSQL.SQLSchemaError: e = sys.exc_info()[1] f = None if e.errno == 20200: log_debug(2, "User Group Membership EXCEEDED") f = rhnFault(43, e.errmsg) if not f: log_error("rhnSQL.SQLSchemaError caught", e) rhnSQL.rollback() # generate the traceback report Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR response = f.getxml() except rhnSQL.SQLError: e = sys.exc_info()[1] log_error("rhnSQL.SQLError caught", e) rhnSQL.rollback() Traceback(method, self.req, extra="SQL Error generated: %s" % e, severity="schema") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: e = sys.exc_info()[1] log_error("Unhandled exception", e) rhnSQL.rollback() # otherwise we do a full stop Traceback(method, self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR else: # if no exception, we don't need to rollback force_rollback = 0 if force_rollback: rhnSQL.rollback() # we only want to log successful actions at this time, that's # why we do it here. Note: "func" might be None, in this case # it will cause AuditLogException below. try: auditlog_xmlrpc(func, method, params, self.req) except AuditLogException, e: # if logging didn't succeed, cancel the whole action rhnSQL.rollback() Traceback(method, self.req, extra="AuditLogging error: %s" % e) return apache.HTTP_INTERNAL_SERVER_ERROR