def test_sighting_tree(self):
        """
        This is a sub tree of a sample stix from QRadar Advisor
        :return:
        """
        stix_sample = {}

        with open(sys.path[0] + "/sample1.stix", "r") as infile:
            stix_sample = json.load(infile)

        dict_copy = copy.deepcopy(stix_sample)

        tree = stix_tree.build_tree(stix_objects=dict_copy["objects"],
                                    log=logging)

        dict_copy2 = copy.deepcopy(stix_sample)
        ret = verify_tree(stix_objects=dict_copy2["objects"], trees=tree)
        #
        # verify that there is no error message
        #
        assert ret == ""

        html = stix_tree.get_html(stix_sample, logging)

        with open(sys.path[0] + "/sample1.html", "w") as outfile:
            outfile.write(html)

        print("Done")
    def do_command(self):
        stix_filename = self.opts_dict["input"]
        html_filename = self.opts_dict["output"]

        with open(stix_filename, "r") as infile:
            stix_json = None
            content_str = infile.read()
            try:
                stix_json = json.loads(content_str)
            except Exception as e:
                # single quote?
                stix_json = ast.literal_eval(content_str)
            html_string = stix_tree.get_html(stix_json, logging)

            with open(html_filename, "w") as outfile:
                outfile.write(html_string)
    def test_relation_tree(self):
        with open(sys.path[0] + "/relation_sample.stix", "r") as infile:
            stix_sample = json.load(infile)

        dict_copy = copy.deepcopy(stix_sample)

        tree = stix_tree.build_tree(stix_objects=dict_copy["objects"],
                                    log=logging)

        dict_copy2 = copy.deepcopy(stix_sample)
        ret = verify_tree(stix_objects=dict_copy2["objects"], trees=tree)
        #
        # verify that there is no error message
        #
        assert ret == ""

        html = stix_tree.get_html(stix_sample, logging)

        with open(sys.path[0] + "/relation_sample.html", "w") as outfile:
            outfile.write(html)
    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)