decyfir
DeCYFIR API's provides External Threat Landscape Management insights.
Data Enrichment & Threat Intelligence · DeCYFIR
Details
| ID | decyfir |
|---|---|
| Provider | CYFIRMA |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
DeCYFIR API’s provides External Threat Landscape Management insights.
This integration was integrated and tested with version v2 of decyfir
Configure DeCYFIR in Cortex
| Parameter | Description | Required |
|---|---|---|
| Incident type | False | |
| DeCYFIR Server URL (e.g. https://decyfir.cyfirma.com) | True | |
| DeCYFIR API Key | True | |
| Fetch incidents | False | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| How much time before the first fetch to retrieve incidents | False | |
| Maximum number of incidents per fetch | The maximum number of incidents to fetch per sub-category. | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
decyfir-takedown-initiate
Initiate a take down request.
Base Command
decyfir-takedown-initiate
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The ID of the alert for which to initiate the take down request. | Required |
Context Output
There is no context output for this command.
Command example
!decyfir-takedown-initiate alert_id=123
Human Readable Output
The take down request was initiated successfully.
decyfir-takedown-list
Get take down list.
Base Command
decyfir-takedown-list
Input
| Argument Name | Description | Required |
|---|---|---|
| sub_category | The sub-category for which to retrieve the take down list. If not provided, the take down list for all sub-categories will be retrieved. | Optional |
| size | The number of records to retrieve. Default is 100. | Optional |
| page | The page number to retrieve. Default is 0. | Optional |
Context Output
There is no context output for this command.
Command example
!decyfir-takedown-list
Human Readable Output
The take down list retrieved successfully..
Configuration parameters
incidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalurl— DeCYFIR Server URL (e.g. https://decyfir.cyfirma.com) (required)api_key— (required)isFetch— Fetch incidentsinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsfirst_fetch— How much time before the first fetch to retrieve incidentsmax_fetch— Maximum number of incidents per fetch
Commands (2)
-
decyfir-takedown-initiateInitiate a take down request.
-
decyfir-takedown-listGet take down list.
import demistomock as demisto from CommonServerPython import * from CommonServerUserPython import * from typing import Any """ IMPORTS """ import urllib3 import json import dateparser urllib3.disable_warnings() """ CONSTANTS """ DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" MAX_INCIDENTS_TO_FETCH = 500 API_TEST_PATH_SUFFIX = "/core/api-ua/v2/data/ping?key={0}" API_PATH_SUFFIX: str = "/core/api-ua/v2/alerts" API_TAKE_DOWN_LIST_PATH_SUFFIX: str = "/core/api-ua/v1/take-down?key={0}&page={1}&size={2}" API_TAKE_DOWN_LIST_WITH_CAT_PATH_SUFFIX: str = API_TAKE_DOWN_LIST_PATH_SUFFIX + "&sub-category={3}" API_INIT_TAKE_DOWN_PATH_SUFFIX: str = "/core/api-ua/v1/takedown-request/create?key={0}&alertId={1}" LABEL_DECYFIR = "DeCYFIR" LABEL_ATTACK_SURFACE = "Attack Surface" LABEL_DIGITAL_RISK = "Digital Risk" LABEL_DIGITAL_RISK_IM_IN = "Impersonation & Infringement" LABEL_DIGITAL_RISK_DB_WM = "Data Breach & Web Monitoring" LABEL_DIGITAL_RISK_S_PE = "Social & Public Exposure" LABEL_OPEN_PORTS = "Open Ports" LABEL_IP_VULNERABILITY = "IP Vulnerability" LABEL_CONFIGURATION = "Configuration" LABEL_CLOUD_WEAKNESS = "Cloud Weakness" LABEL_IP_REPUTATION = "IP Reputation" LABEL_CERTIFICATES = "Certificates" LABEL_DOMAIN_IT_ASSET = "Domain IT Asset" LABEL_EXECUTIVE_PEOPLE = "Executive People" LABEL_PRODUCT_SOLUTION = "Product Solution" LABEL_SOCIAL_HANDLERS = "Social Handlers" LABEL_PHISHING = "Phishing" LABEL_RANSOMWARE = "Ransomware" LABEL_DARK_WEB = "Dark web" LABEL_SOURCE_CODE = "Source Code" LABEL_MALICIOUS_MOBILE_APPS = "Malicious Mobile Apps" LABEL_CONFIDENTIAL_FILES = "Confidential Files" LABEL_DUMPS_PII_CII = "Dumps PII-CII" LABEL_SOCIAL_THREAT = "Social Threat" LABELS_LIST: list = [ LABEL_OPEN_PORTS, LABEL_IP_VULNERABILITY, LABEL_CONFIGURATION, LABEL_CLOUD_WEAKNESS, LABEL_IP_REPUTATION, LABEL_CERTIFICATES, LABEL_DOMAIN_IT_ASSET, LABEL_EXECUTIVE_PEOPLE, LABEL_PRODUCT_SOLUTION, LABEL_SOCIAL_HANDLERS, LABEL_PHISHING, LABEL_RANSOMWARE, LABEL_DARK_WEB, LABEL_SOURCE_CODE, LABEL_MALICIOUS_MOBILE_APPS, LABEL_CONFIDENTIAL_FILES, LABEL_DUMPS_PII_CII, LABEL_SOCIAL_THREAT, ] VAR_ATTACK_SURFACE = "attack-surface" VAR_IMPERSONATION_AND_INFRINGEMENT = "impersonation-and-infringement" VAR_DATA_BREACH_AND_WEB_MONITORING = "data-breach-and-web-monitoring" VAR_SOCIAL_AND_PUBLIC_EXPOSURE = "social-and-public-exposure" # ATTACK SURFACE VAR_OPEN_PORTS = "open-ports" VAR_IP_VULNERABILITY = "ip-vulnerability" VAR_CONFIGURATION = "configuration" VAR_CLOUD_WEAKNESS = "cloud-weakness" VAR_IP_REPUTATION = "ip-reputation" VAR_CERTIFICATES = "certificates" VAR_ATTACK_SURFACES_SUB_TYPES: list = [ VAR_OPEN_PORTS, VAR_IP_VULNERABILITY, VAR_CONFIGURATION, VAR_CLOUD_WEAKNESS, VAR_IP_REPUTATION, VAR_CERTIFICATES, ] # IMPERSONATION & INFRINGEMENT VAR_DOMAIN_IT_ASSET = "domain-it-asset" VAR_EXECUTIVE_PEOPLE = "executive-people" VAR_PRODUCT_SOLUTION = "product-solution" VAR_SOCIAL_HANDLERS = "social-handlers" VAR_IMPERSONATION_AND_INFRINGEMENT_SUB_TYPE: list = [ VAR_DOMAIN_IT_ASSET, VAR_EXECUTIVE_PEOPLE, VAR_PRODUCT_SOLUTION, VAR_SOCIAL_HANDLERS, ] # DATA BREACH AND WEB MONITORING VAR_PHISHING = "phishing" VAR_RANSOMWARE = "ransomware" VAR_DARK_WEB = "dark-web" VAR_DATA_BREACH_AND_WEB_MONITORING_SUB_TYPES: list = [VAR_PHISHING, VAR_RANSOMWARE, VAR_DARK_WEB] # SOCIAL AND PUBLIC EXPOSURE VAR_SOURCE_CODE = "source-code" VAR_MALICIOUS_MOBILE_APPS = "malicious-mobile-apps" VAR_CONFIDENTIAL_FILES = "confidential-files" VAR_DUMPS_PII_CII = "dumps-pii-cii" VAR_SOCIAL_THREAT = "social-threat" VAR_SOCIAL_AND_PUBLIC_EXPOSURE_SUB_TYPES: list = [ VAR_SOURCE_CODE, VAR_MALICIOUS_MOBILE_APPS, VAR_CONFIDENTIAL_FILES, VAR_DUMPS_PII_CII, VAR_SOCIAL_THREAT, ] class Client(BaseClient): """ Client will implement the service API, and should not contain any Demisto logic. Should only do requests and return data. """ def get_severity(self, risk_score: int): if risk_score > 8: return IncidentSeverity.CRITICAL elif risk_score > 5: return IncidentSeverity.HIGH elif risk_score >= 3: return IncidentSeverity.MEDIUM elif risk_score >= 1: return IncidentSeverity.LOW else: return IncidentSeverity.UNKNOWN def decyfir_api_request(self, url) -> list[dict]: response = self._http_request( url_suffix=url, resp_type="response", method="GET", ) if response.status_code == 200 and response.content: return response.json() return [] def request_decyfir_api(self, category, category_type, api_param_query) -> list[dict]: response = self._http_request( url_suffix=f"{API_PATH_SUFFIX}" + f"/{category}?type={category_type}" + api_param_query, resp_type="response", method="GET", ) if response.status_code == 200 and response.content: return response.json() return [] def get_decyfir_data(self, after_val: int, decyfir_api_key: str, incident_type: str, max_fetch): size = max_fetch if max_fetch else MAX_INCIDENTS_TO_FETCH api_param_query = f"&key={decyfir_api_key}&size={size}&after={after_val}&product-name=PALO_ALTO_XSOAR" return_data = {} incident_types = [] if incident_type: incident_types.append(incident_type) else: incident_types.append(LABEL_ATTACK_SURFACE) incident_types.append(LABEL_DIGITAL_RISK_IM_IN) incident_types.append(LABEL_DIGITAL_RISK_S_PE) incident_types.append(LABEL_DIGITAL_RISK_DB_WM) if incident_types: for type_ in incident_types: if type_ == LABEL_ATTACK_SURFACE: for cat_type in VAR_ATTACK_SURFACES_SUB_TYPES: return_data[cat_type] = self.request_decyfir_api(VAR_ATTACK_SURFACE, cat_type, api_param_query) if type_ == LABEL_DIGITAL_RISK_IM_IN: for cat_type in VAR_IMPERSONATION_AND_INFRINGEMENT_SUB_TYPE: return_data[cat_type] = self.request_decyfir_api( VAR_IMPERSONATION_AND_INFRINGEMENT, cat_type, api_param_query ) if type_ == LABEL_DIGITAL_RISK_DB_WM: for cat_type in VAR_DATA_BREACH_AND_WEB_MONITORING_SUB_TYPES: return_data[cat_type] = self.request_decyfir_api( VAR_DATA_BREACH_AND_WEB_MONITORING, cat_type, api_param_query ) if type_ == LABEL_DIGITAL_RISK_S_PE: for cat_type in VAR_SOCIAL_AND_PUBLIC_EXPOSURE_SUB_TYPES: return_data[cat_type] = self.request_decyfir_api( VAR_SOCIAL_AND_PUBLIC_EXPOSURE, cat_type, api_param_query ) return return_data def prepare_incident_json( self, alert_type: str, alert_subtype: str, name: str, date_val: str, severity: int, details: dict, record_id: str ) -> dict[str, Any]: occurred_date = dateparser.parse(date_val) occurred = occurred_date.strftime(DATE_FORMAT) if isinstance(occurred_date, datetime) else None decyfir_data_details = [] for key, value in details.items(): if key != "uid" and value is not None and value != "null": key = str(key).replace("_", " ").capitalize() decyfir_data_details.append({"fields": key, "values": value}) return_data = { "type": f"{alert_type}", "name": name, "occurred": occurred, "severity": severity, "rawJSON": str(json.dumps(details)), "category": alert_type, "subcategory": alert_subtype, "dbotMirrorId": record_id, "sourceBrand": LABEL_DECYFIR, "labels": [ {"type": "Sub Category", "value": alert_subtype}, {"type": "Description", "value": details.get("description")}, {"type": "Alert Id", "value": details.get("alert_uid", details.get("alert_object_uid", ""))}, {"type": "Object Id", "value": details.get("uid")}, {"type": "Risk Score", "value": str(details.get("exposure_score"))}, ], "customFields": {"decyfirdatadetails": decyfir_data_details}, } return return_data def prepare_incidents_for_attack_surface(self, json_data, alert_type: str, alert_subtype: str) -> list[dict]: try: incidents_json = [] for json_ in json_data: severity = self.get_severity(json_.get("risk_score")) ip = json_.get("ip") details = dict(json_) date_val = json_.get("alert_created_date") uid = json_.get("uid") domain: str = "" if json_.get("sub_domain"): domain = json_.get("sub_domain") domain = domain + ", " + json_.get("top_domain") if domain else json_.get("top_domain") name = f"DOMAIN : {domain}" if domain else "" if ip: name = name + f"\n IP: {ip}" if name else f"IP: {ip}" if not name: name = "Asset: {}".format(json_.get("asset_name")) if json_.get("asset_name") else "" incident_json = self.prepare_incident_json(alert_type, alert_subtype, name, date_val, severity, details, uid) incidents_json.append(incident_json) return incidents_json except Exception as e: raise DemistoException(str(e)) def prepare_incidents_for_digital_risk(self, json_data, alert_type: str, alert_subtype: str) -> list: try: incidents_json = [] for json_ in json_data: severity = self.get_severity(json_.get("risk_score")) date_val = json_.get("alert_created_date") details = dict(json_) name: str = json_.get("title") uid = json_.get("uid") incident_json = self.prepare_incident_json(alert_type, alert_subtype, name, date_val, severity, details, uid) incidents_json.append(incident_json) return incidents_json except Exception as e: raise DemistoException(str(e)) def convert_decyfir_data_to_incidents_format(self, decyfir_alerts_incidents): try: return_data: list[dict] = [] # Attack Surface # Open Ports if json_data := decyfir_alerts_incidents.get(VAR_OPEN_PORTS): incidents_json_data = self.prepare_incidents_for_attack_surface(json_data, LABEL_ATTACK_SURFACE, LABEL_OPEN_PORTS) return_data = return_data + incidents_json_data # IP Vulnerability if json_data := decyfir_alerts_incidents.get(VAR_IP_VULNERABILITY): incidents_json_data = self.prepare_incidents_for_attack_surface( json_data, LABEL_ATTACK_SURFACE, LABEL_IP_VULNERABILITY ) return_data = return_data + incidents_json_data # "Configuration" if json_data := decyfir_alerts_incidents.get(VAR_CONFIGURATION): incidents_json_data = self.prepare_incidents_for_attack_surface( json_data, LABEL_ATTACK_SURFACE, LABEL_CONFIGURATION ) return_data = return_data + incidents_json_data # Cloud Weakness if json_data := decyfir_alerts_incidents.get(VAR_CLOUD_WEAKNESS): incidents_json_data = self.prepare_incidents_for_attack_surface( json_data, LABEL_ATTACK_SURFACE, LABEL_CLOUD_WEAKNESS ) return_data = return_data + incidents_json_data # IP Reputation if json_data := decyfir_alerts_incidents.get(VAR_IP_REPUTATION): incidents_json_data = self.prepare_incidents_for_attack_surface( json_data, LABEL_ATTACK_SURFACE, LABEL_IP_REPUTATION ) return_data = return_data + incidents_json_data # Certificates if json_data := decyfir_alerts_incidents.get(VAR_CERTIFICATES): incidents_json_data = self.prepare_incidents_for_attack_surface( json_data, LABEL_ATTACK_SURFACE, LABEL_CERTIFICATES ) return_data = return_data + incidents_json_data # Digital Risk # impersonation & infringement if json_data := decyfir_alerts_incidents.get(VAR_DOMAIN_IT_ASSET): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_IM_IN, LABEL_DOMAIN_IT_ASSET ) return_data = return_data + incidents_json_data # Executive People if json_data := decyfir_alerts_incidents.get(VAR_EXECUTIVE_PEOPLE): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_IM_IN, LABEL_EXECUTIVE_PEOPLE ) return_data = return_data + incidents_json_data # Product Solution if json_data := decyfir_alerts_incidents.get(VAR_PRODUCT_SOLUTION): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_IM_IN, LABEL_PRODUCT_SOLUTION ) return_data = return_data + incidents_json_data # Social Handlers if json_data := decyfir_alerts_incidents.get(VAR_SOCIAL_HANDLERS): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_IM_IN, LABEL_SOCIAL_HANDLERS ) return_data = return_data + incidents_json_data # PHISHING if json_data := decyfir_alerts_incidents.get(VAR_PHISHING): incidents_json_data = self.prepare_incidents_for_digital_risk(json_data, LABEL_DIGITAL_RISK_DB_WM, LABEL_PHISHING) return_data = return_data + incidents_json_data # ransomware if json_data := decyfir_alerts_incidents.get(VAR_RANSOMWARE): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_DB_WM, LABEL_RANSOMWARE ) return_data = return_data + incidents_json_data # Dark web if json_data := decyfir_alerts_incidents.get(VAR_DARK_WEB): incidents_json_data = self.prepare_incidents_for_digital_risk(json_data, LABEL_DIGITAL_RISK_DB_WM, LABEL_DARK_WEB) return_data = return_data + incidents_json_data # Source Code if json_data := decyfir_alerts_incidents.get(VAR_SOURCE_CODE): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_S_PE, LABEL_SOURCE_CODE ) return_data = return_data + incidents_json_data # malicious-mobile-apps if json_data := decyfir_alerts_incidents.get(VAR_MALICIOUS_MOBILE_APPS): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_S_PE, LABEL_MALICIOUS_MOBILE_APPS ) return_data = return_data + incidents_json_data # confidential-files if json_data := decyfir_alerts_incidents.get(VAR_CONFIDENTIAL_FILES): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_S_PE, LABEL_CONFIDENTIAL_FILES ) return_data = return_data + incidents_json_data # dumps-pii-cii if json_data := decyfir_alerts_incidents.get(VAR_DUMPS_PII_CII): incidents_json_data = self.prepare_incidents_for_digital_risk( json_data, LABEL_DIGITAL_RISK_S_PE, LABEL_DUMPS_PII_CII ) return_data = return_data + incidents_json_data return return_data except Exception as e: raise DemistoException(str(e)) def take_down_list_data(self, decyfir_api_key, sub_category, page, size): if sub_category: api_url = API_TAKE_DOWN_LIST_WITH_CAT_PATH_SUFFIX.format(decyfir_api_key, page, size, sub_category) return self.decyfir_api_request(api_url) else: api_url = API_TAKE_DOWN_LIST_PATH_SUFFIX.format(decyfir_api_key, page, size) return self.decyfir_api_request(api_url) def initiate_take_down(self, decyfir_api_key, alert_id) -> Dict: api_path = API_INIT_TAKE_DOWN_PATH_SUFFIX.format(decyfir_api_key, alert_id) response = self._http_request( url_suffix=api_path, resp_type="response", method="POST", ) if response.status_code == 200 and response.content: return response.json() return {} # commands # This is the call made when pressing the integration Test button. def test_module(client, decyfir_api_key): # pragma: no cover url = API_TEST_PATH_SUFFIX.format(decyfir_api_key) response = client._http_request(url_suffix=url, method="GET", resp_type="response") if response.status_code == 200: return "ok" elif response.status_code == 401 or response.status_code == 403: return "Not Authorized" else: return f"Error_code: {response.status_code}, Please contact the DeCYFIR team to assist you further on this." def fetch_incidents(client, last_run, first_fetch, decyfir_api_key, incident_type, max_fetch): try: start_fetch = dateparser.parse(last_run.get("last_fetch")) if last_run else dateparser.parse(first_fetch) start_fetch_timestamp_val: float = start_fetch.timestamp() if isinstance(start_fetch, datetime) else 0.0 start_fetch_timestamp: int = int(start_fetch_timestamp_val * 1000) # To get the DeCYFIR data in JSON format json_decyfir_data = client.get_decyfir_data( after_val=start_fetch_timestamp, decyfir_api_key=decyfir_api_key, incident_type=incident_type, max_fetch=max_fetch ) decyfir_incidents = client.convert_decyfir_data_to_incidents_format(json_decyfir_data) # Assigning the current date time value to last_fetch for next run last_fetch_time = datetime.now().strftime(DATE_FORMAT) last_fetch = {"last_fetch": last_fetch_time} return last_fetch, decyfir_incidents except Exception as e: if "Forbidden" in str(e): return "Authorization Error: make sure API Key is correctly set" else: raise e def take_down_list_command_results(data: List[Dict], title: str) -> CommandResults: if not data: return CommandResults(readable_output="No data found for current request.") if not isinstance(data, list): return CommandResults(readable_output="Unexpected response format.") table_data = [] outputs = [] for da in data: ticket_id = da.get("ticket_name", "") sub_category = da.get("sub_category", "") created_date = da.get("created_date", "") modified_date = da.get("modified_date", "") status = da.get("status", "") domain = da.get("domain", "") modified_by = da.get("modified_by", "") created_by = da.get("created_by", "") row = { "Ticket Id": ticket_id, "URL Status Updated By": da.get("url_status_updated_by", ""), "URL Status": da.get("url_status", ""), "Domain": domain, "Sub Category": sub_category, "Category": da.get("category", ""), "Status": status, "Created Date": created_date, "Modified Date": modified_date, "Created By": created_by, "Modified By": modified_by, } table_data.append(row) outputs.append( { "ticket_id": ticket_id, "sub_category": sub_category, "created_date": created_date, "modified_date": modified_date, "status": status, "domain": domain, "created_by": created_by, "modified_by": modified_by, } ) if not table_data: human_readable = "No data found for current request." else: human_readable = tableToMarkdown(title, table_data, removeNull=True) return CommandResults( readable_output=human_readable, outputs_prefix=f"{LABEL_DECYFIR}.TakeDownList", outputs_key_field="ticket_id", outputs=outputs, raw_response=data, ) def initiate_take_down_request(client: Client, decyfir_api_key: str, args: Dict): alert_id = args.get("alert_id") data: Dict = client.initiate_take_down(decyfir_api_key, alert_id) msg: str = "" if not data: msg = "For no data found for current request." elif bool(data.get("error")) is True: msg = "Error in creating take down request" if msg: return CommandResults( readable_output=msg, outputs_prefix=f"{LABEL_DECYFIR}.InitiateTakeDown", outputs_key_field="ticket_id", outputs=msg, raw_response=data, ) da: Dict = data.get("response", {}) if da: ticket_id = da.get("ticketName", "") msg = f"Take Down Request Created Successfully - TIcket ID: {ticket_id}" else: msg = "Error in creating take down request" return CommandResults( readable_output=msg, outputs_prefix=f"{LABEL_DECYFIR}.InitiateTakeDown", outputs_key_field="ticket_id", outputs=msg, raw_response=data, ) def get_take_down_list(client, decyfir_api_key, args): sub_category = args.get("sub_category", "") size = args.get("size", "100") page = args.get("page", "0") # table_data = [] res_data: list = client.take_down_list_data(decyfir_api_key, sub_category, page, size) return take_down_list_command_results( res_data, f"DeCYFIR Take Down List - Sub Category: {sub_category if sub_category else 'All'}, Page: {page}, Size: {size}" ) def main(): # pragma: no cover params = demisto.params() decyfir_url = params["url"].rstrip("/") decyfir_api_key = params.get("api_key").get("password") incident_type: str = params.get("incidentType") max_fetch: str = params.get("max_fetch") verify_certificate = not params.get("insecure", False) # How much time before the first fetch to retrieve incidents first_fetch = params.get("first_fetch", "30 days").strip() proxy = params.get("proxy", False) args = demisto.args() demisto.info(f"Command being called is {demisto.command()}") try: client = Client(base_url=decyfir_url, verify=verify_certificate, proxy=proxy) if demisto.command() == "test-module": result = test_module(client, decyfir_api_key) demisto.results(result) elif demisto.command() == "fetch-incidents": next_run, incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), first_fetch=first_fetch, decyfir_api_key=decyfir_api_key, incident_type=incident_type, max_fetch=max_fetch, ) # Pushing Incidents data to XSOAR demisto.incidents(incidents) demisto.setLastRun(next_run) elif demisto.command() == "decyfir-takedown-initiate": return_results(initiate_take_down_request(client, decyfir_api_key, args)) elif demisto.command() == "decyfir-takedown-list": return_results(get_take_down_list(client, decyfir_api_key, args)) else: raise NotImplementedError("DeCYFIR error: " + f"command {demisto.command()} is not implemented") # Log exceptions except Exception as e: err = f"Failed to execute {demisto.command()} command. DeCYFIR error: {str(e)}" return_error(err) if __name__ in ("__main__", "__builtin__", "builtins"): main()