Beispiel #1
0
    def _utilities_attachment_zip_list_function(self, event, *args, **kwargs):
        """Function: Reads a ZIP file and produces a list of the file paths, and a list with detailed information about each file."""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"]["workflow_instance_id"]

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number
            attachment_id = kwargs.get("attachment_id")  # number

            log = logging.getLogger(__name__)
            log.info("incident_id: %s", incident_id)
            log.info("task_id: %s", task_id)
            log.info("attachment_id: %s", attachment_id)

            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
            #  yield StatusMessage("starting...")
            #  yield StatusMessage("done...")

            results = {
                "value": "xyz"
            }

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
    def _panorama_create_address_function(self, event, *args, **kwargs):
        """Function: Panorama create new address"""
        try:
            yield StatusMessage("Creating new address")
            rp = ResultPayload("fn_pa_panorama", **kwargs)

            validate_fields(["panorama_name_parameter", "panorama_request_body"], kwargs)

            # Get the function parameters:
            location = self.get_select_param(kwargs.get("panorama_location"))  # select
            vsys = kwargs.get("panorama_vsys")  # text
            name = kwargs.get("panorama_name_parameter")  # text
            body = self.get_textarea_param(kwargs.get("panorama_request_body"))  # textarea

            # Log inputs
            if location is None:
                raise ValueError("panorama_location needs to be set.")
            log.info("panorama_location: {}".format(location))
            log.info("panorama_vsys: {}".format(vsys))
            log.info("panorama_request_body: {}".format(body))
            log.info("panorama_name_parameter: {}".format(name))

            panorama_util = PanoramaClient(self.opts, location, vsys)
            response = panorama_util.add_address(name, body)

            yield StatusMessage("Address created")
            results = rp.done(True, response)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as e:
            yield FunctionError(e)
