ExportIndicators Deprecated
Deprecated. Use the Generic Export Indicators Service integration instead. Use the Export Indicators Service integration to provide an endpoint with a list of indicators as a service for the system indicators.
Data Enrichment & Threat Intelligence · Export Indicators (Deprecated)
Details
| ID | ExportIndicators |
|---|---|
| Provider | Open Source |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/flask-nginx:1.0.0.23674 |
README
Use the Export Indicators Service integration to provide an endpoint with a list of indicators as a service for the system indicators.
Use Cases
- Export a list of malicious IPs to block via a firewall.
- Export a list of indicators to a service such as Splunk, using a supported output format.
Configure ExportIndicators on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for ExportIndicators.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Indicator Query: The query to run to update its list. To view expected results, you can run the following command from the Cortex XSOAR CLI
!findIndicators query=<your query> - Outbound Format: The default format of the entries in the service. Supported formats: text, json, json-seq, csv, XSOAR json, XSOAR json-seq, XSOAR csv, PAN-OS URL, Symantec ProxySG and McAfee Web Gateway.
- List Size: Max amount of entries in the service instance.
- Update On Demand Only: When set to true, will only update the service indicators via eis-update command.
- Refresh Rate: How often to refresh the export indicators list (<number> <time unit>, e.g., 12 hours, 7 days, 3
months, 1 year) - Collapse IPs: Whether to collapse IPs and if so - to ranges or CIDRs.
- Show CSV Formats as Text: If checked, csv and XSOAR-csv formats will create a textual web page instead of downloading a csv file.
- Listen Port: Will run the Export Indicators Service on this port from within Cortex XSOAR. If you have multiple Export Indicators Service integration instances, make sure to use different listening ports to separate the outbound feeds.
- Certificate (Required for HTTPS): HTTPS Certificate provided by pasting its values into this field.
- Private Key (Required for HTTPS): HTTPS private key provided by pasting its values into this field.
- HTTP Server: Ignores certificate and private key, and will run the export indicators service
in HTTP. (Not recommended.) - Username: The username with which to authenticate when fetching the indicators.
- Password: The password with which to authenticate when fetching the indicators.
- Mcafee Gateway Indicator List Type: For use with McAfee Web Gateway format to indicate the list type.
- PAN-OS URL Format Port Strip: For use with PAN-OS URL format - if checked will strip the port off
urls. If not checked - url with ports will be ignored. - PAN-OS URL Format Drop Invalid Entries: For use with PAN-OS URL format - if checked any URL entry which is
not compliant with PAN-OS EDL URL format the entry is dropped instead of being
rewritten. - Symantec ProxySG Default Category: For use with Symantec ProxySG format - set the default category
for the output. - Symantec ProxySG Listed Categories: For use with Symantec ProxySG format - set the categories that should
be listed in the output. If not set will list all existing categories.
- Click Test to validate the URLs, token, and connection.
Access the Export Indicators Service by Instance Name (HTTPS)
Note: By default, the route will be open without security hardening and might expose you to network risks. Cortex XSOAR recommends that you use credentials to connect to connect to the integration.
To access the Export Indicators service by instance name, make sure Instance execute external is enabled.
- In Cortex XSOAR, go to Settings > About > Troubleshooting.
- In the Server Configuration section, verify that the instance.execute.external key is set to true. If this key does not exist, click + Add Server Configuration and add the instance.execute.external and set the value to true. See this documentation for further information.
- In a web browser, go to
https://*<demisto_address>*/instance/execute/*<instance_name>*.
Update values in the export indicators service
Updates values stored in the export indicators service (only avaialable On-Demand).
URL Inline Arguments
Use the following arguments in the URL to change the request:
| Argument Name | Description | Example |
|---|---|---|
| n | The maximum number of entries in the output. If no value is provided, will use the value specified in the List Size parameter configured in the instance configuration. | https://{server_host}/instance/execute/{instance_name}?n=50 |
| s | The starting entry index from which to export the indicators. | https://{server_host}/instance/execute/{instance_name}?s=10&n=50 |
| v | The output format. Supports text, csv, json, json-seq,xsoar-json, xsoar-seq, xsoar-csv, mwg, panosurl and proxysg (alias: bluecoat). |
https://{server_host}/instance/execute/{instance_name}?v=json |
| q | The query used to retrieve indicators from the system. | https://{server_host}/instance/execute/{instance_name}?q="type:ip and sourceBrand:my_source" |
| t | Only with mwg format. The type indicated on the top of the exported list. Supports: string, applcontrol, dimension, category, ip, mediatype, number and regex. |
https://{server_host}/instance/execute/{instance_name}?v=mwg&t=ip |
| sp | Only with panosurl format. If set will strip ports off URLs, otherwise will ignore URLs with ports. |
https://{server_host}/instance/execute/{instance_name}?v=panosurl&sp |
| di | Only with panosurl format. If set will ignore urls which are not compliant with PAN-OS URL format instead of being re-written. |
https://{server_host}/instance/execute/{instance_name}?v=panosurl&di |
| cd | Only with proxysg format. The default category for the exported indicators. |
https://{server_host}/instance/execute/{instance_name}?v=proxysg&cd=default_category |
| ca | Only with proxysg format. The categories which will be exported. Indicators not falling to these categories will be classified as the default category. |
https://{server_host}/instance/execute/{instance_name}?v=proxysg&ca=category1,category2 |
| tr | Whether to collapse IPs. 0 - to not collapse, 1 - collapse to ranges or 2 - collapse to CIDRs | https://{server_host}/instance/execute/{instance_name}?q="type:ip and sourceBrand:my_source"&tr=1 |
| tx | Whether to output csv or xsoar-csv formats as textual web pages. |
https://{server_host}/instance/execute/{instance_name}?v=xsoar-csv&tx |
| sf | The field by which to sort the indicators by. Only applicable with the so argument. |
lastSeen |
| so | The direction by which to order the indicators. The options are asc or desc. Only applicable with the sf argument. |
asc |
Base Command
eis-update
Input
| Argument Name | Description | Required |
|---|---|---|
| query | The query used to retrieve indicators from the system. Leave empty to use the query from the integration parameters. | Optional |
| format | The output format. | Optional |
| list_size | The maximum number of entries in the output. If no value is provided, will use the value specified in the List Size parameter configured in the instance configuration. | Optional |
| offset | The starting entry index from which to export the indicators. | Optional |
| print_indicators | If set to true will print the indicators the that were saved to the export indicators service | Required |
| mwg_type | For use with McAfee Web Gateway format to indicate the list type. | Optional |
| strip_port | For use with PAN-OS URL format - if True will strip the port off urls. If not checked - url with ports will be ignored. | Optional |
| drop_invalids | For use with PAN-OS URL format - if checked any URL entry which is not compliant with PAN-OS EDL URL format the entry is dropped instead of being rewritten. | Optional |
| category_attribute | For use with Symantec ProxySG format - set the categories that should be listed in the output. If not set will list all existing categories. | Optional |
| category_default | For use with Symantec ProxySG format - set the default category for the output. | Optional |
| collapse_ips | Whether to collapse IPs, and if so - to ranges or CIDRs | Optional |
| csv_text | If True, will output csv and XSOAR-csv formats as textual web pages | Optional |
| sort_field | The field by which to sort the indicators by. Only applicable with the sort_order argument. |
Optional |
| sort_order | The direction by which to order the indicators. The options are asc or desc. Only applicable with the sort_field argument. |
Optional |
Context Output
There is no context output for this command.
Command Example
!eis-update print_indicators=true query=type:IP format=text list_size=4
Human Readable Output
| Indicators |
|---|
| 1.1.1.1 |
| 2.2.2.2 |
| 3.3.3.3 |
| 4.4.4.4 |
Configuration parameters
indicators_query— Indicator Queryformat— Outbound Formatcollapse_ips— Should Collapse IPscsv_text— Show CSV Formats as Textlist_size— List Size (required)on_demand— Update On-Demand Onlycache_refresh_rate— Refresh RatelongRunning— Long Running InstancelongRunningPort— Listen Port (required)certificate— Certificate (Required for HTTPS)append_string— Append String To EDLprepend_string— Prepend String To EDLkey— Private Key (Required for HTTPS)credentials— Usernamemwg_type— Mcafee Gateway Indicator List Typehsts_header— Add HSTS headerstrip_port— PAN-OS URL Format Port Stripdrop_invalids— PAN-OS URL Format Drop Invalid Entriescategory_default— Symantec ProxySG Default Categorycategory_attribute— Symantec ProxySG Listed Categoriesnginx_global_directives— NGINX Global Directivesnginx_server_conf— NGINX Server Conf
Commands (1)
-
eis-updateUpdates values stored in the Export Indicators Service (only avaialable On-Demand).
"""Imports""" import json import pytest import demistomock as demisto from netaddr import IPAddress IOC_RES_LEN = 38 '''Tests''' class TestHelperFunctions: def test_get_outbound_ioc_values_1(self, mocker): """Test on_demand""" from ExportIndicators import get_outbound_ioc_values, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict}) request_args = RequestArguments(query='', out_format='text', limit=50, offset=0) ioc_list = get_outbound_ioc_values( on_demand=True, request_args=request_args ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_get_outbound_ioc_values_2(self, mocker): """Test update by not on_demand with no refresh""" import CommonServerPython as CSP mocker.patch.object(CSP, 'parse_date_range', return_value=(1578383899, 1578383899)) import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict}) mocker.patch.object(ei, 'refresh_outbound_context', return_value=iocs_text_dict) mocker.patch.object(demisto, 'getLastRun', return_value={'last_run': 1578383898000}) request_args = ei.RequestArguments(query='', out_format='text', limit=50, offset=0) ioc_list = ei.get_outbound_ioc_values( on_demand=False, request_args=request_args, cache_refresh_rate='1 minute' ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_get_outbound_ioc_values_3(self, mocker): """Test update by not on_demand with refresh""" import CommonServerPython as CSP mocker.patch.object(CSP, 'parse_date_range', return_value=(1578383898, 1578383898)) import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict}) mocker.patch.object(ei, 'refresh_outbound_context', return_value=iocs_text_dict) mocker.patch.object(demisto, 'getLastRun', return_value={'last_run': 1578383898000}) request_args = ei.RequestArguments(query='', out_format='text', limit=50, offset=0) ioc_list = ei.get_outbound_ioc_values( on_demand=False, request_args=request_args, cache_refresh_rate='1 minute' ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_get_outbound_ioc_values_4(self, mocker): """Test update by request params change - limit""" import CommonServerPython as CSP mocker.patch.object(CSP, 'parse_date_range', return_value=(1578383898, 1578383898)) import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict, "last_limit": 1, "last_offset": 0, "last_query": "type:ip", "last_format": "text"}) mocker.patch.object(ei, 'refresh_outbound_context', return_value=iocs_text_dict) mocker.patch.object(demisto, 'getLastRun', return_value={'last_run': 1578383898000}) request_args = ei.RequestArguments(query='type:ip', out_format='text', limit=50, offset=0) ioc_list = ei.get_outbound_ioc_values( on_demand=False, request_args=request_args, cache_refresh_rate='1 minute' ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_get_outbound_ioc_values_5(self, mocker): """Test update by request params change - offset""" import CommonServerPython as CSP mocker.patch.object(CSP, 'parse_date_range', return_value=(1578383898, 1578383898)) import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict, "last_limit": 50, "last_offset": 1, "last_query": "type:ip", "last_format": "text"}) mocker.patch.object(ei, 'refresh_outbound_context', return_value=iocs_text_dict) mocker.patch.object(demisto, 'getLastRun', return_value={'last_run': 1578383898000}) request_args = ei.RequestArguments(query='type:ip', out_format='text', limit=50, offset=0) ioc_list = ei.get_outbound_ioc_values( on_demand=False, request_args=request_args, cache_refresh_rate='1 minute' ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_get_outbound_ioc_values_6(self, mocker): """Test update by request params change - query""" import CommonServerPython as CSP mocker.patch.object(CSP, 'parse_date_range', return_value=(1578383898, 1578383898)) import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_text_values_f: iocs_text_dict = json.loads(iocs_text_values_f.read()) mocker.patch.object(demisto, 'getIntegrationContext', return_value={"last_output": iocs_text_dict, "last_limit": 50, "last_offset": 0, "last_query": "type:URL", "last_format": "text"}) mocker.patch.object(ei, 'refresh_outbound_context', return_value=iocs_text_dict) mocker.patch.object(demisto, 'getLastRun', return_value={'last_run': 1578383898000}) request_args = ei.RequestArguments(query='type:ip', out_format='text', limit=50, offset=0) ioc_list = ei.get_outbound_ioc_values( on_demand=False, request_args=request_args, cache_refresh_rate='1 minute' ) for ioc_row in ioc_list: assert ioc_row in iocs_text_dict def test_list_to_str_1(self): """Test invalid""" from ExportIndicators import list_to_str with pytest.raises(AttributeError): invalid_list_value = 2 list_to_str(invalid_list_value) with pytest.raises(AttributeError): invalid_list_value = {'invalid': 'invalid'} list_to_str(invalid_list_value) def test_list_to_str_2(self): """Test empty""" from ExportIndicators import list_to_str assert list_to_str(None) == '' assert list_to_str([]) == '' assert list_to_str({}) == '' def test_list_to_str_3(self): """Test non empty fields""" from ExportIndicators import list_to_str valid_list_value = [1, 2, 3, 4] assert list_to_str(valid_list_value) == '1,2,3,4' assert list_to_str(valid_list_value, '.') == '1.2.3.4' assert list_to_str(valid_list_value, map_func=lambda x: f'{x}a') == '1a,2a,3a,4a' def test_get_params_port_1(self): """Test invalid""" from CommonServerPython import DemistoException from ExportIndicators import get_params_port params = {'longRunningPort': 'invalid'} with pytest.raises(DemistoException): get_params_port(params) def test_get_params_port_2(self): """Test empty""" from ExportIndicators import get_params_port params = {'longRunningPort': ''} with pytest.raises(ValueError): get_params_port(params) def test_get_params_port_3(self): """Test valid""" from ExportIndicators import get_params_port params = {'longRunningPort': '80'} assert get_params_port(params) == 80 def test_refresh_outbound_context_1(self, mocker): """Test out_format=text""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', return_value=iocs_json) request_args = ei.RequestArguments(query='', out_format='text', limit=38) ei_vals = ei.refresh_outbound_context(request_args) for ioc in iocs_json: ip = ioc.get('value') if ip: assert ip in ei_vals def test_refresh_outbound_context_2(self, mocker): """Test out_format= XSOAR json""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) iocs_json_result = {'iocs': iocs_json, 'total': 100} mocker.patch.object(demisto, 'searchIndicators', return_value=iocs_json_result) request_args = ei.RequestArguments(query='', out_format='XSOAR json', limit=39) ei_vals = ei.refresh_outbound_context(request_args) assert isinstance(ei_vals, str) ei_vals = json.loads(ei_vals) assert iocs_json == ei_vals def test_refresh_outbound_context_3(self, mocker): """Test out_format=xsoar-csv""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', return_value=iocs_json) request_args = ei.RequestArguments(query='', out_format='XSOAR csv', limit=38) ei_vals = ei.refresh_outbound_context(request_args) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_csv.txt', 'r') as iocs_out_f: iocs_out = iocs_out_f.read() for ioc in iocs_out.split('\n'): assert ioc in ei_vals def test_refresh_outbound_context_4(self, mocker): """Test out_format=XSOAR json-seq""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) iocs_json_result = {'iocs': iocs_json, 'total': 100} mocker.patch.object(demisto, 'searchIndicators', return_value=iocs_json_result) request_args = ei.RequestArguments(query='', out_format='XSOAR json-seq', limit=38) ei_vals = ei.refresh_outbound_context(request_args) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_json_seq.txt', 'r') as iocs_out_f: iocs_out = iocs_out_f.read() assert iocs_out == ei_vals def test_refresh_outbound_context_5(self, mocker): """Test out_format=json""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) iocs_json_result = {'iocs': iocs_json, 'total': 100} mocker.patch.object(demisto, 'searchIndicators', return_value=iocs_json_result) request_args = ei.RequestArguments(query='', out_format='json', limit=2) ei_vals = ei.refresh_outbound_context(request_args) ei_vals = json.loads(ei_vals) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_json.json', 'r') as iocs_json_out_f: iocs_json_out = json.loads(iocs_json_out_f.read()) assert iocs_json_out == ei_vals def test_refresh_outbound_context_6(self, mocker): """Test out_format=json-seq""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) iocs_json_result = {'iocs': iocs_json, 'total': 100} mocker.patch.object(demisto, 'searchIndicators', return_value=iocs_json_result) request_args = ei.RequestArguments(query='', out_format='json-seq', limit=38) ei_vals = ei.refresh_outbound_context(request_args) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_json_seq_old.txt', 'r') as iocs_out_f: iocs_out = iocs_out_f.read() for iocs_out_line in iocs_out.split('\n'): assert iocs_out_line in ei_vals def test_refresh_outbound_context_7(self, mocker): """Test out_format=csv""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', return_value=iocs_json) request_args = ei.RequestArguments(query='', out_format='csv', limit=38) ei_vals = ei.refresh_outbound_context(request_args) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_csv_old.txt', 'r') as iocs_out_f: iocs_out = iocs_out_f.read() for ioc in iocs_out.split('\n'): assert ioc in ei_vals def test_find_indicators_with_limit_1(self, mocker): """Test find indicators limit""" import ExportIndicators as ei with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) limit = 30 indicator_searcher_res = [{'iocs': iocs_json[:limit]}, {'iocs': []}] indicator_searcher = ei.IndicatorsSearcher( limit=limit ) mocker.patch.object(indicator_searcher, 'search_indicators_by_version', side_effect=indicator_searcher_res) ei_vals = ei.find_indicators_with_limit(indicator_searcher) assert len(ei_vals) == limit def test_create_values_for_returned_dict_1(self): """Test XSOAR CSV out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_XSOAR_CSV, RequestArguments, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_XSOAR_CSV) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) csv_out = returned_dict.get(CTX_VALUES_KEY) # assert len(csv_out) == IOC_RES_LEN + 1 with open('ExportIndicators_test/TestHelperFunctions/iocs_out_csv.txt', 'r') as iocs_out_f: expected_csv_out = iocs_out_f.read() for csv_line in csv_out.split('\n'): assert csv_line in expected_csv_out def test_create_values_for_returned_dict_2(self): """Test XSOAR JSON out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_XSOAR_JSON, CTX_VALUES_KEY, \ RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.load(iocs_json_f) request_args = RequestArguments(query='', out_format=FORMAT_XSOAR_JSON) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) json_out = json.loads(returned_dict.get(CTX_VALUES_KEY)) assert json_out == iocs_json def test_create_values_for_returned_dict_3(self): """Test XSOAR JSON_SEQ out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_XSOAR_JSON_SEQ, CTX_VALUES_KEY, \ RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_XSOAR_JSON_SEQ) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) json_seq_out = returned_dict.get(CTX_VALUES_KEY) for seq_line in json_seq_out.split('\n'): assert json.loads(seq_line) in iocs_json def test_create_values_for_returned_dict_4(self): """Test TEXT out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_TEXT, CTX_VALUES_KEY, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_TEXT) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) text_out = returned_dict.get(CTX_VALUES_KEY) with open('ExportIndicators_test/TestHelperFunctions/iocs_cache_values_text.json', 'r') as iocs_txt_f: iocs_txt_json = json.load(iocs_txt_f) for line in text_out.split('\n'): assert line in iocs_txt_json def test_create_values_for_returned_dict_5(self): """Test JSON out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_JSON, CTX_VALUES_KEY, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_JSON) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) json_out = json.loads(returned_dict.get(CTX_VALUES_KEY)) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_json.json', 'r') as iocs_json_out_f: iocs_json_out = json.loads(iocs_json_out_f.read()) assert iocs_json_out == json_out def test_create_values_for_returned_dict_6(self): """Test JSON_SEQ out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_JSON_SEQ, CTX_VALUES_KEY, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_JSON_SEQ) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) json_seq_out = returned_dict.get(CTX_VALUES_KEY) with open('ExportIndicators_test/TestHelperFunctions/iocs_out_json.json', 'r') as iocs_json_out_f: iocs_json_out = json.load(iocs_json_out_f) for seq_line in json_seq_out.split('\n'): assert json.loads(seq_line) in iocs_json_out def test_create_values_for_returned_dict_7(self): """Test CSV out""" from ExportIndicators import create_values_for_returned_dict, FORMAT_CSV, RequestArguments, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) request_args = RequestArguments(query='', out_format=FORMAT_CSV) returned_dict, _ = create_values_for_returned_dict(iocs_json, request_args) csv_out = returned_dict.get(CTX_VALUES_KEY) # assert len(csv_out) == IOC_RES_LEN + 1 with open('ExportIndicators_test/TestHelperFunctions/iocs_out_csv_old.txt', 'r') as iocs_out_f: expected_csv_out = iocs_out_f.read() for csv_lint in csv_out.split('\n'): assert csv_lint in expected_csv_out def test_validate_basic_authentication(self): """Test Authentication""" from ExportIndicators import validate_basic_authentication username, password = 'user', 'pwd' data = { "empty_auth": {}, "basic_missing_auth": { "Authorization": "missing basic" }, "colon_missing_auth": { "Authorization": "Basic bWlzc2luZ19jb2xvbg==" }, "wrong_length_auth": { "Authorization": "Basic YTpiOmM=" }, "wrong_credentials_auth": { "Authorization": "Basic YTpi" }, "right_credentials_auth": { "Authorization": "Basic dXNlcjpwd2Q=" } } assert not validate_basic_authentication(data.get('empty_auth'), username, password) assert not validate_basic_authentication(data.get('basic_missing_auth'), username, password) assert not validate_basic_authentication(data.get('colon_missing_auth'), username, password) assert not validate_basic_authentication(data.get('wrong_length_auth'), username, password) assert not validate_basic_authentication(data.get('wrong_credentials_auth'), username, password) assert validate_basic_authentication(data.get('right_credentials_auth'), username, password) def test_panos_url_formatting(self): from ExportIndicators import panos_url_formatting, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) # strips port numbers returned_dict, num_of_indicators = panos_url_formatting(iocs=iocs_json, drop_invalids=True, strip_port=True) returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == "1.2.3.4/wget\nwww.demisto.com/cool" assert num_of_indicators == 2 # should ignore indicators with port numbers returned_dict, num_of_indicators = panos_url_formatting(iocs=iocs_json, drop_invalids=True, strip_port=False) returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == 'www.demisto.com/cool' assert num_of_indicators == 1 def test_create_proxysg_out_format(self): from ExportIndicators import create_proxysg_out_format, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) # classify all categories returned_dict, num_of_indicators = create_proxysg_out_format(iocs=iocs_json, category_default="default", category_attribute='') returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == "define category category2\n1.2.3.4:89/wget\nend\n" \ "define category category1\nwww.demisto.com/cool\nend\n" assert num_of_indicators == 2 # listed category does not exist - all results should be in default category returned_dict, num_of_indicators = create_proxysg_out_format(iocs=iocs_json, category_default="default", category_attribute="category3") returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == "define category default\n1.2.3.4:89/wget\n" \ "www.demisto.com/cool\nend\n" assert num_of_indicators == 2 # list category2 only, the rest go to default returned_dict, num_of_indicators = create_proxysg_out_format(iocs=iocs_json, category_default="default", category_attribute="category2") returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == "define category category2\n1.2.3.4:89/wget\nend\n" \ "define category default\nwww.demisto.com/cool\nend\n" assert num_of_indicators == 2 def test_create_mwg_out_format(self): from ExportIndicators import create_mwg_out_format, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) # listed category does not exist - all results should be in default category returned_dict = create_mwg_out_format(iocs=iocs_json, mwg_type="ip") returned_output = returned_dict.get(CTX_VALUES_KEY) assert returned_output == "type=ip\n\"1.2.3.4:89/wget\" \"AutoFocus Feed\"\n\"" \ "https://www.demisto.com/cool\" \"AutoFocus V2,VirusTotal," \ "Alien Vault OTX TAXII Feed\"" def test_create_json_out_format(self): from ExportIndicators import create_json_out_format, CTX_VALUES_KEY with open('ExportIndicators_test/TestHelperFunctions/demisto_url_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) # listed category does not exist - all results should be in default category returned_dict = create_json_out_format(iocs=iocs_json) returned_output = json.loads(returned_dict.get(CTX_VALUES_KEY)) assert returned_output[0].get('indicator') == '1.2.3.4:89/wget' assert isinstance(returned_output[0].get('value'), dict) assert returned_output[1].get('indicator') == 'https://www.demisto.com/cool' assert isinstance(returned_output[1].get('value'), dict) def test_ips_to_ranges_range(self): from ExportIndicators import ips_to_ranges, COLLAPSE_TO_RANGES ip_list = [IPAddress("1.1.1.1"), IPAddress("25.24.23.22"), IPAddress("22.21.20.19"), IPAddress("1.1.1.2"), IPAddress("1.2.3.4"), IPAddress("1.1.1.3"), IPAddress("2.2.2.2"), IPAddress("1.2.3.5")] ip_range_list = ips_to_ranges(ip_list, COLLAPSE_TO_RANGES) assert "1.1.1.1-1.1.1.3" in ip_range_list assert "1.2.3.4-1.2.3.5" in ip_range_list assert "1.1.1.2" not in ip_range_list assert "2.2.2.2" in ip_range_list assert "25.24.23.22" in ip_range_list def test_ips_to_ranges_cidr(self): from ExportIndicators import ips_to_ranges, COLLAPSE_TO_CIDR ip_list = [IPAddress("1.1.1.1"), IPAddress("25.24.23.22"), IPAddress("22.21.20.19"), IPAddress("1.1.1.2"), IPAddress("1.2.3.4"), IPAddress("1.1.1.3"), IPAddress("2.2.2.2"), IPAddress("1.2.3.5")] ip_range_list = ips_to_ranges(ip_list, COLLAPSE_TO_CIDR) assert "1.1.1.1" in ip_range_list assert "1.1.1.2/31" in ip_range_list assert "1.2.3.4/31" in ip_range_list assert "1.2.3.5" not in ip_range_list assert "1.1.1.3" not in ip_range_list assert "2.2.2.2" in ip_range_list assert "25.24.23.22" in ip_range_list def test_empty_integartion_context_mimtype(self, mocker): from ExportIndicators import get_outbound_mimetype mocker.patch.object(demisto, 'getIntegrationContext', return_value={}) mimtype = get_outbound_mimetype() assert mimtype == 'text/plain' @pytest.mark.parametrize('sort_field, sort_order, expected_first_result', [ ('lastSeen', 'asc', '200.77.186.170'), ('lastSeen', 'desc', '188.166.23.215'), ]) def test_sort_iocs(self, mocker, sort_field, sort_order, expected_first_result): """Test IoCs sorting""" import ExportIndicators as ei from ExportIndicators import refresh_outbound_context, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', side_effect=[iocs_json, []]) request_args = RequestArguments(query='', out_format='text', sort_field=sort_field, sort_order=sort_order) ei_vals = refresh_outbound_context(request_args) assert ei_vals.split('\n', 1)[0] == expected_first_result def test_sort_iocs_with_invalid_order(self, mocker): """Test IoCs sorting with invalid order""" import ExportIndicators as ei from ExportIndicators import refresh_outbound_context, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', side_effect=[iocs_json, []]) request_args = RequestArguments(query='', out_format='text', sort_field='lastSeen', sort_order='invalid_sort_order') ei_vals = refresh_outbound_context(request_args) assert ei_vals.split('\n', 1)[0] == '213.182.138.224' def test_sort_iocs_invalid_field(self, mocker): """Test IoCs sorting wit invalid field""" import ExportIndicators as ei from ExportIndicators import refresh_outbound_context, RequestArguments with open('ExportIndicators_test/TestHelperFunctions/demisto_iocs.json', 'r') as iocs_json_f: iocs_json = json.loads(iocs_json_f.read()) mocker.patch.object(ei, 'find_indicators_with_limit', side_effect=[iocs_json, []]) request_args = RequestArguments(query='', out_format='text', sort_field='invalid_field_name', sort_order='asc') mocker.patch.object(demisto, 'debug') refresh_outbound_context(request_args) debug_list = [call[0][0] for call in demisto.debug.call_args_list] assert 'ExportIndicators - Could not sort IoCs, please verify that you entered the correct field name.\n' \ 'Field used: invalid_field_name' in debug_list