Exemplo n.º 1
0
def test_try_create_search_with_retry__sad(mocker):
    """
    Create an event search with a connection error first, and succesful try after

    Given:
        - Event fetch is to be created via the qradar client
    When:
        - Search first returns ConnectionError
        - Search then returns search object
    Then:
        - Assert search is created with id and status
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    events_query = ""
    offense = RAW_RESPONSES["fetch-incidents"]
    max_retries = 0
    exception_raised = False
    mocker.patch.object(
        client,
        "search",
        side_effect=[ConnectionError, RAW_RESPONSES["qradar-searches"]])

    try:
        try_create_search_with_retry(client, events_query, offense,
                                     max_retries)
    except DemistoException:
        exception_raised = True
    assert exception_raised
Exemplo n.º 2
0
def test_commands(command, command_func, args, mocker):
    """
    Test a set of commands given input->output
    tested commands:
      * qradar-searches
      * qradar-get-search
      * qradar-get-search-results
      * qradar-get-assets
      * qradar-get-asset-by
      * qradar-get-closing-reasons
      * qradar-create-note
      * qradar-get-note

    Given:
        - command - command name
        - command_func - function of command
        - args - arguments for command
    When:
        - Command `command` is being called
    Then:
        - Assert the entryContext matches the COMMAND_OUTPUTS map entry value (expected output)
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    mocker.patch.object(client,
                        "send_request",
                        return_value=RAW_RESPONSES[command])
    mocker.patch.object(demisto, "debug")
    res = command_func(client, **args)
    assert COMMAND_OUTPUTS[command] == res.get("EntryContext")
Exemplo n.º 3
0
    def test_fetch_incidents_long_running_events(self, mocker):
        """
        Assert fetch_incidents_long_running_events updates integration context with the expected id, samples and events

        Given:
            - Fetch incidents is set to: FetchMode.all_events
            - There is an offense to fetch: 450
        When:
            - Fetch loop is triggered
        Then:
            - Assert integration context id is set correctly
            - Assert integration context samples is set with correct length
            - Assert integration context events is set with correct value
        """
        expected_events = "assert ok"

        def mock_enrich_offense_with_events(client, offense, fetch_mode, events_columns, events_limit):
            offense['events'] = expected_events
            return offense

        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        fetch_mode = FetchMode.all_events
        mocker.patch.object(QRadar_v2, "get_integration_context", return_value={})
        mocker.patch.object(QRadar_v2, "fetch_raw_offenses", return_value=[RAW_RESPONSES["fetch-incidents"]])
        QRadar_v2.enrich_offense_with_events = mock_enrich_offense_with_events
        mocker.patch.object(demisto, "createIncidents")
        mocker.patch.object(demisto, "debug")
        sic_mock = mocker.patch.object(QRadar_v2, "set_integration_context")

        fetch_incidents_long_running_events(client, "", "", False, False, fetch_mode, "", "")

        assert sic_mock.call_args[0][0]['id'] == 450
        assert len(sic_mock.call_args[0][0]['samples']) == 1
        incident_raw_json = json.loads(sic_mock.call_args[0][0]['samples'][0]['rawJSON'])
        assert incident_raw_json['events'] == expected_events