Beispiel #3
0
    def _bit9_file_instance_update_function(self, event, *args, **kwargs):
        """Function: Update the approval state of a file instance"""
        try:
            validate_fields(
                ["bit9_file_instance_id", "bit9_file_instance_localstate"],
                kwargs)
            # Get the function parameters:
            bit9_file_instance_id = kwargs.get(
                "bit9_file_instance_id")  # number
            bit9_file_instance_localstate = kwargs.get(
                "bit9_file_instance_localstate")  # number

            log.info(u"bit9_file_instance_id: %s", bit9_file_instance_id)
            log.info(u"bit9_file_instance_localstate: %s",
                     bit9_file_instance_localstate)

            payload = {"localState": bit9_file_instance_localstate}

            bit9_client = CbProtectClient(self.options)
            results = bit9_client.update_file_instance(bit9_file_instance_id,
                                                       payload)

            log.info("Done")
            log.debug(results)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as err:
            log.error(err)
            yield FunctionError(err)
    def _fn_proofpoint_trap_delete_list_member_function(
            self, event, *args, **kwargs):
        """Function: Delete the member of a list."""
        try:
            params = transform_kwargs(kwargs) if kwargs else {}

            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)

            # Get the function parameters:
            trap_list_id = kwargs.get("trap_list_id")  # number
            trap_member_id = kwargs.get("trap_member_id")  # number

            LOG.info("trap_list_id: %s", trap_list_id)
            LOG.info("trap_member_id: %s", trap_member_id)

            validate_fields(["trap_list_id", "trap_member_id"], kwargs)

            pptr = PPTRClient(self.opts, self.options)
            rtn = pptr.delete_list_member(**params)

            results = rp.done(True, rtn)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            LOG.exception(
                "Exception in Resilient Function for Proofpoint TRAP.")
            yield FunctionError()
    def _url_void_function(self, event, *args, **kwargs):
        """Function: Retrieves information of a URL from the  URL Void database."""
        try:
            yield StatusMessage("URL Void function started...")
            rp = ResultPayload("fn_url_void", **kwargs)

            # Add support for Requests Common
            req_common = RequestsCommon(self.opts, self.options)

            api_key = self.options.get("api_key")
            identifier = self.options.get("identifier", "api1000")

            # Get the function parameters:
            artifact_value = kwargs.get("artifact_value")  # text
            url_void_endpoint = self.get_select_param(kwargs.get("url_void_endpoint", "Retrieve"))  # select
            validate_fields(["artifact_value", "url_void_endpoint"], kwargs)

            log.info("artifact_value: %s", artifact_value)
            log.info("url_void_endpoint: %s", url_void_endpoint)

            response = call_url_void_api(req_common, artifact_value, identifier, api_key, url_void_endpoint)

            yield StatusMessage("URL Void function completed successfully...")
            results = rp.done(True, response)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as e:
            yield FunctionError(e)
    def _utilities_resilient_search_function(self, event, *args, **kwargs):
        """Function: Searches Resilient for incident data.
            NOTE: The results may include incidents that the current user cannot access.
            Use with caution, to avoid information disclosure."""
        try:
            # Get the function parameters:
            resilient_search_template = self.get_textarea_param(kwargs.get("resilient_search_template"))  # textarea
            resilient_search_query = kwargs.get("resilient_search_query")  # text

            log = logging.getLogger(__name__)
            log.info("resilient_search_template: %s", resilient_search_template)
            log.info("resilient_search_query: %s", resilient_search_query)

            # Read the search template as JSON
            template = json.loads(resilient_search_template)

            # Add in the search query
            template["query"] = resilient_search_query
            # Add in the current organization id (don't want results outside this org!)
            template["org_id"] = self.rest_client().org_id

            # Run the search and return the results
            yield StatusMessage("Searching...")
            results = self.rest_client().search(template)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
    def _fn_aws_iam_list_user_access_key_ids_function(self, event, *args,
                                                      **kwargs):
        """Function: Get information about the access key IDs associated with the specified IAM user.

        param aws_iam_user_name: An IAM user name.
        """
        try:
            params = transform_kwargs(kwargs) if kwargs else {}
            # Instantiate result payload object
            rp = ResultPayload(CONFIG_DATA_SECTION, **kwargs)
            # Get the function parameters:
            aws_iam_user_name = kwargs.get("aws_iam_user_name")  # text

            LOG.info("aws_iam_user_name: %s", aws_iam_user_name)

            validate_fields(["aws_iam_user_name"], kwargs)

            iam_cli = AwsIamClient(self.options)

            rtn = iam_cli.get("list_access_keys", paginate=True, **params)
            for j in range(len(rtn)):
                rtn[j]["key_last_used"] = \
                    iam_cli.get("get_access_key_last_used",
                                AccessKeyId=rtn[j]['AccessKeyId'])
            results = rp.done(True, rtn)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)

        except Exception as aws_err:
            LOG.exception(
                "ERROR with Exception '%s' in Resilient Function for AWS IAM.",
                aws_err.__repr__())
            yield FunctionError()
Beispiel #8
0
    def _panorama_get_address_groups_function(self, event, *args, **kwargs):
        """Function: Panorama get address groups returns the list of address groups """
        try:
            yield StatusMessage("Getting list of Address Groups")
            rp = ResultPayload("fn_pa_panorama", **kwargs)

            validate_fields(["panorama_name_parameter"], kwargs)

            # Get the function parameters:
            location = self.get_select_param(
                kwargs.get("panorama_location"))  # select
            vsys = kwargs.get("panorama_vsys")  # text
            name = kwargs.get(
                "panorama_name_parameter")  # text (optional parameter)

            # Log inputs
            if location is None:
                raise ValueError("panorama_location needs to be set.")
            log.info("panorama_location: {}".format(location))
            log.info("panorama_vsys: {}".format(vsys))
            log.info("panorama_name_parameter: {}".format(name))

            panorama_util = PanoramaClient(self.opts, location, vsys)
            response = panorama_util.get_address_groups(name)

            yield StatusMessage("{} groups returned.".format(
                response["result"]["@count"]))
            results = rp.done(True, response)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as e:
            yield FunctionError(e)
Beispiel #9
0
    def _qradar_advisor_map_rule_function(self, event, *args, **kwargs):
        """Function: Map rule to MITRE ATT&CK tactic"""
        try:
            # Get the function parameters:
            qradar_rule_name = kwargs.get("qradar_rule_name")  # text

            log = logging.getLogger(__name__)
            log.info("qradar_rule_name: %s", qradar_rule_name)

            qradar_verify_cert = True
            if "verify_cert" in self.options and self.options[
                    "verify_cert"] == "false":
                qradar_verify_cert = False

            yield StatusMessage("starting...")

            client = QRadarCafmClient(
                qradar_host=self.options["qradar_host"],
                cafm_token=self.options["qradar_cafm_token"],
                cafm_app_id=self.options["qradar_cafm_app_id"],
                cafile=qradar_verify_cert,
                log=log)

            tactics = client.find_tactic_mapping(qradar_rule_name)

            yield StatusMessage("done...")

            results = {"tactics": tactics}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as e:
            log.exception(str(e))
            yield FunctionError()
