import json import io import freezegun import pytest from FeedMandiant import MandiantClient def mock_client(): MandiantClient._get_token = lambda x: 'token' client = MandiantClient('url', 'username', 'password', False, False, 60, '90 days', 1, ['Malware']) return client def util_load_json(path): with io.open(path, mode='r', encoding='utf-8') as f: return json.loads(f.read()) def test_generate_token(mocker): """ Given - client When - generating a token Then - Validate the result is as expected """ client = mock_client() mocker.patch.object(client, '_http_request', return_value={'access_token': 'token'}) res = client._generate_token() assert res == 'token' @freezegun.freeze_time('2020-11-25T11:57:28Z') def test_get_token(): """ Given - client When - getting a token Then - Validate the result is as expected """ from FeedMandiant import MandiantClient MandiantClient._generate_token = lambda x: 'token' client = MandiantClient('url', 'username', 'password', False, False, 60, 'x_app_name', 'first_fetch', 1, []) res = client._get_token() assert res == 'token' @pytest.mark.parametrize('info_type, response, result', [('info-type', {'info-type': 'res'}, 'res'), ('', {'info-type': 'res'}, {'info-type': 'res'}), ('attack-pattern', {'attack-patterns': 'redacted'}, []), ('attack-pattern', {'attack-patterns': 'res'}, 'res')]) def test_get_indicator_additional_info(mocker, info_type, response, result): client = mock_client() mocker.patch.object(client, '_http_request', return_value=response) res = client.get_indicator_additional_info('identifier', 'Malware', info_type) assert res == result def test_get_indicators_valid(mocker): client = mock_client() mocker.patch.object(client, '_http_request', return_value={'malware': ['list']}) res = client.get_indicators('Malware') assert res == ['list'] def test_get_indicators_invalid(mocker): from FeedMandiant import DemistoException client = mock_client() mocker.patch.object(client, '_http_request', side_effect=DemistoException('exception')) res = client.get_indicators('Malware') assert res == [] INDICATOR_LIST = [{'last_updated': '2020-11-23T11:57:28Z'}, {'last_updated': '2020-11-24T11:57:28Z'}] @pytest.mark.parametrize('indicator_type, result', [('Indicators', INDICATOR_LIST), ('Malware', INDICATOR_LIST[::-1])]) @freezegun.freeze_time('2020-11-25T11:57:28Z') def test_get_new_indicators(mocker, indicator_type, result): from FeedMandiant import get_new_indicators client = mock_client() mocker.patch.object(client, 'get_indicators', return_value=INDICATOR_LIST) res = get_new_indicators(client, '90 days ago', indicator_type, 10) assert res == result @pytest.mark.parametrize('mscore, res', [(None, 0), ('1', 1), ('22', 0), ('52', 2), ('82', 3), ('101', 0)]) def test_get_verdict(mscore, res): """ Given - mscore When - get_verdict Then - receive valid verdict for each mscore """ from FeedMandiant import get_verdict assert get_verdict(mscore) == res def test_get_indicator_relationships(): from FeedMandiant import get_indicator_relationships, EntityRelationship res = get_indicator_relationships({'field_indicator': [{'entity_b_field': 'value_b'}], 'entity_a_field': 'value_a'}, 'field_indicator', 'entity_a_field', 'entity_a_type', 'entity_b_field', 'entity_b_type', EntityRelationship.Relationships.RELATED_TO, EntityRelationship.Relationships.RELATED_TO) assert len(res) == 1 assert res[0]['entityA'] == 'value_a' assert res[0]['entityAType'] == 'entity_a_type' assert res[0]['entityB'] == 'value_b' assert res[0]['entityBType'] == 'entity_b_type' assert res[0]['name'] == 'related-to' assert res[0]['reverseName'] == 'related-to' BASIC_INDICATOR = { 'operating_systems': 'operatingsystemrefs', 'aliases': 'redacted', 'capabilities': 'capabilities', 'industries': [{'name': 'tags'}], 'detections': 'mandiantdetections', 'yara': [{'name': 'name', 'id': 'id'}], 'roles': 'roles', 'id': 'stixid', 'name': 'name', 'description': 'description', 'last_updated': 'updateddate', 'last_activity_time': 'lastseenbysource', 'actors': [], 'cve': [], 'mscore': 100, 'motivations': 'primarymotivation', 'locations': {'target': [{'name': 'target'}]} } def test_create_malware_indicator(): from FeedMandiant import create_malware_indicator client = mock_client() res = create_malware_indicator(client, BASIC_INDICATOR) assert res['value'] == 'name' assert res['type'] == 'Malware' assert len(res['fields']) == 11 def test_create_actor_indicator(): from FeedMandiant import create_actor_indicator client = mock_client() res = create_actor_indicator(client, BASIC_INDICATOR) assert res['value'] == 'name' assert res['type'] == 'Threat Actor' assert len(res['fields']) == 7 @freezegun.freeze_time('2020-11-25T11:57:28Z') def test_fetch_indicators(mocker): from FeedMandiant import fetch_indicators client = mock_client() mocker.patch.object(client, 'get_indicators', return_value=INDICATOR_LIST) res = fetch_indicators(client, update_context=False) assert len(res) == 1 @pytest.mark.parametrize('command', ['test-module', 'feed-mandiant-get-indicators']) def test_main(mocker, command): from FeedMandiant import main, MandiantClient import demistomock as demisto params = {'auth': {'identifier': 'identifier', 'password': 'password'}, 'insecure': True, 'url': 'https://url.com', 'first_fetch': "89 days ago", 'indicatorMetadata': True, 'limit': 10, 'indicatorRelationships': True, 'type': []} mocker.patch.object(demisto, 'params', return_value=params) mocker.patch.object(MandiantClient, '_generate_token', return_value='token') mocker.patch.object(demisto, 'command', return_value=command) main() def test_get_indicator_list(): """ Given - client When - getting new indicators Then - receive list of indicators """ import FeedMandiant client = mock_client() res_indicators = util_load_json('./test_data/result_indicators.json') def get_new_indicators_mock(a, b, c, d): return res_indicators['new_indicators'] FeedMandiant.get_new_indicators = get_new_indicators_mock res = FeedMandiant.get_indicator_list(client, 2, '90 days ago', 'Indicators') assert res == res_indicators['new_indicators'] def test_get_indicator_list_two_iterations(mocker): """ Given - mock client and response. When - getting new indicators twice. Then - Ensures the right indicator was returned: the first response should be from the get_new_indicators function and the second one from the last run object. """ import FeedMandiant import demistomock as demisto client = mock_client() res_indicators = util_load_json('./test_data/result_indicators.json') def get_new_indicators_mock(a, b, c, d): return res_indicators['new_indicators_2'] FeedMandiant.get_new_indicators = get_new_indicators_mock res = FeedMandiant.get_indicator_list(client, 1, '90 days ago', 'Indicators') assert res == [res_indicators['new_indicators_2'][0]] mocker.patch.object(demisto, 'getLastRun', return_value={'IndicatorsList': [res_indicators['new_indicators_2'][1]]}) FeedMandiant.get_new_indicators = get_new_indicators_mock res = FeedMandiant.get_indicator_list(client, 1, '90 days ago', 'Indicators') assert res == [res_indicators['new_indicators_2'][1]]