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 == []