Beispiel #10
0
    def _cb_notify_when_host_comes_online_function(self, event, *args, **kwargs):
        """Function: Notifies the incident owner when a host comes back online."""
        results = {}
        results["was_successful"] = False
        results["hostname"] = None
        results["Online"] = False

        try:
            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            hostname = kwargs.get("hostname")  # text
            max_days = kwargs.get("max_days")  # number

            log = logging.getLogger(__name__)  # Establish logging

            try:

                days_later_timeout_length = datetime.datetime.now() + datetime.timedelta(days=max_days)  # Max duration length before aborting
                hostname = hostname.upper()[:15]  # CB limits hostname to 15 characters
                sensor = cb.select(Sensor).where('hostname:' + hostname)  # Query CB for the hostname's sensor

                if len(sensor) <= 0:  # Host does not have CB agent, abort
                    yield StatusMessage("[FATAL ERROR] CB could not find hostname: " + str(hostname))
                    yield StatusMessage('[FAILURE] Fatal error caused exit!')
                    yield FunctionResult(results)
                    return

                sensor = sensor[0]  # Get the sensor object from the query
                results["hostname"] = str(hostname).upper()

                now = datetime.datetime.now()

                # Check online status
                if sensor.status != "Online":
                    yield StatusMessage('[INFO] Hostname: ' + str(hostname) + ' is offline. Will notify when online for ' + str(max_days) + ' days...')
                while (sensor.status != "Online") and (days_later_timeout_length >= now):  # Continuously check if the sensor comes online for max_days
                    time.sleep(3)  # Give the CPU a break, it works hard!
                    now = datetime.datetime.now()
                    sensor = (cb.select(Sensor).where('hostname:' + hostname))[0]  # Retrieve the latest sensor vitals

                # Abort after max_days
                if sensor.status != "Online":
                    yield StatusMessage('[FATAL ERROR] Hostname: ' + str(hostname) + ' is still offline!')
                    yield StatusMessage('[FAILURE] Fatal error caused exit!')
                    yield FunctionResult(results)
                    return

            except Exception as err:  # Catch all other exceptions and abort
                yield StatusMessage('[FATAL ERROR] Encountered: ' + str(err))
                yield StatusMessage('[FAILURE] Fatal error caused exit!')

            else:
                yield StatusMessage('[SUCCESS] Hostname: ' + str(hostname) + ' is online!')
                results["was_successful"] = True
                results["Online"] = True

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #11
0
    def _utility_email_file_parser_function(self, event, *args, **kwargs):
        """Function: Parses .eml files for email forensics. Useful for reported phishes."""
        try:
            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            attachment_id = kwargs.get("attachment_id")  # number
            eml_filename = kwargs.get("attachment_name")  # text

            # Get the eml file attachment by its incident and attachment IDs
            eml_file = get_file_attachment(self.rest_client(), incident_id, artifact_id=None, task_id=None, attachment_id=attachment_id)

            yield StatusMessage('Reading and decoding email message (' + eml_filename + ')...')

            # Parse the email content
            mail = email.message_from_string(eml_file.decode("utf-8"))  # Get the email object from the raw contents
            email_body, attachments, urls = get_decoded_email_body(self, incident_id, eml_filename, mail)  # Get the UTF-8 encoded body from the raw email string
            email_header = get_decoded_email_header(mail.items())

            results = {}
            results['body'] = str(email_body)  # The full email, HTML formatted
            results['header'] = email_header  # List of 2-tuples containing all the message’s field headers and values
            # results['mail_items'] = mail.items()  # List of 2-tuples containing all the decoded message’s field headers and values (3/12/2019: deprecated, use 'header')
            results['attachments'] = attachments  # List of attachment names from EML file
            results['urls'] = list(set(urls))  # URLs from body. Set inside of the list used to ensures no duplicates.

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
def get_content(client, incident_id, attachment_id, artifact_id):
    entity = {
        "incident_id": incident_id,
        "id": None,
        "type": "",
        "meta_data": None,
        "data": None
    }

    if attachment_id:
        return client.get_content(
            "/incidents/{0}/attachments/{1}/contents".format(
                entity["incident_id"], attachment_id))

    elif artifact_id:
        entity["meta_data"] = client.get("/incidents/{0}/artifacts/{1}".format(
            entity["incident_id"], artifact_id))

        # handle if artifact has attachment
        if (entity["meta_data"].get("attachment")):
            return client.get_content(
                "/incidents/{0}/artifacts/{1}/contents".format(
                    entity["incident_id"], artifact_id))
        else:
            raise FunctionError("Artifact has no attachment or supported URI")

    else:
        raise ValueError('attachment_id AND artifact_id both None')
    def _utilities_excel_query_function(self, event, *args, **kwargs):
        """Function: Extracts ranges of data or named ranges specified by the user from a Microsoft Excel document.

The function uses a Python library called openpyxl (http://openpyxl.readthedocs.io/en/stable/) to interface with Excel files."""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"]["workflow_instance_id"]

            # Get the function parameters:
            task_id = kwargs.get("task_id")  # number
            excel_ranges = kwargs.get("excel_ranges")  # text
            incident_id = kwargs.get("incident_id")  # number
            excel_defined_names = kwargs.get("excel_defined_names")  # text
            attachment_id = kwargs.get("attachment_id")  # number

            log = logging.getLogger(__name__)
            log.info("task_id: %s", task_id)
            log.info("excel_ranges: %s", excel_ranges)
            log.info("incident_id: %s", incident_id)
            log.info("excel_defined_names: %s", excel_defined_names)
            log.info("attachment_id: %s", attachment_id)

            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
            #  yield StatusMessage("starting...")
            #  yield StatusMessage("done...")

            results = {
                "value": "xyz"
            }

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #14
0
    def _utilities_get_contact_info_function(self, event, *args, **kwargs):
        """Function: Retrieves contact information of the owner and members of an incident or task."""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number

            log = logging.getLogger(__name__)
            log.info("incident_id: %s", incident_id)
            log.info("task_id: %s", task_id)

            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
            #  yield StatusMessage("starting...")
            #  yield StatusMessage("done...")

            results = {"value": "xyz"}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #15
