import pytest
def create_client():
import os
from RecordedFuture import Client
base_url = "https://api.recordedfuture.com/gw/xsoar/"
verify_ssl = True
token = os.environ.get("RF_TOKEN")
headers = {
"X-RFToken": token,
"X-RF-User-Agent": "RecordedFuture.py/2.4 (Linux-5.13.0-1031-aws-x86_64-with) "
"XSOAR/2.4 RFClient/2.4 (Cortex_XSOAR_6.5.0)",
}
return Client(base_url=base_url, verify=verify_ssl, headers=headers, proxy=False)
class TestHelpers:
def test_translate_score(self):
from RecordedFuture import translate_score
from CommonServerPython import Common
test_cases = [
(10, 0, 25, Common.DBotScore.BAD, "Score above 0"),
(10, 10, 25, Common.DBotScore.BAD, "Score above 10"),
(40, 40, 25, Common.DBotScore.BAD, "Score above 40"),
(45, 40, 25, Common.DBotScore.BAD, "Score above 40"),
(10, -1, 25, Common.DBotScore.BAD, "Score above -1"),
(25, -1, 25, Common.DBotScore.BAD, "Score above -1"),
(26, -1, 25, Common.DBotScore.BAD, "Score above -1"),
(25, 40, 25, Common.DBotScore.SUSPICIOUS, "Score above 25"),
(26, 40, 25, Common.DBotScore.SUSPICIOUS, "Score above 25"),
(50, 65, 50, Common.DBotScore.SUSPICIOUS, "Score above 50"),
(10, 11, 25, Common.DBotScore.NONE, ""),
(24, 40, 25, Common.DBotScore.NONE, ""),
(45, 65, 50, Common.DBotScore.NONE, ""),
]
for (
score,
threshold_bad,
threshold_suspicious,
expected_score,
expected_description,
) in test_cases:
dbot_score_details = translate_score(
score=score,
threshold_bad=threshold_bad,
threshold_suspicious=threshold_suspicious,
)
assert dbot_score_details.score == expected_score
assert dbot_score_details.description == expected_description
def test_translate_score_benign(self):
from RecordedFuture import translate_score
from CommonServerPython import Common
# A benign signal with no risk score maps to GOOD.
dbot_score_details = translate_score(
score=0,
threshold_bad=65,
threshold_suspicious=25,
benign=True,
)
assert dbot_score_details.score == Common.DBotScore.GOOD
assert dbot_score_details.description == "No Risk Observed"
# Malicious/suspicious scores still take precedence over the benign flag.
assert translate_score(score=70, threshold_bad=65, threshold_suspicious=25, benign=True).score == Common.DBotScore.BAD
assert (
translate_score(score=30, threshold_bad=65, threshold_suspicious=25, benign=True).score == Common.DBotScore.SUSPICIOUS
)
# Without the benign flag, a zero score stays Unknown (None).
assert translate_score(score=0, threshold_bad=65, threshold_suspicious=25, benign=False).score == Common.DBotScore.NONE
def test_is_benign_action(self):
from RecordedFuture import is_benign_action
def action(entity_type, score, evidence):
return {
"create_indicator": {
"entity": "x",
"entity_type": entity_type,
"score": score,
},
"CommandResults": {"outputs": {"Evidence": evidence}},
}
no_risk = [{"rule": "No Risk Observed", "ruleid": "noKnownRisk"}]
some_risk = [{"rule": "Historically Reported in Threat List", "ruleid": "historicalThreatListMembership"}]
# noKnownRisk on the eligible types -> benign.
assert is_benign_action(action("file", 0, no_risk)) is True
assert is_benign_action(action("url", 0, no_risk)) is True
assert is_benign_action(action("domain", 0, no_risk)) is True
# Empty evidence at score 0 is genuine "Unknown", not benign.
assert is_benign_action(action("domain", 0, [])) is False
# A real risk rule is not benign.
assert is_benign_action(action("domain", 24, some_risk)) is False
# ip/cve are out of scope even with the signal.
assert is_benign_action(action("ip", 0, no_risk)) is False
# Defensive: missing CommandResults/outputs must not raise.
assert is_benign_action({"create_indicator": {"entity_type": "domain", "score": 0}}) is False
@pytest.mark.parametrize(
"demisto_params,expected_bad,expected_suspicious",
[
(
{},
{
"file": 65,
"ip": 65,
"domain": 65,
"url": 65,
"cve": 65,
},
{
"file": 25,
"ip": 25,
"domain": 25,
"url": 25,
"cve": 25,
},
),
(
{
"file_threshold": "",
"ip_threshold": "70",
"domain_threshold": "65",
"url_threshold": "65",
"cve_threshold": "65",
"file_threshold_suspicious": None,
"ip_threshold_suspicious": "30",
"domain_threshold_suspicious": "25",
"url_threshold_suspicious": "25",
"cve_threshold_suspicious": "25",
},
{
"file": 65,
"ip": 70,
"domain": 65,
"url": 65,
"cve": 65,
},
{
"file": 25,
"ip": 30,
"domain": 25,
"url": 25,
"cve": 25,
},
),
],
)
def test_get_indicator_thresholds_uses_defaults_for_missing_or_empty_values(
self, mocker, demisto_params, expected_bad, expected_suspicious
):
import demistomock as demisto
from RecordedFuture import get_indicator_thresholds
mock_params = mocker.patch.object(demisto, "params")
mock_params.return_value = demisto_params
indicator_thresholds = get_indicator_thresholds(demisto.params())
assert indicator_thresholds.bad == expected_bad
assert indicator_thresholds.suspicious == expected_suspicious
@pytest.mark.parametrize(
"demisto_params",
[
{
"file_threshold": "abc",
"ip_threshold": "65",
"domain_threshold": "65",
"url_threshold": "65",
"cve_threshold": "65",
"file_threshold_suspicious": "25",
"ip_threshold_suspicious": "25",
"domain_threshold_suspicious": "25",
"url_threshold_suspicious": "25",
"cve_threshold_suspicious": "25",
},
{
"file_threshold": "65",
"ip_threshold": "65",
"domain_threshold": "65",
"url_threshold": "65",
"cve_threshold": "65",
"file_threshold_suspicious": "25",
"ip_threshold_suspicious": "25",
"domain_threshold_suspicious": "25",
"url_threshold_suspicious": "abc",
"cve_threshold_suspicious": "25",
},
],
)
def test_get_indicator_thresholds_raises_for_invalid_values(self, mocker, demisto_params):
import demistomock as demisto
from CommonServerPython import DemistoException
from RecordedFuture import get_indicator_thresholds
mocker.patch.object(demisto, "params", return_value=demisto_params)
with pytest.raises(DemistoException, match="Invalid threshold configuration"):
get_indicator_thresholds(demisto.params())
def test_determine_hash(self):
from RecordedFuture import determine_hash
assert determine_hash(hash_value="s" * 128) == "SHA512"
assert determine_hash(hash_value="s" * 64) == "SHA256"
assert determine_hash(hash_value="s" * 40) == "SHA1"
assert determine_hash(hash_value="s" * 32) == "MD5"
assert determine_hash(hash_value="s" * 8) == "CRC32"
assert determine_hash(hash_value="s" * 50) == "CTPH"
assert determine_hash(hash_value="s" * 10) == "CTPH"
assert determine_hash(hash_value="s") == "CTPH"
def test_create_indicator_ip(self, mocker):
from RecordedFuture import create_indicator
from CommonServerPython import Common, DBotScoreType
mock_return_value = mocker.Mock()
mocker.patch("CommonServerPython.Common.IP", return_value=mock_return_value)
dbot_score_spy = mocker.spy(Common, "DBotScore")
entity = "8.8.8.8"
entity_type = "ip"
score = 45
description = "test_description"
location = {"asn": "test_asn", "location": {"country": "test_country"}}
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
location=location,
)
assert result == mock_return_value
dbot_score_spy.assert_called_once_with(
entity,
DBotScoreType.IP,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.IP.mock_calls[0]
assert mock_call.args[0] == entity
assert mock_call.args[1].indicator == entity
# mock_call.args[1] - is Common.IP, and we verify it by dbot_score_spy.
# We can't assert it with `==` as the Common.IP does not implement `__eq__` method.
assert mock_call.kwargs == {
"asn": "test_asn",
"geo_country": "test_country",
}
def test_create_indicator_domain(self, mocker):
from RecordedFuture import create_indicator
from CommonServerPython import Common, DBotScoreType
mock_return_value = mocker.Mock()
mocker.patch("CommonServerPython.Common.Domain", return_value=mock_return_value)
dbot_score_spy = mocker.spy(Common, "DBotScore")
entity = "google.com"
entity_type = "domain"
score = 45
description = "test_description"
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_once_with(
entity,
DBotScoreType.DOMAIN,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.Domain.mock_calls[0]
assert mock_call.args[0] == entity
assert mock_call.args[1].indicator == entity
def test_create_indicator_url(self, mocker):
from RecordedFuture import create_indicator
from CommonServerPython import Common, DBotScoreType
mock_return_value = mocker.Mock()
mocker.patch("CommonServerPython.Common.URL", return_value=mock_return_value)
dbot_score_spy = mocker.spy(Common, "DBotScore")
entity = "https://google.com"
entity_type = "url"
score = 45
description = "test_description"
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_once_with(
entity,
DBotScoreType.URL,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.URL.mock_calls[0]
assert mock_call.args[0] == entity
assert mock_call.args[1].indicator == entity
def test_create_indicator_cve(self, mocker):
from RecordedFuture import create_indicator
from CommonServerPython import Common
mock_return_value = mocker.Mock()
mocker.patch("CommonServerPython.Common.CVE", return_value=mock_return_value)
entity = "CVE-123"
entity_type = "cve"
score = 45
description = "test_description"
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
mock_call = Common.CVE.mock_calls[0]
assert mock_call.args[0] == entity
assert mock_call.args[1] == ""
assert mock_call.args[2] == ""
assert mock_call.args[3] == ""
assert mock_call.args[4] == description
def test_create_indicator_file(self, mocker):
from RecordedFuture import create_indicator
from CommonServerPython import Common, DBotScoreType
mock_return_value = mocker.Mock()
mocker.patch("CommonServerPython.Common.File", return_value=mock_return_value)
dbot_score_spy = mocker.spy(Common, "DBotScore")
entity_type = "file"
score = 45
description = "test_description"
# MD5.
entity = "s" * 32
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_once_with(
entity,
DBotScoreType.FILE,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.File.mock_calls[0]
assert mock_call.args[0].indicator == entity
assert mock_call.kwargs.get("md5") == entity
# SHA1.
entity = "s" * 40
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_with(
entity,
DBotScoreType.FILE,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.File.mock_calls[-1]
assert mock_call.args[0].indicator == entity
assert mock_call.kwargs.get("sha1") == entity
# SHA256.
entity = "s" * 64
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_with(
entity,
DBotScoreType.FILE,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.File.mock_calls[-1]
assert mock_call.args[0].indicator == entity
assert mock_call.kwargs.get("sha256") == entity
# SHA512.
entity = "s" * 128
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_with(
entity,
DBotScoreType.FILE,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.File.mock_calls[-1]
assert mock_call.args[0].indicator == entity
assert mock_call.kwargs.get("sha512") == entity
# CRC32.
entity = "s" * 20 # Length different from any previous hashes.
result = create_indicator(
entity=entity,
entity_type=entity_type,
score=score,
description=description,
)
assert result == mock_return_value
dbot_score_spy.assert_called_with(
entity,
DBotScoreType.FILE,
"Recorded Future v2",
Common.DBotScore.SUSPICIOUS,
"Score above 25",
# reliability=DBotScoreReliability.B
reliability=None,
)
mock_call = Common.File.mock_calls[-1]
assert mock_call.args[0].indicator == entity
assert mock_call.kwargs == {}
class TestRFClient:
def test_whoami(self, mocker):
client = create_client()
mock_http_request = mocker.patch.object(client, "_http_request")
client.whoami()
mock_http_request.assert_called_once_with(
method="get",
url_suffix="info/whoami",
timeout=60,
)
def test_get_writeback_data_writeback_off(self, mocker):
"""
Test _get_writeback_data with writeback turned OFF.
"""
import demistomock as demisto
client = create_client()
mocker.patch.object(demisto, "params", return_value={"writeback": False})
assert client._get_writeback_data() is None
def test_get_writeback_data_writeback_on(self, mocker):
"""
Test _get_writeback_data with writeback turned ON.
"""
import demistomock as demisto
client = create_client()
mocker.patch.object(demisto, "params", return_value={"collective_insights": "On"})
demisto.callingContext = {"context": {"ExecutionContext": "to be removed", "Incidents": []}}
assert client._get_writeback_data() == {"context": {"Incidents": []}}
#
def test_call_writeback_on(self, mocker):
"""
Test _call() with writeback turned ON.
"""
import os
import demistomock as demisto
STATUS_TO_RETRY = [500, 501, 502, 503, 504]
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
# Mock data for writeback.
mocker.patch.object(
demisto,
"params",
return_value={
"collective_insights": "On",
},
)
mock_calling_context = {
"context": {"ExecutionContext": "to be removed", "Incidents": []},
"other": "data",
}
demisto.callingContext = mock_calling_context
client = create_client()
mock_http_request = mocker.patch.object(client, "_http_request")
mock_url_suffix = "mock_url_suffix"
client._call(url_suffix=mock_url_suffix)
json_data = {
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"callingContext": {
"context": {"Incidents": []},
},
}
mock_http_request.assert_called_once_with(
method="post",
url_suffix=mock_url_suffix,
json_data=json_data,
timeout=90,
retries=3,
status_list_to_retry=STATUS_TO_RETRY,
)
def test_call_writeback_off(self, mocker):
"""
Test _call() with writeback turned OFF.
"""
import os
import demistomock as demisto
STATUS_TO_RETRY = [500, 501, 502, 503, 504]
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
# Mock data for writeback.
mocker.patch.object(
demisto,
"params",
return_value={
"collective_insights": "Off",
},
)
mock_calling_context = {
"context": {"ExecutionContext": "to be removed", "other": "data"},
"other": "data",
}
demisto.callingContext = mock_calling_context
client = create_client()
mock_http_request = mocker.patch.object(client, "_http_request")
mock_url_suffix = "mock_url_suffix"
client._call(url_suffix=mock_url_suffix)
json_data = {
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
}
mock_http_request.assert_called_once_with(
method="post",
url_suffix=mock_url_suffix,
json_data=json_data,
timeout=90,
retries=3,
status_list_to_retry=STATUS_TO_RETRY,
)
def test_call_with_kwargs(self, mocker):
"""
Test _call() with kwargs.
"""
import os
import demistomock as demisto
STATUS_TO_RETRY = [500, 501, 502, 503, 504]
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_http_request = mocker.patch.object(client, "_http_request")
mock_url_suffix = "mock_url_suffix"
client._call(url_suffix=mock_url_suffix, timeout=120, any_other_kwarg=True)
json_data = {
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
}
mock_http_request.assert_called_once_with(
method="post",
url_suffix=mock_url_suffix,
json_data=json_data,
timeout=120,
retries=3,
status_list_to_retry=STATUS_TO_RETRY,
any_other_kwarg=True,
)
def test_call_returns_response(self, mocker):
"""
Test _call() returns response.
"""
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_response = {"response": {"data": "mock data"}}
mocker.patch.object(client, "_http_request", return_value=mock_response)
mock_url_suffix = "mock_url_suffix"
response = client._call(url_suffix=mock_url_suffix)
assert response == mock_response
def test_call_response_processing_return_error(self, mocker):
"""
Test _call() return_error response processing.
"""
import os
import demistomock as demisto
STATUS_TO_RETRY = [500, 501, 502, 503, 504]
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
mock_return_error = mocker.patch("RecordedFuture.return_error")
client = create_client()
mock_http_request = mocker.patch.object(
client,
"_http_request",
return_value={"return_error": {"message": "mock error"}},
)
mock_url_suffix = "mock_url_suffix"
client._call(url_suffix=mock_url_suffix)
json_data = {
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
}
mock_http_request.assert_called_once_with(
method="post",
url_suffix=mock_url_suffix,
json_data=json_data,
timeout=90,
retries=3,
status_list_to_retry=STATUS_TO_RETRY,
)
mock_return_error.assert_called_once_with(message="mock error")
def test_call_response_processing_404(self, mocker):
"""
Test _call() response processing.
"""
import os
import demistomock as demisto
from CommonServerPython import DemistoException, CommandResults
STATUS_TO_RETRY = [500, 501, 502, 503, 504]
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
mocker.patch("RecordedFuture.return_error")
client = create_client()
def mock_http_request_method(*args, **kwargs):
# Imitate how CommonServerPython handles bad responses (when status code not in ok_codes,
# or if ok_codes=None - it uses requests.Response.ok to check whether response is good).
raise DemistoException("404")
mocker.patch.object(client, "_http_request", mock_http_request_method)
spy_http_request = mocker.spy(client, "_http_request")
mock_url_suffix = "mock_url_suffix"
result = client._call(url_suffix=mock_url_suffix)
json_data = {
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
}
spy_http_request.assert_called_once_with(
method="post",
url_suffix=mock_url_suffix,
json_data=json_data,
timeout=90,
retries=3,
status_list_to_retry=STATUS_TO_RETRY,
)
assert isinstance(result, CommandResults)
assert result.outputs_prefix == ""
assert result.outputs_key_field == ""
assert result.outputs == {}
assert result.raw_response == {}
assert result.readable_output == "No results found."
def test_fetch_incidents(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mock_params = {"param1": "param1 value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
mocker.patch.object(demisto, "params", return_value=mock_params)
mock_last_run_dict = {"lastRun": "2022-08-31T12:12:20+00:00"}
mocker.patch.object(demisto, "getLastRun", return_value=mock_last_run_dict)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.fetch_incidents()
mock_call.assert_called_once_with(
json_data={
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"demisto_last_run": mock_last_run_dict,
"demisto_params": mock_params,
},
timeout=120,
url_suffix="/v2/alert/fetch_incidents",
)
assert response == mock_call_response
def test_entity_search(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.entity_search()
mock_call.assert_called_once_with(url_suffix="/v2/search")
assert response == mock_call_response
def test_get_intelligence(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_intelligence()
mock_call.assert_called_once_with(url_suffix="/v2/lookup/intelligence")
assert response == mock_call_response
def test_get_links(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_links()
mock_call.assert_called_once_with(url_suffix="/v2/lookup/links")
assert response == mock_call_response
def test_get_single_alert(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_single_alert()
mock_call.assert_called_once_with(url_suffix="/v2/alert/lookup")
assert response == mock_call_response
def test_get_alerts(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_alerts()
mock_call.assert_called_once_with(url_suffix="/v2/alert/search")
assert response == mock_call_response
def test_get_alert_rules(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_alert_rules()
mock_call.assert_called_once_with(url_suffix="/v2/alert/rule")
assert response == mock_call_response
def test_alert_set_status(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
alert_data = {"mock": "data"}
response = client.alert_set_status(alert_data)
mock_call.assert_called_once_with(
url_suffix="/v2/alert/set_status",
json_data={
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"alerts_update_data": alert_data,
},
)
assert response == mock_call_response
response = client.alert_set_status()
mock_call.assert_called_with(
url_suffix="/v2/alert/set_status",
json_data={
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"alerts_update_data": None,
},
)
assert response == mock_call_response
def test_alert_set_note(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
alert_data = {"mock": "data"}
response = client.alert_set_note(alert_data)
mock_call.assert_called_once_with(
url_suffix="/v2/alert/set_note",
json_data={
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"alerts_update_data": alert_data,
},
)
assert response == mock_call_response
response = client.alert_set_note()
mock_call.assert_called_with(
url_suffix="/v2/alert/set_note",
json_data={
"demisto_command": mock_command_name,
"demisto_args": mock_command_args,
"alerts_update_data": None,
},
)
assert response == mock_call_response
def test_get_triage(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "command_name"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "mock response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_triage()
mock_call.assert_called_once_with(url_suffix="/v2/lookup/triage")
assert response == mock_call_response
def test_get_threat_map(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "threat_map"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "threat map response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_threat_map()
mock_call.assert_called_once_with(url_suffix="/v2/threat/actors")
assert response == mock_call_response
def test_get_threat_links(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "threat_links"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "threat links response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_threat_links()
mock_call.assert_called_once_with(url_suffix="/v2/links/search")
assert response == mock_call_response
def test_get_detection_rules(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "detection_rules"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "detection rules response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.get_detection_rules()
mock_call.assert_called_once_with(url_suffix="/v2/detection_rules/search")
assert response == mock_call_response
def test_submit_collective_insight(self, mocker):
import os
import demistomock as demisto
# This is needed for CommonServerPython module to not add demisto.params() into callingContext.
os.environ["COMMON_SERVER_NO_AUTO_PARAMS_REMOVE_NULLS"] = "True"
# Mock demisto command and args.
mock_command_name = "collective_insight"
mock_command_args = {"arg1": "arg1_value", "arg2": "arg2_value"}
mocker.patch.object(demisto, "command", return_value=mock_command_name)
mocker.patch.object(demisto, "args", return_value=mock_command_args)
client = create_client()
mock_call_response = {"response": {"data": "collective insight response"}}
mock_call = mocker.patch.object(client, "_call", return_value=mock_call_response)
response = client.submit_detection_to_collective_insight()
mock_call.assert_called_once_with(url_suffix="/v2/collective-insights/detections")
assert response == mock_call_response
class TestActions:
def test_init(self, mocker):
from RecordedFuture import Actions
mock_client = mocker.Mock()
actions = Actions(mock_client)
assert actions.client == mock_client
def test_process_result_actions_404(self, mocker):
from RecordedFuture import Actions
from CommonServerPython import CommandResults
mock_client = mocker.Mock()
actions = Actions(mock_client)
# Test if response is CommandResults
# (case when we got 404 on response, and it was processed in self.client._call() method).
response = CommandResults(readable_output="Mock")
result_actions = actions._process_result_actions(response=response)
assert result_actions == [response]
def test_process_result_actions_response_is_not_dict(self, mocker):
from RecordedFuture import Actions
mock_client = mocker.Mock()
actions = Actions(mock_client)
# Test if response is not CommandResults and not Dict.
response = "Mock string - not CommandResults and not dict"
result_actions = actions._process_result_actions(response=response) # type: ignore
assert result_actions is None
def test_process_result_actions_no_or_empty_result_actions_in_response(self, mocker):
from RecordedFuture import Actions
mock_client = mocker.Mock()
actions = Actions(mock_client)
# Test no results_actions in response.
response = {"data": "mock"}
result_actions = actions._process_result_actions(response=response)
assert result_actions is None
# Test case when bool(results_actions) in response is False.
response = {"data": "mock", "result_actions": None}
result_actions = actions._process_result_actions(response=response)
assert result_actions is None
response = {"data": "mock", "result_actions": []}
result_actions = actions._process_result_actions(response=response)
assert result_actions is None
response = {"data": "mock", "result_actions": {}}
result_actions = actions._process_result_actions(response=response)
assert result_actions is None
def test_process_result_actions_command_results_only(self, mocker):
from RecordedFuture import Actions, CommandResults
mock_client = mocker.Mock()
actions = Actions(mock_client)
response = {
"data": "mock",
"result_actions": [
{
"CommandResults": {
"outputs_prefix": "mock_outputs_prefix",
"outputs": "mock_outputs",
"raw_response": "mock_raw_response",
"readable_output": "mock_readable_output",
"outputs_key_field": "mock_outputs_key_field",
},
}
],
}
result_actions = actions._process_result_actions(response=response)
assert len(result_actions) == 1
r_a = result_actions[0]
assert isinstance(r_a, CommandResults)
assert r_a.outputs_prefix == "mock_outputs_prefix"
assert r_a.outputs == "mock_outputs"
assert r_a.raw_response == "mock_raw_response"
assert r_a.readable_output == "mock_readable_output"
assert r_a.outputs_key_field == "mock_outputs_key_field"
def test_process_result_actions_create_indicator_and_default_command_results(self, mocker):
import RecordedFuture
spy_create_indicator = mocker.spy(
RecordedFuture,
"create_indicator",
)
mock_client = mocker.Mock()
actions = RecordedFuture.Actions(mock_client)
response = {
"data": "mock",
"result_actions": [
{
"create_indicator": {
"entity": "mock_entity",
"entity_type": "ip",
"score": 15,
"description": "mock_description",
"location": {"country": "mock_country", "ans": "mock_asn"},
},
}
],
}
result_actions = actions._process_result_actions(response=response)
spy_create_indicator.assert_called_once_with(
entity="mock_entity",
entity_type="ip",
score=15,
description="mock_description",
location={"country": "mock_country", "ans": "mock_asn"},
benign=False,
)
assert len(result_actions) == 1
r_a = result_actions[0]
assert isinstance(r_a, RecordedFuture.CommandResults)
assert r_a.readable_output == (
"### New indicator was created.\n"
"|DBotScore(val.Indicator && val.Indicator == obj.Indicator && val.Vendor == "
"obj.Vendor && val.Type == obj.Type)|IP(val.Address && val.Address == "
"obj.Address)|\n"
"|---|---|\n"
"| Indicator: mock_entity
Type: ip
Vendor: Recorded Future v2
Score: "
"0 | Address: mock_entity |\n"
)
def test_process_result_actions_create_indicator_and_command_results(self, mocker):
import RecordedFuture
spy_create_indicator = mocker.spy(
RecordedFuture,
"create_indicator",
)
mock_client = mocker.Mock()
actions = RecordedFuture.Actions(mock_client)
response = {
"data": "mock",
"result_actions": [
{
"create_indicator": {
"entity": "mock_entity",
"entity_type": "ip",
"score": 15,
"description": "mock_indicator_description",
},
"CommandResults": {
"outputs_prefix": "mock_outputs_prefix",
"outputs": "mock_outputs",
"raw_response": "mock_raw_response",
"readable_output": "mock_readable_output",
"outputs_key_field": "mock_outputs_key_field",
"indicator": "indicator",
},
}
],
}
result_actions = actions._process_result_actions(response=response)
spy_create_indicator.assert_called_once_with(
entity="mock_entity",
entity_type="ip",
score=15,
description="mock_indicator_description",
benign=False,
)
assert len(result_actions) == 1
r_a = result_actions[0]
assert isinstance(r_a, RecordedFuture.CommandResults)
assert r_a.outputs_prefix == "mock_outputs_prefix"
assert r_a.outputs == "mock_outputs"
assert r_a.raw_response == "mock_raw_response"
assert r_a.readable_output == "mock_readable_output"
assert r_a.outputs_key_field == "mock_outputs_key_field"
assert r_a.indicator.to_context() == {
"DBotScore(val.Indicator && val.Indicator == obj.Indicator && val.Vendor == obj.Vendor && val.Type == obj.Type)": {
"Indicator": "mock_entity",
"Score": 0,
"Type": "ip",
"Vendor": "Recorded Future v2",
},
"IP(val.Address && val.Address == obj.Address)": {"Address": "mock_entity"},
}
def test_fetch_incidents_with_incidents_present(self, mocker):
from RecordedFuture import Actions
import demistomock as demisto
client = create_client()
mock_incidents_value = [
{"mock_incident_key1": "mock_incident_value1"},
{"mock_incident_key2": "mock_incident_value2"},
]
mock_demisto_last_run_value = "mock_demisto_last_run"
mock_alerts_update_data_value = "mock_alerts_update_data_value"
mock_client_fetch_incidents_response = {
"incidents": mock_incidents_value,
"demisto_last_run": mock_demisto_last_run_value,
"data": "mock",
"alerts_update_data": mock_alerts_update_data_value,
}
mock_client_fetch_incidents = mocker.patch.object(
client, "fetch_incidents", return_value=mock_client_fetch_incidents_response
)
mock_client_alert_set_status = mocker.patch.object(
client,
"alert_set_status",
)
mock_demisto_incidents = mocker.patch.object(demisto, "incidents")
mock_demisto_set_last_run = mocker.patch.object(demisto, "setLastRun")
actions = Actions(client)
actions.fetch_incidents()
mock_client_fetch_incidents.assert_called_once_with()
mock_demisto_incidents.assert_called_once_with(mock_incidents_value)
mock_demisto_set_last_run.assert_called_once_with(mock_demisto_last_run_value)
# Verify that we update alert status.
mock_client_alert_set_status.assert_called_once_with(mock_alerts_update_data_value)
def test_malware_search_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_entity_search = mocker.patch.object(client, "entity_search", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.malware_search_command()
mock_client_entity_search.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_lookup_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_entity_lookup = mocker.patch.object(client, "entity_lookup", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.lookup_command()
mock_client_entity_lookup.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_intelligence_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_intelligence = mocker.patch.object(client, "get_intelligence", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.intelligence_command()
mock_client_get_intelligence.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_get_links_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_links = mocker.patch.object(client, "get_links", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.get_links_command()
mock_client_get_links.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_get_single_alert_command_with_result_actions(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_single_alert = mocker.patch.object(client, "get_single_alert", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.get_single_alert_command()
mock_client_get_single_alert.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
# As there are some result actions - return those result actions.
assert result == mock_process_result_actions_return_value
def test_get_single_alert_command_without_result_actions(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_single_alert = mocker.patch.object(client, "get_single_alert", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = None
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.get_single_alert_command()
mock_client_get_single_alert.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
# As there is no result actions - just return response.
assert result == mock_response
def test_get_alerts_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_alerts = mocker.patch.object(client, "get_alerts", return_value=mock_response)
actions = Actions(client)
result = actions.get_alerts_command()
mock_client_get_alerts.assert_called_once_with()
assert result == mock_response
def test_get_alert_rules_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_alert_rules = mocker.patch.object(client, "get_alert_rules", return_value=mock_response)
actions = Actions(client)
result = actions.get_alert_rules_command()
mock_client_get_alert_rules.assert_called_once_with()
assert result == mock_response
def test_alert_set_status_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_alert_set_status = mocker.patch.object(client, "alert_set_status", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.alert_set_status_command()
mock_client_alert_set_status.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_alert_set_note_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_alert_set_note = mocker.patch.object(client, "alert_set_note", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.alert_set_note_command()
mock_client_alert_set_note.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_triage_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_response"
mock_client_get_triage = mocker.patch.object(client, "get_triage", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.triage_command()
mock_client_get_triage.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_threat_map_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_threat_map"
mock_client_get_threat_map = mocker.patch.object(client, "get_threat_map", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "mock_process_result_actions_return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.threat_actors_command()
mock_client_get_threat_map.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_threat_links_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_threat_links"
mock_client_get_threat_links = mocker.patch.object(client, "get_threat_links", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.threat_links_command()
mock_client_get_threat_links.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_detection_rules_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_detection_rules"
mock_get_detection_rules = mocker.patch.object(client, "get_detection_rules", return_value=mock_response)
actions = Actions(client)
mock_process_result_actions_return_value = "return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.detection_rules_command()
mock_get_detection_rules.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_collective_insight_command(self, mocker):
from RecordedFuture import Actions
client = create_client()
mock_response = "mock_collective_insight"
mock_submit_detection_to_collective_insight = mocker.patch.object(
client, "submit_detection_to_collective_insight", return_value=mock_response
)
actions = Actions(client)
mock_process_result_actions_return_value = "return_value"
mock_process_result_actions = mocker.patch.object(
actions,
"_process_result_actions",
return_value=mock_process_result_actions_return_value,
)
result = actions.collective_insight_command()
mock_submit_detection_to_collective_insight.assert_called_once_with()
mock_process_result_actions.assert_called_once_with(response=mock_response)
assert result == mock_process_result_actions_return_value
def test_test_module(self, mocker):
import RecordedFuture
import demistomock as demisto
import platform
mocker.patch.object(demisto, "command", return_value="test-module")
mocker.patch.object(demisto, "demistoVersion", return_value={"version": "mock_version"})
mocker.patch.object(demisto, "params", return_value={"token": {"password": "mocktoken"}})
mocker.patch.object(platform, "platform", return_value="mock_platform")
mocker.patch.object(RecordedFuture.Client, "whoami")
mocked_return_res = mocker.patch.object(RecordedFuture, "return_results")
RecordedFuture.main()
mocked_return_res.assert_called_with("ok")
def test_test_module_with_boom(self, mocker):
import RecordedFuture
import demistomock as demisto
import platform
mocker.patch.object(demisto, "command", return_value="test-module")
mocker.patch.object(demisto, "demistoVersion", return_value={"version": "mock_version"})
mocker.patch.object(demisto, "params", return_value={"token": {"password": "mocktoken"}})
mocker.patch.object(platform, "platform", return_value="mock_platform")
mock_whoami = mocker.patch.object(RecordedFuture.Client, "whoami")
mock_whoami.side_effect = Exception("Side effect triggered")
mocked_return_err = mocker.patch.object(RecordedFuture, "return_error")
RecordedFuture.main()
mocked_return_err.assert_called_with(
message=(
f"Failed to execute {demisto.command()} command: "
"Failed due to - Unknown error. Please verify that the API URL and Token are correctly configured. "
"RAW Error: Side effect triggered"
),
error=mocker.ANY,
)