diff --git a/plugins/palo_alto_cortex_xdr/.CHECKSUM b/plugins/palo_alto_cortex_xdr/.CHECKSUM index 1e1b71e396..ecba0eb240 100644 --- a/plugins/palo_alto_cortex_xdr/.CHECKSUM +++ b/plugins/palo_alto_cortex_xdr/.CHECKSUM @@ -1,7 +1,7 @@ { - "spec": "0021d4893d4c50661ed40749bfb99813", - "manifest": "9fd4cfed8de8d55916980ade6ac7ad3a", - "setup": "300ec46a66a2a1a2a434e9d68f841583", + "spec": "5f65f97ed0704bd87cb78e24eb9dc1b3", + "manifest": "094c90db12918a2d28277d8b94124397", + "setup": "67c9748687eb5d9ea0eccfccb53610e1", "schemas": [ { "identifier": "allow_file/schema.py", diff --git a/plugins/palo_alto_cortex_xdr/bin/icon_palo_alto_cortex_xdr b/plugins/palo_alto_cortex_xdr/bin/icon_palo_alto_cortex_xdr index 1df338dc70..61b80408fa 100755 --- a/plugins/palo_alto_cortex_xdr/bin/icon_palo_alto_cortex_xdr +++ b/plugins/palo_alto_cortex_xdr/bin/icon_palo_alto_cortex_xdr @@ -6,7 +6,7 @@ from sys import argv Name = "Palo Alto Cortex XDR" Vendor = "rapid7" -Version = "4.0.2" +Version = "4.0.3" Description = "Stop modern attacks with the industry's first extended detection and response platform that spans your endpoints, network and cloud data" diff --git a/plugins/palo_alto_cortex_xdr/help.md b/plugins/palo_alto_cortex_xdr/help.md index 5dd52f9bcf..1f2a247d4e 100644 --- a/plugins/palo_alto_cortex_xdr/help.md +++ b/plugins/palo_alto_cortex_xdr/help.md @@ -927,6 +927,7 @@ Isolate Endpoint fails with 500 error - This will happen if an isolation action # Version History +* 4.0.3 - `Monitor Incidents` - Add custom config exception handling * 4.0.2 - SDK bump to 6.1.4 * 4.0.1 - SDK Bump to 6.1.3 * 4.0.0 - `Get Alerts`: Fixed issue where trigger was failing due to empty and different typed output fields - updated to generic object | Added Monitor_alert tasks | SDK Bump to 6.1.2 diff --git a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/triggers/get_incidents/trigger.py b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/triggers/get_incidents/trigger.py index 16fe861735..76c9a5f56a 100755 --- a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/triggers/get_incidents/trigger.py +++ b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/triggers/get_incidents/trigger.py @@ -33,7 +33,7 @@ def run(self, params={}): ) # Separate the host identifier values for incident in incidents: - incident["hosts"] = Util.split_list_values(incident.get("hosts", []), ":") + incident["hosts"] = Util.split_list_values(incident.get("hosts", [])) # Process incidents from oldest to newest for incident_time in Util.send_items_to_platform_for_trigger( self, incidents, Output.INCIDENT, last_event_processed_time_ms, time_field diff --git a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/api.py b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/api.py index 0c834c409b..50e18f51cf 100644 --- a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/api.py +++ b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/api.py @@ -491,9 +491,29 @@ def build_request(self, url: str, headers: dict, post_body: dict) -> Response: request = requests.Request(method="post", url=url, headers=headers, json=post_body) + custom_config_exceptions = { + HTTPStatusCodes.BAD_REQUEST: PluginException(cause="API Error. ", assistance="Bad request, invalid JSON."), + HTTPStatusCodes.UNAUTHORIZED: PluginException( + cause="API Error. ", assistance="Authorization failed. Check your API Key ID & API Key." + ), + HTTPStatusCodes.PAYMENT_REQUIRED: PluginException( + cause="API Error. ", + assistance="Unauthorized access. User does not have the required license type to run this API.", + ), + HTTPStatusCodes.FORBIDDEN: PluginException( + cause="API Error. ", + assistance="Forbidden. The provided API Key does not have the required RBAC permissions to run this API.", + ), + HTTPStatusCodes.NOT_FOUND: PluginException( + cause="API Error. ", + assistance=f"The object at {url} does not exist. Check the FQDN connection setting and try again.", + ), + } + response = make_request( _request=request, timeout=60, + exception_custom_configs=custom_config_exceptions, exception_data_location=ResponseExceptionData.RESPONSE, allowed_status_codes=[HTTPStatusCodes.UNAUTHORIZED], ) diff --git a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/util.py b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/util.py index c4be915d5e..70d8d98f2d 100644 --- a/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/util.py +++ b/plugins/palo_alto_cortex_xdr/icon_palo_alto_cortex_xdr/util/util.py @@ -15,7 +15,7 @@ def now_ms(): return int(time.time() * 1000) @staticmethod - def split_list_values(input_list: list, separator: str) -> list: + def split_list_values(input_list: list) -> list: """Splits each string in a list based on a separator and returns a list of all separated values :param input_list: Input list of string :type input_list: list, required @@ -27,9 +27,11 @@ def split_list_values(input_list: list, separator: str) -> list: output_list = [] for item in input_list: if isinstance(item, str): - item_split = item.split(separator) + item_split = item.split(":") output_list.extend(item_split) + duplicates = set() + return [item for item in output_list if not (item in duplicates or duplicates.add(item))] @staticmethod diff --git a/plugins/palo_alto_cortex_xdr/plugin.spec.yaml b/plugins/palo_alto_cortex_xdr/plugin.spec.yaml index d309780d9d..e66ac6eda7 100644 --- a/plugins/palo_alto_cortex_xdr/plugin.spec.yaml +++ b/plugins/palo_alto_cortex_xdr/plugin.spec.yaml @@ -4,7 +4,7 @@ products: [insightconnect] name: palo_alto_cortex_xdr title: Palo Alto Cortex XDR description: Stop modern attacks with the industry's first extended detection and response platform that spans your endpoints, network and cloud data -version: 4.0.2 +version: 4.0.3 connection_version: 2 cloud_ready: true sdk: @@ -38,6 +38,7 @@ key_features: - "Add files to the block or allow lists" troubleshooting: "Isolate Endpoint fails with 500 error - This will happen if an isolation action (Isolate or Unisolate) is in progress on the selected endpoint. Wait a few minutes and try again." version_history: + - "4.0.3 - `Monitor Incidents` - Add custom config exception handling" - "4.0.2 - SDK bump to 6.1.4" - "4.0.1 - SDK Bump to 6.1.3" - "4.0.0 - `Get Alerts`: Fixed issue where trigger was failing due to empty and different typed output fields - updated to generic object | Added Monitor_alert tasks | SDK Bump to 6.1.2" diff --git a/plugins/palo_alto_cortex_xdr/setup.py b/plugins/palo_alto_cortex_xdr/setup.py index 348a9258a5..b83aa613b6 100755 --- a/plugins/palo_alto_cortex_xdr/setup.py +++ b/plugins/palo_alto_cortex_xdr/setup.py @@ -3,7 +3,7 @@ setup(name="palo_alto_cortex_xdr-rapid7-plugin", - version="4.0.2", + version="4.0.3", description="Stop modern attacks with the industry's first extended detection and response platform that spans your endpoints, network and cloud data", author="rapid7", author_email="", diff --git a/plugins/palo_alto_cortex_xdr/unit_test/test_get_incidents.py b/plugins/palo_alto_cortex_xdr/unit_test/test_get_incidents.py index 75642fb6dd..ca72e4df54 100644 --- a/plugins/palo_alto_cortex_xdr/unit_test/test_get_incidents.py +++ b/plugins/palo_alto_cortex_xdr/unit_test/test_get_incidents.py @@ -67,7 +67,7 @@ def check_error(): } if MockTrigger.actual == expected: return True - + TestCase.maxDiff = None TestCase.assertDictEqual(TestCase(), MockTrigger.actual, expected) diff --git a/plugins/palo_alto_cortex_xdr/unit_test/test_monitor_alerts.py b/plugins/palo_alto_cortex_xdr/unit_test/test_monitor_alerts.py index ff2753a8eb..23809875c9 100644 --- a/plugins/palo_alto_cortex_xdr/unit_test/test_monitor_alerts.py +++ b/plugins/palo_alto_cortex_xdr/unit_test/test_monitor_alerts.py @@ -129,15 +129,23 @@ def test_monitor_alerts_pagination( "Bad Request", STUB_STATE_ERROR, PluginException( - data="An error occurred during plugin execution!\n\nThe server is unable to process the request. Verify your plugin input is correct and not malformed and try again. If the issue persists, please contact support." + data="An error occurred during plugin execution!\n\nAPI Error. Bad request, invalid JSON." ), 400, ], + [ + "Wrong License", + STUB_STATE_ERROR, + PluginException( + data="An error occurred during plugin execution!\n\nAPI Error. Unauthorized access. User does not have the required license type to run this API." + ), + 402, + ], [ "Forbidden", STUB_STATE_ERROR, PluginException( - data="An error occurred during plugin execution!\n\nThe account configured in your connection is unauthorized to access this service. Verify the permissions for your account and try again." + data="An error occurred during plugin execution!\n\nAPI Error. Forbidden. The provided API Key does not have the required RBAC permissions to run this API." ), 403, ], @@ -145,7 +153,7 @@ def test_monitor_alerts_pagination( "Not Found", STUB_STATE_ERROR, PluginException( - data="An error occurred during plugin execution!\n\nInvalid or unreachable endpoint provided. Verify the URLs or endpoints in your configuration are correct." + data="An error occurred during plugin execution!\n\nAPI Error. The object at https://example.com/public_api/v1/alerts/get_alerts does not exist. Check the FQDN connection setting and try again." ), 404, ], @@ -166,6 +174,7 @@ def test_monitor_alerts_error_handling( error_msg: Union[str, PluginException], error_code: int, ) -> None: + # This if statement is to handle the "if not type response" statement specifically if error_code == 500: mocked_response = mock_conditions(200, file_name="monitor_alerts_faulty_response")