0
    def _mitre_groups_technique_intersection_function(self, event, *args,
                                                      **kwargs):
        """Function: For given Techniques return the Groups that are know to use all of them."""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            # Get the function parameters:
            mitre_technique_name = kwargs.get("mitre_technique_name")  # text
            mitre_technique_id = kwargs.get("mitre_technique_id")  # text

            log = logging.getLogger(__name__)
            log.info("mitre_technique_name: %s", mitre_technique_name)
            log.info("mitre_technique_id: %s", mitre_technique_id)

            result_payload = ResultPayload(
                "fn_mitre_integration",
                mitre_technique_name=mitre_technique_name,
                mitre_technique_id=mitre_technique_id)

            if not mitre_technique_id and not mitre_technique_name:
                raise ValueError(
                    "At least one of the inputs(mitre_technique_name or mitre_technique_id) "
                    "should be provided.")

            yield StatusMessage("Getting technique information...")

            mitre_conn = mitre_attack.MitreAttackConnection()

            techniques = mitre_attack_utils.get_multiple_techniques(
                mitre_conn,
                mitre_technique_ids=mitre_technique_id,
                mitre_technique_names=mitre_technique_name)

            intersection_query = ",".join([t.id for t in techniques])

            yield StatusMessage("Getting group intersection information...")
            groups = mitre_attack.MitreAttackGroup.get_by_technique_intersection(
                mitre_conn, techniques)

            if len(groups) == 0:
                yield StatusMessage(
                    "No groups were found using all of the given techniques. Done"
                )
            else:
                yield StatusMessage("Done. Returning results.")

            # Storing the techniques specified to query this group
            for group in groups:
                group.technique_id = intersection_query

            groups = [x.dict_form()
                      for x in groups]  # prepare the data for viewing

            results = {"mitre_groups": groups}
            # Produce a FunctionResult with the results
            yield FunctionResult(result_payload.done(True, results))
        except Exception as e:
            yield FunctionError(e)
    def _misp_sighting_list_function(self, event, *args, **kwargs):
        """Function: Return a list of sightings associated with a given event"""
        try:

            API_KEY, URL, VERIFY_CERT = common.validate(self.options)

            # Get the function parameters:
            event_id = int(kwargs.get("misp_event_id"))  # text

            log = logging.getLogger(__name__)
            log.info("event_id: %s", event_id)

            yield StatusMessage("Setting up connection to MISP")

            proxies = common.get_proxies(self.opts, self.options)

            misp_client = misp_helper.get_misp_client(URL,
                                                      API_KEY,
                                                      VERIFY_CERT,
                                                      proxies=proxies)

            yield StatusMessage("Getting sighted list")

            sighting_list_result = misp_helper.get_misp_sighting_list(
                misp_client, event_id)

            yield StatusMessage("Finished getting sighting list")

            results = {"success": True, "content": sighting_list_result}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #17
