def test_fetch_incidents(requests_mock, mocker): from PaloAltoNetworks_XDR import fetch_incidents, Client, sort_all_list_incident_fields get_incidents_list_response = load_test_data('./test_data/get_incidents_list.json') raw_incident = load_test_data('./test_data/get_incident_extra_data.json') modified_raw_incident = raw_incident['reply']['incident'].copy() modified_raw_incident['alerts'] = raw_incident['reply'].get('alerts').get('data') modified_raw_incident['file_artifacts'] = raw_incident['reply'].get('file_artifacts').get('data') modified_raw_incident['network_artifacts'] = raw_incident['reply'].get('network_artifacts').get('data') modified_raw_incident['mirror_direction'] = 'In' modified_raw_incident['mirror_instance'] = 'MyInstance' requests_mock.post(f'{XDR_URL}/public_api/v1/incidents/get_incidents/', json=get_incidents_list_response) requests_mock.post(f'{XDR_URL}/public_api/v1/incidents/get_incident_extra_data/', json=raw_incident) mocker.patch.object(demisto, 'params', return_value={"extra_data": True, "mirror_direction": "Incoming"}) client = Client( base_url=f'{XDR_URL}/public_api/v1', headers={} ) next_run, incidents = fetch_incidents(client, '3 month', 'MyInstance') sort_all_list_incident_fields(modified_raw_incident) assert len(incidents) == 2 assert incidents[0]['name'] == "#1 - 'Local Analysis Malware' generated by XDR Agent detected on host AAAAA " \ "involving user Administrator" if 'network_artifacts' not in json.loads(incidents[0]['rawJSON']): assert False assert incidents[0]['rawJSON'] == json.dumps(modified_raw_incident)
def test_get_remote_data_command_should_close_issue(requests_mock): """ Given: - an XDR client - arguments (id and lastUpdate time set to a lower than incident modification time) - a raw incident (get-extra-data results) indicating the incident was closed on XDR side When - running get_remote_data_command Then - the mirrored_object in the GetRemoteDataResponse is the same as the modified raw incident - the entries in the GetRemoteDataResponse holds the closing entry """ from PaloAltoNetworks_XDR import get_remote_data_command, Client, sort_all_list_incident_fields client = Client(base_url=f'{XDR_URL}/public_api/v1', headers={}) args = {'id': 1, 'lastUpdate': 0} raw_incident = load_test_data('./test_data/get_incident_extra_data.json') raw_incident['reply']['incident']['status'] = 'resolved_threat_handled' raw_incident['reply']['incident']['resolve_comment'] = 'Handled' expected_modified_incident = raw_incident['reply']['incident'].copy() expected_modified_incident['alerts'] = raw_incident['reply'].get( 'alerts').get('data') expected_modified_incident['network_artifacts'] = raw_incident[ 'reply'].get('network_artifacts').get('data') expected_modified_incident['file_artifacts'] = raw_incident['reply'].get( 'file_artifacts').get('data') expected_modified_incident['id'] = expected_modified_incident.get( 'incident_id') expected_modified_incident['assigned_user_mail'] = '' expected_modified_incident['assigned_user_pretty_name'] = '' expected_modified_incident['closeReason'] = 'Resolved' expected_modified_incident['closeNotes'] = 'Handled' expected_modified_incident['in_mirror_error'] = '' del expected_modified_incident['creation_time'] expected_closing_entry = { 'Type': 1, 'Contents': { 'dbotIncidentClose': True, 'closeReason': 'Resolved', 'closeNotes': 'Handled' }, 'ContentsFormat': 'json' } requests_mock.post( f'{XDR_URL}/public_api/v1/incidents/get_incident_extra_data/', json=raw_incident) response = get_remote_data_command(client, args) sort_all_list_incident_fields(expected_modified_incident) assert response.mirrored_object == expected_modified_incident assert expected_closing_entry in response.entries
def test_get_remote_data_command_sync_owners(requests_mock, mocker): """ Given: - an XDR client - arguments (id and lastUpdate time set to a lower than incident modification time) - a raw incident (get-extra-data results) with assigned mail [email protected] When - running get_remote_data_command Then - the mirrored_object in the GetRemoteDataResponse is the same as the modified raw incident with the equivalent owner of the assigned mail - the entries in the GetRemoteDataResponse in empty """ from PaloAltoNetworks_XDR import get_remote_data_command, Client, sort_all_list_incident_fields mocker.patch.object(demisto, 'params', return_value={"sync_owners": True}) mocker.patch.object(demisto, 'findUser', return_value={ "email": "*****@*****.**", 'username': '******' }) client = Client(base_url=f'{XDR_URL}/public_api/v1', headers={}) args = {'id': 1, 'lastUpdate': 0} raw_incident = load_test_data('./test_data/get_incident_extra_data.json') raw_incident['reply']['incident']['assigned_user_mail'] = '*****@*****.**' expected_modified_incident = raw_incident['reply']['incident'].copy() expected_modified_incident['alerts'] = raw_incident['reply'].get( 'alerts').get('data') expected_modified_incident['network_artifacts'] = raw_incident[ 'reply'].get('network_artifacts').get('data') expected_modified_incident['file_artifacts'] = raw_incident['reply'].get( 'file_artifacts').get('data') expected_modified_incident['id'] = expected_modified_incident.get( 'incident_id') expected_modified_incident['assigned_user_mail'] = '*****@*****.**' expected_modified_incident['assigned_user_pretty_name'] = None expected_modified_incident['owner'] = 'username' expected_modified_incident['in_mirror_error'] = '' del expected_modified_incident['creation_time'] requests_mock.post( f'{XDR_URL}/public_api/v1/incidents/get_incident_extra_data/', json=raw_incident) response = get_remote_data_command(client, args) sort_all_list_incident_fields(expected_modified_incident) assert response.mirrored_object == expected_modified_incident assert response.entries == []
def test_fetch_incidents_with_rate_limit_error(requests_mock, mocker): """ Given: - a Rate limit error occurs in the second call for 'get_extra_data_command' When - running fetch_incidents command Then - the first successful incident is being created - the second incident is saved for the next run """ from PaloAltoNetworks_XDR import fetch_incidents, Client, sort_all_list_incident_fields get_incidents_list_response = load_test_data('./test_data/get_incidents_list.json') raw_incident = load_test_data('./test_data/get_incident_extra_data.json') modified_raw_incident = raw_incident['reply']['incident'].copy() modified_raw_incident['alerts'] = raw_incident['reply'].get('alerts').get('data') modified_raw_incident['file_artifacts'] = raw_incident['reply'].get('file_artifacts').get('data') modified_raw_incident['network_artifacts'] = raw_incident['reply'].get('network_artifacts').get('data') modified_raw_incident['mirror_direction'] = 'In' modified_raw_incident['mirror_instance'] = 'MyInstance' requests_mock.post(f'{XDR_URL}/public_api/v1/incidents/get_incidents/', json=get_incidents_list_response) requests_mock.post(f'{XDR_URL}/public_api/v1/incidents/get_incident_extra_data/', json=raw_incident) mocker.patch('PaloAltoNetworks_XDR.get_incident_extra_data_command', side_effect=return_extra_data_result) mocker.patch.object(demisto, 'params', return_value={"extra_data": True, "mirror_direction": "Incoming"}) client = Client( base_url=f'{XDR_URL}/public_api/v1', headers={} ) next_run, incidents = fetch_incidents(client, '3 month', 'MyInstance') sort_all_list_incident_fields(modified_raw_incident) assert len(incidents) == 1 # because the second one raised a rate limit error assert incidents[0]['name'] == "#1 - 'Local Analysis Malware' generated by XDR Agent detected on host AAAAA " \ "involving user Administrator" incidents_from_previous_run = next_run.get('incidents_from_previous_run') assert incidents_from_previous_run assert len(incidents_from_previous_run) == 1 assert incidents_from_previous_run[0].get('incident_id') == '2' if 'network_artifacts' not in json.loads(incidents[0]['rawJSON']): assert False assert incidents[0]['rawJSON'] == json.dumps(modified_raw_incident)
def test_sort_all_list_incident_fields(): """ Given: - A raw incident When - running sort_all_list_incident_fields on it Then - the list fields (alerts for example) are sorted """ from PaloAltoNetworks_XDR import sort_all_list_incident_fields raw_incident = load_test_data('test_data/raw_fetched_incident.json') sort_all_list_incident_fields(raw_incident) assert raw_incident.get('alerts')[0].get('alertid') == "42" assert raw_incident.get('alerts')[1].get('alertid') == "55" assert raw_incident.get('alerts')[2].get('alertid') == "60" assert raw_incident.get('hosts')[0] == 'HOST1' assert raw_incident.get('hosts')[1] == 'HOST2' assert raw_incident.get('file_artifacts')[0].get('filename') == 'file.exe' assert raw_incident.get('file_artifacts')[1].get('filename') == 'file2.exe'
def test_get_remote_data_command_should_update(requests_mock): """ Given: - an XDR client - arguments (id and lastUpdate time set to a lower than incident modification time) - a raw incident (get-extra-data results) When - running get_remote_data_command Then - the mirrored_object in the GetRemoteDataResponse is the same as the modified raw incident - the entries in the GetRemoteDataResponse in empty """ from PaloAltoNetworks_XDR import get_remote_data_command, Client, sort_all_list_incident_fields client = Client(base_url=f'{XDR_URL}/public_api/v1', headers={}) args = {'id': 1, 'lastUpdate': 0} raw_incident = load_test_data('./test_data/get_incident_extra_data.json') expected_modified_incident = raw_incident['reply']['incident'].copy() expected_modified_incident['alerts'] = raw_incident['reply'].get( 'alerts').get('data') expected_modified_incident['network_artifacts'] = raw_incident[ 'reply'].get('network_artifacts').get('data') expected_modified_incident['file_artifacts'] = raw_incident['reply'].get( 'file_artifacts').get('data') expected_modified_incident['id'] = expected_modified_incident.get( 'incident_id') expected_modified_incident['assigned_user_mail'] = '' expected_modified_incident['assigned_user_pretty_name'] = '' expected_modified_incident['in_mirror_error'] = '' del expected_modified_incident['creation_time'] requests_mock.post( f'{XDR_URL}/public_api/v1/incidents/get_incident_extra_data/', json=raw_incident) response = get_remote_data_command(client, args) sort_all_list_incident_fields(expected_modified_incident) assert response.mirrored_object == expected_modified_incident assert response.entries == []