Пример #1
0
    def _umbrella_pattern_search_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Pattern Search."""
        try:
            # Get the function parameters:
            umbinv_regex = kwargs.get("umbinv_regex")  # text
            umbinv_start_epoch = kwargs.get("umbinv_start_epoch")  # datetimepicker
            umbinv_start_relative = kwargs.get("umbinv_start_relative")  # text
            umbinv_limit = kwargs.get("umbinv_limit")  # number
            umbinv_include_category = kwargs.get("umbinv_include_category")  # boolean

            log = logging.getLogger(__name__)
            log.info("umbinv_regex: %s", umbinv_regex)
            log.info("umbinv_start_epoch: %s", umbinv_start_epoch)
            log.info("umbinv_start_relative: %s", umbinv_start_relative)
            log.info("umbinv_limit: %s", umbinv_limit)
            log.info("umbinv_include_category: %s", umbinv_include_category)

            if is_none(umbinv_regex):
                raise ValueError("Required parameter 'regex' not set")

            yield StatusMessage("Starting...")
            regex = None
            process_result = {}
            params = {"regex": umbinv_regex.strip(), "start_epoch": umbinv_start_epoch,
                            "start_relative": umbinv_start_relative,
                            "limit": umbinv_limit, "include_category": umbinv_include_category}

            validate_params(params)
            process_params(params, process_result)

            if "_regex" not in process_result:
               raise ValueError("Parameter 'umbinv_regex' was not processed correctly")
            else:
                regex = process_result.pop("_regex")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.search(regex, **omit_params(params, ["regex"]))
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if len(rtn["matches"]) == 0:
                log.debug(json.dumps(rtn))
                yield StatusMessage("No Results returned for regular expression '{}'.".format(regex))
                results = {}
            else:
                # Add "query_execution_time" to result to facilitate post-processing.
                results = {"search_matches": json.loads(json.dumps(rtn)), "query_execution_time": query_execution_time}
                yield StatusMessage("Returning 'search_matches' results for regex '{}'.".format(regex))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_ip_latest_malicious_domains_function(self, event, *args,
                                                       **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Latest Malicious Domains for an IP."""
        try:
            # Get the function parameters:
            umbinv_ipaddr = kwargs.get("umbinv_ipaddr")  # text

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

            if is_none(umbinv_ipaddr):
                raise ValueError("Required parameter 'umbinv_ipaddr' not set")

            yield StatusMessage("Starting...")
            ipaddr = None
            process_result = {}
            params = {"ipaddr": umbinv_ipaddr.strip()}

            validate_params(params)
            process_params(params, process_result)

            if "_ipaddr" not in process_result:
                raise ValueError(
                    "Parameter 'ipaddr' was not processed correctly")
            else:
                ipaddr = process_result.pop("_ipaddr")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.latest_domains(ipaddr)
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if len(rtn) == 0:
                log.debug(json.dumps(rtn))
                yield StatusMessage(
                    "No Results returned for ip address '{}'.".format(ipaddr))
                results = {}
            else:
                # Add  "query_execution_time" and "ip_address" to result to facilitate post-processing.
                results = {
                    "latest_malicious_domains": json.loads(json.dumps(rtn)),
                    "ip_address": ipaddr,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'latest_malicious_domains' results for ip address '{}'."
                    .format(ipaddr))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