0
    def _utilities_xml_transformation_function(self, event, *args, **kwargs):
        """Function: Transforms an XML document using a preexisting `xsl` stylesheet. The resulting content is returned."""
        try:

            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            yield StatusMessage(
                "Starting 'utilities_xml_transformation' running in workflow '{0}'"
                .format(wf_instance_id))

            # Get the function parameters:
            xml_stylesheet = kwargs.get("xml_stylesheet")  # text
            xml_source = kwargs.get("xml_source")  # text

            log = logging.getLogger(__name__)
            log.info("xml_stylesheet: %s", xml_stylesheet)
            log.info("xml_source: %s", xml_source)

            ##############################################
            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE #
            ##############################################

            yield StatusMessage(
                "Finished 'utilities_xml_transformation' that was running in workflow '{0}'"
                .format(wf_instance_id))

            results = {"content": "xyz"}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #18
0
    def _fn_check_hsts_function(self, event, *args, **kwargs):
        """Function: None"""
        try:

            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            yield StatusMessage(
                "Starting 'fn_check_hsts' running in workflow '{0}'".format(
                    wf_instance_id))

            # Get the function parameters:
            domain_name = kwargs.get("domain_name")  # text

            log = logging.getLogger(__name__)
            log.info("domain_name: %s", domain_name)

            result = self.has_hsts(domain_name)

            results = {"has_hsts": result}

            yield StatusMessage(
                "Finished 'fn_check_hsts' that was running in workflow '{0}'".
                format(wf_instance_id))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #19
0
        def get_input_entity(client, incident_id, attachment_id, artifact_id):
          
          re_uri_match_pattern = r"""(?:(?:https?|ftp):\/\/|\b(?:[a-z\d]+\.))(?:(?:[^\s()<>]+|\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))?\))+(?:\((?:[^\s()<>]+|(?:\(?:[^\s()<>]+\)))?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))?"""
          entity = {"incident_id": incident_id, "id": None, "type": "", "meta_data": None, "data": None}

          if (attachment_id):
            entity["id"] = attachment_id
            entity["type"] = "attachment"
            entity["meta_data"] = client.get("/incidents/{0}/attachments/{1}".format(entity["incident_id"], entity["id"]))
            entity["data"] = client.get_content("/incidents/{0}/attachments/{1}/contents".format(entity["incident_id"], entity["id"]))
          
          elif (artifact_id):
            entity["id"] = artifact_id
            entity["type"] = "artifact"
            entity["meta_data"] = client.get("/incidents/{0}/artifacts/{1}".format(entity["incident_id"], entity["id"]))

            # handle if artifact has attachment
            if (entity["meta_data"]["attachment"]):
              entity["data"] = client.get_content("/incidents/{0}/artifacts/{1}/contents".format(entity["incident_id"], entity["id"]))

            # else handle if artifact.value contains an URI using RegEx
            else:
              match = re.match(re_uri_match_pattern, entity["meta_data"]["value"])

              if (match):
                entity["uri"] = match.group()
            
              else:
                raise FunctionError("Artifact has no attachment or supported URI")
          
          else:
            raise ValueError('attachment_id AND artifact_id both None')

          return entity