Exemplo n.º 4
0
def test_try_create_search_with_retry__semi_happy(mocker):
    """
    Create an event search with a connection error first, and succesful try after

    Given:
        - Event fetch is to be created via the qradar client
    When:
        - Search first returns ConnectionError
        - Search then returns search object
    Then:
        - Assert search is created with id and status
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    events_query = ""
    offense = RAW_RESPONSES["fetch-incidents"]
    max_retries = 3

    mocker.patch.object(
        client,
        "search",
        side_effect=[ConnectionError, RAW_RESPONSES["qradar-searches"]])

    actual_status, actual_id = try_create_search_with_retry(
        client, events_query, offense, max_retries)
    assert actual_status == "EXECUTE"
    assert actual_id == "a135f4cb-c22a-4b3a-aa7d-83058c219d33"
Exemplo n.º 5
0
    def test_enrich_offense_result(self, mocker):
        """
        Enrich offense results with assets, domains and rules

        Given:
            - Offense response was fetched from QRadar with rule ids and domain ids
        When:
            - Enriching fetched offense
        Then:
            - domain_name has been added to offense
            - domain_name has been added to offense asset
            - rule name has been added to offense
        """
        closing_reason_dict = [{'is_deleted': False, 'is_reserved': False, 'text': 'False-Positive, Tuned', 'id': 2}]
        offense_types = [{'property_name': 'sourceIP', 'custom': False, 'name': 'Source IP', 'id': 0}]
        domains = [{'name': '', 'tenant_id': 0, 'id': 0, 'log_source_group_ids': []}]
        rules = [{'name': 'Outbound port scan', 'id': 100452}]
        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        offense = deepcopy(RAW_RESPONSES["qradar-update-offense"])
        offense['assets'] = deepcopy(RAW_RESPONSES['qradar-get-asset-by-id'])
        response = [offense]

        mocker.patch.object(client, "get_closing_reasons", return_value=closing_reason_dict)
        mocker.patch.object(client, "get_offense_types", return_value=offense_types)
        mocker.patch.object(client, "get_devices", return_value=domains)
        mocker.patch.object(client, "get_rules", return_value=rules)

        enrich_offense_result(client, response)
        assert 'domain_name' in response[0]
        assert 'domain_name' in response[0]['assets'][0]
        assert 'name' in response[0]['rules'][0]
Exemplo n.º 6
0
def test_try_poll_offense_events_with_retry__semi_happy(mocker):
    """
    Poll event with a failure, recovery and success flow

    Given:
        - Event fetch is to be polled via the qradar client
    When:
        - Search first returns ConnectionError
        - Search then returns search is COMPLETED
    Then:
        - Assert events are fetched correctly
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    offense_id = 450
    query_status = "EXECUTE"
    search_id = "1"
    max_retries = 3
    expected = [{'MY Source IPs': '8.8.8.8'}]

    mocker.patch.object(QRadar_v2, "is_reset_triggered", return_value=False)
    mocker.patch.object(
        client,
        "get_search",
        side_effect=[ConnectionError, RAW_RESPONSES["qradar-get-search"]])
    mocker.patch.object(
        client,
        "get_search_results",
        return_value=RAW_RESPONSES["qradar-get-search-results"])
    mocker.patch.object(demisto, "debug")

    actual = try_poll_offense_events_with_retry(client, offense_id,
                                                query_status, search_id,
                                                max_retries)
    assert actual == expected
Exemplo n.º 7
0
def test_try_poll_offense_events_with_retry__reset(mocker):
    """
    Poll event with when reset is set

    Given:
        - Event fetch is to be polled via the qradar client
    When:
        - Reset trigger is waiting
    Then:
        - Stop fetch and return empty list
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    offense_id = 450
    query_status = "EXECUTE"
    search_id = "1"
    max_retries = 3

    mocker.patch.object(QRadar_v2, "is_reset_triggered", return_value=True)
    mocker.patch.object(
        client,
        "get_search",
        side_effect=[ConnectionError, RAW_RESPONSES["qradar-get-search"]])
    mocker.patch.object(
        client,
        "get_search_results",
        return_value=RAW_RESPONSES["qradar-get-search-results"])
    mocker.patch.object(demisto, "debug")

    actual = try_poll_offense_events_with_retry(client, offense_id,
                                                query_status, search_id,
                                                max_retries)
    assert actual == []
Exemplo n.º 8
0
def test_fetch_incidents_long_running_no_events(mocker):
    """
    Assert fetch_incidents_long_running_no_events updates integration context with the expected id and samples

    Given:
        - Fetch incidents is set to: FetchMode.no_events
        - There is an offense to fetch: 450
    When:
        - Fetch loop is triggered
    Then:
        - Assert integration context id is set correctly
        - Assert integration context samples is set with correct length
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    mocker.patch.object(QRadar_v2, "get_integration_context", return_value={})
    mocker.patch.object(QRadar_v2,
                        "fetch_raw_offenses",
                        return_value=[RAW_RESPONSES["fetch-incidents"]])
    mocker.patch.object(demisto, "createIncidents")
    mocker.patch.object(demisto, "debug")
    sic_mock = mocker.patch.object(QRadar_v2,
                                   "set_to_integration_context_with_retries")

    fetch_incidents_long_running_no_events(client,
                                           '',
                                           user_query="",
                                           ip_enrich=False,
                                           asset_enrich=False)

    assert sic_mock.call_args[0][0]['id'] == 450
    assert len(sic_mock.call_args[0][0]['samples']) == 1
