Secneurx Threat Feeds

SecneurX provides real-time threat intelligence that protects companies against the latest cyber threats, including APTs, phishing, malware, ransomware, data exfiltration, and brand infringement. Security teams rely on our dependable and rich data to expand their threat landscape visibility, resulting in improved detection rates and response times.

Data Enrichment & Threat Intelligence · Secneurx Threat Feeds · Feed

Details

IDSecneurx Threat Feeds
ProviderSecneurX
CategoryData Enrichment & Threat Intelligence
From Version6.2.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

SecneurX provides real-time threat intelligence that protects companies against the latest cyber threats, including APTs, phishing, malware, ransomware, data exfiltration, and brand infringement. Security teams rely on our dependable and rich data to expand their threat landscape visibility, resulting in improved detection rates and response times.
This integration was integrated and tested with version 1.0.0 of SecneurX Threat Feeds

Configure SecneurX Threat Feeds in Cortex

Parameter Description Required
Feed URL Input the url of SecneurX Threat Intelligence Feeds. True
API Key Input the API key for fetching feed from the source. True
Fetch indicators Select this option if you want this integration instance to fetch indicators from the SecneurX Threat Intelligence feed. False
Indicator Reputation Indicators from this integration instance will be marked with this reputation False
Tags Supports CSV values. False
Source Reliability Reliability of the source providing the intelligence data True
Feed Fetch Interval How often do fetch indicators from this integration instance. You can specify the interval in days, hours, or minutes. True
Feed Expiration Policy   False
Traffic Light Protocol Color The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed False
First fetch First fetch query e.g., 12 hours, 7 days. SecurityScorecard provides a maximum of 7 days back. To ensure no alerts are missed, it’s recommended to use a value less than 2 days. False
Bypass exclusion list When selected, the exclusion list is ignored for indicators from this feed. This means that if an indicator from this feed is on the exclusion list, the indicator might still be added to the system. False
proxy Use system proxy settings False
insecure Trust any certificate (not secure) 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.

snxfeeds-get-indicators


Retrieves a limited number of the indicators.

Base Command

snxfeeds-get-indicators

Input

Argument Name Description Required
limit The maximum number of indicators to return. The default is 10. Optional

Context Output

There is no context output for this command.

Human Readable Output

Type Value Fields
Domain mak.logupdates.xyz firstseenbysource: 2022-06-13T10:37:23Z, indicatoridentification: indicator–c0f9425f-a3e9-4fcf-85c5-58e809f4e763, verdict: Malicious, tags: apt , Donot APT, modified: 2022-06-13T10:37:23Z, reportedby: SecneurX Threat Feeds

Notes

Be aware, due to API limitations, fetch-indicators fetches only a limited number of indicators for each interval.
Fetching all the indicators can take up to 24 hours.

Configuration parameters

  • url — Feed URL (required)
  • apikey — API Key (required)
  • feed — Fetch indicators
  • feedReputation — Indicator Reputation
  • feedTags — Tags
  • feedReliability — Source Reliability (required)
  • feedFetchInterval — Feed Fetch Interval
  • feedExpirationPolicy
  • tlp_color — Traffic Light Protocol Color
  • first_fetch — First fetch
  • feedExpirationInterval
  • feedBypassExclusionList — Bypass exclusion list
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (1)

  • snxfeeds-get-indicators

    Retrieves a limited number of the indicators.

import demistomock as demisto
from CommonServerPython import *  # noqa # pylint: disable=unused-wildcard-import

""" IMPORTS """


import requests  # noqa
import traceback  # noqa
from typing import Dict, Any  # noqa
from datetime import datetime, timedelta  # noqa
import urllib3

# Disable insecure warnings
urllib3.disable_warnings()  # pylint: disable=no-member
DEMISO_DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"  # ISO8601 format with UTC, default in XSOAR