Beispiel #20
0
    def _greynoise_ip_query_function(self, event, *args, **kwargs):
        """Function: Perform IP Address analysis"""
        try:
            # Get the function parameters:
            greynoise_value = kwargs.get("greynoise_value")  # text
            greynoise_type = self.get_select_param(
                kwargs.get("greynoise_type"))  # select

            log = logging.getLogger(__name__)
            log.info("greynoise_value: %s", greynoise_value)
            log.info("greynoise_type: %s", greynoise_type)

            # validate input
            validate_fields(("greynoise_type", "greynoise_value"), kwargs)
            validate_fields(("api_key"), self.options)

            yield StatusMessage("starting...")

            # build result
            result_payload = ResultPayload(SECTION_HEADER, **kwargs)

            greynoise_result = call_greynoise(self.opts, self.options,
                                              greynoise_type, greynoise_value)

            results = result_payload.done(True, greynoise_result)

            yield StatusMessage("done...")

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
    def _a_mock_function_with_no_unicode_characters_in_name_function(
            self, event, *args, **kwargs):
        """Function: A mock description of 'A Mock Function with No Unicode Characters in Name' with unicode:  ล ฦ ว ศ ษ ส ห ฬ อ"""
        try:

            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            yield StatusMessage(
                "Starting 'a_mock_function_with_no_unicode_characters_in_name' running in workflow '{0}'"
                .format(wf_instance_id))

            # Get the function parameters:
            mock_input_text = kwargs.get("mock_input_text")  # text

            log = logging.getLogger(__name__)
            log.info("mock_input_text: %s", mock_input_text)

            ##############################################
            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE #
            ##############################################

            yield StatusMessage(
                "Finished 'a_mock_function_with_no_unicode_characters_in_name' that was running in workflow '{0}'"
                .format(wf_instance_id))

            results = {"content": "xyz"}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #22
0
    def _funct_zia_get_url_categories_function(self, event, *args, **kwargs):
        """Function: None"""
        try:
            rp = ResultPayload(PACKAGE_NAME, **kwargs)

            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            yield StatusMessage(
                "Starting '{0}' running in workflow '{1}'".format(
                    FN_NAME, wf_instance_id))

            # Get and validate required function inputs:
            fn_inputs = validate_fields([], kwargs)

            LOG.info("'{0}' inputs: %s", fn_inputs)

            if fn_inputs.get("zia_category_id") and fn_inputs.get(
                    "zia_custom_only").lower() == "false":
                raise ValueError(
                    "If parameter '{0}' is set then parameter '{1}' should be set to '{2}'."
                    .format("zia_category_id", "zia_custom_only", "true"))

            # Test any enabled filters to ensure they are valid regular expressions.
            for f in ["zia_name_filter", "zia_url_filter"]:
                patt = fn_inputs.get(f)
                if patt and not is_regex(patt):
                    raise ValueError(
                        "The query filter '{}' does not have a valid regular expression."
                        .format(repr(f)))

            # Remove 'zia_' prefix from function parameters.
            fn_inputs = dict(
                (k.split('_', 1)[1], v) for k, v in fn_inputs.items())

            yield StatusMessage(
                "Validations complete. Starting business logic")

            ziacli = ZiaClient(self.opts, self.fn_options)
            result = ziacli.get_url_categories(**fn_inputs)

            yield StatusMessage(
                "Finished '{0}' that was running in workflow '{1}'".format(
                    FN_NAME, wf_instance_id))

            results = rp.done(True, result)

            LOG.info("'%s' complete", FN_NAME)

            yield StatusMessage(
                "Returning results for function '{}' with parameters '{}'.".
                format(
                    FN_NAME, ", ".join("{!s}={!r}".format(k, v)
                                       for (k, v) in fn_inputs.items())))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception as e:
            yield FunctionError(e)
    def _utilities_attachment_zip_extract_function(self, event, *args,
                                                   **kwargs):
        """Function: Extracts a file from a ZIP file attachment, producing a base64 string.

That string can then be used as input to subsequent functions that might write it as a file attachment, as a malware sample artifact, or in other ways."""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number
            attachment_id = kwargs.get("attachment_id")  # number
            file_path = kwargs.get("file_path")  # text
            zipfile_password = kwargs.get("zipfile_password")  # text

            log = logging.getLogger(__name__)
            log.info("incident_id: %s", incident_id)
            log.info("task_id: %s", task_id)
            log.info("attachment_id: %s", attachment_id)
            log.info("file_path: %s", file_path)
            log.info("zipfile_password: %s", zipfile_password)

            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
            #  yield StatusMessage("starting...")
            #  yield StatusMessage("done...")

            results = {"value": "xyz"}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #24
