import json
import demistomock as demisto
import pytest
class MockResponse:
def __init__(self, json_data, status_code):
self.json_data = json_data
self.status_code = status_code
self.content = "test_content"
def test_login_failed(requests_mock, mocker):
"""
Given:
- Cybereason instance with invalid credentials
When:
- Running test module
Then:
- Ensure an indicative error is returned that authorization failed
"""
login_failed_html = b"""
Cybereason | Login
# noqa: E501
# noqa: E501
""" # noqa: E501
mocker.patch.object(
demisto,
"params",
return_value={
"server": "http://server",
"credentials": {"identifier": "username", "password": "password"},
"proxy": True,
},
)
mocker.patch.object(demisto, "command", return_value="test-module")
return_error_mock = mocker.patch("Cybereason.return_error")
requests_mock.post("http://server/login.html", content=login_failed_html)
requests_mock.post("http://server/rest/visualsearch/query/simple", content=login_failed_html)
requests_mock.get("http://server/logout")
from Cybereason import main
main()
assert return_error_mock.call_count == 1
err_msg = return_error_mock.call_args[0][0]
assert "Failed to process the API response. Authentication failed, verify the credentials are correct." in err_msg
params = {"server": "http://server", "credentials": {"identifier": "username", "password": "password"}, "proxy": True}
def load_mock_response(file_name: str) -> str:
"""
Load mock file that simulates an API response.
Args:
file_name (str): Name of the mock response JSON file to return.
Returns:
str: Mock file content.
"""
with open(f"test_data/{file_name}", encoding="utf-8") as mock_file:
return mock_file.read()
def test_cybereason_api_call(mocker):
"""
Given:
- API call returns a redirect to the login page (session expired).
When:
- cybereason_api_call() is executed.
Then:
- Should trigger re-login, update token, and retry request successfully.
"""
from Cybereason import Client
import time
mock_response_login_redirect = mocker.Mock()
mock_response_login_redirect.status_code = 200
mock_response_login_redirect.url = "https://server/login.html"
mock_response_success = mocker.Mock()
mock_response_success.status_code = 200
mock_response_success.url = "https://server/some_api"
mock_response_success.json.return_value = {"result": "ok"}
mock_http_request = mocker.Mock(side_effect=[mock_response_login_redirect, mock_response_success])
mock_login = mocker.patch("Cybereason.login", return_value=("new_token", int(time.time())))
mocker.patch("Cybereason.get_integration_context", return_value={})
mock_set_context = mocker.patch("Cybereason.set_integration_context")
mock_headers = mocker.patch("Cybereason.HEADERS", {"Cookie": ""})
client = Client(base_url="https://server", verify=False, headers=mock_headers, proxy=False)
client._http_request = mock_http_request
result = client.cybereason_api_call("GET", "/some_api", json_body={})
# Assertions
mock_login.assert_called_once()
assert result == {"result": "ok"}
assert mock_set_context.called
assert "JSESSIONID=new_token" in mock_headers["Cookie"]
assert mock_http_request.call_count == 2
def test_validate_jsession_two(mocker):
"""
Given:
- A token validity scenario (valid or expired).
When:
- validate_jsession() is called.
Then:
- If token is valid → should NOT refresh.
- If token expired → should refresh and update context.
"""
from Cybereason import validate_jsession
import time
token_valid = False
expected_refresh = True
mock_time = int(time.time())
valid_until = mock_time + 10000 if token_valid else mock_time - 10
mock_integration_context = {
"jsession_id": "old_token",
"valid_until": valid_until,
}
mocker.patch("Cybereason.get_integration_context", return_value=mock_integration_context)
mock_set_context = mocker.patch("Cybereason.set_integration_context")
mock_headers = mocker.patch("Cybereason.HEADERS", {})
mock_login = mocker.patch("Cybereason.login", return_value=("new_token", mock_time))
mock_client = mocker.Mock()
validate_jsession(mock_client)
if expected_refresh:
# Expired case: login called, context updated
mock_login.assert_called_once()
mock_set_context.assert_called_once()
assert mock_integration_context["jsession_id"] == "new_token"
assert mock_integration_context["valid_until"] == mock_time + 28000
assert "JSESSIONID=new_token" in mock_headers["Cookie"]
else:
# Valid token case: no refresh
mock_login.assert_not_called()
mock_set_context.assert_not_called()
assert "JSESSIONID=old_token" in mock_headers["Cookie"]
def test_one_query_file(mocker):
from Cybereason import Client, query_file_command
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"file_hash": "4778901e54f55d54435b2626923054a8"}
machine_raw_response = json.loads(load_mock_response("machine_outputs.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=machine_raw_response)
raw_response = json.loads(load_mock_response("file_outputs.json"))
mocker.patch("Cybereason.query_file", return_value=raw_response)
command_output = query_file_command(client, args)
assert command_output.outputs_prefix == "Cybereason.File"
def test_two_query_file(mocker):
from Cybereason import Client, query_file_command
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"file_hash": "4778901e54f55d54435b2626923054a8"}
machine_raw_response = json.loads(load_mock_response("machine_outputs.json"))
mocker.patch("Cybereason.get_file_machine_details", return_value=machine_raw_response)
raw_response = {"status": "SUCCESS", "data": None}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
query_file_command(client, args)
assert exc_info.match(r"No results found.")
args = {"file_hash": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value={})
with pytest.raises(Exception) as exc_info:
query_file_command(client, args)
assert exc_info.match(r"Hash type is not supported.")
def test_validate_jsession(mocker):
from Cybereason import Client, validate_jsession, HEADERS
import time
# Mock constants and objects
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
creation_time = int(time.time())
# Mocking integration context functions
mock_integration_context = {
"jsession_id": "valid_token",
"valid_until": creation_time - 1000, # Expired token
}
mocker.patch("Cybereason.get_integration_context", return_value=mock_integration_context)
mock_set_context = mocker.patch("Cybereason.set_integration_context")
mocker.patch("Cybereason.login", return_value=("new_token", creation_time))
# Patch the global HEADERS
mock_headers = mocker.patch("Cybereason.HEADERS", HEADERS)
# Call function
validate_jsession(client)
# Assertions
assert mock_headers["Cookie"] == "JSESSIONID=new_token", f"Expected Cookie to be set, but got: {mock_headers}"
mock_set_context.assert_called_once_with({"jsession_id": "new_token", "valid_until": creation_time + 28000})
def test_get_remediation_action_status_success(mocker):
from Cybereason import get_remediation_action_status, Client
# Mock dependencies
mocker.patch(
"Cybereason.dict_safe_get", side_effect=lambda d, keys: "remediation123" if "remediationId" in keys else "SUCCESS"
)
mocker.patch("Cybereason.get_remediation_action_progress", return_value={"Remediation status": "SUCCESS"})
mocker.patch("Cybereason.add_comment")
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
# Prepare test inputs
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
user_name = "test_user"
malop_guid = "malop123"
response = {"remediationId": "remediation123"}
comment = "Remediation successful."
# Call the function
result = get_remediation_action_status(client, user_name, malop_guid, response, comment)
# Assertions
assert result["Remediation status"] == "SUCCESS"
assert result["Remediation ID"] == "remediation123"
def test_malop_processes_command(mocker):
from Cybereason import malop_processes_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuids": "11.-6236127207710541535", "machineName": "desktop", "dateTime": "None"}
raw_response = json.loads(load_mock_response("malop_processes_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
mocker.patch.object(demisto, "results")
command_output = malop_processes_command(client, args)
assert command_output.outputs[0].get("Name", "") == "bdata.bin"
assert command_output.outputs[0].get("SHA1", "") == "f56238da9fbfa3864d443a85bb80743bd2415682"
args = {"malopGuids": None, "machineName": "desktop", "dateTime": "2022/08/01 00:00:00"}
mocker.patch.object(demisto, "results")
with pytest.raises(Exception) as exc_info:
command_output = malop_processes_command(client, args)
assert exc_info.match(r"malopGuids must be array of strings")
def test_is_probe_connected_command(mocker):
from Cybereason import is_probe_connected_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"machine": "desktop-j60ivd0", "is_remediation_commmand": True}
raw_response = json.loads(load_mock_response("is_probe_connected_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = is_probe_connected_command(client, args)
assert command_output.readable_output == "True"
def test_query_processes_command(mocker):
from Cybereason import query_processes_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": ["desktop-vg9ke2u"],
"hasOutgoingConnection": "true",
"hasIncomingConnection": "true",
"hasExternalConnection": "true",
"unsignedUnknownReputation": "true",
"fromTemporaryFolder": "true",
"privilegesEscalation": "true",
"maliciousPsExec": "true",
"processName": "test_process",
"onlySuspicious": "true",
}
raw_response = json.loads(load_mock_response("query_processes_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = query_processes_command(client, args)
assert command_output.outputs[0].get("SHA1", "") == "1bc5066ddf693fc034d6514618854e26a84fd0d1"
def test_query_connections_command(mocker):
from Cybereason import query_connections_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"ip": "192.168.1.103"}
raw_response = json.loads(load_mock_response("query_processes_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = query_connections_command(client, args)
assert command_output.outputs[0]["Name"] == "svchost.exe"
args = {"machine": "desktop"}
command_output = query_connections_command(client, args)
assert command_output.outputs[0]["Name"] == "svchost.exe"
args = {"machine": "desktop", "ip": "192.168.1.103"}
with pytest.raises(Exception) as exc_info:
command_output = query_connections_command(client, args)
assert exc_info.match(r"Too many arguments given.")
args = {}
with pytest.raises(Exception) as exc_info:
command_output = query_connections_command(client, args)
assert exc_info.match(r"Not enough arguments given.")
def test_isolate_machine_command(mocker):
from Cybereason import isolate_machine_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"machine": "desktop-vg9ke2u"}
raw_response = json.loads(load_mock_response("isolate_machine_raw_response.json"))
mocker.patch("Cybereason.get_pylum_id", return_value="PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F")
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = isolate_machine_command(client, args)
assert command_output[0].outputs_prefix == "Cybereason"
def test_unisolate_machine_command(mocker):
from Cybereason import unisolate_machine_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"machine": "desktop-vg9ke2u"}
raw_response = json.loads(load_mock_response("isolate_machine_raw_response.json"))
mocker.patch("Cybereason.get_pylum_id", return_value="PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F")
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = unisolate_machine_command(client, args)
assert command_output[0].outputs_prefix == "Cybereason"
def test_get_non_edr_malop_data(mocker):
from Cybereason import get_detection_details
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuid": "AAAA0yUlnvXGQODT"}
raw_response = json.loads(load_mock_response("malop_detection_data.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = get_detection_details(client, args)
assert command_output["malops"][0]["guid"] == "AAAA0yUlnvXGQODT"
def test_query_malops_command(mocker):
from Cybereason import query_malops_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"withinLastDays": 10}
malop_process_raw_response = json.loads(load_mock_response("query_malop_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=malop_process_raw_response)
command_output = query_malops_command(client, args)
assert command_output.outputs[0]["AffectedMachine"] == ["desktop-j60ivd0"]
def test_query_malop_management_command(mocker):
from Cybereason import query_malop_management_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"guid": "AAAA0w7GERjl3oae"}
query_malop_management_raw_response = json.loads(load_mock_response("query_malop_management_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=query_malop_management_raw_response)
command_output = query_malop_management_command(client, args)
assert command_output.outputs[0]["GUID"] == "AAAA0w7GERjl3oae"
def test_cybereason_process_attack_tree_command(mocker):
from Cybereason import cybereason_process_attack_tree_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"processGuid": "HobXaEWU0CZ6S6LC"}
url = "https://test.server.com:8888/#/processTree?guid=HobXaEWU0CZ6S6LC&viewedGuids=HobXaEWU0CZ6S6LC&rootType=Process"
expected_response = [
{
"ProcessID": "HobXaEWU0CZ6S6LC",
"URL": url,
}
]
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=expected_response)
mocker.patch("Cybereason.SERVER", new="https://test.server.com:8888")
command_output = cybereason_process_attack_tree_command(client, args)
assert command_output.outputs[0] == expected_response[0]
def test_update_malop_status_command(mocker):
from Cybereason import update_malop_status_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuid": "11.-7780537507363356527", "status": "To Review"}
raw_response = {"status": "SUCCESS"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = update_malop_status_command(client, args)
assert command_output.outputs["GUID"] == "11.-7780537507363356527"
assert command_output.outputs["Status"] == "To Review"
raw_response = {"status": "SUCESS"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = update_malop_status_command(client, args)
assert exc_info.match(r"message")
args = {"malopGuid": "11.-7780537507363356527", "status": "test"}
with pytest.raises(Exception) as exc_info:
command_output = update_malop_status_command(client, args)
assert exc_info.match(r"Invalid status.")
def test_update_malop_investigation_status_command(mocker):
from Cybereason import update_malop_investigation_status_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuid": "11.-7780537507363356527", "investigationStatus": "Under Investigation"}
raw_response = {"status": "SUCCESS"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = update_malop_investigation_status_command(client, args)
assert command_output.outputs["GUID"] == "11.-7780537507363356527"
assert command_output.outputs["InvestigationStatus"] == "Under Investigation"
raw_response = {"status": "SUCESS"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = update_malop_investigation_status_command(client, args)
assert exc_info.match(r"message")
args = {"malopGuid": "11.-7780537507363356527", "investigationStatus": "test"}
with pytest.raises(Exception) as exc_info:
command_output = update_malop_investigation_status_command(client, args)
assert exc_info.match(r"Invalid investigation status")
def test_prevent_file_command(mocker):
from Cybereason import prevent_file_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"md5": "fc61fdcad5a9d52a01bd2d596f2c92b9"}
raw_response = json.loads(load_mock_response("prevent_file_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = prevent_file_command(client, args)
assert command_output.outputs["MD5"] == "fc61fdcad5a9d52a01bd2d596f2c92b9"
raw_response = {"outcome": "failure"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = prevent_file_command(client, args)
assert exc_info.match(r"Failed to prevent file")
def test_unprevent_file_command(mocker):
from Cybereason import unprevent_file_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"md5": "fc61fdcad5a9d52a01bd2d596f2c92b9"}
raw_response = json.loads(load_mock_response("prevent_file_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = unprevent_file_command(client, args)
assert command_output.outputs["MD5"] == "fc61fdcad5a9d52a01bd2d596f2c92b9"
raw_response = {"outcome": "failure"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = unprevent_file_command(client, args)
assert exc_info.match(r"Failed to unprevent file")
def test_query_domain_command(mocker):
from Cybereason import query_domain_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"domain": "www2.bing.com"}
raw_response = json.loads(load_mock_response("query_domain_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = query_domain_command(client, args)
assert command_output.outputs_prefix == "Cybereason.Domain"
mocker.patch("Cybereason.Client.cybereason_api_call", return_value={})
with pytest.raises(Exception) as exc_info:
command_output = query_domain_command(client, args)
assert exc_info.match(r"Error occurred while trying to query the file.")
raw_response = {"status": "SUCCESS", "data": None}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = query_domain_command(client, args)
assert exc_info.match(r"No results found.")
def test_query_user_command(mocker):
from Cybereason import query_user_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"username": "desktop-vg9ke2u"}
raw_response = json.loads(load_mock_response("query_user_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = query_user_command(client, args)
assert command_output.outputs[0]["Username"] == "desktop-vg9ke2u"
mocker.patch("Cybereason.Client.cybereason_api_call", return_value={})
with pytest.raises(Exception) as exc_info:
command_output = query_user_command(client, args)
assert exc_info.match(r"Error occurred while trying to query the file.")
raw_response = {"status": "SUCCESS", "data": None}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
command_output = query_user_command(client, args)
assert exc_info.match(r"No results found.")
def test_available_remediation_actions_command(mocker):
from Cybereason import available_remediation_actions_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuid": "11.-7780537507363356527"}
raw_response = json.loads(load_mock_response("available_remediation_actions_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = available_remediation_actions_command(client, args)
assert command_output.outputs_prefix == "Cybereason.Remediation"
def test_start_fetchfile_command(mocker):
from Cybereason import start_fetchfile_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGUID": "11.-7780537507363356527", "userName": "desktop-vg9ke2u"}
raw_response = json.loads(load_mock_response("get_file_guids_raw_response.json"))
mocker.patch("Cybereason.get_file_guids", return_value=raw_response)
raw_response = json.loads(load_mock_response("start_fetch_file_raw_response.json"))
mocker.patch("Cybereason.start_fetchfile", return_value=raw_response)
command_output = start_fetchfile_command(client, args)
assert command_output.readable_output[0] == "S"
def test_fetchfile_progress_command(mocker):
from Cybereason import fetchfile_progress_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"malopGuid": "11.-7780537507363356527"}
raw_response = json.loads(load_mock_response("get_file_guids_raw_response.json"))
mocker.patch("Cybereason.get_file_guids", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_batch_id_raw_response.json"))
mocker.patch("Cybereason.get_batch_id", return_value=raw_response)
command_output = fetchfile_progress_command(client, args)
assert command_output.outputs["MalopID"] == "11.-7780537507363356527"
def test_quarantine_file_command(mocker):
from Cybereason import quarantine_file_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Quarantine the File",
"timeout": 60,
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
quarantine_file_command(client, args)
assert exc_info.match(r"Quarantine file remediation")
def test_unquarantine_file_command(mocker):
from Cybereason import unquarantine_file_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Unquarantine the File",
"timeout": 60,
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
unquarantine_file_command(client, args)
assert exc_info.match(r"Unquarantine file remediation")
def test_block_file_command(mocker):
from Cybereason import block_file_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Block the File",
"timeout": 60,
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
block_file_command(client, args)
assert exc_info.match(r"Block file remediation")
def test_kill_process_command(mocker):
from Cybereason import kill_process_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Kill the Process",
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
kill_process_command(client, args)
assert exc_info.match(r"Kill process remediation")
def test_get_sensor_id_command(mocker):
from Cybereason import get_sensor_id_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"machineName": "desktop-vg9ke2u"}
raw_response = json.loads(load_mock_response("get_sensor_id_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = get_sensor_id_command(client, args)
assert command_output.readable_output == (
"Available Sensor IDs are {'desktop-vg9ke2u': "
"'5e77883de4b0575ddcf824ef:PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F'}"
)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value={"sensors": []})
with pytest.raises(Exception) as exc_info:
command_output = get_sensor_id_command(client, args)
assert exc_info.match(r"Could not find any Sensor ID for the machine")
def test_number_one_fetch_scan_status_command(mocker):
from Cybereason import fetch_scan_status_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"batchID": "-1112786456"}
raw_response = json.loads(load_mock_response("fetch_scan_status_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = fetch_scan_status_command(client, args)
assert command_output.raw_response == "The given batch ID does not match with any actions on sensors."
def test_malware_query_command(mocker):
from Cybereason import malware_query_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"limit": "5", "needsAttention": "True", "status": "Done", "type": "KnownMalware", "timestamp": "1582206286000"}
raw_response = raw_response = json.loads(load_mock_response("malware_query_raw_data.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = malware_query_command(client, args)
assert command_output.raw_response["status"] == "SUCCESS"
args = {"limit": "0"}
with pytest.raises(Exception) as exc_info:
command_output = malware_query_command(client, args)
assert exc_info.match(r"Limit cannot be zero or a negative number.")
def test_unsuspend_process_command(mocker):
from Cybereason import unsuspend_process_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Unsuspend Process",
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
unsuspend_process_command(client, args)
assert exc_info.match(r"Unsuspend process remediation")
def test_kill_prevent_unsuspend_command(mocker):
from Cybereason import kill_prevent_unsuspend_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Kill Prevent",
"timeout": "30",
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
kill_prevent_unsuspend_command(client, args)
assert exc_info.match(r"Kill prevent unsuspend")
def test_delete_registry_key_command(mocker):
from Cybereason import delete_registry_key_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {
"machine": "desktop-vg9ke2u",
"malopGuid": "11.-7780537507363356527",
"targetId": "-1845090846.-1424333057657783286",
"userName": "desktop-vg9ke2u",
"comment": "Remove the registry key",
"timeout": 30,
}
mocker.patch("Cybereason.is_probe_connected_command", return_value=True)
raw_response = json.loads(load_mock_response("get_remediation_action.json"))
mocker.patch("Cybereason.get_remediation_action", return_value=raw_response)
raw_response = json.loads(load_mock_response("get_remediation_action_status.json"))
mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response)
with pytest.raises(Exception) as exc_info:
delete_registry_key_command(client, args)
assert exc_info.match(r"Delete registry key")
def test_add_comment_command(mocker):
from Cybereason import add_comment_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"comment": "New comment", "malopGuid": "11.-7780537507363356527"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value={})
command_output = add_comment_command(client, args)
assert command_output.readable_output == "Comment added successfully"
def test_fetch_incidents(mocker):
from Cybereason import fetch_incidents
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
raw_response = json.loads(load_mock_response("query_malop_management_raw_response.json"))
mocker.patch("Cybereason.get_malop_management_data", return_value=raw_response)
malop_process_raw_response = json.loads(load_mock_response("query_malop_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=malop_process_raw_response)
command_output = fetch_incidents(client)
command_output = str(command_output)
assert command_output == "None"
def test_archive_sensor_command(mocker):
from Cybereason import archive_sensor_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
test_reponse = MockResponse({"key1": "val1"}, 204)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = archive_sensor_command(client, args)
assert command_output.readable_output == (
"The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for archive."
)
test_reponse = MockResponse({"key1": "val1"}, 404)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = archive_sensor_command(client, args)
assert exc_info.match(r"Your request failed")
def test_unarchive_sensor_command(mocker):
from Cybereason import unarchive_sensor_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
test_reponse = MockResponse({"key1": "val1"}, 204)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = unarchive_sensor_command(client, args)
assert command_output.readable_output == (
"The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for unarchive."
)
test_reponse = MockResponse({"key1": "val1"}, 404)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = unarchive_sensor_command(client, args)
assert exc_info.match(r"Your request failed")
def test_delete_sensor_command(mocker):
from Cybereason import delete_sensor_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
test_reponse = MockResponse({"key1": "val1"}, 200)
args = {"sensorID": "5e77883de4b0575ddcf824ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ-4CTUN1V_123CC99CA7E5"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = delete_sensor_command(client, args)
assert command_output.readable_output == "Sensor deleted successfully."
test_reponse = MockResponse({"key1": "val1"}, 204)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = delete_sensor_command(client, args)
assert command_output.readable_output == (
"The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for deleting."
)
test_reponse = MockResponse({"key1": "val1"}, 404)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"}
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = delete_sensor_command(client, args)
assert exc_info.match(r"Your request failed")
def test_start_host_scan_command(mocker):
from Cybereason import start_host_scan_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ", "scanType": "FULL"}
test_reponse = MockResponse({"key1": "val1"}, 204)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = start_host_scan_command(client, args)
assert command_output.readable_output == (
"Given Sensor ID/ID's ['5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ'] is/are not available for scanning."
)
test_reponse = MockResponse({"key1": "val1"}, 404)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = start_host_scan_command(client, args)
assert exc_info.match(r"Your request failed")
def test_number_two_fetch_scan_status_command(mocker):
from Cybereason import fetch_scan_status_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"batchID": "123456"}
test_reponse = [{"batchId": 123456}]
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = fetch_scan_status_command(client, args)
assert command_output.raw_response == test_reponse[0]
test_reponse = [{"batchId": "123456"}]
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = fetch_scan_status_command(client, args)
assert command_output.raw_response == "The given batch ID does not match with any actions on sensors."
def test_download_fetchfile_command(mocker):
from Cybereason import download_fetchfile_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"batchID": "-1044817479"}
test_reponse = MockResponse({"key1": "val1"}, 404)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = download_fetchfile_command(client, args)
assert exc_info.match(r"request failed with the following error:")
test_reponse = MockResponse({"key1": "val1"}, 200)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
command_output = download_fetchfile_command(client, args)
assert command_output["File"] == "download.zip"
def test_close_fetchfile_command(mocker):
from Cybereason import close_fetchfile_command, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"batchID": "-796720096"}
test_reponse = MockResponse({"key1": "val1"}, 200)
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
close_fetchfile_command(client, args)
assert exc_info.match(r"The given Batch ID does not exist")
def test_malop_to_incident_edr_malop(mocker):
from Cybereason import malop_to_incident
args = {
"guidString": "12345A",
"status": 1,
"simpleValues": {
"detectionType": {"values": ["EXTENSION_MANIPULATION"]},
"creationTime": {"values": ["1721798910159"]},
"malopLastUpdateTime": {"values": ["1728032260900"]},
},
"elementValues": {
"primaryRootCauseElements": {"elementValues": [{"elementType": "File", "name": "avg_secure_browser_setup.pdf.exe"}]}
},
"isEdr": True,
}
command_output = malop_to_incident(args)
assert all(
[
(command_output["name"] == "Cybereason Malop 12345A"),
(command_output["status"] == 0),
(command_output["CustomFields"]["malopcreationtime"] == "1721798910159"),
(command_output["CustomFields"]["malopupdatetime"] == "1728032260900"),
(command_output["CustomFields"]["malopdetectiontype"] == "EXTENSION_MANIPULATION"),
(command_output["CustomFields"]["maloprootcauseelementname"] == "avg_secure_browser_setup.pdf.exe"),
(command_output["CustomFields"]["maloprootcauseelementtype"] == "File"),
(command_output["CustomFields"]["malopedr"]),
(command_output["dbotmirrorid"] == "12345A"),
]
)
with pytest.raises(Exception) as exc_info:
command_output = malop_to_incident("args")
assert exc_info.match(r"Cybereason raw response is not valid")
def test_malop_to_incident_remediated_non_edr_malop(mocker):
from Cybereason import malop_to_incident
args = {
"guidString": "12345C",
"status": "Remediated",
"malopDetectionType": "ABCD",
"creationTime": "23456",
"lastUpdateTime": "6789",
"edr": False,
}
command_output = malop_to_incident(args)
assert all(
[
(command_output["name"] == "Cybereason Malop 12345C"),
(command_output["status"] == 1),
(command_output["CustomFields"]["malopcreationtime"] == "23456"),
(command_output["CustomFields"]["malopupdatetime"] == "6789"),
(command_output["CustomFields"]["malopdetectiontype"] == "ABCD"),
(not command_output["CustomFields"]["malopedr"]),
(command_output["dbotmirrorid"] == "12345C"),
]
)
with pytest.raises(Exception) as exc_info:
command_output = malop_to_incident("args")
assert exc_info.match(r"Cybereason raw response is not valid")
def test_malop_to_incident_resolved_non_edr_malop(mocker):
from Cybereason import malop_to_incident
args = {
"guidString": "12345D",
"status": "RESOLVED",
"malopDetectionType": "ABCD",
"creationTime": "23456",
"lastUpdateTime": "6789",
"edr": False,
}
command_output = malop_to_incident(args)
assert all(
[
(command_output["name"] == "Cybereason Malop 12345D"),
(command_output["status"] == 2),
(command_output["CustomFields"]["malopcreationtime"] == "23456"),
(command_output["CustomFields"]["malopupdatetime"] == "6789"),
(command_output["CustomFields"]["malopdetectiontype"] == "ABCD"),
(not command_output["CustomFields"]["malopedr"]),
(command_output["dbotmirrorid"] == "12345D"),
]
)
with pytest.raises(Exception) as exc_info:
command_output = malop_to_incident("args")
assert exc_info.match(r"Cybereason raw response is not valid")
def test_malop_to_incident_active_non_edr_malop(mocker):
from Cybereason import malop_to_incident
args = {
"guidString": "12345D",
"status": "Active",
"malopDetectionType": "ABCD",
"creationTime": "23456",
"lastUpdateTime": "6789",
"edr": False,
}
command_output = malop_to_incident(args)
assert all(
[
(command_output["name"] == "Cybereason Malop 12345D"),
(command_output["status"] == 0),
(command_output["CustomFields"]["malopcreationtime"] == "23456"),
(command_output["CustomFields"]["malopupdatetime"] == "6789"),
(command_output["CustomFields"]["malopdetectiontype"] == "ABCD"),
(not command_output["CustomFields"]["malopedr"]),
(command_output["dbotmirrorid"] == "12345D"),
]
)
with pytest.raises(Exception) as exc_info:
command_output = malop_to_incident("args")
assert exc_info.match(r"Cybereason raw response is not valid")
def test_get_pylum_id(mocker):
from Cybereason import get_pylum_id, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
test_reponse = {
"data": {
"resultIdToElementDataMap": {
"-1845090846.1198775089551518743": {
"simpleValues": {"pylumId": {"totalValues": 1, "values": [None]}},
}
}
}
}
raw_response = json.loads(load_mock_response("get_pylum_id_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = get_pylum_id(client, "test_machine")
assert command_output == "PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F"
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse)
with pytest.raises(Exception) as exc_info:
command_output = get_pylum_id(client, "test_machine")
assert exc_info.match(r"Could not find machine")
def test_get_machine_guid(mocker):
from Cybereason import get_machine_guid, Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
raw_response = json.loads(load_mock_response("get_machine_guid_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = get_machine_guid(client, "test_machine")
assert command_output == "-1826875736.1198775089551518743"
def test_get_machine_details_command(mocker):
from Cybereason import get_machine_details_command
from Cybereason import Client
HEADERS = {"Content-Type": "application/json", "Connection": "close"}
client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True)
args = {"machineName": "empow_2"}
raw_response = json.loads(load_mock_response("fetch_machine_details_raw_response.json"))
mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response)
command_output = get_machine_details_command(client, args)
assert command_output.outputs[0]["GroupName"] == "Test"
assert command_output.outputs[0]["MachineName"] == "empow_2"