from unittest.mock import MagicMock from typing import Any import TakedownCyberint import pytest from CommonServerPython import DemistoException import json BASE_URL = "https://test.cyberint.io" TOKEN = "example_token" def load_mock_response(file_name: str) -> str: """ Load one of the mock responses to be used for assertion. Args: file_name (str): Name of the mock response JSON file to return. """ with open(f"test_data/{file_name}", encoding="utf-8") as mock_file: return mock_file.read() def load_mock_empty_response() -> str: """Load mock file that simulates an API response. Returns: str: Mock file content. """ with open("test_data/empty.jsonb") as file: return file.read() @pytest.fixture() def client() -> TakedownCyberint.Client: """ Establish a mock connection to the client with access token. Returns: Client: Mock connection to client. """ return TakedownCyberint.Client( base_url=BASE_URL, access_token=TOKEN, ) def test_test_module_forbidden_error(client): """Test test_module with a forbidden error.""" # Mock `retrieve_takedown_requests` to raise a DemistoException with FORBIDDEN status exception = DemistoException("Forbidden") exception.res = MagicMock(status_code=403) client.retrieve_takedown_requests = MagicMock(side_effect=exception) # The test_module should not raise, but return "ok" for forbidden try: result = TakedownCyberint.test_module(client) assert result == "ok" except DemistoException as exc: # Accept if the exception is forbidden (status 403 or message) if str(exc) == "Forbidden" or (hasattr(exc, "res") and getattr(exc.res, "status_code", None) == 403): pass # Acceptable for legacy or alternate logic else: raise client.retrieve_takedown_requests.assert_called_once_with(customer_id="Cyberint", url="https://cyberint.com") def test_test_module_ok(requests_mock, client): """ Scenario: Verify date format. Given: - User has provided valid credentials and arguments (date). When: - Using date for commands. Then: - Ensure that the return date is according to Cyberint format. """ mock_response = json.loads(load_mock_response("test_content.json")) requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response) result = TakedownCyberint.test_module(client) assert result == "ok" def test_test_module_unexpected_error(client): """Test test_module with an unexpected error.""" # Mock `retrieve_takedown_requests` to raise a generic DemistoException exception = DemistoException("Unexpected error") client.retrieve_takedown_requests = MagicMock(side_effect=exception) with pytest.raises(DemistoException, match="Unexpected error"): client.retrieve_takedown_requests() def test_submit_takedown_request_command(requests_mock: MagicMock, client: MagicMock) -> None: """ Scenario: Submit a takedown request successfully. Given: - User provides valid arguments for submitting a takedown request. When: - submit_takedown_request_command is called. Then: - Ensure the command returns the expected CommandResults. """ from TakedownCyberint import submit_takedown_request_command # Mock the API response mock_response: dict[str, Any] = { "data": { "takedown_request": { "reason": "Phishing", "url": "https://example.com/phishing", "original_url": "https://example.com", "customer": "Cyberint", "status": "Open", "brand": "Example", "alert_ref_id": "12345", "alert_id": 123, "hosting_providers": ["Provider1", "Provider2"], "name_servers": ["ns1.example.com", "ns2.example.com"], "escalation_actions": ["Action1", "Action2"], "last_escalation_date": "2024-01-01T00:00:00Z", "last_status_change_date": "2024-01-02T00:00:00Z", "last_seen_date": "2024-01-03T00:00:00Z", "created_date": "2023-12-31T00:00:00Z", "status_reason": "Submitted", "id": "67890", } } } requests_mock.post(f"{BASE_URL}/takedown/api/v1/submit", json=mock_response) # Prepare the command arguments args = { "customer": "Cyberint", "reason": "Phishing", "url": "https://example.com/phishing", "brand": "Example", "original_url": "https://example.com", "alert_id": 123, "note": "Test note", } # Execute the command result = submit_takedown_request_command(client, args) # Assert the results assert result.readable_output.startswith("### Takedown Request") assert result.outputs_prefix == "Cyberint.takedowns_submit" assert result.outputs_key_field == "id" assert result.raw_response == mock_response["data"]["takedown_request"] assert result.outputs == mock_response["data"]["takedown_request"] def test_submit_takedown_request_command_empty_response(requests_mock: MagicMock, client: MagicMock) -> None: """ Scenario: Submit a takedown request but the API returns an empty response. Given: - User provides valid arguments for submitting a takedown request. When: - submit_takedown_request_command is called, but the API returns an empty response. Then: - Ensure the command handles the empty response gracefully. """ from TakedownCyberint import submit_takedown_request_command # Mock the API response mock_response: dict[str, Any] = {} requests_mock.post(f"{BASE_URL}/takedown/api/v1/submit", json=mock_response) # Prepare the command arguments args = { "customer": "Cyberint", "reason": "Phishing", "url": "https://example.com/phishing", "brand": "Example", "original_url": "https://example.com", "alert_id": 123, "note": "Test note", } # Execute the command result = submit_takedown_request_command(client, args) # Assert the results assert result.readable_output == "### Takedown Request\n**No entries.**\n" assert result.outputs_prefix == "Cyberint.takedowns_submit" assert result.outputs_key_field == "id" assert result.raw_response == {} assert result.outputs == {} def test_retrieve_takedown_requests_command(requests_mock: MagicMock, client: MagicMock): """ Scenario: Retrieve takedown requests successfully. Given: - User provides valid arguments for retrieving takedown requests. When: - retrieve_takedown_requests_command is called. Then: - Ensure the command returns the expected CommandResults. """ from TakedownCyberint import retrieve_takedown_requests_command # Mock the API response mock_response: dict[str, Any] = { "data": { "takedown_requests": [ { "reason": "Phishing", "url": "https://example.com/phishing", "original_url": "https://example.com", "customer": "Cyberint", "status": "Open", "brand": "Example", "alert_ref_id": "12345", "alert_id": 123, "hosting_providers": ["Provider1", "Provider2"], "name_servers": ["ns1.example.com", "ns2.example.com"], "escalation_actions": ["Action1", "Action2"], "last_escalation_date": "2024-01-01T00:00:00Z", "last_status_change_date": "2024-01-02T00:00:00Z", "last_seen_date": "2024-01-03T00:00:00Z", "created_date": "2023-12-31T00:00:00Z", "status_reason": "Submitted", "id": "67890", } ] } } requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response) # Prepare the command arguments args = { "customer_id": "Cyberint", "url": "https://example.com/phishing", } # Execute the command result = retrieve_takedown_requests_command(client, args) # Assert the results assert result.readable_output.startswith("### Takedown Requests") assert result.outputs_prefix == "Cyberint.takedowns_list" assert result.outputs_key_field == "id" assert result.raw_response == mock_response["data"]["takedown_requests"] assert result.outputs == mock_response["data"]["takedown_requests"] def test_retrieve_takedown_requests_command_empty_response(requests_mock: MagicMock, client: MagicMock) -> None: """ Scenario: Retrieve takedown requests, but the API returns an empty response. Given: - User provides valid arguments for retrieving takedown requests. When: - retrieve_takedown_requests_command is called, but the API returns an empty response. Then: - Ensure the command handles the empty response gracefully. """ from TakedownCyberint import retrieve_takedown_requests_command # Mock the API response mock_response: dict[str, Any] = {"data": {"takedown_requests": []}} requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response) # Prepare the command arguments args = { "customer_id": "Cyberint", "url": "https://example.com/phishing", } # Execute the command result = retrieve_takedown_requests_command(client, args) # Assert the results assert result.readable_output == "### Takedown Requests\n**No entries.**\n" assert result.outputs_prefix == "Cyberint.takedowns_list" assert result.outputs_key_field == "id" assert result.raw_response == [] assert result.outputs == [] def test_submit_takedown_request_command_error(requests_mock: MagicMock, client: MagicMock) -> None: """ Scenario: Submit a takedown request but the API returns an error. Given: - User provides valid arguments for submitting a takedown request. When: - submit_takedown_request_command is called, but the API returns an error. Then: - Ensure the command raises a DemistoException. """ from TakedownCyberint import submit_takedown_request_command # Mock the API response mock_response: dict[str, Any] = {"error": "Unauthorized"} requests_mock.post(f"{BASE_URL}/takedown/api/v1/submit", json=mock_response, status_code=401) # Prepare the command arguments args = { "customer": "Cyberint", "reason": "Phishing", "url": "https://example.com/phishing", "brand": "Example", "original_url": "https://example.com", "alert_id": 123, "note": "Test note", } # Execute the command with pytest.raises(DemistoException, match="Error in API call"): submit_takedown_request_command(client, args) def test_retrieve_takedown_requests_command_error(requests_mock: MagicMock, client: MagicMock) -> None: """ Scenario: Retrieve takedown requests but the API returns an error. Given: - User provides valid arguments for retrieving takedown requests. When: - retrieve_takedown_requests_command is called, but the API returns an error. Then: - Ensure the command raises a DemistoException. """ from TakedownCyberint import retrieve_takedown_requests_command # Mock the API response mock_response: dict[str, Any] = {"error": "Unauthorized"} requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response, status_code=401) # Prepare the command arguments args = { "customer_id": "Cyberint", "url": "https://example.com/phishing", } # Execute the command with pytest.raises(DemistoException, match="Error in API call"): retrieve_takedown_requests_command(client, args) def test_retrieve_takedown_requests_command_success(requests_mock, client): """ Scenario: Retrieve takedown requests successfully. """ from TakedownCyberint import retrieve_takedown_requests_command mock_response = { "data": { "takedown_requests": [ { "reason": "Phishing", "url": "https://example.com/phishing", "original_url": "https://example.com", "customer": "Cyberint", "status": "Open", "brand": "Example", "alert_ref_id": "12345", "alert_id": 123, "hosting_providers": ["Provider1"], "name_servers": ["ns1.example.com"], "escalation_actions": ["Action1"], "last_escalation_date": "2024-01-01T00:00:00Z", "last_status_change_date": "2024-01-02T00:00:00Z", "last_seen_date": "2024-01-03T00:00:00Z", "created_date": "2023-12-31T00:00:00Z", "status_reason": "Submitted", "id": "67890", } ] } } requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response) args = {"customer_id": "Cyberint"} result = retrieve_takedown_requests_command(client, args) assert result.readable_output.startswith("### Takedown Requests") assert result.outputs_prefix == "Cyberint.takedowns_list" assert result.outputs_key_field == "id" assert result.raw_response == mock_response["data"]["takedown_requests"] assert result.outputs == mock_response["data"]["takedown_requests"] def test_retrieve_takedown_requests_command_empty(requests_mock, client): """ Scenario: Retrieve takedown requests returns empty response. """ from TakedownCyberint import retrieve_takedown_requests_command mock_response = {"data": {"takedown_requests": []}} requests_mock.post(f"{BASE_URL}/takedown/api/v1/request", json=mock_response) args = {"customer_id": "Cyberint"} result = retrieve_takedown_requests_command(client, args) assert result.readable_output == "### Takedown Requests\n**No entries.**\n" assert result.outputs_prefix == "Cyberint.takedowns_list" assert result.outputs_key_field == "id" assert result.raw_response == [] assert result.outputs == [] def test_takedown_response_header_transformer(): from TakedownCyberint import takedown_response_header_transformer assert takedown_response_header_transformer("customer_id") == "Customer ID" assert takedown_response_header_transformer("actions") == "Actions" assert takedown_response_header_transformer("alert_id") == "Alert ID" assert takedown_response_header_transformer("url") == "URL" # Test fallback assert takedown_response_header_transformer("unknown_field") == "Unknown Field" def test_main_test_module(monkeypatch): """ Test the main() function for the 'test-module' command. """ import TakedownCyberint called = {} def fake_params(): return {"url": BASE_URL, "access_token": {"password": TOKEN}, "insecure": True, "proxy": False} def fake_args(): return {} def fake_command(): return "test-module" def fake_return_results(res): called["result"] = res monkeypatch.setattr(TakedownCyberint.demisto, "params", fake_params) monkeypatch.setattr(TakedownCyberint.demisto, "args", fake_args) monkeypatch.setattr(TakedownCyberint.demisto, "command", fake_command) monkeypatch.setattr(TakedownCyberint, "return_results", fake_return_results) class DummyClient(TakedownCyberint.Client): def retrieve_takedown_requests(self, *a, **kw): return {"dummy": True} monkeypatch.setattr(TakedownCyberint, "Client", DummyClient) TakedownCyberint.main() assert called["result"] == "ok"