0
    def _base64_to_attachment_function(self, event, *args, **kwargs):
        """Function: """
        try:
            log = logging.getLogger(__name__)

            # Get the function parameters:
            # artifact_file_type:
            # "Email Attachment", "Malware Sample", "Log File", "X509 Certificate File", "Other File", etc.
            base64content = kwargs.get("base64content")  # text
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number
            file_name = kwargs.get("file_name")  # text
            content_type = kwargs.get("content_type")  # text

            content_type = content_type \
                           or mimetypes.guess_type(file_name or "")[0] \
                           or "application/octet-stream"

            log.info("incident_id: %s", incident_id)
            log.info("task_id: %s", task_id)
            log.info("file_name: %s", file_name)
            log.info("content_type: %s", content_type)


            yield StatusMessage("Writing attachment...")

            datastream = BytesIO(base64.b64decode(base64content))
            client = self.rest_client()
            new_attachment  = write_file_attachment(client, file_name, datastream, incident_id, task_id, content_type)


            log.info(json.dumps(new_attachment))
            yield FunctionResult(new_attachment)
        except Exception:
            yield FunctionError()
Beispiel #25
0
    def _utilities_resilient_search_function(self, event, *args, **kwargs):
        """Function: This function searches the Resilient platform for incident data according to the criteria specified, and returns the results to your workflow. It can be used to find incidents containing data that matches any string, or incidents currently assigned to a given user, or a very wide range of other search conditions.

**NOTE:** The search results may include data from incidents that the current Resilient user (the person who triggered the workflow) cannot access. Often your Resilient users have the `Default` role that allows them to only see incidents where they are members. This function runs with the permissions of your integration account, which typically may have much wider access privileges. **Use with caution, to avoid information disclosure.**"""
        try:
            # Get the wf_instance_id of the workflow this Function was called in
            wf_instance_id = event.message["workflow_instance"][
                "workflow_instance_id"]

            # Get the function parameters:
            resilient_search_template = self.get_textarea_param(
                kwargs.get("resilient_search_template"))  # textarea
            resilient_search_query = kwargs.get(
                "resilient_search_query")  # text

            log = logging.getLogger(__name__)
            log.info("resilient_search_template: %s",
                     resilient_search_template)
            log.info("resilient_search_query: %s", resilient_search_query)

            # PUT YOUR FUNCTION IMPLEMENTATION CODE HERE
            #  yield StatusMessage("starting...")
            #  yield StatusMessage("done...")

            results = {"value": "xyz"}

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #26
0
    def _mcafee_epo_find_a_system_function(self, event, *args, **kwargs):
        """Function: Find an ePO system based on property such as system name, tag, IP address, MAC address, etc."""
        try:
            # Get the function parameters:
            validate_fields(["mcafee_epo_systems"], kwargs)
            mcafee_epo_systems = kwargs.get("mcafee_epo_systems")  # text
            client = init_client(self.opts, self.options)

            log = logging.getLogger(__name__)
            log.info("mcafee_epo_systems: %s", mcafee_epo_systems)

            yield StatusMessage("Starting")

            rc = ResultPayload(PACKAGE_NAME, **kwargs)

            params = {"searchText": mcafee_epo_systems.strip()}
            response = client.request("system.find", params)

            yield StatusMessage("Finished")

            results = rc.done(True, response)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
    def _fn_amp_get_event_types_function(self, event, *args, **kwargs):
        """Function: Events are identified and filtered by a unique ID. Provides a human readable name, and short
        description of each event by ID."""
        try:
            # Get the function parameters:

            log = logging.getLogger(__name__)

            amp = Ampclient(self.options, RATE_LIMITER)

            yield StatusMessage("Running Cisco AMP get computers query...")

            rtn = amp.get_event_types()
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            # Add in "query_execution_time" and "ip_address" to result to facilitate post-processing.
            results = {
                "response": rtn,
                "query_execution_time": query_execution_time
            }
            yield StatusMessage("Returning 'event types' results")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception(
                "Exception in Resilient Function for Cisco AMP for endpoints.")
            yield FunctionError()
