def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging) resp = client.offense_insights(self.opts_dict["offense"]) print("Status: {}\n Content: {}".format(str(resp), resp.content))
def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging) resp = client.quick_search(self.opts_dict["search"]) print(str(resp))
def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging, opts={}, function_opts=self.opts_dict) client.get_csrf_token() print("The XSRF_TOKEN is {}".format(client.http_info.xsrf_token))
def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging, opts={}, function_opts=self.opts_dict) resp = client.offense_insights(self.opts_dict["offense"]) print("Return: {}".format(str(resp)))
def test_full_search_by_id(self, mocked_get_search_result, mocked_get_session, mocked_update_session): # # First verify that if there is no CSRF token, the full_search # function will call get_csrf_token to get one # mocked_cookies = Mock() # Use this to mock the member variables mocked_session = Mock(cookies=mocked_cookies) mocked_get_session.return_value = mocked_session client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=QRADAR_VERIFY, log=logging) # # when a QRadarAdvisorClient is instantiated, its http_info shall # has no csrf token # assert not client.http_info.xsrf_token try: mocked_session.get.return_value = _generate_response({}, 400) client.full_search_by_id(123456) assert False except CsrfTokenError: # # because the CSRF token is None, full_search has to call get_csrf_token # to get it. Since we returned 400 above, the full_search call # shall throw this exception # assert True # # Now put a CSRF token # client.http_info.xsrf_token = CSRF_TOKEN ret_cookies = {"XSRF-TOKEN": CSRF_TOKEN} mocked_cookies.get_dict.return_value = ret_cookies # # This time full_search will call the full search endpoint # stix_json = {"type": "bundles"} mocked_get_search_result.return_value = stix_json search_id = 1234 ret = client.full_search_by_id(search_id) mocked_get_search_result.assert_called_with(search_id) assert ret == stix_json
def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging) offense_id = self.opts_dict["offense_id"] restart_if_existed = self.opts_dict.get("restart_if_exist", "False") == "True" stix_json = client.offense_analysis( offense_id=offense_id, restart_if_existed=restart_if_existed) print(json.dumps(stix_json))
def test_set_methods(self): stage = "stage1" timeout = 3600 period = 10 client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=False, log=logging) client.set_full_search_stage(stage) assert client.full_search_stage == stage client.set_full_search_timeout(timeout) assert client.full_search_timeout == timeout client.set_full_search_period(period) assert client.full_search_period == period
def _qradar_advisor_quick_search_function(self, event, *args, **kwargs): """Function: Perform a QRadar Advisor quick search for an indicator. The indicator is given as qradar_advisor_search_value in the input. The QRadar Advisor reply is in json format. This function forwards the QRadar Advisor reply to Resilient server, so that user can process it in post-process script. """ try: # Get the function parameters: qradar_advisor_search_value = kwargs.get( "qradar_advisor_search_value") # text log = logging.getLogger(__name__) log.info("qradar_advisor_search_value: %s", qradar_advisor_search_value) qradar_verify_cert = True if "verify_cert" in self.options and self.options[ "verify_cert"] == "false": qradar_verify_cert = False yield StatusMessage("starting...") client = QRadarAdvisorClient( qradar_host=self.options["qradar_host"], qradar_token=self.options["qradar_advisor_token"], advisor_app_id=self.options["qradar_advisor_app_id"], cafile=qradar_verify_cert, log=log, opts=self.opts, function_opts=self.options) ret_json = client.quick_search(qradar_advisor_search_value) yield StatusMessage("done...") log.debug("Return json is:{}".format(json.dumps(ret_json))) results = ret_json # Produce a FunctionResult with the results yield FunctionResult(results) except Exception as e: log.error(str(e)) yield FunctionError(str(e))
def test_get_csrf_token(self, mocked_get_session, mocked_update_session): mocked_cookies = Mock() # Use this to mock the member variables mocked_session = Mock(cookies=mocked_cookies) mocked_get_session.return_value = mocked_session client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=QRADAR_VERIFY, log=logging) mocked_session.get.return_value = _generate_response({}, 200) ret_cookies = {"XSRF-TOKEN": CSRF_TOKEN} mocked_cookies.get_dict.return_value = ret_cookies client.get_csrf_token() # # Assert that QRadarAdvisorClient is calling the /about endpoint to get CSRF token # url = QRADAR_API_BASE_URL + "/about" mocked_session.get.assert_called_with(url=url, verify=QRADAR_VERIFY) # # Assert that QRadarAdvisorClient is using the cookies (ret_cookies here) # returned from the mocked session to update the HttpInfo. # mocked_update_session.assert_called_with(ret_cookies) # # Verify error handling. Simulate that the /about endpoint returns 400 # mocked_session.get.return_value = _generate_response({}, 400) try: client.get_csrf_token() assert False except CsrfTokenError: assert True
def do_command(self): client = QRadarAdvisorClient(qradar_host=self.system_host, qradar_token=self.system_token, advisor_app_id=self.opts_dict["app_id"], cafile=False, log=logging) search_value = self.opts_dict["search"] try: search_id = int(search_value) # # It is a serach id. # For example: -i 1102 -s 2 # resp = client.full_search_by_id(search_id) except ValueError as e: # # It is not a search_id. Try the full search from start # For example: -i 1102 -s user:jsmith # resp = client.full_search(self.opts_dict["search"]) print(str(resp))
def selftest_function(opts): """ Placeholder for selftest function. An example use would be to test package api connectivity. Suggested return values are be unimplemented, success, or failure. """ qradar_verify_cert = True options = opts.get("fn_qradar_advisor", {}) if "verify_cert" in options and options["verify_cert"] == "false": qradar_verify_cert = False try: qraw_client = QRadarAdvisorClient(qradar_host=options["qradar_host"], qradar_token=options["qradar_advisor_token"], advisor_app_id=options["qradar_advisor_app_id"], cafile=qradar_verify_cert, log=log, opts=opts, function_opts=options) r = qraw_client.test_connectivity() if r.status_code == 200: return {"state": "success", "status_code": r.status_code} else: return {"state": "failure", "status_code": r.status_code} except Exception as e: return {"state": "failure", "status_code": str(e)}
def test_offense_analysis(self, mocked_get_search_result, mocked_perform_search, mocked_get_session): # # First verify that if there is no CSRF token, the full_search # function will call get_csrf_token to get one # mocked_cookies = Mock() # Use this to mock the member variables mocked_session = Mock(cookies=mocked_cookies) mocked_get_session.return_value = mocked_session client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=QRADAR_VERIFY, log=logging) # # when a QRadarAdvisorClient is instantiated, its http_info shall # has no csrf token # assert not client.http_info.xsrf_token try: mocked_session.get.return_value = _generate_response({}, 400) client.offense_analysis(123456) assert False except CsrfTokenError: # # because the CSRF token is None, full_search has to call get_csrf_token # to get it. Since we returned 400 above, the full_search call # shall throw this exception # assert True # # Now put a CSRF token # client.http_info.xsrf_token = CSRF_TOKEN ret_cookies = {"XSRF-TOKEN": CSRF_TOKEN} mocked_cookies.get_dict.return_value = ret_cookies # # This time offense_analysis shall call the QRadarOffenseAnalysis # stix_json = {"type": "bundles"} mocked_get_search_result.return_value = stix_json mocked_perform_search.return_value = stix_json offense_id = 12345 ret = client.offense_analysis(offense_id, restart_if_existed=False) assert ret == stix_json # because we set restart_if_existed=False, verify we call get_search_result # directly mocked_get_search_result.assert_called_with(offense_id) ret = client.offense_analysis(offense_id, restart_if_existed=True) assert ret == stix_json # because we set restart_if_existed=True, verify we call perform_search # to start a new analysis mocked_perform_search.assert_called_with(offense_id)
def test_offense_insights(self, mocked_get_session, mocked_update_session): # # First verify that if there is no CSRF token, the full_search # function will call get_csrf_token to get one # mocked_cookies = Mock() # Use this to mock the member variables mocked_session = Mock(cookies=mocked_cookies) mocked_get_session.return_value = mocked_session client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=QRADAR_VERIFY, log=logging) # # when a QRadarAdvisorClient is instantiated, its http_info shall # has no csrf token # assert not client.http_info.xsrf_token try: mocked_session.get.return_value = _generate_response({}, 400) client.offense_insights(12345678) assert False except CsrfTokenError: # # because the CSRF token is None, full_search has to call get_csrf_token # to get it. Since we returned 400 above, the full_search call # shall throw this exception # assert True # # Now put a CSRF token # client.http_info.xsrf_token = CSRF_TOKEN ret_cookies = {"XSRF-TOKEN": CSRF_TOKEN} mocked_cookies.get_dict.return_value = ret_cookies offense_id = 12345 url = QRADAR_API_BASE_URL + "/offense/" + str(offense_id) + "/insights" ret_json = {"insights": "Sample insights from Watson"} mocked_session.get.return_value = _generate_response(ret_json, 200) ret = client.offense_insights(offense_id) assert ret == ret_json # # Now test non 200 status_code # try: mocked_session.get.return_value = _generate_response(ret_json, 403) client.offense_insights(offense_id) assert False except OffenseInsightsError: assert True # # Test exception # try: mocked_session.get.side_effect = Exception("Some error exception") client.offense_insights(offense_id) assert False except OffenseInsightsError: assert True
def test_quick_search(self, mocked_get_session, mocked_update_session): # # First verify that if there is no CSRF token, the full_search # function will call get_csrf_token to get one # mocked_cookies = Mock() # Use this to mock the member variables mocked_session = Mock(cookies=mocked_cookies) mocked_get_session.return_value = mocked_session client = QRadarAdvisorClient(qradar_host=QRADAR_HOST, advisor_app_id=QRADAR_APP_ID, qradar_token=QRADAR_TOKEN, cafile=QRADAR_VERIFY, log=logging) # # when a QRadarAdvisorClient is instantiated, its http_info shall # has no csrf token # assert not client.http_info.xsrf_token try: mocked_session.get.return_value = _generate_response({}, 400) client.quick_search("Not matter here") assert False except CsrfTokenError: # # because the CSRF token is None, full_search has to call get_csrf_token # to get it. Since we returned 400 above, the full_search call # shall throw this exception # assert True # # Now put a CSRF token # client.http_info.xsrf_token = CSRF_TOKEN ret_cookies = {"XSRF-TOKEN": CSRF_TOKEN} mocked_cookies.get_dict.return_value = ret_cookies url = QRADAR_API_BASE_URL + "/search/quick" search_value = "user:jsmith" search_dict = {"indicator": search_value} dict_str = json.dumps(search_dict) quick_search_result = { "suspicious_observables": [], "other_observables": [] } mocked_session.post.return_value = _generate_response( quick_search_result, 200) ret = client.quick_search(search_value) assert ret == quick_search_result mocked_session.post.assert_called_with(url=url, data=dict_str, verify=QRADAR_VERIFY) # # Verify status_code other than 200 shall result in exception # mocked_session.post.return_value = _generate_response( quick_search_result, 422) try: client.quick_search(search_value) assert False except QuickSearchError: assert True # # Verify exception of post call # mocked_session.post.side_effect = Exception("Some error exception") try: client.quick_search(search_value) assert False except QuickSearchError: assert True
def _qradar_advisor_offense_analysis_function(self, event, *args, **kwargs): """Function: This function performs two tasks: 1. call the QRadar Advisor REST API to retrieve insights for a given QRadar offense 2. call the QRadar Advisor REST API to perform analysis on the QRadar offense The input is qradar_offense_id in the input. The reply from QRadar Advisor analysis is in stix format. This function then 1. extract the observables from the stix objects 2. generate a html representation for the stix The return to Resilient server includes the above two, together with the raw replies for offense insights and offense analysis.""" try: # Get the function parameters: qradar_offense_id = kwargs.get("qradar_offense_id") # text qradar_advisor_result_stage = self.get_select_param(kwargs.get("qradar_advisor_result_stage")) # select, values: "stage1", "stage2", "stage3" qradar_analysis_restart_if_existed = kwargs.get("qradar_analysis_restart_if_existed") # boolean log = logging.getLogger(__name__) log.info("qradar_offense_id: %s", qradar_offense_id) log.info("qradar_advisor_result_stage: %s", qradar_advisor_result_stage) log.info("qradar_analysis_restart_if_existed: %s", qradar_analysis_restart_if_existed) qradar_verify_cert = True if "verify_cert" in self.options and self.options["verify_cert"] == "false": qradar_verify_cert = False yield StatusMessage("starting...") if qradar_analysis_restart_if_existed: # User wants restart a new analysis. Warn him/her it could take some time yield StatusMessage("Restarting a new analysis. It could take up to 15 minutes...") offense_analysis_timeout = int(self.options.get("offense_analysis_timeout", 1200)) offense_analysis_period = int(self.options.get("offense_analysis_period", 5)) log.debug("Using timeout: {}".format(str(offense_analysis_timeout))) log.debug("Using period: {}".format(str(offense_analysis_period))) client = QRadarAdvisorClient(qradar_host=self.options["qradar_host"], qradar_token=self.options["qradar_advisor_token"], advisor_app_id=self.options["qradar_advisor_app_id"], cafile=qradar_verify_cert, log=log) stix_json = client.offense_analysis(offense_id=qradar_offense_id, restart_if_existed=qradar_analysis_restart_if_existed, return_stage=qradar_advisor_result_stage, timeout=offense_analysis_timeout, period=offense_analysis_period) # # extract list of observables from this stix bundle # observables = stix_utils.get_observables(stix_json=stix_json, log=log) # # generate a folder-tree like structure in html for this stix bundle # html_str = stix_tree.get_html(stix_json, log) # # get the insights for this offense # insights = client.offense_insights(offense_id=qradar_offense_id) yield StatusMessage("done...") yield StatusMessage("Returning {} observables".format(str(len(observables)))) results = { "observables": observables, "note": html_str, "insights": insights, # Return the raw insights dict "stix": stix_json # Return the raw stix2 dict } # Produce a FunctionResult with the results yield FunctionResult(results) except Exception as e: log.error(str(e)) yield FunctionError(str(e))
def _qradar_advisor_full_search_function(self, event, *args, **kwargs): """Function: Perform a QRadar Advisor full search on an indicator. The indicator is given as the qradar_advisor_search_value of the input. Another input is qradar_advisor_result_stage. This can be "stage1", "stage2", or "stage3". The return from QRadar Advisor is a report in stix format. Then this function calls util funtions from lib to 1. extract observables from objects 2. generate a html representation of the stix objects 3. generate a summary All of the above 3 will be returned to Resilient server, together with the raw stix """ try: # Get the function parameters: qradar_advisor_search_value = kwargs.get( "qradar_advisor_search_value") # text qradar_advisor_result_stage = self.get_select_param( kwargs.get("qradar_advisor_result_stage") ) # select, values: "stage1", "stage2", "stage3" log = logging.getLogger(__name__) log.info("qradar_advisor_search_value: %s", qradar_advisor_search_value) log.info("qradar_advisor_result_stage: %s", qradar_advisor_result_stage) qradar_verify_cert = True if "verify_cert" in self.options and self.options[ "verify_cert"] == "false": qradar_verify_cert = False yield StatusMessage("starting...") # Warn the user yield StatusMessage( "Watson Search with Local Context could take up to 15 minutes..." ) stix_json = None client = QRadarAdvisorClient( qradar_host=self.options["qradar_host"], qradar_token=self.options["qradar_advisor_token"], advisor_app_id=self.options["qradar_advisor_app_id"], cafile=qradar_verify_cert, log=log) full_search_timeout = self.options.get("full_search_timeout", 1200) full_search_period = self.options.get("full_search_period", 5) log.debug("Using timeout: {}".format(str(full_search_timeout))) log.debug("Using period: {}".format(str(full_search_period))) client.full_search_timeout = int(full_search_timeout) client.full_search_period = int(full_search_period) client.set_full_search_stage(qradar_advisor_result_stage) stix_json = client.full_search(qradar_advisor_search_value) # # extract list of observables from this stix bundle # observables = stix_utils.get_observables(stix_json=stix_json, log=log) # # generate a folder-tree like structure in html for this stix bundle # html_str = stix_tree.get_html(stix_json, log) yield StatusMessage("Returning {} observables".format( str(len(observables)))) # # no insights # summary = "Watson Search with Local Context of indicator {} returns {} observables.".format( qradar_advisor_search_value, str(len(observables))) if len(observables) == 1: summary = "Watson Search with Local Context of indicator {} returns {} observable.".format( qradar_advisor_search_value, str(len(observables))) results = { "observables": observables, "note": html_str, "summary": summary, "stix": stix_json } # Produce a FunctionResult with the results yield FunctionResult(results) except Exception as e: log.error(e.message) yield FunctionError(e.message)