Exemplo n.º 9
0
def test_try_poll_offense_events_with_retry__sad(mocker):
    """
    Poll event with a failure

    Given:
        - Event fetch is to be polled via the qradar client
    When:
        - Search first returns ConnectionError
        - Recovery is set to 0
    Then:
        - Stop fetch and return empty list
    """
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    offense_id = 450
    query_status = "EXECUTE"
    search_id = "1"
    max_retries = 0

    mocker.patch.object(QRadar_v2, "is_reset_triggered", return_value=False)
    mocker.patch.object(
        client,
        "get_search",
        side_effect=[ConnectionError, RAW_RESPONSES["qradar-get-search"]])
    mocker.patch.object(demisto, "debug")

    actual = try_poll_offense_events_with_retry(client, offense_id,
                                                query_status, search_id,
                                                max_retries)
    assert actual == []
Exemplo n.º 10
0
class TestGetCustomProperties:
    error = 'Can\'t send the `filter` argument with `field_name` or `like_name`'
    client = QRadarClient("https://example.com", {}, {
        "identifier": "*",
        "password": "******"
    })

    def test_filter_with_field_name(self):
        from QRadar_v2 import get_custom_properties_command
        with pytest.raises(DemistoException, match=self.error):
            get_custom_properties_command(self.client,
                                          filter='name="hatul"',
                                          field_name='b,c')

    def test_filter_with_like_name(self):
        from QRadar_v2 import get_custom_properties_command
        with pytest.raises(DemistoException, match=self.error):
            get_custom_properties_command(self.client,
                                          filter='name="hatul"',
                                          like_name='b,c')

    def test_filter_with_like_name_and_name_field(self):
        from QRadar_v2 import get_custom_properties_command
        with pytest.raises(DemistoException, match=self.error):
            get_custom_properties_command(self.client,
                                          filter='name="hatul"',
                                          field_name='a,g',
                                          like_name='b,c')

    def test_filter_only(self, requests_mock):
        from QRadar_v2 import get_custom_properties_command
        requests_mock.get(
            'https://example.com/api/config/event_sources/custom_properties/regex_properties?filter=name%3D%22trol%22',
            json=[{
                'name': 'bloop'
            }])
        resp = get_custom_properties_command(self.client, filter='name="trol"')
        assert resp['EntryContext']['QRadar.Properties'][0]['name'] == 'bloop'

    def test_name_field_only(self, requests_mock):
        from QRadar_v2 import get_custom_properties_command
        requests_mock.get(
            'https://example.com/api/config/event_sources/custom_properties/regex_properties?filter=name%3D+%22trol%22',
            json=[{
                'name': 'bloop'
            }])
        resp = get_custom_properties_command(self.client, field_name='trol')
        assert resp['EntryContext']['QRadar.Properties'][0]['name'] == 'bloop'

    def test_like_name_only(self, requests_mock):
        from QRadar_v2 import get_custom_properties_command
        requests_mock.get(
            'https://example.com/api/config/event_sources/custom_properties/regex_properties?filter=name+ILIKE+%22%25trol%25%22',
            json=[{
                'name': 'bloop'
            }])
        resp = get_custom_properties_command(self.client, like_name='trol')
        assert resp['EntryContext']['QRadar.Properties'][0]['name'] == 'bloop'