Beispiel #28
0
    def _fn_get_contact_info_function(self, event, *args, **kwargs):
        """Function: Retrieve contact information for an incidents owner and members or those from a task"""
        try:
            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            task_id = kwargs.get("task_id")  # number

            log = logging.getLogger(__name__)
            log.info("incident_id: %s", incident_id)
            log.info("task_id: %s", task_id)

            if incident_id is None:
                raise ValueError("incident_id is required")

            yield StatusMessage("starting...")
            res_client = self.rest_client()
            if incident_id and task_id is None:
                results = self.get_contact_info_by_incident(
                    res_client, incident_id)
            else:
                results = self.get_contact_info_by_task(
                    res_client, incident_id, task_id)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Beispiel #29
0
    def _fn_bigfix_assets_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Bigfix assets - Get properties in BigFix for an endpoint."""
        try:
            # Get the function parameters:
            bigfix_asset_name = kwargs.get("bigfix_asset_name")  # text
            bigfix_asset_id = kwargs.get("bigfix_asset_id")  # number
            bigfix_incident_id = kwargs.get("bigfix_incident_id")  # number

            log = logging.getLogger(__name__)
            log.info("bigfix_asset_name: %s", bigfix_asset_name)
            log.info("bigfix_asset_id: %s", bigfix_asset_id)
            log.info("bigfix_incident_id: %s", bigfix_incident_id)

            params = {
                "asset_name": bigfix_asset_name,
                "asset_id": bigfix_asset_id,
                "incident_id": bigfix_incident_id
            }

            validate_params(params, "fn_bigfix_assets")

            yield StatusMessage(
                u"Running BigFix Query for Endpoint id {0}, with name {1} ...".
                format(params["asset_id"], params["asset_name"]))
            bigfix_client = BigFixClient(self.options)

            try:
                # Perform the BigFix Query
                response = bigfix_client.get_bf_computer_properties(
                    params["asset_id"])
            except Exception as e:
                log.exception("Failed to query a BigFix asset.")
                yield StatusMessage(
                    "Failed with exception '{}' while trying to query a BigFix asset"
                    .format(type(e).__name__))
                raise Exception(
                    "Failed with exception '{}' while trying to query a BigFix asset"
                    .format(type(e).__name__))

            if not response:
                yield StatusMessage(
                    "No properties retrieved for the asset id '{}'".format(
                        params["asset_id"]))
                results = {}
            else:
                # Create a Resilient attachment
                file_name = "bigfix-properties-" + params["asset_name"] + "-" + \
                            datetime.datetime.today().strftime('%Y%m%d') + ".xml"
                att_report = create_attachment(self.rest_client(), file_name,
                                               response, params)
                results = {"status": "OK", "att_name": att_report["name"]}

            yield StatusMessage("done...")

            log.debug(results)

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
    def _qradar_find_reference_set_item_function(self, event, *args, **kwargs):
        """Function: Find an item from a given QRadar reference set"""
        try:
            # Get the function parameters:
            qradar_reference_set_name = kwargs.get("qradar_reference_set_name")  # text
            qradar_reference_set_item_value = kwargs.get("qradar_reference_set_item_value")  # text

            log = logging.getLogger(__name__)
            log.info("qradar_reference_set_name: %s", qradar_reference_set_name)
            log.info("qradar_reference_set_item_value: %s", qradar_reference_set_item_value)

            qradar_verify_cert = True
            if "verify_cert" in self.options and self.options["verify_cert"] == "false":
                qradar_verify_cert = False

            log.debug("Connection to {} using {}".format(self.options["host"], self.options["username"]))

            yield StatusMessage("starting...")

            qradar_client = QRadarClient(host=self.options["host"],
                                         username=self.options["username"],
                                         password=self.options["qradarpassword"],
                                         token=None,
                                         cafile=qradar_verify_cert)

            result = qradar_client.search_ref_set(qradar_reference_set_name,
                                                  qradar_reference_set_item_value)

            yield StatusMessage("done...")
            # Produce a FunctionResult with the results
            yield FunctionResult(result)
        except Exception as e:
            log.error(str(e))
            yield FunctionError()