SNX_TYPES_TO_DEMISTO_TYPES = {
    "url:value": FeedIndicatorType.URL,
    "md5:value": FeedIndicatorType.File,
    "sha-1:value": FeedIndicatorType.File,
    "sha-256:value": FeedIndicatorType.File,
    "ipv4-addr:value": FeedIndicatorType.IP,
    "domain:value": FeedIndicatorType.Domain,
    "ipv6-addr:value": FeedIndicatorType.IPv6,
    "email-addr:value": FeedIndicatorType.Email,
    "domain-name:value": FeedIndicatorType.Domain,
    "file:hashes.MD5": FeedIndicatorType.File,
    "file:hashes.SHA256": FeedIndicatorType.File,
    "file:hashes.SHA1": FeedIndicatorType.File,
}

STIX_INTEL_TYPE_TO_DEMISTO_TYPES = {
    "campaign": ThreatIntel.ObjectsNames.CAMPAIGN,
    "attack-pattern": ThreatIntel.ObjectsNames.ATTACK_PATTERN,
    "report": ThreatIntel.ObjectsNames.REPORT,
    "malware": ThreatIntel.ObjectsNames.MALWARE,
    "course-of-action": ThreatIntel.ObjectsNames.COURSE_OF_ACTION,
    "intrusion-set": ThreatIntel.ObjectsNames.INTRUSION_SET,
    "tool": ThreatIntel.ObjectsNames.TOOL,
    "threat-actor": ThreatIntel.ObjectsNames.THREAT_ACTOR,
    "infrastructure": ThreatIntel.ObjectsNames.INFRASTRUCTURE,
}

XSOAR_RELATIONSHIP_TYPES = EntityRelationship.Relationships.RELATIONSHIPS_NAMES.keys()


class DemistoScore:
    UNKNOWN = 0
    BENIGN = 1
    SUSPICIOUS = 2
    MALICIOUS = 3


class SNXIocParse:
    SNX_ID_KEY = "id"
    SNX_URL_KEY = "URL"
    SNX_TYPE_KEY = "type"
    SNX_NAME_KEY = "name"
    SNX_VALUE_KEY = "value"
    SNX_BENIGN_TYPE = "benign"
    SNX_PATTERN_KEY = "pattern"
    SNX_OBJECTS_KEY = "objects"
    SNX_CREATED_KEY = "created"
    SNX_MALWARE_KEY = "malware"
    SNX_UNKNOWN_TYPE = "unknown"
    SNX_MODIFIED_KEY = "modified"
    SNX_INDICATOR_KEY = "indicator"
    SNX_INDICATES_KEY = "indicates"
    SNX_SOURCE_REF_KEY = "source_ref"
    SNX_TARGET_REF_KEY = "target_ref"
    SNX_CONFIDENCE_KEY = "confidence"
    SNX_EXTERNAL_ID_KEY = "external_id"
    SNX_VALID_UNTIL_KEY = "valid_until"
    SNX_FILE_MD5_KEY = "file:hashes.MD5"
    SNX_ONION_ADDR_KEY = "Onion address"
    SNX_DESCRIPTIONS_KEY = "description"
    SNX_RELATIONSHIP_KEY = "relationship"
    SNX_MALWARE_TYPE_KEY = "malware_types"
    SNX_FEED_KEY = "SecneurX Threat Feeds"
    SNX_RELATIONSHIPS_KEY = "relationships"
    SNX_ATTACK_PATTERN_KEY = "attack-pattern"
    SNX_INDICATORS_TYPE_KEY = "indicator_types"
    SNX_EXTERNAL_REF_KEY = "external_references"
    DEMISTO_ONION_ADDRESS_TYPE = "Onion Address"
    SNX_RELATIONSHIP_TYPE_KEY = "relationship_type"
    SNX_MALICIOUS_LIST = ["malicious-activity", "compromised"]
    SNX_SUSPICIOUS_LIST = ["anomalous-activity", "anonymization"]


class Client(BaseClient):
    """Implements class for SecneurX Threat Feeds."""

    def get_feeds(self, feed_date: Optional[str] = None):
        try:
            params = {}
            if feed_date:
                params = {"date": feed_date}
            return self._http_request(
                method="GET",
                url_suffix="/getfeeds",
                params=params,
                timeout=90,
            ), None

        except Exception as e:
            return None, e


def test_module(client: Client) -> Any:
    getIndicatorsCommand(client, {"limit": 2})
    return "ok"