Exemplo n.º 11
0
def test_get_assets_for_offense__empty():
    """Check get assets for offense returns an empty list when no value is given

    Given:
    - No assets_ips
    When:
    - Calling get_assets_for_offense
    Then:
    - Return an empty list
    """
    from QRadar_v2 import get_assets_for_offense
    client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
    assert [] == get_assets_for_offense(client, [])
Exemplo n.º 12
0
    def test_fetch_incidents_long_running_events__timeout(self, mocker):
        """
        Assert raw offenses are populated as expected when timeout is reached

        Given:
            - Fetch incidents is set to: FetchMode.all_events
            - There is an offense to fetch: 450
        When:
            - Fetch loop is triggered
        Then:
            - Assert print_debug_msg was called with timeout message
            - Assert integration context id is set correctly
            - Assert integration context samples is set with correct length
            - Assert integration context events is not set
        """
        def mock_enrich_offense_with_events(client, offense, fetch_mode,
                                            events_columns, events_limit):
            time.sleep(0.001)
            return offense

        QRadar_v2.DEFAULT_EVENTS_TIMEOUT = 0
        offense_with_no_events = RAW_RESPONSES["fetch-incidents"]
        if 'events' in offense_with_no_events:
            del offense_with_no_events['events']
        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        fetch_mode = FetchMode.all_events
        mocker.patch.object(QRadar_v2,
                            "get_integration_context",
                            return_value={})
        mocker.patch.object(QRadar_v2,
                            "fetch_raw_offenses",
                            return_value=[offense_with_no_events])
        print_debug_msg_mock = mocker.patch.object(QRadar_v2,
                                                   "print_debug_msg")
        QRadar_v2.enrich_offense_with_events = mock_enrich_offense_with_events
        mocker.patch.object(demisto, "createIncidents")
        mocker.patch.object(demisto, "debug")
        sic_mock = mocker.patch.object(QRadar_v2, "set_integration_context")

        fetch_incidents_long_running_events(client, "", "", False, False,
                                            fetch_mode, "", "")

        assert print_debug_msg_mock.call_args_list[0].args[
            0] == "Timed out while waiting for events"
        assert sic_mock.call_args[0][0]['id'] == 450
        assert len(sic_mock.call_args[0][0]['samples']) == 1
        incident_raw_json = json.loads(
            sic_mock.call_args[0][0]['samples'][0]['rawJSON'])
        assert 'events' not in incident_raw_json
        QRadar_v2.DEFAULT_EVENTS_TIMEOUT = 30
Exemplo n.º 13
0
def test_get_assets_for_offense__happy(requests_mock, mocker):
    """Check get assets for offense returns the expected assets

    Given:
    - 1 item in assets_ips
    When:
    - Calling get_assets_for_offense
    Then:
    - Return the asset correlating to assets_ips
    - The asset properties are flatten
    - The interfaces are simplified
    - The assets match the mapping fields
    """
    from QRadar_v2 import get_assets_for_offense, get_mapping_fields
    client = QRadarClient("https://example.com", {}, {
        "identifier": "*",
        "password": "******"
    })
    requests_mock.get('https://example.com/api/asset_model/assets',
                      json=RAW_RESPONSES['qradar-get-asset-by-id'])
    mocker.patch.object(QRadarClient, 'get_custom_fields', return_value=[])
    mapping_fields = get_mapping_fields(client)

    res = get_assets_for_offense(client, ['8.8.8.8'])
    res_interfaces = res[0]['interfaces'][0]

    assert res[0]['id'] == 1928

    # flatten properties check
    assert res[0][
        'Unified Name'] == 'ec2-44-234-115-112.us-west-2.compute.amazonaws.com'

    # simplify interfaces check
    assert len(res_interfaces) == 3
    assert res_interfaces['mac_address'] == 'Unknown NIC'
    assert res_interfaces['id'] == 1915
    assert res_interfaces['ip_addresses'] == [{
        'type': 'IPV4',
        'value': '8.8.8.8'
    }]

    # assets match the mapping fields
    mapping_fields_interfaces = mapping_fields['Assets']['assets'][
        'interfaces']
    assert set(res_interfaces.keys()).issubset(
        mapping_fields_interfaces.keys())
    assert res_interfaces['ip_addresses'][0].keys(
    ) == mapping_fields_interfaces['ip_addresses'].keys()
