Nozomi Networks
The Nozomi Networks platform, available as a hardware, virtual appliance, or via the Vantage Cloud product, provides comprehensive monitoring for OT, IoT, and IT networks. It combines asset discovery, network visualization, vulnerability assessment, risk monitoring, and advanced threat detection in a unified solution. The integration is designed to gather alerts and asset information from Nozomi, whether deployed on-premises or in the cloud via Vantage, ensuring seamless visibility and security across environments.
Network Security · Nozomi Networks
Details
| ID | Nozomi Networks |
|---|---|
| Provider | Mitsubishi Electric |
| Category | Network Security |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
The Nozomi Networks integration enables the collection of alert and asset information from Nozomi’s suite of products, including Guardian, CMC, and the cloud-based Vantage platform. These solutions provide comprehensive OT/IoT/IT network monitoring through asset discovery, network visualization, vulnerability assessment, risk monitoring, and threat detection — all within a unified platform.
This integration is used to gather alert and asset information from Nozomi.
Configure Nozomi Networks in Cortex
| Parameter | Description | Required |
|---|---|---|
| endpoint | Endpoint url | True |
| username | Username | True |
| password | Password | True |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
| isFetch | Fetch incidents | False |
| fetchTime | Get incidents from last | False |
| riskFrom | Get incidents from risk level | False |
| fecthAlsoIncidents | Fetch also nozomi incidents | False |
| incidentPerRun | Specifies the maximum number of incidents to retrieve | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
nozomi-find-assets
This command permits you to get some assets from Nozomi, you can use the query filter to to refine your search. With the limits you can decide the max number of assets you can retrieve from Nozomi, the limit can’t be bigger than 1000.
Base Command
nozomi-find-assets
Input
| Argument Name | Description | Required |
|---|---|---|
| filter | You can add a filter to get exactly the assets you want. For example ‘where ip match 10.0.1.10’, ‘where vendor == Selta Telematica S.p.a’ | Optional |
| limit | Maximun number of assets get from Nozomi, can’t be bigger than 1000 | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Nozomi.Asset.id | String | uniq id of an asset |
| Nozomi.Asset.level | Number | network layer |
| Nozomi.Asset.capture_device | String | source from which the asset was captured |
| Nozomi.Asset.ip | Unknown | array of asset ip |
| Nozomi.Asset.mac_address | Unknown | array of asset mac address |
| Nozomi.asset.mac_vendor | Unknown | array of mac vendor |
| os | String | operating system |
| vendor | String | asset vendor |
| Nozomi.Asset.firmware_version | String | firmaware version |
| serial_number | String | serial number |
| product_name | String | product name |
| type | String | asset type as ‘OT_device’ |
| protocols | Unknown | array of asset protocols |
Command Example
!nozomi-find-assets limit=3 filter="| where level == 4"
Context Example
{
"Nozomi": {
"Asset": [
{
"name": "10.197.23.146",
"level": "1",
"id": "a3707ec4-7c85-437e-9d46-dbabd39b4dc2",
"appliance_hosts": [
"nozomi-dev"
],
"capture_device": "/vagrant/ids-testapi/fixtures/iec104_mestre_mini.pcap",
"ip": [
"10.197.23.146"
],
"mac_address": [
"00:02:3e:99:fe:1b"
],
"mac_address_level": {
"00:02:3e:99:fe:1b": "unconfirmed"
},
"vlan_id": [],
"mac_vendor": [
"Selta Telematica S.p.a"
],
"os": "",
"roles": [
"slave"
],
"vendor": "",
"_asset_kb_id": "",
"vendor:info": {
"source": "passive"
},
"firmware_version": "",
"firmware_version:info": {
"source": "passive"
},
"os_or_firmware": "",
"serial_number": "",
"serial_number:info": {
"source": "passive"
},
"product_name": "",
"product_name:info": {
"source": "passive"
},
"type": "OT_device",
"type:info": {
"source": "passive"
},
"protocols": [
"iec104"
],
"nodes": [
"10.197.23.146"
],
"zones": [
"RemoteRTU"
],
"custom_fields": {}
}
]
}
}
Human Readable Output
Nozomi Networks - No assets found
nozomi-close-incidents-as-security
Close incidents as security
Base Command
nozomi-close-incidents-as-security
Input
| Argument Name | Description | Required |
|---|---|---|
| ids | List of IDs to close as security | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Nozomi.CloseStatus | String | Status of the request |
| Ids | Unknown | Ids closed |
| CloseAction | String | As the incidents are closed |
Command Example
!nozomi-close-incidents-as-security ids=['fa441619-39d4-46c1-a2fb-fc3b285c0b64']
Context Example
{
"Nozomi": {
"CloseAction": "closed_as_security",
"CloseStatus": "SUCCESS",
"Ids": [
"fa441619-39d4-46c1-a2fb-fc3b285c0b64"
]
}
}
Human Readable Output
Command changes the status of alerts passed as “closed_as_security” in Nozomi Networks platform.
nozomi-close-incidents-as-change
Close incidents as change
Base Command
nozomi-close-incidents-as-change
Input
| Argument Name | Description | Required |
|---|---|---|
| ids | List of IDs to close as change. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Nozomi.CloseStatus | String | Status of the request |
| Ids | Unknown | Ids closed |
| CloseAction | String | As the incidents are closed |
Command Example
!nozomi-close-incidents-as-change ids=['fa441619-39d4-46c1-a2fb-fc3b285c0b64']
Context Example
{
"Nozomi": {
"CloseAction": "closed_as_change",
"CloseStatus": "SUCCESS",
"Ids": [
"fa441619-39d4-46c1-a2fb-fc3b285c0b64"
]
}
}
Human Readable Output
Command changes the status of alerts passed as “closed_as_change” in Nozomi Networks platform.
nozomi-query
Can execute a nozomi query to get all the information you want.
A query can be something like that: “alerts | select id name status ack | where status == open”
Take a look to n2os manual to know how to do a query.
Base Command
nozomi-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query | A valid query | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Nozomi.Query.Result | Unknown | An array of items |
| Nozomi.Error | String | In case the query is not correct the errors shows you the reason. |
Command Example
!nozomi-query query="links | where from match 192.168.10.2 | where protocol match ssh"
Context Example
{
"Nozomi": {
"Result": []
}
}
Human Readable Output
Nozomi Networks - Results for Query
No entries.
nozomi-find-ip-by-mac
Find a node ip from a mac address
Base Command
nozomi-find-ip-by-mac
Input
| Argument Name | Description | Required |
|---|---|---|
| mac | a mac address | Required |
| only_nodes_confirmed | This argument permit you to return only the nodes IPs from a mac address of nodes having the status to ‘confirmed’. Default value is True. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Nozomi.IpByMac.ips | Unknown | Array of ips found for the mac address passed, empty if not found. |
| Nozomi.Error | String | Usually an ip not found error |
Command Example
!nozomi-find-ip-by-mac mac='00:0c:29:22:50:26' only_nodes_confirmed='True'
Context Example
{
"Nozomi": {
"Error": "Ip not found"
}
}
Human Readable Output
Nozomi Networks - No IP results were found for mac address: ‘00:0c:29:22:50:26’
Configuration parameters
endpoint— Endpoint url (required)credentials— Username (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typefetchTime— Get incidents from lastriskFrom— Get incidents from risk levelfecthAlsoIncidents— Fetch also Nozomi incidentsincidentFetchInterval— Incidents Fetch IntervalincidentPerRun— Incidents per run
Commands (5)
-
nozomi-close-incidents-as-changeClose incidents as change.
-
nozomi-close-incidents-as-securityClose incidents as security.
-
nozomi-find-assetsThis command permits you to get some assets from Nozomi, you can use the query filter to to refine your search. With the limits you can decide the max number of assets you can retrieve from Nozomi, the limit can't be bigger than 100.
-
nozomi-find-ip-by-macFind a node ip from a mac address.
-
nozomi-queryCan execute a nozomi query to get all the information you want. A query can be something like that: "alerts | select id name status ack | where status == open" Take a look to n2os manual to know how to do a query.
import pytest from NozomiNetworks import * import demistomock as demisto from unittest.mock import MagicMock, patch demisto.callingContext = {"context": {"IntegrationBrand": "NozomiNetworks"}} NOZOMIGUARDIAN_URL = "https://test.com" def mock_sign_in(client): client.bearer_token = "mock_access_token" client.token_expiry = datetime.now() + timedelta(seconds=1800) client.use_basic_auth = False @pytest.fixture def client_with_mock_sign_in(): client = Client(base_url=NOZOMIGUARDIAN_URL) client.sign_in = MagicMock(side_effect=lambda: mock_sign_in(client)) return client @pytest.mark.parametrize("obj, expected", [({"last_fetch": "a_timestamp"}, True), ({}, False), (None, False)]) def test_has_last_run(obj, expected): assert has_last_run(obj) is expected def test_start_time_return_value(): assert start_time({"last_fetch": 1540390400000}) == "1540390400000" def test_start_time_return_timestamp(): time = start_time({}) assert time is not None assert len(time) == 13 def test_start_time_if_last_run_0_return_default(): time = start_time({"last_fetch": "0"}) assert time is not None assert len(time) == 13 @pytest.mark.parametrize( "obj, expected", [ (None, ""), ("", ""), ("1540390400000", " | where record_created_at > 1540390400000"), ], ) def test_time_filter(obj, expected): assert better_than_time_filter(obj) == expected def test_incidents_when_ibtt_is_none(requests_mock): st = "1392048082000" last_run = {"last_fetch": "1392048082000"} risk = "4" also_n2os_incidents = True client = __get_client([], requests_mock) with patch("NozomiNetworks.incidents_better_than_time", return_value=None): incidents_result, lft = incidents(st, last_run, risk, also_n2os_incidents, client) assert incidents_result == [] assert lft == last_run.get("last_fetch", st) def test_parse_incidents(): i = parse_incident( { "id": "1af93f46-65c1-4f52-a46a-2a181597fb0c", "type_id": "NET:RST-FROM-SLAVE", "name": "Link RST sent by Slave", "description": "The slave 10.197.23.139 sent a RST of the connection to the master.", "severity": 10, "mac_src": "00:02:3e:99:c9:5d", "mac_dst": "00:c0:c9:30:04:f1", "ip_src": "10.197.23.182", "ip_dst": "10.197.23.139", "risk": "4.5", "protocol": "iec104", "src_roles": "master", "dst_roles": "slave", "record_created_at": 1392048082242, "ack": False, "port_src": 1097, "port_dst": 2404, "status": "open", "threat_name": "", "type_name": "Link RST sent by Slave", "zone_src": "RemoteRTU", "zone_dst": "RemoteRTU", } ) del i["occurred"] assert i == { "name": "Link RST sent by Slave_1af93f46-65c1-4f52-a46a-2a181597fb0c", "severity": 2, "rawJSON": '{"id": "1af93f46-65c1-4f52-a46a-2a181597fb0c", ' '"type_id": "NET:RST-FROM-SLAVE", "name": "Link RST sent by Slave", ' '"description": "The slave 10.197.23.139 sent a RST of the connection to the master.", ' '"severity": 10, "mac_src": "00:02:3e:99:c9:5d", "mac_dst": "00:c0:c9:30:04:f1", ' '"ip_src": "10.197.23.182", "ip_dst": "10.197.23.139", "risk": "4.5", "protocol": "iec104", ' '"src_roles": "master", "dst_roles": "slave", "record_created_at": 1392048082242, "ack": false, ' '"port_src": 1097, "port_dst": 2404, "status": "open", "threat_name": "", ' '"type_name": "Link RST sent by Slave", "zone_src": "RemoteRTU", "zone_dst": "RemoteRTU"}', } @pytest.mark.parametrize("obj, expected", [(10, 4), (9.0, 4), (8.5, 4), (2.3, 1), (1.6, 1)]) def test_parse_severity(obj, expected): assert parse_severity({"risk": obj}) is expected def test_http_incident_request(requests_mock): request_path = "/api/open/query/do?query=alerts" r = __get_client( [{"json": __load_test_data("./test_data/query_alerts.json"), "path": request_path}], requests_mock ).http_get_request(request_path) assert len(r["result"]) == 126 assert r["total"] == 126 def test_response_with_error(): client = MagicMock() client.http_post_request.return_value = {"error": "pippo"} assert ack_unack_alerts(ids=[1, 2, 3], status=True, client=client) is None def test_ack_unack_alerts_no_call_for_empty_data(): client = MagicMock() ack_unack_alerts([], True, client) client.http_post_request.assert_not_called() def test_incidents_filtered(requests_mock): fi, lr = incidents( "1392048082000", {}, "4", True, __get_client( [ { "json": __load_test_data("./test_data/incidents_better_than_time.json"), "path": "/api/open/query/do?query=alerts | sort record_created_at asc " "| where record_created_at > 1392048082000 | where risk >= 4&page=1&count=100", } ], requests_mock, ), ) assert lr == 1392048082242 assert [{"name": f"{i['name'].partition('_')[0]}", "severity": i["severity"]} for i in fi] == [ {"name": "Link RST sent by Slave", "severity": 2}, {"name": "New Node", "severity": 4}, ] def test_incidents_equal_to_time_returns_data(requests_mock): import urllib.parse st = "1392048082000" risk = "4" also_n2os_incidents = True query = f"alerts | sort record_created_at asc | where record_created_at == {st} | where risk >= 4" request_path = f"/api/open/query/do?query={urllib.parse.quote(query)}&page=1&count=100" client = __get_client( [ { "json": { "result": [ {"id": 1, "name": "Exact Time Incident 1", "record_created_at": int(st), "risk": 5.0}, {"id": 2, "name": "Exact Time Incident 2", "record_created_at": int(st), "risk": 4.0}, ], "total": 2, }, "path": request_path, } ], requests_mock, ) incidents_result = incidents_equal_to_time(st, page=1, risk=risk, also_n2os_incidents=also_n2os_incidents, client=client) assert requests_mock.called assert len(incidents_result) == 2 assert incidents_result[0]["name"] == "Exact Time Incident 1" assert incidents_result[1]["name"] == "Exact Time Incident 2" def test_incidents_calls_equal_to_time_when_max_page_reached(): st = "1392048082000" last_run = {"last_fetch": st, "page": MAX_PAGE_NUMBER_REACHABLE} risk = "4" also_n2os_incidents = True mock_ibtt = [{"id": 1, "name": "From Better Than", "record_created_at": int(st), "risk": 5.0}] mock_iett = [ {"id": 1, "name": "From Better Than", "record_created_at": int(st), "risk": 5.0}, {"id": 2, "name": "From Equal To", "record_created_at": int(st), "risk": 4.0}, ] client = MagicMock() with ( patch("NozomiNetworks.incidents_better_than_time", return_value=mock_ibtt) as mock_btt, patch("NozomiNetworks.incidents_equal_to_time", return_value=mock_iett) as mock_ett, ): results, lft = incidents(st, last_run, risk, also_n2os_incidents, client) assert mock_btt.called assert mock_ett.called assert len(results) == 2 names = [i["name"].split("_")[0] for i in results] # remove incident ID suffix assert "From Better Than" in names assert "From Equal To" in names def test_nozomi_alerts_ids_from_demisto_incidents(): assert nozomi_alerts_ids_from_demisto_incidents([]) == [] def test_is_alive(requests_mock): requests_mock.post( f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", json={"access_token": "mock_access_token", "token_type": "Bearer", "expires_in": 1800}, ) requests_mock.get( f"{NOZOMIGUARDIAN_URL}/api/open/query/do?query=alerts | count", json={"result": [{"count": 126}], "total": 1} ) client = Client(base_url=NOZOMIGUARDIAN_URL) assert is_alive(client) == "ok" def test_ids_from_incidents(): assert ids_from_incidents([{"id": 1}, {"id": 2}]) == [1, 2] @pytest.mark.parametrize("obj, expected", [("8", " | where risk >= 8"), ("", ""), (None, "")]) def test_risk_filter(obj, expected): assert risk_filter(obj) == expected @pytest.mark.parametrize("obj, expected", [(True, ""), (False, " | where is_incident == false")]) def test_also_n2os_incidents_filter_true(obj, expected): assert also_n2os_incidents_filter(True) == "" def test_find_assets(requests_mock): result = find_assets( {}, __get_client( [ { "json": __load_test_data("./test_data/find_assets.json"), "path": "/api/open/query/do?query=assets | sort id | head 50", } ], requests_mock, ), ) assert ("### Nozomi Networks - Results for Find Assets" in result["readable_output"]) is True assert len(result["outputs"]) == 8 assert result["outputs_key_field"] == "id" assert result["outputs_prefix"] == "Nozomi.Asset" def test_find_assets_with_none_result_in_loop(requests_mock): response_sequence = [{"result": None}, {"result": [{"id": "1", "name": "Asset 1"}]}] client = MagicMock() client.http_get_request = MagicMock(side_effect=response_sequence) args = {} head = 10 result = find_assets(args, client, head=head) client.http_get_request.assert_called() assert len(result["outputs"]) == 1 assert result["outputs"][0]["id"] == "1" assert "Nozomi.Asset" in result["outputs_prefix"] assert result["outputs_key_field"] == "id" assert "Asset 1" in result["readable_output"] def test_assets_limit_from_args(): assert assets_limit_from_args({"limit": 40}) == 40 def test_assets_limit_from_args_string(): assert assets_limit_from_args({"limit": "40"}) == 40 def test_assets_limit_from_args_empty(): assert assets_limit_from_args({}) == 50 def test_assets_max_limit_reached_return_1000(): assert assets_limit_from_args({"limit": 1001}) == 100 def test_assets_limit_from_args_none(): assert assets_limit_from_args(None) == 50 def test_find_assets_empty(requests_mock): result = find_assets( {"filter": " | where level == 4"}, __get_client( [ { "json": __load_test_data("./test_data/empty_find_asset.json"), "path": "/api/open/query/do?query=assets | sort id | where level == 4 | head 50", } ], requests_mock, ), ) assert result["outputs"] == [] assert result["readable_output"] == "Nozomi Networks - No assets found" def test_better_than_id_filter_empty(): assert better_than_id_filter(None) == "" assert better_than_id_filter("") == "" def test_better_than_id_filter(): assert better_than_id_filter("an_id") == " | where id > an_id" def test_filter_from_args_empty(): filter_from_args({}) assert filter_from_args({}) == "" def test_filter_from_args_none(): assert filter_from_args(None) == "" def test_filter_from_args_valid(): assert filter_from_args({"filter": " | where id == 123"}) == " | where id == 123" def test_filter_without_where(): assert filter_from_args({"filter": "id == 123"}) == " | where id == 123" def test_filter_with_where(): assert filter_from_args({"filter": "| where id == 123"}) == "| where id == 123" def test_ip_from_mac(requests_mock): mac = "00:d0:c9:ca:bd:6a" result = find_ip_by_mac( {"mac": mac, "only_nodes_confirmed": False}, __get_client( [ { "json": __load_test_data("./test_data/find_by_mac.json"), "path": "/api/open/query/do?query=nodes | select ip mac_address | where mac_address == 00:d0:c9:ca:bd:6a", } ], requests_mock, ), ) assert result["readable_output"] == "Nozomi Networks - Results for the Ip from Mac Search is ['10.196.97.231', '172.16.0.4']" assert result["outputs"] == {"ips": ["10.196.97.231", "172.16.0.4"], "mac": mac} assert result["outputs_prefix"] == "Nozomi.IpByMac" assert result["outputs_key_field"] is None def test_ip_from_mac_not_found(requests_mock): result = find_ip_by_mac( {"mac": "12:33:44:55:bd:6a", "only_nodes_confirmed": False}, __get_client( [ { "json": __load_test_data("./test_data/empty_find_by_mac.json"), "path": "/api/open/query/do?query=nodes | select ip mac_address | where mac_address == 12:33:44:55:bd:6a", } ], requests_mock, ), ) assert result["readable_output"] == "Nozomi Networks - No IP results were found for mac address: 12:33:44:55:bd:6a" assert result["outputs"] is None def test_incidents_head_limit(requests_mock): import urllib.parse query = "alerts | sort record_created_at asc | where record_created_at > 1392048082000 | where risk >= 4" request_path = f"/api/open/query/do?query={urllib.parse.quote(query)}&page=1&count=100" client = __get_client( [ { "json": { "result": [ { "id": 1, "name": "Mock Incident 1", "record_created_at": 1392048082001, "risk": 4.5, # Example field for severity parsing }, {"id": 2, "name": "Mock Incident 2", "record_created_at": 1392048082002, "risk": 3.0}, ], "total": 2, }, "path": request_path, } ], requests_mock, ) incidents_result, lft = incidents("1392048082000", {}, "4", True, client) assert requests_mock.called assert lft == 1392048082002 assert len(incidents_result) == 2 assert incidents_result[0]["name"] == "Mock Incident 1_1" assert incidents_result[1]["name"] == "Mock Incident 2_2" def test_last_fetched_time_empty_incidents(): last_run = {"last_fetch": 1392048082000} result = last_fetched_time([], last_run) assert result == 1392048082000 incidents = [{"id": 1}] result = last_fetched_time(incidents, last_run) assert result == 1392048082000 def test_query_count_alerts(requests_mock): result = query( {"query": "alerts | count"}, __get_client( [{"json": __load_test_data("./test_data/alive.json"), "path": "/api/open/query/do?query=alerts | count | head 500"}], requests_mock, ), ) assert result["outputs"] == [{"count": 126}] assert result["outputs_prefix"] == "Nozomi.Query.Result" assert result["outputs_key_field"] == "" def test_sign_in(client_with_mock_sign_in): client = client_with_mock_sign_in client.sign_in() assert client.bearer_token == "mock_access_token" assert not client.use_basic_auth def test_fallback_to_basic_auth_real_logic(requests_mock, capfd): with capfd.disabled(): client = Client(base_url=NOZOMIGUARDIAN_URL) requests_mock.post(f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", status_code=500) try: client.sign_in() except Exception as e: assert "Authentication failed" in str(e) assert client.use_basic_auth def test_sign_in_successful(requests_mock): requests_mock.post( f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", json={}, status_code=200, headers={"Authorization": "Bearer mock_token"} ) client = Client(base_url=NOZOMIGUARDIAN_URL, auth_credentials=("mock_key", "mock_token")) client.sign_in() assert client.bearer_token == "Bearer mock_token" assert not client.use_basic_auth def test_sign_in_failure_with_auth_fallback(requests_mock): requests_mock.post(f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", status_code=401, text="Unauthorized") client = Client(base_url=NOZOMIGUARDIAN_URL, auth_credentials=("mock_key", "mock_token")) client.sign_in() assert client.bearer_token is None assert client.use_basic_auth def test_sign_in_exception_handling(requests_mock): requests_mock.post(f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", exc=requests.exceptions.ConnectionError) client = Client(base_url=NOZOMIGUARDIAN_URL, auth_credentials=("mock_key", "mock_token")) client.sign_in() assert client.bearer_token is None assert client.use_basic_auth def test_request_auth_failure(): __run_request_test(401, "Authentication failure or resource forbidden.") def test_request_forbidden_failure(): __run_request_test(403, "Authentication failure or resource forbidden.") @patch("NozomiNetworks.handle_proxy") def test_build_proxies_with_proxy_enabled(mock_handle_proxy): mock_handle_proxy.return_value = {"http": "pippoebasta"} client = Client(base_url="https://test.com", proxy=True) proxies = client.build_proxies() assert proxies == {"http": "pippoebasta"} mock_handle_proxy.assert_called_once() def test_build_proxies_without_proxy(): client = Client(base_url="https://test.com", proxy=False) proxies = client.build_proxies() assert proxies == {} def test_build_proxies_with_none_proxy(): client = Client(base_url="https://test.com", proxy=None) proxies = client.build_proxies() assert proxies == {} @pytest.mark.parametrize( "use_basic_auth, bearer_token, expected_headers", [ (True, "dummy_token", {"accept": "application/json"}), (False, "Bearer my_token", {"accept": "application/json", "Authorization": "Bearer my_token"}), (True, None, {"accept": "application/json"}), ], ) def test_build_headers(use_basic_auth, bearer_token, expected_headers): client = Client(bearer_token=bearer_token, use_basic_auth=use_basic_auth) assert client.build_headers() == expected_headers @pytest.mark.parametrize( "demisto_params, expected_result, expect_exception", [ ({"incidentPerRun": "15"}, 15, False), ({}, DEFAULT_COUNT_ALERTS, False), ({"incidentPerRun": "abc"}, None, True), ], ) def test_incident_per_run(demisto_params, expected_result, expect_exception): with patch("NozomiNetworks.demisto") as mock_demisto: mock_demisto.params.return_value = demisto_params if expect_exception: with pytest.raises(ValueError): incident_per_run() else: result = incident_per_run() assert result == expected_result @pytest.mark.parametrize( "current_page, incidents_count, incident_per_run_value, expected_next_page", [ (50, 10, 20, 1), (50, 30, 20, 51), (100, 10, 20, 1), (99, 0, 20, 99), (100, 0, 20, 100), (50, 20, 20, 51), (100, 50, 20, 1), ], ) def test_build_next_page(current_page, incidents_count, incident_per_run_value, expected_next_page): with patch("NozomiNetworks.incident_per_run", return_value=incident_per_run_value): result = build_next_page(current_page, incidents_count) assert result == expected_next_page @pytest.mark.parametrize( "last_fetch, next_page, st, expected_result", [ (1672531200000, 1, 1672617600000, 1672531200000), (1672531200000, 2, 1672617600000, 1672617600000), (1672531200000, 10, 1672617600000, 1672617600000), ], ) def test_last_fetch_to_set(last_fetch, next_page, st, expected_result): result = last_fetch_to_set(last_fetch, next_page, st) assert result == expected_result def __get_client(dummy_responses, requests_mock): requests_mock.post( f"{NOZOMIGUARDIAN_URL}/api/open/sign_in", json={"access_token": "mock_access_token", "token_type": "Bearer", "expires_in": 1800}, ) for dummy_response in dummy_responses: requests_mock.get(f'{NOZOMIGUARDIAN_URL}{dummy_response["path"]}', json=dummy_response["json"]) client = Client(base_url=NOZOMIGUARDIAN_URL) client.sign_in() return client def __run_request_test(status_code, expected_exception_message): client = Client(base_url=NOZOMIGUARDIAN_URL) client.bearer_token = "mock_token" with patch("NozomiNetworks.requests.request") as mock_request: mock_response = MagicMock() mock_response.status_code = status_code mock_request.return_value = mock_response with pytest.raises(Exception) as exc_info: client._make_request("GET", "/test/path") assert str(exc_info.value) == expected_exception_message def __load_test_data(json_path): with open(json_path) as f: return json.load(f)