Cyjax Feed
The feed allows customers to pull indicators of compromise from cyber incidents (IP addresses, URLs, domains, CVE and file hashes).
Data Enrichment & Threat Intelligence · Cyjax Feed · Feed
Details
| ID | Cyjax Feed |
|---|---|
| Provider | CYJAX |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/cyjax:1.0.0.10133006 |
| Supported Modules | Agentix XSIAM |
README
The feed allows customers to pull indicators of compromise from cyber incidents (IP addresses, URLs, domains, CVEs, and file hashes).
CYJAX API token
- Log in to CYJAX threat intelligence portal.
- On the top navigation bar, hover the cursor over your user icon and go to Profile Settings.
- Open the API tokens tab.
- Generate a new token and enable the Indicators API scope.
- Record the API token, as it will not be accessible after the window is closed.
Feed installation
- Navigate to Settings > Integrations > Servers & Services.
- Search for Cyjax Feed.
- Click Add instance to create and configure a new integration instance.
Configuration
- Enter feed name, e.g.,
CYJAX Feed. - API URL:
https://api.cymon.co/v2. - Enter CYJAX API token.
- Set proxy if required by your installation.
- Indicator reputation (the reputation assigned to the indicators fetched from this feed; the default is Suspicious).
- Source reliability: A - Completely reliable.
- Traffic Light Protocol Color - The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed.
- Use CYJAX feed TLP (selected by default) - Whether to use the TLP set by CYJAX. This will override the TLP set above.
- Set feed tags (optional, comma-delimited, e.g., MyTag, YourTag).
- Set Indicator Expiration Method (default is never).
- Set fetch interval (default is to fetch every 1 hour).
- First fetch time. The time interval for the first fetch (retroactive). The default is 3 days.
- Test connection.
- Click done to save.
Commands
You can execute these commands from the Cortex XSOAR CLI, as part of automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
!cyjax-get-indicators
Get indicators from the CYJAX API.
| Argument | Description | Required |
|---|---|---|
| since | The start date time in ISO 8601 format | Optional |
| until | The end date time in ISO 8601 format | Optional |
| type | The indicator type. If not specified all indicators are returned. Allowed values are IPv4, IPv6, Domain, Hostname, Email, FileHash-SHA1, FileHash-SHA256, FileHash-MD5, FileHash-SSDEEP | Optional |
| source_type | The indicator source type. Allowed values are incident-report, my-report | Optional |
| source_id | The indicator source ID | Optional |
| limit | The maximum number of indicators to get. The default value is 50. | Optional |
Example: !cyjax-get-indicators since=2020-10-23T00:00:00 type=IPv4
!cyjax-indicator-sighting
Get the CYJAX sighting of an indicator.
| Argument | Description | Required |
|---|---|---|
| value | The indicator value | Required |
Example: !cyjax-indicator-sighting value=176.117.5.126
!cyjax-unset-indicators-last-fetch-date
Unset the indicators feed last fetch date. Should only be used if a user needs to use the re-fetch button
and wants to fetch old indicators from CYJAX. The next feed will use the date set in first_fetch (default is the last 3 days).
Configuration parameters
url— Cyjax API URL (required)apikey— API Key (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsfeed— Fetch indicatorsfeedReputation— Indicator ReputationfeedReliability— Source Reliability (required)tlp_color— Traffic Light Protocol Coloruse_cyjax_tlp— Use Cyjax feed TLPfeedTags— TagsfeedExpirationPolicy—feedExpirationInterval—feedIncremental— Incremental FeedfeedBypassExclusionList— Bypass exclusion listfeedFetchInterval— Feed Fetch Intervalfirst_fetch— First fetch time (required)
Commands (3)
-
cyjax-get-indicatorsGet indicators.
-
cyjax-indicator-sightingGet sighting of a indicator.
-
cyjax-unset-indicators-last-fetch-dateUnset the indicators feed last fetch date. Should only be used if user needs to use `re-fetch` button and wants to fetch old indicators from CYJAX. Next feed will use date set in first_fetch (default is last 3 days).
from datetime import datetime, timedelta, timezone import dateparser import demistomock as demisto from CommonServerPython import * from FeedCyjax import ( DATE_FORMAT, INDICATORS_LAST_FETCH_KEY, INDICATORS_LIMIT, Client, UnauthorizedException, convert_cyjax_indicator, fetch_indicators_command, get_indicators_command, get_indicators_last_fetch_date, indicator_sighting_command, main, map_indicator_type, map_reputation_to_score, set_indicators_last_fetch_date, ) from FeedCyjax import test_module as module_test from test_data.enrichment import mocked_enrichment from test_data.indicators import mocked_indicators client_for_testing = Client(None, "test-xsoar-api-token") default_reputation = "Suspicious" def test_constants(): assert INDICATORS_LAST_FETCH_KEY == "last_fetch" assert DATE_FORMAT == "%Y-%m-%dT%H:%M:%SZ" assert INDICATORS_LIMIT == 50 def test_map_reputation_to_score(): assert map_reputation_to_score("Unknown") == 0 assert map_reputation_to_score("None") == 0 assert map_reputation_to_score("Good") == 1 assert map_reputation_to_score("Suspicious") == 2 assert map_reputation_to_score("Bad") == 3 def test_map_indicator_type(): assert map_indicator_type("IPv4") == FeedIndicatorType.IP assert FeedIndicatorType.IPv6 == map_indicator_type("IPv6") assert map_indicator_type("URL") == FeedIndicatorType.URL assert FeedIndicatorType.Email == map_indicator_type("Email") assert FeedIndicatorType.Domain == map_indicator_type("Domain") assert FeedIndicatorType.Domain == map_indicator_type("Hostname") assert FeedIndicatorType.File == map_indicator_type("FileHash-SHA1") assert FeedIndicatorType.File == map_indicator_type("FileHash-SHA256") assert FeedIndicatorType.File == map_indicator_type("FileHash-MD5") assert FeedIndicatorType.SSDeep == map_indicator_type("FileHash-SSDEEP") assert None is map_indicator_type("IP") assert None is map_indicator_type("invalid") def test_get_incidents_last_fetch_date(mocker): date = datetime(2020, 6, 17, 15, 20, 10, tzinfo=timezone.utc) # noqa: UP017 timestamp = int(date.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: str(timestamp)}) last_fetch_date = get_indicators_last_fetch_date() assert isinstance(last_fetch_date, datetime) last_timestamp = int(last_fetch_date.timestamp()) assert timestamp == last_timestamp def test_get_incidents_last_fetch_timestamp_on_fist_fetch(mocker): three_days_ago = datetime.now() - timedelta(days=3) three_days_ago_timestamp = int(three_days_ago.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={}) last_fetch_date = get_indicators_last_fetch_date() assert isinstance(last_fetch_date, datetime) last_timestamp = int(last_fetch_date.timestamp()) assert three_days_ago_timestamp <= last_timestamp def test_set_indicators_last_fetch_date(mocker): mocker.patch.object(demisto, "getIntegrationContext", return_value={}) assert demisto.getIntegrationContext() == {} date = datetime(2020, 6, 17, 15, 20, 10, tzinfo=timezone.utc) # noqa: UP017 timestamp = int(date.timestamp()) set_indicators_last_fetch_date(timestamp) assert demisto.getIntegrationContext() == {INDICATORS_LAST_FETCH_KEY: timestamp} def test_set_indicators_last_fetch_date_does_not_break_existing_context(mocker): mocker.patch.object(demisto, "getIntegrationContext", return_value={"Test": True, "Value": 12345}) assert demisto.getIntegrationContext() == {"Test": True, "Value": 12345} date = datetime(2020, 6, 17, 15, 20, 10, tzinfo=timezone.utc) # noqa: UP017 timestamp = int(date.timestamp()) set_indicators_last_fetch_date(timestamp) context = demisto.getIntegrationContext() assert context.get(INDICATORS_LAST_FETCH_KEY) == timestamp assert context.get("Test") is True assert context.get("Value") == 12345 def test_convert_cyjax_indicator_with_default_score(): cyjax_indicator = mocked_indicators[0] indicator_date = dateparser.parse(cyjax_indicator.get("discovered_at")) xsoar_indicator = convert_cyjax_indicator(cyjax_indicator) assert xsoar_indicator.get("value") == cyjax_indicator.get("value") assert xsoar_indicator.get("rawJSON") == cyjax_indicator assert xsoar_indicator.get("type") == FeedIndicatorType.URL assert xsoar_indicator.get("score") == 2 assert indicator_date.strftime(DATE_FORMAT) == xsoar_indicator["fields"]["firstseenbysource"] assert cyjax_indicator["geoip"]["country_name"] == xsoar_indicator["fields"]["geocountry"] assert cyjax_indicator["geoip"]["city_name"] == xsoar_indicator["fields"]["city"] assert xsoar_indicator["fields"]["geolocation"] == "Lon: 37.7759, Lat: 47.9917" assert cyjax_indicator["ttp"] == xsoar_indicator["fields"]["cyjaxtechniquestacticsprocedures"] assert cyjax_indicator["industry_type"] == xsoar_indicator["fields"]["cyjaxindustrytypes"] assert cyjax_indicator["source"] == xsoar_indicator["fields"]["source"] assert cyjax_indicator["description"] == xsoar_indicator["fields"]["description"] assert cyjax_indicator["handling_condition"] == xsoar_indicator["fields"]["trafficlightprotocol"] def test_convert_cyjax_indicator_with_set_score(): cyjax_indicator = mocked_indicators[1] xsoar_indicator = convert_cyjax_indicator(cyjax_indicator, map_reputation_to_score("Bad")) assert xsoar_indicator.get("value") == cyjax_indicator.get("value") assert xsoar_indicator.get("rawJSON") == cyjax_indicator assert FeedIndicatorType.File == xsoar_indicator.get("type") assert xsoar_indicator.get("score") == 3 def test_test_module(mocker): ioc_mock = mocker.MagicMock() ioc_mock.list.return_value = [] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", return_value=ioc_mock) assert module_test(client_for_testing) == "ok" mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", side_effect=Exception("Invalid Api Key")) assert module_test(client_for_testing) == "Could not connect to Cyjax API (Invalid Api Key)" def test_fetch_indicators_command(mocker): cyjax_indicator = mocked_indicators mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=cyjax_indicator) last_fetch = datetime(2020, 12, 30, 15, 38) last_fetch_timestamp = int(last_fetch.timestamp()) result = fetch_indicators_command(client_for_testing, last_fetch, default_reputation) assert isinstance(result, tuple) next_run, incidents = result assert last_fetch_timestamp != next_run assert next_run != "1640988032" assert next_run == 1640988032 expected_indicators = [ convert_cyjax_indicator(cyjax_indicator[0]), convert_cyjax_indicator(cyjax_indicator[1]), convert_cyjax_indicator(cyjax_indicator[2]), convert_cyjax_indicator(cyjax_indicator[3]), ] assert isinstance(incidents, list) assert expected_indicators == incidents assert len(incidents) == 4 def test_fetch_indicators_no_new_indicators(mocker): mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[]) last_fetch = datetime(2020, 12, 30, 15, 38) last_fetch_timestamp = int(last_fetch.timestamp()) result = fetch_indicators_command(client_for_testing, last_fetch, default_reputation) assert isinstance(result, tuple) next_run, incidents = result assert last_fetch_timestamp == next_run assert isinstance(incidents, list) assert incidents == [] assert len(incidents) == 0 def test_fetch_indicators_when_skd_throws_error(mocker): mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", side_effect=Exception("Not found")) last_fetch = datetime(2020, 12, 30, 15, 38) last_fetch_timestamp = int(last_fetch.timestamp()) result = fetch_indicators_command(client_for_testing, last_fetch, default_reputation) assert isinstance(result, tuple) next_run, incidents = result assert last_fetch_timestamp == next_run assert isinstance(incidents, list) assert incidents == [] assert len(incidents) == 0 def test_get_indicators_command_arguments_specified(mocker): client = client_for_testing list_call_spy = mocker.spy(client, "fetch_indicators") cyjax_indicator = mocked_indicators list_mock = mocker.MagicMock() list_mock.list.return_value = cyjax_indicator mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", return_value=list_mock) mocker.patch.object( demisto, "args", return_value={ "since": "2020-10-10", "until": "2021-01-15", "type": "URL", "source_type": "incident-report", "source_id": "50000", "limit": "12", }, ) result = get_indicators_command(client_for_testing, demisto.args()) list_call_spy.assert_called_with( since="2020-10-10T00:00:00Z", until="2021-01-15T00:00:00Z", indicator_type="URL", source_type="incident-report", source_id=50000, limit=12, ) assert isinstance(result, dict) def test_get_indicators_command_without_arguments_specified(mocker): client = client_for_testing list_call_spy = mocker.spy(client, "fetch_indicators") cyjax_indicator = mocked_indicators list_mock = mocker.MagicMock() list_mock.list.return_value = cyjax_indicator mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", return_value=list_mock) result = get_indicators_command(client_for_testing, demisto.args()) list_call_spy.assert_called_with(since=None, until=None, indicator_type=None, source_type=None, source_id=None, limit=50) assert isinstance(result, dict) def test_get_indicators_command_response(mocker): cyjax_indicator = mocked_indicators mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=cyjax_indicator) result = get_indicators_command(client_for_testing, demisto.args()) assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN expected_indicators = [ convert_cyjax_indicator(cyjax_indicator[0]), convert_cyjax_indicator(cyjax_indicator[1]), convert_cyjax_indicator(cyjax_indicator[2]), convert_cyjax_indicator(cyjax_indicator[3]), ] assert expected_indicators == result.get("Contents") def test_indicator_sighting_command_response(mocker): mocker.patch.object( demisto, "args", return_value={ "value": "236.516.247.352", }, ) mocked_response = mocked_enrichment mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.enrichment", return_value=mocked_response) result = indicator_sighting_command(client_for_testing, demisto.args()) assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN expected_contents = mocked_response.get("sightings") assert expected_contents == result.get("Contents") def test_indicator_sighting_command_response_not_found(mocker): mocker.patch.object( demisto, "args", return_value={ "value": "236.516.247.352", }, ) mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.enrichment", side_effect=Exception("Invalid indicator")) result = indicator_sighting_command(client_for_testing, demisto.args()) assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" not in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN assert result.get("Contents") == [] """ MAIN COMMAND FUNCTIONS TEST""" def test_fetch_indicators_main_command_call(mocker): mocker.patch.object( demisto, "params", return_value={"apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com", "use_cyjax_tlp": True}, ) last_fetch = datetime(2020, 12, 27, 15, 45) last_fetch_timestamp = int(last_fetch.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: last_fetch_timestamp}) cyjax_indicator = mocked_indicators expected_indicators = [ convert_cyjax_indicator(cyjax_indicator[0]), convert_cyjax_indicator(cyjax_indicator[1]), convert_cyjax_indicator(cyjax_indicator[2]), convert_cyjax_indicator(cyjax_indicator[3]), ] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=cyjax_indicator) mocker.patch.object(demisto, "command", return_value="fetch-indicators") mocker.patch.object(demisto, "createIndicators") mocker.patch.object(demisto, "setIntegrationContext") main() assert demisto.createIndicators.call_count == 1 assert demisto.setIntegrationContext.call_count == 1 demisto.createIndicators.assert_called_with(expected_indicators) demisto.setIntegrationContext.assert_called_with({"last_fetch": 1640988032}) def test_fetch_indicators_main_command_call_no_new_indicators(mocker): mocker.patch.object(demisto, "params", return_value={"apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com"}) last_fetch = datetime(2020, 12, 27, 15, 45) last_fetch_timestamp = int(last_fetch.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: last_fetch_timestamp}) mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[]) mocker.patch.object(demisto, "command", return_value="fetch-indicators") mocker.patch.object(demisto, "createIndicators") mocker.patch.object(demisto, "setIntegrationContext") main() assert demisto.createIndicators.call_count == 0 assert demisto.setIntegrationContext.call_count == 0 demisto.createIndicators.assert_not_called() demisto.setIntegrationContext.assert_not_called() def test_fetch_indicators_main_command_call_use_cyjax_tlp(mocker): mocker.patch.object( demisto, "params", return_value={ "apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com", "use_cyjax_tlp": True, "tlp_color": "AMBER", }, ) last_fetch = datetime(2020, 12, 27, 15, 45) last_fetch_timestamp = int(last_fetch.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: last_fetch_timestamp}) cyjax_indicator = mocked_indicators expected_indicators = [convert_cyjax_indicator(cyjax_indicator[1])] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[cyjax_indicator[1]]) mocker.patch.object(demisto, "command", return_value="fetch-indicators") mocker.patch.object(demisto, "createIndicators") mocker.patch.object(demisto, "setIntegrationContext") main() assert demisto.createIndicators.call_count == 1 assert demisto.setIntegrationContext.call_count == 1 demisto.createIndicators.assert_called_with(expected_indicators) assert expected_indicators[0]["fields"]["trafficlightprotocol"] == "GREEN" def test_fetch_indicators_main_command_call_use_set_tlp(mocker): mocker.patch.object( demisto, "params", return_value={ "apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com", "use_cyjax_tlp": False, "tlp_color": "AMBER", }, ) last_fetch = datetime(2020, 12, 27, 15, 45) last_fetch_timestamp = int(last_fetch.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: last_fetch_timestamp}) cyjax_indicator = mocked_indicators expected_indicators = [convert_cyjax_indicator(cyjax_indicator[1], None, "AMBER")] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[cyjax_indicator[1]]) mocker.patch.object(demisto, "command", return_value="fetch-indicators") mocker.patch.object(demisto, "createIndicators") mocker.patch.object(demisto, "setIntegrationContext") main() assert demisto.createIndicators.call_count == 1 assert demisto.setIntegrationContext.call_count == 1 demisto.createIndicators.assert_called_with(expected_indicators) assert expected_indicators[0]["fields"]["trafficlightprotocol"] == "AMBER" def test_fetch_indicators_main_command_call_use_tags(mocker): mocker.patch.object( demisto, "params", return_value={ "apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com", "use_cyjax_tlp": True, "feedTags": "TestTag, YellowTag", }, ) last_fetch = datetime(2020, 12, 27, 15, 45) last_fetch_timestamp = int(last_fetch.timestamp()) mocker.patch.object(demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: last_fetch_timestamp}) cyjax_indicator = mocked_indicators expected_indicators = [convert_cyjax_indicator(cyjax_indicator[1], None, None, "TestTag, YellowTag")] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[cyjax_indicator[1]]) mocker.patch.object(demisto, "command", return_value="fetch-indicators") mocker.patch.object(demisto, "createIndicators") mocker.patch.object(demisto, "setIntegrationContext") main() assert demisto.createIndicators.call_count == 1 assert demisto.setIntegrationContext.call_count == 1 demisto.createIndicators.assert_called_with(expected_indicators) assert expected_indicators[0]["fields"]["tags"] == "TestTag, YellowTag" def test_get_indicators_main_command_call_with_one_new_indicator(mocker): mocker.patch.object(demisto, "params", return_value={"apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com"}) mocker.patch.object( demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: int(datetime(2020, 12, 27, 15, 45).timestamp())}, ) cyjax_indicator = mocked_indicators expected_indicators = [convert_cyjax_indicator(cyjax_indicator[0])] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[cyjax_indicator[0]]) mocker.patch.object(demisto, "command", return_value="cyjax-get-indicators") mocker.patch.object(demisto, "results") main() assert demisto.results.call_count == 1 result = demisto.results.call_args[0][0] assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN assert expected_indicators == result.get("Contents") def test_since_date_in_get_indicators_command_no_new_indicators_found(mocker): client = client_for_testing fetch_indicators_spy = mocker.spy(client, "fetch_indicators") last_fetch = datetime(2020, 12, 27, 15, 0, 0, 0) last_fetch_timestamp = int(last_fetch.timestamp()) expected_since = datetime(2020, 12, 27, 15, 0, 1, 0) mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=[]) next_run, indicators = fetch_indicators_command(client_for_testing, last_fetch, "good") fetch_indicators_spy.assert_called_with(since=expected_since.isoformat()) assert indicators == [] assert last_fetch_timestamp == next_run def test_since_date_in_get_indicators_command_new_indicators_found(mocker): client = client_for_testing fetch_indicators_spy = mocker.spy(client, "fetch_indicators") last_fetch = datetime(2020, 12, 31, 15, 0, 0, 0) expected_since = datetime(2020, 12, 31, 15, 0, 1, 0) cyjax_indicator = mocked_indicators mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=cyjax_indicator) next_run, indicators = fetch_indicators_command(client_for_testing, last_fetch, "good") fetch_indicators_spy.assert_called_with(since=expected_since.isoformat()) assert next_run == 1640988032 def test_get_indicators_main_command_call_no_new_indicators(mocker): mocker.patch.object(demisto, "params", return_value={"apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com"}) mocker.patch.object( demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: int(datetime(2020, 12, 27, 15, 45).timestamp())}, ) cyjax_indicator = mocked_indicators expected_indicators = [ convert_cyjax_indicator(cyjax_indicator[0]), convert_cyjax_indicator(cyjax_indicator[1]), convert_cyjax_indicator(cyjax_indicator[2]), convert_cyjax_indicator(cyjax_indicator[3]), ] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.list", return_value=cyjax_indicator) mocker.patch.object(demisto, "command", return_value="cyjax-get-indicators") mocker.patch.object(demisto, "results") main() assert demisto.results.call_count == 1 result = demisto.results.call_args[0][0] assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN assert expected_indicators == result.get("Contents") def test_test_module_main_command_call(mocker): ioc_mock = mocker.MagicMock() ioc_mock.list.return_value = [] mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", return_value=ioc_mock) mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(demisto, "results") main() assert demisto.results.call_count == 1 assert demisto.results.call_args[0][0] == "ok" mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", side_effect=Exception("Server not responding")) main() assert demisto.results.call_count == 2 assert demisto.results.call_args[0][0] == "Could not connect to Cyjax API (Server not responding)" def test_test_module_main_command_call_invalid_api_key(mocker): mocker.patch.object(demisto, "command", return_value="test-module") mocker.patch.object(demisto, "results") mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise", side_effect=UnauthorizedException()) main() assert demisto.results.call_count == 1 assert demisto.results.call_args[0][0] == "Could not connect to Cyjax API (Unauthorized)" def test_unset_indicators_last_fetch_date_main_command_call(mocker): mocker.patch.object( demisto, "getIntegrationContext", return_value={INDICATORS_LAST_FETCH_KEY: 1640988032, "Something": "Else"} ) assert demisto.getIntegrationContext() == {INDICATORS_LAST_FETCH_KEY: 1640988032, "Something": "Else"} mocker.patch.object(demisto, "command", return_value="cyjax-unset-indicators-last-fetch-date") mocker.patch.object(demisto, "results") main() assert demisto.results.call_count == 1 assert demisto.getIntegrationContext() == {"Something": "Else"} def test_indicators_sigthing_main_command_call(mocker): mocker.patch.object(demisto, "params", return_value={"apikey": "test-api-key", "url": "https://cyjax-api-for-testing.com"}) mocker.patch.object( demisto, "args", return_value={ "value": "236.516.247.352", }, ) mocked_response = mocked_enrichment mocker.patch("FeedCyjax.cyjax_sdk.IndicatorOfCompromise.enrichment", return_value=mocked_response) mocker.patch.object(demisto, "command", return_value="cyjax-indicator-sighting") mocker.patch.object(demisto, "results") main() assert demisto.results.call_count == 1 result = demisto.results.call_args[0][0] assert isinstance(result, dict) assert "Type" in result assert "ContentsFormat" in result assert "Contents" in result assert "ReadableContentsFormat" in result assert "HumanReadable" in result assert "EntryContext" in result assert result.get("Type") == EntryType.NOTE assert result.get("ContentsFormat") == EntryFormat.JSON assert result.get("ReadableContentsFormat") == EntryFormat.MARKDOWN expected_sightings = mocked_response.get("sightings") assert expected_sightings == result.get("Contents")