Пример #3
0
    def _umbrella_domain_related_domains_function(self, event, *args,
                                                  **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for lrelated domains for a Domain."""
        try:
            # Get the function parameters:
            umbinv_domain = kwargs.get("umbinv_domain")  # text

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

            if is_none(umbinv_domain):
                raise ValueError("Required parameter 'umbinv_domain' not set")

            yield StatusMessage("Starting...")
            domain = None
            process_result = {}
            params = {"domain": umbinv_domain.strip()}

            validate_params(params)
            process_params(params, process_result)

            if "_domain" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_domain' was not processed correctly")
            else:
                domain = process_result.pop("_domain")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.related(domain)
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if rtn["found"] is None or str(rtn["found"]).lower() == 'false':
                log.debug(json.dumps(rtn))
                yield StatusMessage(
                    "No Results returned for domain '{}'.".format(domain))
                results = {}
            else:
                # Add "query_execution_time" and "domain_name" to result to facilitate post-processing.
                results = {
                    "related_domains": json.loads(json.dumps(rtn)),
                    "domain_name": domain,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'related_domains' results for domain '{}'.".
                    format(domain))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_ip_as_info_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for ASA information for an IP address."""
        try:
            # Get the function parameters:
            umbinv_resource = kwargs.get("umbinv_resource")  # text

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

            if is_none(umbinv_resource):
                raise ValueError(
                    "Required parameter 'umbinv_resource' not set")

            yield StatusMessage("Starting...")
            res = None
            res_type = None
            process_result = {}
            params = {"resource": umbinv_resource.strip()}

            validate_params(params)
            process_params(params, process_result)

            if "_res" not in process_result or "_res_type" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_resource' was not processed correctly")
            else:
                res = process_result.pop("_res")
                res_type = process_result.pop("_res_type")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            if res_type == "ip_address":
                rtn = rinv.as_for_ip(res)
                # Add "query_execution_time" and "ip_address" key to result to facilitate post-processing.
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
                results = {
                    "as_for_ip": json.loads(json.dumps(rtn)),
                    "ip_address": res,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'as_for_ip' results for ip address '{}'.".
                    format(res))

            elif res_type == "as_number":
                rtn = rinv.prefixes_for_asn(res)
                # Add "query_execution_time" and "ip_address" key to result to facilitate post-processing.
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
                results = {
                    "prefixes_for_asn": json.loads(json.dumps(rtn)),
                    "asn": res,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'prefixes_for_asn' results for AS number '{}'.".
                    format(res))
            else:
                raise ValueError(
                    "Parameter 'umbinv_resource' was an incorrect type '{}' should be an 'ip address' "
                    "or an 'AS number'".format(res_type))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_domain_whois_info_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Domain Whois info."""
        try:
            # Get the function parameters:
            umbinv_resource = kwargs.get("umbinv_resource")  # text
            umbinv_limit = kwargs.get("umbinv_limit")  # number
            umbinv_sortby = kwargs.get("umbinv_sortby")  # text
            umbinv_offset = kwargs.get("umbinv_offset")  # number

            log = logging.getLogger(__name__)
            log.info("umbinv_resource: %s", umbinv_resource)
            log.info("umbinv_limit: %s", umbinv_limit)
            log.info("umbinv_sortby: %s", umbinv_sortby)
            log.info("umbinv_offset: %s", umbinv_offset)

            if is_none(umbinv_resource):
                raise ValueError(
                    "Required parameter 'umbinv_resource' not set")

            yield StatusMessage("Starting...")
            res = None
            res_type = None
            process_result = {}
            params = {
                "resource": umbinv_resource.strip(),
                "limit": umbinv_limit,
                "sort_field": umbinv_sortby,
                "offset": umbinv_offset
            }

            validate_params(params)
            process_params(params, process_result)

            if "_res" not in process_result or "_res_type" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_resource' was not processed correctly")
            else:
                res = process_result.pop("_res")
                res_type = process_result.pop("_res_type")

            if res_type != "domain_name" and res_type != "email_address":
                raise ValueError(
                    "Parameter 'umbinv_resource' was an incorrect type '{}', should be a 'domain name', "
                    "an 'email address' or a 'nameserver'.".format(res_type))

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url)

            yield StatusMessage("Running Cisco Investigate query...")

            if res_type == "domain_name":
                # Can be either domain name or name server.
                # Execute wois query for domain history.
                rtn_dom = rinv.domain_whois_history(res, params["limit"])
                # Execute whois query for nameserver.
                rtn_ns = rinv.ns_whois(res,
                                       **omit_params(params, ["resource"]))
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')

                if len(rtn_dom) != 0:
                    # Test if resource is a name server.
                    for entry in rtn_dom:
                        for ns in entry["nameServers"]:
                            if res == ns:
                                res_type = "nameserver"
                                log.debug(
                                    "Resource '{}' is a nameserver.".format(
                                        res))
                                break

                # Add "query_execution_time", 'resource' and 'resource_type' key to result to facilitate post-processing.
                results = {
                    "domain_whois": json.loads(json.dumps(rtn_dom)),
                    "ns_whois": json.loads(json.dumps(rtn_ns)),
                    "resource": res,
                    "resource_type": res_type,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'whois' results for resource '{}' of resource type '{}'."
                    .format(res, res_type))
            elif res_type == "email_address":
                rtn = rinv.email_whois(res,
                                       **omit_params(params, ["resource"]))
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
                # Add "query_execution_time" and "emails" key to result to facilitate post-processing.
                results = {
                    "email_whois": json.loads(json.dumps(rtn)),
                    "emails": res,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'email_whois' results for resource '{}'.".
                    format(res))
            else:
                raise ValueError(
                    "Parameter 'umbinv_resource' was an incorrect type '{}', should be a 'domain name', "
                    "an 'email address' or a 'nameserver'.".format(res_type))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
Пример #6
0
    def _umbrella_timeline_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate Investigate for  Timeline."""
        try:
            # Get the function parameters:
            umbinv_resource = kwargs.get("umbinv_resource")  # text

            log = logging.getLogger(__name__)

            log.info("resource: %s", umbinv_resource)

            if is_none(umbinv_resource):
                raise ValueError("Required parameter 'umbinv_resource' not set")

            yield StatusMessage("Starting...")
            res = None
            res_type = None
            process_result = {}
            params = {"resource": umbinv_resource.strip()}

            validate_params(params)
            process_params(params, process_result)

            if "_res" not in process_result or "_res_type" not in process_result:
                raise ValueError("Parameter 'umbinv_resource' was not processed correctly")
            else:
                res = process_result.pop("_res")
                res_type = process_result.pop("_res_type")

            if res_type != "domain_name" and res_type != "ip_address" and res_type != "url":
                raise ValueError("Parameter 'umbinv_resource' was an incorrect type '{}', should be a 'domain name', "
                                 "an 'ip address' or a 'url'.".format(res_type))

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.timeline(res)
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if len(rtn) == 0:
                log.debug(json.dumps(rtn))
                yield StatusMessage("No Results returned for resource '{}'.".format(res))
                results = {}
            else:
                # Make timestamp more readable
                for x in range(len(rtn)):
                    try:
                        secs = int(rtn[x]['timestamp']) / 1000
                        ts_readable = datetime.fromtimestamp(secs).strftime('%Y-%m-%d %H:%M:%S')
                        rtn[x]['timestamp_converted'] = ts_readable
                    except ValueError:
                        yield FunctionError('timestamp value incorrectly specified')
                # Add  "query_execution_time" to result to facilitate post-processing.
                results = {"timeline": json.loads(json.dumps(rtn)), "resource_name": res,
                           "query_execution_time": query_execution_time}
                yield StatusMessage("Returning 'thread_grid_samples' results for resource '{}'.".format(res))

            yield StatusMessage("done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_threat_grid_sample_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Threat Grid sample for an MD5, SHA1 or SHA256 hash ."""
        try:
            # Get the function parameters:
            umbinv_hash = kwargs.get("umbinv_hash")  # text
            umbinv_sample_endpoint = self.get_select_param(kwargs.get(
                "umbinv_sample_endpoint"))  # select, values: "basic", "artifacts", "connections", "samples", "behaviors"
            umbinv_limit = kwargs.get("umbinv_limit")  # number
            umbinv_offset = kwargs.get("umbinv_offset")  # number

            log = logging.getLogger(__name__)
            log.info("umbinv_hash: %s", umbinv_hash)
            log.info("umbinv_sample_endpoint: %s", umbinv_sample_endpoint)
            log.info("umbinv_limit: %s", umbinv_limit)
            log.info("umbinv_offset: %s", umbinv_offset)

            if is_none(umbinv_hash):
                raise ValueError("Required parameter 'umbinv_hash' not set")

            if is_none(umbinv_sample_endpoint):
                raise ValueError("Required parameter 'umbinv_sample_endpoint' not set")

            yield StatusMessage("Starting...")
            hash = None
            process_result = {}
            params = {"hash": umbinv_hash.strip(), "sample_endpoint": umbinv_sample_endpoint,
                      "limit": umbinv_limit, "offset": umbinv_offset}

            validate_params(params)
            process_params(params, process_result)

            if "_hash" not in process_result:
               raise ValueError("Parameter 'umbinv_hash' was not processed correctly")
            else:
                hash = process_result.pop("_hash")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            params = omit_params(params, ["hash", "sample_endpoint"])
            if umbinv_sample_endpoint == "basic":
                rtn = rinv.sample(hash, **params)
                result_header = "sample_basic"
            elif umbinv_sample_endpoint == "artifacts":
                rtn = rinv.sample_artifacts(hash, **params)
                result_header = "sample_artifacts"
            elif umbinv_sample_endpoint == "connections":
                rtn = rinv.sample_connections(hash, **params)
                result_header = "sample_connections"
            elif umbinv_sample_endpoint == "samples":
                rtn = rinv.sample_samples(hash, **params)
                result_header = "sample_samples"
            elif umbinv_sample_endpoint == "behaviors":
                rtn = rinv.sample_behaviors(hash, **params)
                result_header = "sample_behaviors"
            else :
                raise ValueError("Incorrect value for parameter parameter 'umbinv_sample_endpoint'.")
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if ("error" in rtn and len(rtn["error"]) != 0):
                log.debug(json.dumps(rtn))
                yield StatusMessage("Umbrella Investigate returned error message '{}'.".format(rtn["error"]))
                results = {}
            else:
                # Add "query_execution_time" and "hash" key to result to facilitate post-processing.
                results = {result_header: json.loads(json.dumps(rtn)), "hash": hash,
                           "query_execution_time": query_execution_time}
                yield StatusMessage("Returning '{}' results for hash '{}'.".format(result_header, hash))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
Пример #8
0
    def _umbrella_dns_rr_hist_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for DNS RR History for a IP, Type and Domain Name"""
        try:
            # Get the function parameters:
            umbinv_resource = kwargs.get("umbinv_resource")  # text
            umbinv_dns_type = self.get_select_param(
                kwargs.get("umbinv_dns_type")
            )  # select, values: "A", "NS", "MX", "TXT", "CNAME"
            incident_id = kwargs.get("incident_id")  # number
            artifact_type = kwargs.get("artifact_type")  # text

            log = logging.getLogger(__name__)
            log.info("umbinv_resource: %s", umbinv_resource)
            log.info("umbinv_dns_type: %s", umbinv_dns_type)
            log.info("incident_id: %s", incident_id)
            log.info("artifact_type: %s", artifact_type)

            if is_none(umbinv_resource):
                raise ValueError(
                    "Required parameter 'umbinv_resource' not set")

            if is_none(umbinv_dns_type):
                raise ValueError(
                    "Required parameter 'umbinv_dns_type' not set")

            if is_none(incident_id):
                raise ValueError("Required parameter 'incident_id' not set")

            if is_none(artifact_type):
                raise ValueError("Required parameter 'artifact_type' not set")

            yield StatusMessage("Starting...")
            res = None
            res_type = None
            process_result = {}
            func_name = event.name

            params = {
                "resource": umbinv_resource.strip(),
                "dns_type": umbinv_dns_type,
                "incident_id": incident_id,
                "artifact_type": artifact_type
            }

            validate_params(params)
            process_params(params, process_result)

            if "_res" not in process_result or "_res_type" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_resource' was not processed correctly")
            else:
                res = process_result.pop("_res")
                res_type = process_result.pop("_res_type")

            if res_type != "domain_name" and res_type != "ip_address":
                raise ValueError(
                    "Parameter 'umbinv_resource' was an incorrect type '{}', should be a 'domain name', "
                    "or an 'ip address'.".format(res_type))

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.rr_history(res, query_type=umbinv_dns_type)
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            if ("rrs" in rtn and len(rtn["rrs"]) == 0) \
                    or ("rrs_tf" in rtn and len(rtn["rrs_tf"]) == 0):
                log.debug(json.dumps(rtn))
                yield StatusMessage(
                    "No Results returned for resource '{}' with query type '{}'."
                    .format(res, umbinv_dns_type))
                results = {}
            elif ("rrs" in rtn and len(rtn["rrs"]) > int(self.options.get("results_limit", "200"))) \
                    or ("rrs_tf" in rtn and len(rtn["rrs_tf"]) > int(self.options.get("results_limit", "200"))):

                att_report = create_attachment(self, func_name, res, params,
                                               rtn, query_execution_time)
                # Add in "query_execution_time" and "ip_address" to result to facilitate post-processing.
                results = {
                    "over_limit": True,
                    "resource_name": res,
                    "att_name": att_report["name"],
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'dns_rr_history' results for resource '{0}' as attachment: {1} ."
                    .format(res, att_report["name"]))
            else:
                # Add in "query_execution_time" and "ip_address" to result to facilitate post-processing.
                results = {
                    "dns_rr_history": json.loads(json.dumps(rtn)),
                    "resource_name": res,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning 'dns_rr_history' results for resource '{}'.".
                    format(res))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_domain_volume_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Domain Volume."""
        try:
            # Get the function parameters:
            umbinv_domain = kwargs.get("umbinv_domain")  # text
            umbinv_match = self.get_select_param(kwargs.get(
                "umbinv_match"))  # select, values: "all", "component", "exact"
            umbinv_start_epoch = kwargs.get(
                "umbinv_start_epoch")  # datetimepicker
            umbinv_start_relative = kwargs.get("umbinv_start_relative")  # text
            umbinv_stop_epoch = kwargs.get(
                "umbinv_stop_epoch")  # datetimepicker
            umbinv_stop_relative = kwargs.get("umbinv_stop_relative")  # text

            log = logging.getLogger(__name__)
            log.info("umbinv_domain: %s", umbinv_domain)
            log.info("umbinv_match: %s", umbinv_match)
            log.info("umbinv_start_epoch: %s", umbinv_start_epoch)
            log.info("umbinv_start_relative: %s", umbinv_start_relative)
            log.info("umbinv_stop_epoch: %s", umbinv_stop_epoch)
            log.info("umbinv_stop_relative: %s", umbinv_stop_relative)

            if is_none(umbinv_domain):
                raise ValueError("Required parameter 'umbinv_domain' not set")

            if is_none(umbinv_match):
                raise ValueError("Required parameter 'umbinv_match' not set")

            yield StatusMessage("Starting...")
            domain = None
            process_result = {}
            params = {
                "domain": umbinv_domain.strip(),
                "start_epoch": umbinv_start_epoch,
                "match": str(umbinv_match),
                "start_relative": umbinv_start_relative,
                "stop_epoch": umbinv_stop_epoch,
                "stop_relative": umbinv_stop_relative
            }

            validate_params(params)
            process_params(params, process_result)

            if "_domain" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_domain' was not processed correctly")
            else:
                domain = process_result.pop("_domain")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.domain_volume(domain, **omit_params(params, ["domain"]))
            dates_converted = []
            for d in rtn["dates"]:
                try:
                    secs = int(d) / 1000
                    ts_readable = datetime.fromtimestamp(secs).strftime(
                        '%Y-%m-%d %H:%M:%S')
                    dates_converted.append(ts_readable)
                except ValueError:
                    yield FunctionError(
                        'timestamp value incorrectly specified')
            rtn["dates_converted"] = dates_converted
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            results = {
                "domain_volume": json.loads(json.dumps(rtn)),
                "domain_name": domain,
                "query_execution_time": query_execution_time
            }
            yield StatusMessage(
                "Returning 'domain_volume' results for domain '{}'.".format(
                    domain))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_classifiers_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for  Classifiers."""
        try:
            # Get the function parameters:
            umbinv_domain = kwargs.get("umbinv_domain")  # text

            log = logging.getLogger(__name__)

            log.info("umbinv_domain: %s", umbinv_domain)

            if is_none(umbinv_domain):
                raise ValueError("Required parameter 'umbinv_domain' not set.")

            yield StatusMessage("Starting...")
            domain = None
            process_result = {}
            params = {"domain": umbinv_domain.strip()}

            validate_params(params)
            process_params(params, process_result)

            if "_domain" not in process_result:
                raise ValueError(
                    "Parameter 'umbinv_domain' was not processed correctly")
            else:
                domain = process_result.pop("_domain")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url)

            yield StatusMessage("Running Cisco Investigate query...")
            classifiers_res = True
            info_res = True
            # Run against 'classifiers' endpoint
            rtn_classifiers = rinv.classifiers_classifiers(domain)
            # Run against 'info' endpoint
            rtn_info = rinv.classifiers_info(domain)
            query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

            if ("securityCategories" in rtn_classifiers and not rtn_classifiers["securityCategories"]) and \
                    ("attacks" in rtn_classifiers and not rtn_classifiers["attacks"]) and \
                    ("threatTypes" in rtn_classifiers and not rtn_classifiers["threatTypes"]):
                classifiers_res = False

            if "firstQueried" in rtn_info and rtn_info["firstQueried"] is None:
                info_res = False
            else:
                # Make 'firstQueried' more readable
                fq = rtn_info["firstQueried"]
                try:
                    secs = int(fq) / 1000
                    fq_readable = datetime.fromtimestamp(secs).strftime(
                        '%Y-%m-%d %H:%M:%S')
                    rtn_info["first_queried_converted"] = fq_readable
                except ValueError:
                    yield FunctionError(
                        'timestamp value incorrectly specified')

            if not classifiers_res and not info_res:
                log.debug(json.dumps(rtn_classifiers))
                log.debug(json.dumps(rtn_info))
                results = {}
                yield StatusMessage(
                    "No Results returned for domain '{}'.".format(domain))
            else:
                # Add "query_execution_time" and "domain_name" to result to facilitate post-processing.
                results = {
                    "classifiers_classifiers":
                    json.loads(json.dumps(rtn_classifiers)),
                    "classifiers_info":
                    json.loads(json.dumps(rtn_info)),
                    "domain_name":
                    domain,
                    "query_execution_time":
                    query_execution_time
                }
                yield StatusMessage(
                    "Returning 'classifiers and info' results for domain '{}'."
                    .format(domain))

            yield StatusMessage("done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
Пример #11
0
    def _umbrella_domain_status_and_category_function(self, event, *args,
                                                      **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Domain Status and Categorization."""
        try:
            # Get the function parameters:
            umbinv_domains = kwargs.get("umbinv_domains")  # text
            umbinv_showlabels = kwargs.get("umbinv_showlabels")  # boolean
            umbinv_status_endpoint = self.get_select_param(
                kwargs.get("umbinv_status_endpoint")
            )  # select, values: "categorization", "categories"

            log = logging.getLogger(__name__)
            log.info("umbinv_domains: %s", umbinv_domains)
            log.info("umbinv_showlabels: %s", umbinv_showlabels)
            log.info("umbinv_status_endpoint: %s", umbinv_status_endpoint)

            if is_none(umbinv_status_endpoint):
                raise ValueError(
                    "Required parameter 'umbinv_status_endpoint' not set")

            if is_none(umbinv_domains
                       ) and umbinv_status_endpoint == "categorization":
                raise ValueError(
                    "Parameter 'umbinv_domains' should be set if 'umbinv_status_endpoint' has value 'categories'."
                )

            if not is_none(
                    umbinv_domains) and umbinv_status_endpoint == "categories":
                raise ValueError(
                    "Parameter 'umbinv_domains' should not be set if 'umbinv_status_endpoint' has value 'categories'."
                )

            yield StatusMessage("Starting...")
            domains = None
            process_result = {}
            params = {
                "domains": umbinv_domains,
                "showlabels": umbinv_showlabels,
                "status_endpoint": umbinv_status_endpoint
            }

            # Reset 'domains' and 'showlabels' param if inmput paramater set.
            if not is_none(umbinv_domains):
                params.setdefault("domains", umbinv_domains.strip())

            if umbinv_showlabels:
                params.setdefault('showlabels', None)

            validate_params(params)
            process_params(params, process_result)

            if umbinv_status_endpoint == "categorization":
                if "_domains" not in process_result:
                    raise ValueError(
                        "Parameter 'umbinv_domains' was not processed correctly"
                    )
                else:
                    domains = process_result.pop("_domains")

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            if (umbinv_status_endpoint == "categories"):
                cat_keys = []
                # Add metadata of "query_execution_time", "min_id" and "max_id" keys to make it easier in post-processing.
                rtn = rinv.categories()
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
                for c in rtn:
                    cat_keys.append(c)
                    cat_keys_int = list(map(int, cat_keys))
                max_cat_keys = max(cat_keys_int)
                results = {
                    "categories": json.loads(json.dumps(rtn)),
                    "min_id": min(cat_keys_int),
                    "max_id": max(cat_keys_int),
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage("Returning 'categories' list results.")

            elif (umbinv_status_endpoint == "categorization"):
                dom_list = []
                if domains is not None:
                    rtn = rinv.categorization(domains, params["showlabels"])
                for d in rtn:
                    dom_list.append(d)
                query_execution_time = datetime.now().strftime(
                    '%Y-%m-%d %H:%M:%S')
                # Add "query_execution_time" and "domains" key to result to facilitate post-processing.
                results = {
                    "statuses": json.loads(json.dumps(rtn)),
                    "domains": dom_list,
                    "query_execution_time": query_execution_time
                }
                yield StatusMessage(
                    "Returning categorization 'statuses' results for domains '{}'."
                    .format(dom_list))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            #Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()
    def _umbrella_threat_grid_samples_function(self, event, *args, **kwargs):
        """Function: Resilient Function : Cisco Umbrella Investigate for Threat Grid samples for domain, IP or URL resource."""
        try:
            # Get the function parameters:
            umbinv_resource = kwargs.get("umbinv_resource")  # text
            umbinv_limit = kwargs.get("umbinv_limit")  # number
            umbinv_offset = kwargs.get("umbinv_offset")  # number
            umbinv_sortby = kwargs.get("umbinv_sortby")  # text

            log = logging.getLogger(__name__)
            log.info("umbinv_resource: %s", umbinv_resource)
            log.info("umbinv_limit: %s", umbinv_limit)
            log.info("umbinv_offset: %s", umbinv_offset)
            log.info("umbinv_sortby: %s", umbinv_sortby)

            if is_none(umbinv_resource):
                raise ValueError("Required parameter 'umbinv_resource' not set")

            yield StatusMessage("Starting...")
            res = None
            res_type = None
            process_result = {}
            params = {"resource": umbinv_resource.strip(), "limit": umbinv_limit, "sortby": umbinv_sortby,
                      "offset": umbinv_offset}

            validate_params(params)
            process_params(params, process_result)

            if "_res" not in process_result or "_res_type" not in process_result:
                raise ValueError("Parameter 'umbinv_resource' was not processed correctly")
            else:
                res = process_result.pop("_res")
                res_type = process_result.pop("_res_type")

            if res_type != "domain_name" and res_type != "ip_address" and res_type != "url":
                raise ValueError("Parameter 'umbinv_resource' was an incorrect type '{}', should be a 'domain name', "
                                 "an 'ip address' or a 'url'.".format(res_type))

            api_token = self.options.get("api_token")
            base_url = self.options.get("base_url")
            rinv = ResilientInv(api_token, base_url, proxies=self.proxies)

            yield StatusMessage("Running Cisco Investigate query...")
            rtn = rinv.samples(res, **omit_params(params, ["resource", "resource_type"]))
            if "error" in rtn:
                log.debug(json.dumps(rtn))
                yield StatusMessage("Investigate returned 'error' status: '{}'.".format(rtn["error"]))
                results = {}
            elif len(rtn) == 0 or ("samples" in rtn and len(rtn["samples"]) == 0):
                log.debug(json.dumps(rtn))
                yield StatusMessage("No Results returned for resource '{}'.".format(res))
                results = {}
            else:
                query_execution_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                # Make each sample 'firstSeen' and "lastSeen" property more readable.
                for i in range(len(rtn["samples"])):
                    fs = rtn["samples"][i]["firstSeen"]
                    ls = rtn["samples"][i]["lastSeen"]
                    try:
                        secs = int(fs) / 1000
                        fs_readable = datetime.fromtimestamp(secs).strftime('%Y-%m-%d %H:%M:%S')
                        rtn["samples"][i]["first_seen_converted"] = fs_readable
                        secs = int(ls) / 1000
                        ls_readable = datetime.fromtimestamp(secs).strftime('%Y-%m-%d %H:%M:%S')
                        rtn["samples"][i]["last_seen_converted"] = ls_readable
                    except ValueError:
                        yield FunctionError('Timestamp value incorrectly specified')

                # Add "query_execution_time" and "domains" key to result to facilitate post-processing.
                results = {"thread_grid_samples": json.loads(json.dumps(rtn)), "resource_name": params["resource"],
                           "query_execution_time": query_execution_time}
                yield StatusMessage("Returning 'thread_grid_samples' results for resource '{}'.".format(res))

            yield StatusMessage("Done...")

            log.debug(json.dumps(results))
            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            log.exception("Exception in Resilient Function.")
            yield FunctionError()