Exemplo n.º 14
0
    def test_enrich_offense_with_events__correlations(self, mocker):
        """
        Assert enrich_offense_with_events adds an additional WHERE query when FetchMode.correlations_only

        Given:
            - Fetch incidents is set to: FetchMode.correlations_only
        When:
            - Event fetch query is built via in enrich_offense_with_event
        Then:
            - Assert search is created with additional WHERE query
        """
        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        offense = RAW_RESPONSES["fetch-incidents"]
        fetch_mode = FetchMode.correlations_only
        events_cols = ""
        events_limit = ""

        poee_mock = mocker.patch.object(QRadar_v2, "perform_offense_events_enrichment", return_value=offense)
        enrich_offense_with_events(client, offense, fetch_mode, events_cols, events_limit)
        assert poee_mock.call_args[0][1] == "AND LOGSOURCETYPENAME(devicetype) = 'Custom Rule Engine'"
Exemplo n.º 15
0
    def test_enrich_offense_with_events__all_events(self, mocker):
        """
        Assert enrich_offense_with_events doesn't add an additional WHERE query when FetchMode.all_events

        Given:
            - Fetch incidents is set to: FetchMode.all_events
        When:
            - Event fetch query is built via in enrich_offense_with_event
        Then:
            - Assert search is created without additional WHERE query
        """
        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        offense = RAW_RESPONSES["fetch-incidents"]
        fetch_mode = FetchMode.all_events
        events_cols = ""
        events_limit = ""

        poee_mock = mocker.patch.object(QRadar_v2, "perform_offense_events_enrichment", return_value=offense)
        enrich_offense_with_events(client, offense, fetch_mode, events_cols, events_limit)
        assert poee_mock.call_args[0][1] == ""
Exemplo n.º 16
0
    def test_get_mapping_fields(self, mocker):
        """Check keys available in the mapping

        Given:
        - One custom field

        When:
        - Calling get-mapping-fields from the UI

        Then:
        - Validate main keys are in
        - Validate custom field came back as intended
        """
        from QRadar_v2 import get_mapping_fields
        custom_fields = [{'name': 'bloop', 'property_type': 'string'}]
        mocker.patch.object(QRadarClient, 'get_custom_fields', return_value=custom_fields)
        client = QRadarClient("", {}, {"identifier": "*", "password": "******"})
        response = get_mapping_fields(client)
        assert response['Offense']
        assert response['Events: Builtin Fields']
        assert response['Assets']
        assert response['Events: Custom Fields']['events']['bloop'] == 'string'
Exemplo n.º 17
0
    def test_fetch_event_no_event_field(self, mocker):
        """
        Given:
            - fetch mode: fetching all event
            - events_columns: None

        Then:
            - Run test_module

        Then:
            - Validate DemistoException is raised
        """
        client = QRadarClient('', {}, {"identifier": '*', 'password': '******'})
        mocker.patch.object(client, 'test_connection', return_value=True)
        mocker.patch.object(client, 'get_offenses', return_value=True)
        mocker.patch.object(demisto, 'params', return_value={
            'longRunning': True,
            'fetch_mode': FetchMode.all_events,
            'events_columns': None
        })
        with pytest.raises(DemistoException):
            QRadar_v2.test_module(client)