def parseIndicators(feedJson: dict) -> Any:
    try:
        indicatorList = []
        if feedJson:
            jsonContent = feedJson[SNXIocParse.SNX_OBJECTS_KEY]
            relationship_iocs = []
            ioc_contents = {}
            for ioc_data in jsonContent:
                try:
                    tagList = []
                    mitreIdValue = None
                    createdValue = None
                    modifiedValue = None
                    indicatorType = None
                    indicatorValue = None
                    confidenceValue = None
                    expirationValue = None
                    indicatorIdValue = None
                    descriptionValue = None
                    reportByValue = SNXIocParse.SNX_FEED_KEY
                    verdictScore = DemistoScore.MALICIOUS
                    if ioc_data[SNXIocParse.SNX_TYPE_KEY] == SNXIocParse.SNX_INDICATOR_KEY:
                        if SNXIocParse.SNX_ID_KEY in ioc_data:
                            indicatorIdValue = ioc_data[SNXIocParse.SNX_ID_KEY]
                        if SNXIocParse.SNX_PATTERN_KEY in ioc_data:
                            patternKey, patternValue = parse_ioc_values(ioc_data)
                            if patternKey and patternValue:
                                indicatorType = patternKey
                                indicatorValue = patternValue
                            else:
                                continue
                        if SNXIocParse.SNX_CREATED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_CREATED_KEY]
                            createdValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_MODIFIED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_MODIFIED_KEY]
                            modifiedValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_DESCRIPTIONS_KEY in ioc_data:
                            tagsInfo = ioc_data[SNXIocParse.SNX_DESCRIPTIONS_KEY]
                            tagList = tagsInfo.split(",")
                        if SNXIocParse.SNX_CONFIDENCE_KEY in ioc_data:
                            confidenceValue = ioc_data[SNXIocParse.SNX_CONFIDENCE_KEY]
                        if SNXIocParse.SNX_VALID_UNTIL_KEY in ioc_data:
                            expirationValue = ioc_data[SNXIocParse.SNX_VALID_UNTIL_KEY]
                        if SNXIocParse.SNX_INDICATORS_TYPE_KEY in ioc_data:
                            verdictInfo = ioc_data[SNXIocParse.SNX_INDICATORS_TYPE_KEY]
                            if len(verdictInfo) >= 1:
                                verdictInfo = verdictInfo[0]
                                if verdictInfo.lower() in SNXIocParse.SNX_MALICIOUS_LIST:
                                    verdictScore = DemistoScore.MALICIOUS
                                elif verdictInfo.lower() in SNXIocParse.SNX_SUSPICIOUS_LIST:
                                    verdictScore = DemistoScore.SUSPICIOUS
                                elif verdictInfo.lower() == SNXIocParse.SNX_BENIGN_TYPE:
                                    verdictScore = DemistoScore.BENIGN
                                elif verdictInfo.lower() == SNXIocParse.SNX_UNKNOWN_TYPE:
                                    verdictScore = DemistoScore.UNKNOWN
                                else:
                                    verdictScore = DemistoScore.MALICIOUS
                        if indicatorType == SNXIocParse.SNX_URL_KEY and SNXIocParse.SNX_ONION_ADDR_KEY in tagList:
                            indicatorType = SNXIocParse.DEMISTO_ONION_ADDRESS_TYPE
                        ioc_contents[indicatorIdValue] = {"type": indicatorType, "value": indicatorValue}

                    elif ioc_data[SNXIocParse.SNX_TYPE_KEY] == SNXIocParse.SNX_MALWARE_KEY:
                        indicatorType = STIX_INTEL_TYPE_TO_DEMISTO_TYPES[SNXIocParse.SNX_MALWARE_KEY]
                        if SNXIocParse.SNX_ID_KEY in ioc_data:
                            indicatorIdValue = ioc_data[SNXIocParse.SNX_ID_KEY]
                        if SNXIocParse.SNX_NAME_KEY in ioc_data:
                            indicatorValue = ioc_data[SNXIocParse.SNX_NAME_KEY]
                        if SNXIocParse.SNX_CREATED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_CREATED_KEY]
                            createdValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_MODIFIED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_MODIFIED_KEY]
                            modifiedValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_MALWARE_TYPE_KEY in ioc_data:
                            tagList = ioc_data[SNXIocParse.SNX_MALWARE_TYPE_KEY]
                            if SNXIocParse.SNX_UNKNOWN_TYPE in tagList:
                                tagList.clear()
                                tagList.append(indicatorValue)
                        if SNXIocParse.SNX_DESCRIPTIONS_KEY in ioc_data:
                            descriptionValue = ioc_data[SNXIocParse.SNX_DESCRIPTIONS_KEY]
                        verdictScore = ThreatIntel.ObjectsScore.MALWARE
                        ioc_contents[indicatorIdValue] = {"type": indicatorType, "value": indicatorValue}

                    elif ioc_data[SNXIocParse.SNX_TYPE_KEY] == SNXIocParse.SNX_RELATIONSHIP_KEY:
                        relationship_iocs.append(ioc_data)

                    elif ioc_data[SNXIocParse.SNX_TYPE_KEY] == SNXIocParse.SNX_ATTACK_PATTERN_KEY:
                        indicatorType = STIX_INTEL_TYPE_TO_DEMISTO_TYPES[SNXIocParse.SNX_ATTACK_PATTERN_KEY]
                        if SNXIocParse.SNX_ID_KEY in ioc_data:
                            indicatorIdValue = ioc_data[SNXIocParse.SNX_ID_KEY]
                        if SNXIocParse.SNX_NAME_KEY in ioc_data:
                            indicatorValue = ioc_data[SNXIocParse.SNX_NAME_KEY]
                        if SNXIocParse.SNX_CREATED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_CREATED_KEY]
                            createdValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_MODIFIED_KEY in ioc_data:
                            timeData = ioc_data[SNXIocParse.SNX_MODIFIED_KEY]
                            modifiedValue = datetime.strptime(timeData, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(DEMISO_DATE_FORMAT)
                        if SNXIocParse.SNX_DESCRIPTIONS_KEY in ioc_data:
                            descriptionValue = ioc_data[SNXIocParse.SNX_DESCRIPTIONS_KEY]
                        if SNXIocParse.SNX_EXTERNAL_REF_KEY in ioc_data:
                            externalRefList = ioc_data[SNXIocParse.SNX_EXTERNAL_REF_KEY]
                            for externalRef in externalRefList:
                                if SNXIocParse.SNX_EXTERNAL_ID_KEY in externalRef:
                                    mitreIdValue = externalRef[SNXIocParse.SNX_EXTERNAL_ID_KEY]
                                    tagList = mitreIdValue
                        verdictScore = ThreatIntel.ObjectsScore.ATTACK_PATTERN
                        ioc_contents[indicatorIdValue] = {"type": indicatorType, "value": indicatorValue}

                    else:
                        continue

                    indicatorObj = {}
                    if indicatorValue is not None:
                        indicatorObj["value"] = indicatorValue
                    else:
                        continue
                    if indicatorType is not None:
                        indicatorObj["type"] = indicatorType
                    else:
                        continue
                    indicatorObj["score"] = verdictScore
                    indicatorObj["rawJson"] = ioc_data
                    indicatorObj["fields"] = {}
                    if len(tagList) >= 1:
                        indicatorObj["fields"]["tags"] = tagList
                    if indicatorIdValue is not None:
                        indicatorObj["fields"]["stixid"] = indicatorIdValue
                        indicatorObj["fields"]["indicatoridentification"] = indicatorIdValue
                    if createdValue is not None:
                        indicatorObj["fields"]["firstseenbysource"] = createdValue
                    if modifiedValue is not None:
                        indicatorObj["fields"]["modified"] = modifiedValue
                    if expirationValue is not None:
                        indicatorObj["fields"]["expiration_date"] = expirationValue
                    if confidenceValue is not None:
                        indicatorObj["fields"]["confidence"] = confidenceValue
                    if descriptionValue is not None:
                        indicatorObj["fields"]["description"] = descriptionValue
                    if mitreIdValue is not None:
                        indicatorObj["fields"]["mitreid"] = mitreIdValue
                    indicatorObj["fields"]["reportedby"] = reportByValue
                    indicatorList.append(indicatorObj)

                except Exception as e:
                    raise DemistoException(e)
            if relationship_iocs:
                indicatorList.append(parse_ioc_relationships(relationship_iocs, ioc_contents))

    except Exception as e:
        raise DemistoException(e)
    return indicatorList


def parse_ioc_values(ioc_data):
    try:
        patternInfo = ioc_data[SNXIocParse.SNX_PATTERN_KEY]
        patternInfo = patternInfo.replace("[", "")
        patternData = patternInfo.replace("]", "")
        patternKey = patternData.split("=")[0].strip()
        patternValue = patternData.split("=")[1].replace("'", "").strip()
        ioc_type = None
        if patternKey == SNXIocParse.SNX_FILE_MD5_KEY:
            ioc_type = patternKey
        else:
            ioc_type = patternKey.lower()
        if ioc_type in SNX_TYPES_TO_DEMISTO_TYPES:
            patternKey = SNX_TYPES_TO_DEMISTO_TYPES[ioc_type]
            return patternKey, patternValue
        else:
            return None, None

    except Exception as e:
        raise DemistoException(e)


def parse_ioc_relationships(relationshipIocs, ioc_contents):
    dummy_indicator: dict[str, Any] = {}
    relationships_list = []
    try:
        for relation_obj in relationshipIocs:
            try:
                sourceRefIoc = None
                targetRefIoc = None
                sourceRefIocType = None
                targetRefIocType = None
                relationshipType = None
                reverseRelationshipType = None
                if SNXIocParse.SNX_RELATIONSHIP_TYPE_KEY in relation_obj:
                    iocRelationType = relation_obj[SNXIocParse.SNX_RELATIONSHIP_TYPE_KEY]
                    if iocRelationType.lower() == SNXIocParse.SNX_INDICATES_KEY:
                        relationshipType = EntityRelationship.Relationships.INDICATOR_OF
                        reverseRelationshipType = "indicated-by"
                    else:
                        demisto.debug(f"Invalid relation type: {relationshipType}")
                        continue

                if SNXIocParse.SNX_SOURCE_REF_KEY in relation_obj:
                    try:
                        sourceRefId = relation_obj[SNXIocParse.SNX_SOURCE_REF_KEY]
                        sourceRefIocType = ioc_contents[sourceRefId]["type"]
                        sourceRefIoc = ioc_contents[sourceRefId]["value"]
                    except Exception:
                        continue

                if SNXIocParse.SNX_TARGET_REF_KEY in relation_obj:
                    try:
                        targetRefId = relation_obj[SNXIocParse.SNX_TARGET_REF_KEY]
                        targetRefIocType = ioc_contents[targetRefId]["type"]
                        targetRefIoc = ioc_contents[targetRefId]["value"]
                    except Exception:
                        continue

                if not sourceRefIocType or not targetRefIocType:
                    continue
                attackPatternType = STIX_INTEL_TYPE_TO_DEMISTO_TYPES[SNXIocParse.SNX_ATTACK_PATTERN_KEY]
                if sourceRefIocType == attackPatternType or targetRefIocType == attackPatternType:
                    relationshipType = EntityRelationship.Relationships.USES
                    reverseRelationshipType = "used-by"
                timelineFields = {
                    "lastseenbysource": relation_obj[SNXIocParse.SNX_MODIFIED_KEY],
                    "firstseenbysource": relation_obj[SNXIocParse.SNX_CREATED_KEY],
                }
                entityRelation = EntityRelationship(
                    name=relationshipType,
                    entity_a=sourceRefIoc,
                    entity_a_type=sourceRefIocType,
                    entity_b=targetRefIoc,
                    entity_b_type=targetRefIocType,
                    fields=timelineFields,
                    reverse_name=reverseRelationshipType,
                )
                relationships_list.append(entityRelation.to_indicator())

            except Exception as e:
                raise DemistoException(e)

        if relationships_list:
            dummy_indicator[SNXIocParse.SNX_VALUE_KEY] = "$$DummyIndicator$$"
            dummy_indicator[SNXIocParse.SNX_RELATIONSHIPS_KEY] = relationships_list

    except Exception as e:
        raise DemistoException(e)
    return dummy_indicator


def getIndicatorsCommand(client: Client, args: dict[str, int]) -> CommandResults:
    count = arg_to_number(args.get("limit")) or 2
    feedJson, err_msg = client.get_feeds(None)
    if feedJson:
        indicatorList = parseIndicators(feedJson)
        finalIndicatorList = indicatorList[:count]
        readableOutput = tableToMarkdown(
            "SecneurX Threat Feeds Indicators: ", t=finalIndicatorList, headers=["type", "value", "fields"]
        )
        command_result = CommandResults(
            outputs_prefix="", outputs_key_field="", outputs={}, readable_output=readableOutput, raw_response=finalIndicatorList
        )
        return command_result
    else:
        msg = None
        try:
            if err_msg.res.status_code == 403:
                msg = "Authorization Error: make sure API Key (or) Feed URL is correctly set"
            elif err_msg.res.status_code == 401:
                msg = "Authorization Error: API Key is expired"
            else:
                msg = "Configuration Error"
        except Exception:
            msg = "Endpoint Error: Invalid Feed URL"
        raise DemistoException(msg)


def fetchThreatFeeds(client: Client, feed_date: Optional[str] = None) -> Any:
    feedJson, err_msg = client.get_feeds(feed_date)
    if feedJson:
        indicators = parseIndicators(feedJson)
        return indicators
    else:
        return None


def getListOfDays(startDate, endDate) -> List:
    daysList = []
    try:
        daysData = endDate - startDate
        daysCount = daysData.days
        if daysCount == 0:
            daysList.append(endDate.strftime("%Y%m%d"))
            return daysList
        else:
            for _i in range(daysCount):
                day = startDate + timedelta(days=1)
                daysList.append(day.strftime("%Y%m%d"))
                startDate = day

    except Exception as e:
        demisto.error(e)
    return daysList


def fetchFeedDates(firstFetchDate, firstFetchValue):
    startDate = None
    endDate = None
    if not firstFetchDate:
        startDateValue, endDateValue = parse_date_range(firstFetchValue)
        startDate = startDateValue.date()
        endDate = endDateValue.date()
    else:
        startDate = datetime.strptime(firstFetchDate, "%Y-%m-%d")
        startDate = startDate.date()
        endDate = datetime.now().date()
    return startDate, endDate


def createIndicatorsInDemisto(client: Client, dateList, test_case):
    for i in dateList:
        indicatorList = fetchThreatFeeds(client, i)
        if indicatorList and len(indicatorList) > 0:
            if not test_case:
                demisto.createIndicators(indicatorList)
        else:
            return False
    return True


def main():
    api_key = demisto.params().get("apikey")
    base_url = urljoin(demisto.params().get("url"), "/API/v1")
    verify_certificate = not demisto.params().get("insecure", False)
    proxy = demisto.params().get("proxy", False)
    demisto.debug(f"Command being called is {demisto.command()}")
    try:
        headers = {"x-api-key": f"{api_key}"}
        client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy)
        firstFetchDate = None
        firstFetchValue = demisto.params().get("first_fetch")
        integrationCache = demisto.getIntegrationContext()
        if "first_fetch_date" in integrationCache:
            firstFetchDate = integrationCache.get("first_fetch_date")

        if demisto.command() == "test-module":
            result = test_module(client)
            return_results(result)

        elif demisto.command() == "snxfeeds-get-indicators":
            return_results(getIndicatorsCommand(client, demisto.args()))

        elif demisto.command() == "fetch-indicators":
            startDate, endDate = fetchFeedDates(firstFetchDate, firstFetchValue)
            dateList = getListOfDays(startDate, endDate)
            bRet = createIndicatorsInDemisto(client, dateList, False)
            if bRet is True:
                demisto.info("Successfully created the indicators")
                endDateFormat = endDate.strftime("%Y-%m-%d")
                demisto.setIntegrationContext({"first_fetch_date": str(endDateFormat)})
            else:
                raise DemistoException("Cannot create the indicators in demisto")

    except Exception as e:
        demisto.error(traceback.format_exc())
        return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}")


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()