From 12e0e3d6b3f78545f866e26fd8efe9f86f5c0116 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Fri, 14 Jul 2023 14:18:24 -0700 Subject: [PATCH 01/53] Remove semgrep workflow file --- .github/workflows/semgrep.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml deleted file mode 100644 index 712cc1b..0000000 --- a/.github/workflows/semgrep.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Semgrep -on: - pull_request_target: - branches: - - next - - main - push: - branches: - - next - - main -jobs: - semgrep: - runs-on: ubuntu-latest - steps: - - if: github.event_name == 'push' - run: | - echo "REPOSITORY=${{ github.repository }}" >> $GITHUB_ENV - echo "REF=${{ github.REF }}" >> $GITHUB_ENV - - if: github.event_name == 'pull_request_target' - run: | - echo "REPOSITORY=${{ github.event.pull_request.head.repo.full_name }}" >> $GITHUB_ENV - echo "REF=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV - - uses: 'phantomcyber/dev-cicd-tools/github-actions/semgrep@main' - with: - SEMGREP_DEPLOYMENT_ID: ${{ secrets.SEMGREP_DEPLOYMENT_ID }} - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} - REPOSITORY: ${{ github.repository }} - REF: ${{ github.ref }} From ca06a6999ccbea03f6adf7c5a7c2d985d9284ae9 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Tue, 1 Aug 2023 11:59:08 -0700 Subject: [PATCH 02/53] 'convert readme.html to manual_readme_content.md' --- manual_readme_content.md | 76 ++++++++++++++++++++++++++++++++++++++ readme.html | 79 ---------------------------------------- 2 files changed, 76 insertions(+), 79 deletions(-) create mode 100644 manual_readme_content.md delete mode 100644 readme.html diff --git a/manual_readme_content.md b/manual_readme_content.md new file mode 100644 index 0000000..6d52965 --- /dev/null +++ b/manual_readme_content.md @@ -0,0 +1,76 @@ +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2017-2023 Splunk Inc." +[comment]: # "" +[comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');" +[comment]: # "you may not use this file except in compliance with the License." +[comment]: # "You may obtain a copy of the License at" +[comment]: # "" +[comment]: # " http://www.apache.org/licenses/LICENSE-2.0" +[comment]: # "" +[comment]: # "Unless required by applicable law or agreed to in writing, software distributed under" +[comment]: # "the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND," +[comment]: # "either express or implied. See the License for the specific language governing permissions" +[comment]: # "and limitations under the License." +[comment]: # "" +Below points are considered for providing the **URL Category** parameter value. + +- Entire URL category string has to be mentioned in block letters + +- The most child category on UI has to be passed as the URL category parameter value to the action + +- From the URL category value on UI, every space has to be replaced by an underscore '\_' before + passing it in the action's parameter value + + + + - For example, **Alternate Lifestyle** on UI becomes **ALTERNATE_LIFESTYLE** + +- When you specify a **url_category** , you can give it either the name you created or the ID + which is assigned to it from Zscaler. The search will first search for the name, as opposed to + the ID. So if you create a category **phantom-block** , you could use either **phantom-block** + or **CUSTOM\_\*\*** . The name for these is case sensitive. + +The following are considered for providing the **URL** parameter value. + +- The comma-separated values of **URL** should correctly be given e.g. test.com,test1.com else the + Phantom framework's parameter validator will return the error mentioning **Exception occurred: + string index out of range** . + +Configure and set up permissions for the **lookup_url** action + +- Login to Zscaler UI using the Administrator credentials. +- Once logged in, go to **Administration -> Role Management** section. +- Click on the **Edit** icon beside the role that your account uses to configure the test + connectivity. +- Go to the **Functional Scope** section, enable **Security** if disabled, and save it. + +The above steps would help run the Lookup URL action as expected. + +The Sandbox Submission API requires a separate API key and uses a different host +(csbapi.\[zscaler-cloud-name\]). For the **submit_file** action, the **sandbox_base_url** and +**sandbox_api_token** asset configuration parameters should be configured. These two asset +parameters won't affect test_connectivity. Follow the below steps to fetch these credentials for the +**submit_file** action + +- Log in to the ZIA Admin Portal using your **admin** credentials. +- Once logged in, go to **Administration -> Cloud Service API Key Management** section. In order + to view the Cloud Service API Key Management page, the admin must be assigned an admin role. +- For the Cloud Sandbox Submission API used in this action, the base URL and token are displayed + on the **Sandbox Submission API Token** tab. +- The base URL and token displayed here can be configured in the asset parameters in + **sandbox_base_url** and **sandbox_api_token** parameters respectively and will be used for the + submit_file action. + +The above steps would help run the Submit File action as expected. + +**NOTE:** This action would work according to the API behavior + +Port Information + +The app uses HTTP/ HTTPS protocol for communicating with the Zscaler server. Below are the default +ports used by Splunk SOAR. + +|         Service Name | Transport Protocol | Port | +|----------------------|--------------------|------| +|         http | tcp | 80 | +|         https | tcp | 443 | diff --git a/readme.html b/readme.html deleted file mode 100644 index b00f74c..0000000 --- a/readme.html +++ /dev/null @@ -1,79 +0,0 @@ - - -

Below points are considered for providing the URL Category parameter value. -

-

- -

The following are considered for providing the URL parameter value. -

-

- -

Configure and set up permissions for the lookup_url action

-

-

- The above steps would help run the Lookup URL action as expected. -

- -

The Sandbox Submission API requires a separate API key and uses a different host (csbapi.[zscaler-cloud-name]). For the submit_file action, the sandbox_base_url and sandbox_api_token asset configuration parameters should be configured. These two asset parameters won't affect test_connectivity. Follow the below steps to fetch these credentials for the submit_file action

-

-

- The above steps would help run the Submit File action as expected. -

NOTE: This action would work according to the API behavior

-

- -

Port Information

-

- The app uses HTTP/ HTTPS protocol for communicating with the Zscaler server. Below are the default ports used by Splunk SOAR. - - - - - - - - - - - - - - - - -
        Service NameTransport ProtocolPort
        httptcp80
        httpstcp443
-

From 285ee67f9d8ebe736886a4f73acf8afcecfab447 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 5 Aug 2024 15:06:42 -0700 Subject: [PATCH 03/53] PAPP-34458: inital work --- zscaler.json | 119 +++++++++++++++++++++++++++++++++++++++++++ zscaler_connector.py | 57 ++++++++++++++++++++- 2 files changed, 175 insertions(+), 1 deletion(-) diff --git a/zscaler.json b/zscaler.json index 5ed9741..cc6ab14 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3000,6 +3000,125 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "get whitelist", + "identifier": "get_whitelist", + "description": "get urls on the allow list", + "type": "investigate", + "read_only": true, + "parameters": {}, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.data.*.whitelistUrls", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test Total url categories: 97" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "title": "List URL Categories", + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "get blakclist", + "identifier": "get_blacklist", + "description": "get urls on the deny list", + "type": "investigate", + "read_only": true, + "parameters": { + "filter": { + "description": "Filter results be url or ip", + "data_type": "string", + "primary": true, + "contains": [ + "url", + "ip" + ], + "example_values": [ + "127.0.0.1" + ], + "order": 0 + }, + "query": { + "description": "Regular expression to match url or ip against", + "data_type": "string", + "primary": true, + "example_values": [ + "8...8" + ], + "order": 1 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.data.*.whitelistUrls", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test Total url categories: 97" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "title": "List URL Categories", + "type": "table" + }, + "versions": "EQ(*)" } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index dd0686c..d0b15c9 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -25,7 +25,7 @@ from bs4 import BeautifulSoup from phantom.action_result import ActionResult from phantom.base_connector import BaseConnector - +import socket from zscaler_consts import * @@ -990,6 +990,55 @@ def _handle_remove_group_user(self, param): return action_result.set_status(phantom.APP_SUCCESS) + def _handle_get_whitelist(self, param): + """ + This action is used to get the default whitelist in zscalar + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + ret_val, response = self._make_rest_call_helper('/api/v1/settings', action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + self.debug_print(response) + + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_get_blacklist(self, param): + """ + This action is used to get the blacklist in zscalar + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + ret_val, response = self._make_rest_call_helper('/api/v1/settings/advanced', action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + filter = param.get("filter") + query = param.get("query") + + self.debug_print(response) + if not filter and not query: + return action_result.set_status(phantom.APP_SUCCESS) + + parsed_data = [] + + self.debug_print(response) + for entry in response: + self.debug_print(entry) + url = entry.get(url, "") + ip = socket.socket.gethostbyname(url) + if url == filter or ip == filter: + parsed_data.append(entry) + elif query and (re.fullmatch(query, url) or re.fullmatch(query, ip)): + parsed_data.append(entry) + + return action_result.set_status(phantom.APP_SUCCESS) + def handle_action(self, param): ret_val = phantom.APP_SUCCESS @@ -1056,6 +1105,12 @@ def handle_action(self, param): elif action_id == 'remove_group_user': ret_val = self._handle_remove_group_user(param) + elif action_id == 'get_whitelist': + ret_val = self._handle_get_whitelist(param) + + elif action_id == 'get_blacklist': + ret_val = self._handle_get_blacklist(param) + return ret_val def initialize(self): From 1e02979f055d70288882511b1e455c1a00418028 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 5 Aug 2024 22:12:23 +0000 Subject: [PATCH 04/53] Update README.md --- README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/README.md b/README.md index e954575..3b972d8 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,8 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [get groups](#action-get-groups) - Gets a list of groups [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group +[get whitelist](#action-get-whitelist) - get urls on the allow list +[get blakclist](#action-get-blakclist) - get urls on the deny list ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -745,4 +747,43 @@ action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get whitelist' +get urls on the allow list + +Type: **investigate** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.data.\*.whitelistUrls | string | | +action_result.message | string | | test Total url categories: 97 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get blakclist' +get urls on the deny list + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**filter** | optional | Filter results be url or ip | string | `url` `ip` +**query** | optional | Regular expression to match url or ip against | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.data.\*.whitelistUrls | string | | +action_result.message | string | | test Total url categories: 97 +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From ce2fd3fa06b581a7ad9781f39ef822d368d2940a Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 5 Aug 2024 15:53:46 -0700 Subject: [PATCH 05/53] PAPP-34459: Update user action working --- zscaler.json | 189 +++++++++++++++++++++++++++++++++++++++++++ zscaler_connector.py | 27 +++++++ 2 files changed, 216 insertions(+) diff --git a/zscaler.json b/zscaler.json index 5ed9741..0fcd677 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3000,6 +3000,195 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "update user", + "identifier": "update_user", + "description": "Update user with given id", + "type": "correct", + "read_only": false, + "parameters": { + "user_id": { + "description": "ZScaler User Id", + "data_type": "numeric", + "required": true, + "primary": true, + "contains": [ + "zscaler user id" + ], + "example_values": [ + 889814 + ], + "order": 0 + }, + "user": { + "description": "JSON object containing the user details (see https://help.zscaler.com/zia/user-management#/users/{userId}-put)", + "data_type": "string", + "primary": true, + "order": 1 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.user", + "data_type": "string", + "column_name": "User", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "numeric", + "contains": [ + "zscaler user id" + ], + "column_name": "User ID", + "column_order": 0, + "example_values": [ + 889814 + ] + }, + { + "data_path": "action_result.data.*.adminUser", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.comments", + "data_type": "string", + "example_values": [ + "test This is test user" + ] + }, + { + "data_path": "action_result.data.*.deleted", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.department.id", + "data_type": "numeric", + "example_values": [ + 81896690 + ] + }, + { + "data_path": "action_result.data.*.department.name", + "data_type": "string", + "example_values": [ + "test IT" + ] + }, + { + "data_path": "action_result.data.*.email", + "data_type": "string", + "contains": [ + "email" + ], + "example_values": [ + "test first.last@domain.com" + ], + "column_name": "User Email", + "column_order": 2 + }, + { + "data_path": "action_result.data.*.groups.*.id", + "data_type": "numeric", + "contains": [ + "zscaler group id" + ], + "example_values": [ + 8894813 + ], + "column_name": "Group ID", + "column_order": 3 + }, + { + "data_path": "action_result.data.*.groups.*.name", + "data_type": "string", + "example_values": [ + "test Super Admin" + ], + "column_name": "Group Name", + "column_order": 4 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "numeric", + "contains": [ + "zscaler user id" + ], + "example_values": [ + 889814 + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string", + "example_values": [ + "test First Last" + ], + "column_name": "User Name", + "column_order": 1 + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index dd0686c..ba539db 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -990,6 +990,30 @@ def _handle_remove_group_user(self, param): return action_result.set_status(phantom.APP_SUCCESS) + def _handle_update_user(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + user_id = param['user_id'] + + try: + data = json.loads(param["user"]) + except Exception as e: + return action_result.set_status( + phantom.APP_ERROR, + "User object needs to be valid json: {}".format(e) + ) + + ret_val, response = self._make_rest_call_helper(f'/api/v1/users/{user_id}', action_result, data=data, method='put') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + self.debug_print(response) + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "User updated" + return action_result.set_status(phantom.APP_SUCCESS) + def handle_action(self, param): ret_val = phantom.APP_SUCCESS @@ -1056,6 +1080,9 @@ def handle_action(self, param): elif action_id == 'remove_group_user': ret_val = self._handle_remove_group_user(param) + elif action_id == "update_user": + ret_val = self._handle_update_user(param) + return ret_val def initialize(self): From 7ce74a948e472a65f91d35b0705ec46be9bb0fbc Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 5 Aug 2024 22:54:26 +0000 Subject: [PATCH 06/53] Update README.md --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index e954575..569137a 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [get groups](#action-get-groups) - Gets a list of groups [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group +[update user](#action-update-user) - Update user with given id ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -745,4 +746,39 @@ action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'update user' +Update user with given id + +Type: **correct** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | ZScaler User Id | numeric | `zscaler user id` +**user** | optional | JSON object containing the user details (see https://help.zscaler.com/zia/user-management#/users/{userId}-put) | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.user | string | | +action_result.parameter.user_id | numeric | `zscaler user id` | 889814 +action_result.data.\*.adminUser | boolean | | True False +action_result.data.\*.comments | string | | test This is test user +action_result.data.\*.deleted | boolean | | True False +action_result.data.\*.department.id | numeric | | 81896690 +action_result.data.\*.department.name | string | | test IT +action_result.data.\*.email | string | `email` | test first.last@domain.com +action_result.data.\*.groups.\*.id | numeric | `zscaler group id` | 8894813 +action_result.data.\*.groups.\*.name | string | | test Super Admin +action_result.data.\*.id | numeric | `zscaler user id` | 889814 +action_result.data.\*.name | string | | test First Last +action_result.summary | string | | +action_result.summary.message | string | | test User removed from group +action_result.message | string | | test User removed from group +summary.message | string | | +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From 3540483cc7f3a84a961a0ac59d7cd9692ad241e3 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 5 Aug 2024 16:57:03 -0700 Subject: [PATCH 07/53] PAPP-34461: Create destination group action done --- zscaler.json | 379 +++++++++++++++++++++++++++++++++++++++++++ zscaler_connector.py | 32 ++++ 2 files changed, 411 insertions(+) diff --git a/zscaler.json b/zscaler.json index 5ed9741..7a6b43e 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3000,6 +3000,385 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "create destination group", + "identifier": "create_destination_group", + "description": "Create destination group", + "type": "generic", + "read_only": false, + "parameters": { + "name": { + "description": "Destination IP group name", + "data_type": "string", + "required": true, + "primary": true, + "order": 0 + }, + "type": { + "description": "Destination IP group type (i.e., the group can contain destination IP addresses, countries, URL categories or FQDNs)", + "data_type": "string", + "required": true, + "primary": true, + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ], + "order": 1 + }, + "addresses": { + "description": "Comma seperated string of destination IP addresses, FQDNs, or wildcard FQDNs added to the group", + "data_type": "string", + "order": 2 + }, + "description": { + "description": "Additional information about the destination IP group.", + "data_type": "string", + "order": 3 + }, + "ip_categories": { + "description": "Destination IP address URL categories", + "data_type": "string", + "order": 4 + }, + "countries": { + "description": "Destination IP address countries. You can identify destinations based on the location of a server.", + "data_type": "string", + "order": 5 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.countries", + "data_type": "string", + "column_name": "Countries", + "column_order": 4 + }, + { + "data_path": "action_result.parameter.ip_categories", + "data_type": "string", + "column_name": "Ip Categories", + "column_order": 3 + }, + { + "data_path": "action_result.parameter.addresses", + "data_type": "string", + "column_name": "Addresses", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.type", + "data_type": "string", + "column_name": "Type", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.name", + "data_type": "string", + "column_name": "Name", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string", + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ] + }, + { + "data_path": "action_result.data.*.addresses", + "data_type": "string", + "example_values": [ + "192.168.1.1" + ] + }, + { + "data_path": "action_result.data.*.countries", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.ipCategories", + "data_type": "string", + "example_values": [ + "TRADING_BROKARAGE_INSURANCE" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "list destination group", + "identifier": "list_destination_group", + "description": "List destination group", + "type": "investigate", + "read_only": false, + "parameters": { + "ip_group_id": { + "description": "A comma-separated list of unique identifiers for the IP destination groups", + "data_type": "string", + "primary": true, + "order": 0 + }, + "exclude_type": { + "description": "The IP group type to be excluded from the results", + "data_type": "string", + "primary": true, + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ], + "order": 1 + }, + "category_type": { + "description": "The IP group type to be filtered from results. This argument is only supported when the 'lite' argument is set to True", + "data_type": "string", + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ], + "order": 2 + }, + "include_ipv6": { + "description": "Retrieve IPv6 destination groups", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "default": false, + "order": 3 + }, + "limit": { + "description": "Limit of the results to be retrieved", + "data_type": "numeric", + "default": 50, + "order": 4 + }, + "all_results": { + "description": "Whether to retrieve all results at once", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "default": false, + "order": 5 + }, + "lite": { + "description": "Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "default": false, + "order": 6 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.lite", + "data_type": "boolean", + "column_name": "Lite", + "column_order": 6 + }, + { + "data_path": "action_result.parameter.all_reuslts", + "data_type": "boolean", + "column_name": "All Results", + "column_order": 5 + }, + { + "data_path": "action_result.parameter.limit", + "data_type": "numeric", + "column_name": "Limit", + "column_order": 4 + }, + { + "data_path": "action_result.parameter.include_ipv6", + "data_type": "boolean", + "column_name": "Include Ipv6", + "column_order": 3 + }, + { + "data_path": "action_result.parameter.category_type", + "data_type": "string", + "column_name": "Category Type", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.exclude_type", + "data_type": "string", + "column_name": "Exclude Type", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.ip_group_id", + "data_type": "string", + "column_name": "Ip Group ID", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string", + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ] + }, + { + "data_path": "action_result.data.*.addresses", + "data_type": "string", + "example_values": [ + "192.168.1.1" + ] + }, + { + "data_path": "action_result.data.*.countries", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.ipCategories", + "data_type": "string", + "example_values": [ + "TRADING_BROKARAGE_INSURANCE" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "Retreived Destination Groups" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Retreived Destination Groups" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index dd0686c..600e90b 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -990,6 +990,35 @@ def _handle_remove_group_user(self, param): return action_result.set_status(phantom.APP_SUCCESS) + def _handle_create_destination_group(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + addresses = param.get("addresses", "") + ip_categories = param.get("ip_categories", "") + countries = param.get("countries", "") + + data = {} + data["name"] = param["name"] + data["type"] = param["type"] + if addresses: + data["addresses"] = [item.strip() for item in addresses.split(',')] + data["description"] = param.get("description", "") + if ip_categories: + data["ip_categories"] = [item.strip() for item in ip_categories.split(',')] + if countries: + data["countries"] = [item.strip() for item in countries.split(',')] + + ret_val, response = self._make_rest_call_helper('/api/v1/ipDestinationGroups', action_result, data=data, method='post') + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Destination IP added" + + return action_result.set_status(phantom.APP_SUCCESS) + def handle_action(self, param): ret_val = phantom.APP_SUCCESS @@ -1056,6 +1085,9 @@ def handle_action(self, param): elif action_id == 'remove_group_user': ret_val = self._handle_remove_group_user(param) + elif action_id == 'create_destination_group': + ret_val = self._handle_create_destination_group(param) + return ret_val def initialize(self): From e62fbc8563f101378d43a95be8664643a7130ed3 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 5 Aug 2024 23:57:42 +0000 Subject: [PATCH 08/53] Update README.md --- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/README.md b/README.md index e954575..8bdb88e 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,8 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [get groups](#action-get-groups) - Gets a list of groups [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group +[create destination group](#action-create-destination-group) - Create destination group +[list destination group](#action-list-destination-group) - List destination group ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -745,4 +747,85 @@ action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'create destination group' +Create destination group + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**name** | required | Destination IP group name | string | +**type** | required | Destination IP group type (i.e., the group can contain destination IP addresses, countries, URL categories or FQDNs) | string | +**addresses** | optional | Comma seperated string of destination IP addresses, FQDNs, or wildcard FQDNs added to the group | string | +**description** | optional | Additional information about the destination IP group. | string | +**ip_categories** | optional | Destination IP address URL categories | string | +**countries** | optional | Destination IP address countries. You can identify destinations based on the location of a server. | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.countries | string | | +action_result.parameter.ip_categories | string | | +action_result.parameter.addresses | string | | +action_result.parameter.type | string | | +action_result.parameter.name | string | | +action_result.data.\*.id | numeric | | +action_result.data.\*.name | string | | +action_result.data.\*.type | string | | DSTN_IP DSTN_FQDN DSTN_DOMAIN DSTN_OTHER +action_result.data.\*.addresses | string | | 192.168.1.1 +action_result.data.\*.countries | string | | +action_result.data.\*.description | string | | +action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.summary | string | | +action_result.summary.message | string | | test User removed from group +action_result.message | string | | test User removed from group +summary.message | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list destination group' +List destination group + +Type: **investigate** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_group_id** | optional | A comma-separated list of unique identifiers for the IP destination groups | string | +**exclude_type** | optional | The IP group type to be excluded from the results | string | +**category_type** | optional | The IP group type to be filtered from results. This argument is only supported when the 'lite' argument is set to True | string | +**include_ipv6** | optional | Retrieve IPv6 destination groups | boolean | +**limit** | optional | Limit of the results to be retrieved | numeric | +**all_results** | optional | Whether to retrieve all results at once | boolean | +**lite** | optional | Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.lite | boolean | | +action_result.parameter.all_reuslts | boolean | | +action_result.parameter.limit | numeric | | +action_result.parameter.include_ipv6 | boolean | | +action_result.parameter.category_type | string | | +action_result.parameter.exclude_type | string | | +action_result.parameter.ip_group_id | string | | +action_result.data.\*.id | numeric | | +action_result.data.\*.name | string | | +action_result.data.\*.type | string | | DSTN_IP DSTN_FQDN DSTN_DOMAIN DSTN_OTHER +action_result.data.\*.addresses | string | | 192.168.1.1 +action_result.data.\*.countries | string | | +action_result.data.\*.description | string | | +action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.summary | string | | +action_result.summary.message | string | | Retreived Destination Groups +action_result.message | string | | Retreived Destination Groups +summary.message | string | | +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From 538805ba814654b9539ebc5ef4752308772ac613 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Tue, 6 Aug 2024 12:02:37 -0700 Subject: [PATCH 09/53] PAPP-34461: Destination ip group actions complete --- zscaler.json | 280 ++++++++++++++++++++++++++++++++++++++++++- zscaler_connector.py | 193 +++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+), 3 deletions(-) diff --git a/zscaler.json b/zscaler.json index 7a6b43e..50bf19d 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3064,12 +3064,18 @@ "data_path": "action_result.parameter.countries", "data_type": "string", "column_name": "Countries", - "column_order": 4 + "column_order": 5 }, { "data_path": "action_result.parameter.ip_categories", "data_type": "string", "column_name": "Ip Categories", + "column_order": 4 + }, + { + "data_path": "action_result.parameter.description", + "data_type": "string", + "column_name": "Description", "column_order": 3 }, { @@ -3179,7 +3185,7 @@ "type": "investigate", "read_only": false, "parameters": { - "ip_group_id": { + "ip_group_ids": { "description": "A comma-separated list of unique identifiers for the IP destination groups", "data_type": "string", "primary": true, @@ -3198,7 +3204,7 @@ "order": 1 }, "category_type": { - "description": "The IP group type to be filtered from results. This argument is only supported when the 'lite' argument is set to True", + "description": "Comma seperated list of IP group types to be filtered from results. This argument is only supported when the 'lite' argument is set to True", "data_type": "string", "example_values": [ "DSTN_IP", @@ -3379,6 +3385,274 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "edit destination group", + "identifier": "edit_destination_group", + "description": "Edit destination group", + "type": "generic", + "read_only": false, + "parameters": { + "ip_group_id": { + "description": "The unique identifier for the IP destination group", + "data_type": "numeric", + "required": true, + "primary": true, + "order": 0 + }, + "name": { + "description": "Destination IP group name", + "data_type": "string", + "primary": true, + "order": 1 + }, + "addresses": { + "description": "Comma seperated string of destination IP addresses, FQDNs, or wildcard FQDNs added to the group", + "data_type": "string", + "order": 2 + }, + "description": { + "description": "Additional information about the destination IP group.", + "data_type": "string", + "order": 3 + }, + "ip_categories": { + "description": "Destination IP address URL categories", + "data_type": "string", + "order": 4 + }, + "countries": { + "description": "Destination IP address countries. You can identify destinations based on the location of a server.", + "data_type": "string", + "order": 5 + }, + "is_non_editable": { + "description": "If set to true, the destination IP address group is non-editable. This field is applicable only to predefined IP address groups, which cannot be modified", + "data_type": "boolean", + "default": false, + "example_values": [ + true, + false + ], + "order": 6 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.is_non_editable", + "data_type": "boolean", + "column_name": "Is Non Editab;e", + "column_order": 6 + }, + { + "data_path": "action_result.parameter.countries", + "data_type": "string", + "column_name": "Countries", + "column_order": 5 + }, + { + "data_path": "action_result.parameter.ip_categories", + "data_type": "string", + "column_name": "Ip Categories", + "column_order": 4 + }, + { + "data_path": "action_result.parameter.description", + "data_type": "string", + "column_name": "Description", + "column_order": 3 + }, + { + "data_path": "action_result.parameter.addresses", + "data_type": "string", + "column_name": "Addresses", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.name", + "data_type": "string", + "column_name": "Name", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.ip_group_id", + "data_type": "numeric", + "column_name": "IP Group Id", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string", + "example_values": [ + "DSTN_IP", + "DSTN_FQDN", + "DSTN_DOMAIN", + "DSTN_OTHER" + ] + }, + { + "data_path": "action_result.data.*.addresses", + "data_type": "string", + "example_values": [ + "192.168.1.1" + ] + }, + { + "data_path": "action_result.data.*.countries", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.ipCategories", + "data_type": "string", + "example_values": [ + "TRADING_BROKARAGE_INSURANCE" + ] + }, + { + "data_path": "action_result.data.*.creatorContext", + "data_type": "string" + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "delete destination group", + "identifier": "delete_destination_group", + "description": "Delete destination group", + "type": "generic", + "read_only": false, + "parameters": { + "ip_group_ids": { + "description": "A comma-separated list of unique identifiers for the IP destination groups", + "data_type": "string", + "primary": true, + "order": 0 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.ip_group_ids", + "data_type": "string", + "column_name": "IP Group Ids", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.ip_group_ids", + "data_type": "string" + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "test User removed from group" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index 600e90b..a495112 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -991,6 +991,16 @@ def _handle_remove_group_user(self, param): return action_result.set_status(phantom.APP_SUCCESS) def _handle_create_destination_group(self, param): + """ + This action is used to create an IP Destination Group + :param name: IP destination group name + :param type: IP destination group type + :param addresses: Destination IP addresses, FQDNs, or wildcard FQDNs + :param description: Additional information about the destination IP group + :param ip_categories: Destination IP address URL categories + :param countries: Destination IP address countries + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) @@ -1019,6 +1029,180 @@ def _handle_create_destination_group(self, param): return action_result.set_status(phantom.APP_SUCCESS) + def _get_destination_group(self, id, action_result, exclude_type=None, category_type=None, lite=False): + + ret_val, response = self._make_rest_call_helper(f'/api/v1/ipDestinationGroups/{id}', action_result) + if phantom.is_fail(ret_val): + return action_result.get_status(), None + + group_type = response["type"] + + if group_type == exclude_type: + return phantom.APP_SUCCESS, None + + if lite: + if category_type and group_type not in category_type: + return phantom.APP_SUCCESS, None + + lite_resp = {"id": response["id"], "name": response["name"], "type": group_type} + return phantom.APP_SUCCESS, lite_resp + + return phantom.APP_SUCCESS, response + + def _get_batched_groups(self, endpoint, params, action_result): + limit = params['pageSize'] + + while True: + params['pageSize'] = min(limit, ZSCALER_MAX_PAGESIZE) + ret_val, get_groups = self._make_rest_call_helper('/api/v1' + endpoint, action_result, params=params) + self.debug_print("get groups is {0}".format(get_groups)) + if phantom.is_fail(ret_val): + return action_result.get_status() + for group in get_groups: + if "extensions" in group: + extensions = group.pop("extensions") + for key in extensions: + group[key] = extensions[key] + action_result.add_data(group) + limit = limit - params['pageSize'] + if limit <= 0 or len(get_groups) == 0: + break + params['page'] += 1 + + return phantom.APP_SUCCESS + + def _handle_list_destination_group(self, param): + """ + This action is used to list IP Destination Groups + :param ip_group_ids: Destination groups to retrieve + :param exclude_type: Group types to exclude from search + :param category_type: Destination types to filter by + :param include_ipv6: Retrieve IPv6 groups + :param limit: Number of groups to retrieve + :param lite: Retrieve limited information for each group + :param all_results: + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + ip_group_ids = param.get("ip_group_ids", "") + ip_ids_lst = [item.strip() for item in ip_group_ids.split(',') if item.strip()] + exclude_type = param.get("exclude_type", "") + category_type = param.get("category_type", "") + category_type_list = [item.strip() for item in category_type.split(',') if item.strip()] + include_ipv6 = param.get("include_ipv6", False) + limit = param.get("limit", 50) + # all_results = param.get("all_results", False) + lite = param.get("lite", False) + + params = {} + endpoint = '/ipDestinationGroups' + params['excludeType'] = exclude_type + self.debug_print("ip id list {0}".format(ip_ids_lst)) + if ip_ids_lst: + for ip in ip_ids_lst: + ret_val, response = self._get_destination_group(ip, action_result, exclude_type, category_type, lite) + if phantom.is_fail(ret_val): + return action_result.get_status() + action_result.add_data(response) + + summary = action_result.update_summary({}) + summary['message'] = "Destination groups retrieved" + return action_result.set_status(phantom.APP_SUCCESS) + + elif lite: + endpoint = '/ipDestinationGroups/lite' + params['type'] = category_type_list + + params['page'] = 1 + params['pageSize'] = limit + ret_val = self._get_batched_groups(endpoint, params, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + if include_ipv6: + self.save_progress("Retrieving ipv6 destination groups") + params['page'] = 1 + params['pageSize'] = limit + endpoint = '/ipDestinationGroups/ipv6DestinationGroups/lite' if lite else '/ipDestinationGroups/ipv6DestinationGroups' + ret_val = self._get_batched_groups(endpoint, params, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + # action_result.add_data(destination_groups) + summary = action_result.update_summary({}) + summary['message'] = "Destination groups retrieved" + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_edit_destination_group(self, param): + """ + This action is used to edit an IP Destination Group + :param ip_group_id: Id of destination group to edit + :param name: IP destination group name + :param addresses: Destination IP addresses, FQDNs, or wildcard FQDNs + :param description: Additional information about the destination IP group + :param ip_categories: Destination IP address URL categories + :param countries: Destination IP address countries + :param is_non_editable: If set to true, the destination IP address group is non-editable + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + group_id = param['ip_group_id'] + + ret_val, group_resp = self._get_destination_group(group_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + self.debug_print("handle edit response {0}".format(group_resp)) + if param.get("name"): + group_resp["name"] = param["name"] + if param.get('addresses'): + addresses = param["addresses"] + group_resp["addresses"] = [item.strip() for item in addresses.split(',') if item.strip()] + if param.get("description"): + group_resp["description"] = param["description"] + if param.get("ip_categories"): + ip_categories = param["ip_categories"] + group_resp["ip_categories"] = [item.strip() for item in ip_categories.split(',') if item.strip()] + if param.get("countries"): + countries = param["countries"] + group_resp["countries"] = [item.strip() for item in countries.split(',') if item.strip()] + group_resp["isNonEditable"] = param["is_non_editable"] + + ret_val, response = self._make_rest_call_helper(f'/api/v1/ipDestinationGroups/{group_id}', action_result, data=group_resp, method='put') + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Destination IP edited" + + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_delete_destination_group(self, param): + """ + This action is used to delete IP Destination Groups + :param ip_group_ids: Ids of destination group to delete + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + group_ids = param.get("ip_group_ids", "") + list_group_ids = [item.strip() for item in group_ids.split(',') if item.strip()] + + for group_id in list_group_ids: + ret_val, response = self._make_rest_call_helper(f'/api/v1/ipDestinationGroups/{group_id}', action_result, method='delete') + if phantom.is_fail(ret_val): + return action_result.get_status() + action_result.add_data({"ip_group_id": group_id}) + + summary = action_result.update_summary({}) + summary['message'] = "Destination groups deleted" + return action_result.set_status(phantom.APP_SUCCESS) + def handle_action(self, param): ret_val = phantom.APP_SUCCESS @@ -1088,6 +1272,15 @@ def handle_action(self, param): elif action_id == 'create_destination_group': ret_val = self._handle_create_destination_group(param) + elif action_id == 'list_destination_group': + ret_val = self._handle_list_destination_group(param) + + elif action_id == 'edit_destination_group': + ret_val = self._handle_edit_destination_group(param) + + elif action_id == 'delete_destination_group': + ret_val = self._handle_delete_destination_group(param) + return ret_val def initialize(self): From 2de414809a155b6c516b45cac00fd50f516addd7 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Tue, 6 Aug 2024 19:03:59 +0000 Subject: [PATCH 10/53] Update README.md --- README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8bdb88e..9506fe8 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,8 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [remove group user](#action-remove-group-user) - Remove user from group [create destination group](#action-create-destination-group) - Create destination group [list destination group](#action-list-destination-group) - List destination group +[edit destination group](#action-edit-destination-group) - Edit destination group +[delete destination group](#action-delete-destination-group) - Delete destination group ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -771,6 +773,7 @@ DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES action_result.status | string | | test success test failed action_result.parameter.countries | string | | action_result.parameter.ip_categories | string | | +action_result.parameter.description | string | | action_result.parameter.addresses | string | | action_result.parameter.type | string | | action_result.parameter.name | string | | @@ -797,9 +800,9 @@ Read only: **False** #### Action Parameters PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- -**ip_group_id** | optional | A comma-separated list of unique identifiers for the IP destination groups | string | +**ip_group_ids** | optional | A comma-separated list of unique identifiers for the IP destination groups | string | **exclude_type** | optional | The IP group type to be excluded from the results | string | -**category_type** | optional | The IP group type to be filtered from results. This argument is only supported when the 'lite' argument is set to True | string | +**category_type** | optional | Comma seperated list of IP group types to be filtered from results. This argument is only supported when the 'lite' argument is set to True | string | **include_ipv6** | optional | Retrieve IPv6 destination groups | boolean | **limit** | optional | Limit of the results to be retrieved | numeric | **all_results** | optional | Whether to retrieve all results at once | boolean | @@ -828,4 +831,71 @@ action_result.summary.message | string | | Retreived Destination Groups action_result.message | string | | Retreived Destination Groups summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'edit destination group' +Edit destination group + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_group_id** | required | The unique identifier for the IP destination group | numeric | +**name** | optional | Destination IP group name | string | +**addresses** | optional | Comma seperated string of destination IP addresses, FQDNs, or wildcard FQDNs added to the group | string | +**description** | optional | Additional information about the destination IP group. | string | +**ip_categories** | optional | Destination IP address URL categories | string | +**countries** | optional | Destination IP address countries. You can identify destinations based on the location of a server. | string | +**is_non_editable** | optional | If set to true, the destination IP address group is non-editable. This field is applicable only to predefined IP address groups, which cannot be modified | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.is_non_editable | boolean | | +action_result.parameter.countries | string | | +action_result.parameter.ip_categories | string | | +action_result.parameter.description | string | | +action_result.parameter.addresses | string | | +action_result.parameter.name | string | | +action_result.parameter.ip_group_id | numeric | | +action_result.data.\*.id | numeric | | +action_result.data.\*.name | string | | +action_result.data.\*.type | string | | DSTN_IP DSTN_FQDN DSTN_DOMAIN DSTN_OTHER +action_result.data.\*.addresses | string | | 192.168.1.1 +action_result.data.\*.countries | string | | +action_result.data.\*.description | string | | +action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.creatorContext | string | | +action_result.summary | string | | +action_result.summary.message | string | | test User removed from group +action_result.message | string | | test User removed from group +summary.message | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'delete destination group' +Delete destination group + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**ip_group_ids** | optional | A comma-separated list of unique identifiers for the IP destination groups | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.ip_group_ids | string | | +action_result.data.\*.ip_group_ids | string | | +action_result.summary | string | | +action_result.summary.message | string | | test User removed from group +action_result.message | string | | test User removed from group +summary.message | string | | +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From aae9e0c09aee6d751b5daaef474632a7045a4b5b Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Tue, 6 Aug 2024 15:48:39 -0700 Subject: [PATCH 11/53] PAPP-34458: get blacklist and get whitelist working --- zscaler.json | 52 ++++++++++++++++++++++++++++++++++--------- zscaler_connector.py | 53 ++++++++++++++++++++++++++------------------ 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/zscaler.json b/zscaler.json index cc6ab14..8326859 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3018,14 +3018,21 @@ ] }, { - "data_path": "action_result.data.*.whitelistUrls", + "data_path": "action_result.data.*.whitelistUrl", "data_type": "string" }, { - "data_path": "action_result.message", + "data_path": "action_result.summary.total_whitelist_items", + "data_type": "numeric", + "example_values": [ + 10 + ] + }, + { + "data_path": "action_result.summary.message", "data_type": "string", "example_values": [ - "test Total url categories: 97" + "Whitelist retrieved" ] }, { @@ -3050,7 +3057,7 @@ "versions": "EQ(*)" }, { - "action": "get blakclist", + "action": "get blacklist", "identifier": "get_blacklist", "description": "get urls on the deny list", "type": "investigate", @@ -3060,13 +3067,10 @@ "description": "Filter results be url or ip", "data_type": "string", "primary": true, - "contains": [ + "value_list": [ "url", "ip" ], - "example_values": [ - "127.0.0.1" - ], "order": 0 }, "query": { @@ -3089,14 +3093,40 @@ ] }, { - "data_path": "action_result.data.*.whitelistUrls", + "data_path": "action_result.parameter.query", + "data_type": "string", + "column_name": "Query", + "example_values": [ + "8...8" + ], + "column_order": 1 + }, + { + "data_path": "action_result.parameter.filter", + "data_type": "string", + "column_name": "Filter", + "value_list": [ + "url", + "ip" + ], + "column_order": 0 + }, + { + "data_path": "action_result.data.*.blacklistUrl", "data_type": "string" }, { - "data_path": "action_result.message", + "data_path": "action_result.summary.message", "data_type": "string", "example_values": [ - "test Total url categories: 97" + "Blacklist retrieved" + ] + }, + { + "data_path": "action_result.summary.total_blacklist_items", + "data_type": "numeric", + "example_values": [ + 10 ] }, { diff --git a/zscaler_connector.py b/zscaler_connector.py index d0b15c9..269e95c 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -18,6 +18,7 @@ import json import re import time +import ipaddress import phantom.app as phantom import phantom.rules as phantom_rules @@ -25,7 +26,6 @@ from bs4 import BeautifulSoup from phantom.action_result import ActionResult from phantom.base_connector import BaseConnector -import socket from zscaler_consts import * @@ -998,14 +998,26 @@ def _handle_get_whitelist(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - ret_val, response = self._make_rest_call_helper('/api/v1/settings', action_result) + ret_val, response = self._get_allowlist(action_result) if phantom.is_fail(ret_val): - return action_result.get_status() + return RetVal(ret_val, None) - self.debug_print(response) + whitelist = response.get('whitelistUrls', []) + for allowed in whitelist: + action_result.add_data(allowed) + summary = action_result.update_summary({}) + summary['total_whitelist_items'] = action_result.get_data_size() + summary['message'] = "Whitelist retrieved" return action_result.set_status(phantom.APP_SUCCESS) + def _is_ip_address(self, address): + try: + ipaddress.ip_address(address) + return True + except ValueError: + return False + def _handle_get_blacklist(self, param): """ This action is used to get the blacklist in zscalar @@ -1014,29 +1026,28 @@ def _handle_get_blacklist(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - ret_val, response = self._make_rest_call_helper('/api/v1/settings/advanced', action_result) + ret_val, response = self._get_blocklist(action_result) if phantom.is_fail(ret_val): - return action_result.get_status() + return RetVal(ret_val, None) filter = param.get("filter") query = param.get("query") - self.debug_print(response) - if not filter and not query: - return action_result.set_status(phantom.APP_SUCCESS) - - parsed_data = [] - - self.debug_print(response) - for entry in response: - self.debug_print(entry) - url = entry.get(url, "") - ip = socket.socket.gethostbyname(url) - if url == filter or ip == filter: - parsed_data.append(entry) - elif query and (re.fullmatch(query, url) or re.fullmatch(query, ip)): - parsed_data.append(entry) + summary = action_result.update_summary({}) + summary['message'] = "Blacklist retrieved" + blocklist = response.get('blacklistUrls', []) + for blocked in blocklist: + is_ip = self._is_ip_address(blocked) + if filter == "ip" and not is_ip: + continue + if filter == "url" and is_ip: + continue + if query and not re.fullmatch(query, blocked): + continue + action_result.add_data(blocked) + + summary['total_blacklist_items'] = action_result.get_data_size() return action_result.set_status(phantom.APP_SUCCESS) def handle_action(self, param): From a09bd24ee3525ae33542ec3b6f992ff46bf45948 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Tue, 6 Aug 2024 22:49:25 +0000 Subject: [PATCH 12/53] Update README.md --- README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3b972d8..edebb46 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group [get whitelist](#action-get-whitelist) - get urls on the allow list -[get blakclist](#action-get-blakclist) - get urls on the deny list +[get blacklist](#action-get-blacklist) - get urls on the deny list ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -762,12 +762,13 @@ No parameters are required for this action DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | test success test failed -action_result.data.\*.whitelistUrls | string | | -action_result.message | string | | test Total url categories: 97 +action_result.data.\*.whitelistUrl | string | | +action_result.summary.total_whitelist_items | numeric | | 10 +action_result.summary.message | string | | Whitelist retrieved summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 -## action: 'get blakclist' +## action: 'get blacklist' get urls on the deny list Type: **investigate** @@ -776,14 +777,17 @@ Read only: **True** #### Action Parameters PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- -**filter** | optional | Filter results be url or ip | string | `url` `ip` +**filter** | optional | Filter results be url or ip | string | **query** | optional | Regular expression to match url or ip against | string | #### Action Output DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | test success test failed -action_result.data.\*.whitelistUrls | string | | -action_result.message | string | | test Total url categories: 97 +action_result.parameter.query | string | | 8...8 +action_result.parameter.filter | string | | +action_result.data.\*.blacklistUrl | string | | +action_result.summary.message | string | | Blacklist retrieved +action_result.summary.total_blacklist_items | numeric | | 10 summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From abe77a1387342e72f8406c7745c425addf961e2d Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Wed, 7 Aug 2024 09:29:55 -0700 Subject: [PATCH 13/53] PAPP-34460: categories work --- zscaler.json | 143 +++++++++++++++++++++++++++++++++++++++++++ zscaler_connector.py | 36 +++++++++++ 2 files changed, 179 insertions(+) diff --git a/zscaler.json b/zscaler.json index 5ed9741..4e234ef 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3000,6 +3000,149 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "add category url", + "description": "Add urls to a cetgory", + "type": "generic", + "identifier": "add_category_url", + "read_only": false, + "parameters": { + "category_id": { + "description": "The ID of the category to add the specified URLs to", + "data_type": "string", + "order": 0, + "example_values": [ + "RADIO_STATIONS" + ], + "primary": true, + "required": true + }, + "urls": { + "description": "A comma-separated list of URLs to add to the specified category", + "data_type": "string", + "order": 1, + "primary": true + }, + "retaining-parent-category-url": { + "description": "A comma-separated list of URLs to add to the retaining parent category section inside the specified category", + "data_type": "string", + "primary": true, + "order": 2 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.category_id", + "data_type": "string", + "example_values": [ + "RADIO_STATIONS" + ] + }, + { + "data_path": "action_result.parameter.urls", + "data_type": "string" + }, + { + "data_path": "action_result.parameter.retaining-parent-category-url", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Total messages returned: 1" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "get categories", + "description": "Retrieve categories", + "type": "investigative", + "identifier": "get_categories", + "read_only": false, + "parameters": { + "get_ids_and_names_only": { + "description": "Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned", + "data_type": "boolean", + "order": 0, + "default": false, + "example_values": [ + true, + false + ], + "primary": true + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.get_ids_and_names_only", + "data_type": "string", + "example_values": [ + "RADIO_STATIONS" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Total messages returned: 1" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index dd0686c..675d162 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -989,6 +989,36 @@ def _handle_remove_group_user(self, param): summary['message'] = "User removed from group" return action_result.set_status(phantom.APP_SUCCESS) + + def _get_category_details(self, id, action_result): + ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{id}', action_result) + if phantom.is_fail(ret_val): + return action_result.get_status(), None + return phantom.APP_SUCCESS, response + + def _handle_add_category_url(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + category_id = param["category_id"] + + ret_val, category_details = self._get_category_details(category_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + configuredName = category_details["configuredName"] + urls = param["urls"] + urls_list = [item.strip() for item in urls.split(',') if item.strip()] + retaining_parent_category_url = param["retaining-parent-category-url"] + parent_urls = [item.strip() for item in retaining_parent_category_url.split(',') if item.strip()] + data = {} + data["configuredName"] = configuredName + data["urls"] = urls_list + #do get_categories because custom categories need name so just pass name with every call + + def _handle_get_categories(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + get_ids_and_names_only = param["get_ids_and_names_only"] def handle_action(self, param): @@ -1055,6 +1085,12 @@ def handle_action(self, param): elif action_id == 'remove_group_user': ret_val = self._handle_remove_group_user(param) + + elif action_id == 'add_category_url': + ret_val = self._handle_add_category_url(param) + + elif action_id == 'get_categories': + ret_val = self._handle_get_categories(param) return ret_val From 166154a5736ed7cb27a92ef6fa3d188121e1efc9 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Wed, 7 Aug 2024 16:30:39 +0000 Subject: [PATCH 14/53] Update README.md --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/README.md b/README.md index e954575..ec4a31a 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,8 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [get groups](#action-get-groups) - Gets a list of groups [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group +[add category url](#action-add-category-url) - Add urls to a cetgory +[get categories](#action-get-categories) - Retrieve categories ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -745,4 +747,48 @@ action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'add category url' +Add urls to a cetgory + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**category_id** | required | The ID of the category to add the specified URLs to | string | +**urls** | optional | A comma-separated list of URLs to add to the specified category | string | +**retaining-parent-category-url** | optional | A comma-separated list of URLs to add to the retaining parent category section inside the specified category | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.category_id | string | | RADIO_STATIONS +action_result.parameter.urls | string | | +action_result.parameter.retaining-parent-category-url | string | | +action_result.message | string | | Total messages returned: 1 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get categories' +Retrieve categories + +Type: **investigative** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**get_ids_and_names_only** | optional | Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.get_ids_and_names_only | string | | RADIO_STATIONS +action_result.message | string | | Total messages returned: 1 +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From 6684e59677cd00d07eae0542c0eb6ddf8f624824 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Wed, 7 Aug 2024 12:36:04 -0700 Subject: [PATCH 15/53] PAPP-34461: removing all_results parameter --- zscaler.json | 18 +----------------- zscaler_connector.py | 2 -- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/zscaler.json b/zscaler.json index 50bf19d..eee0c34 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3230,16 +3230,6 @@ "default": 50, "order": 4 }, - "all_results": { - "description": "Whether to retrieve all results at once", - "data_type": "boolean", - "example_values": [ - true, - false - ], - "default": false, - "order": 5 - }, "lite": { "description": "Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups", "data_type": "boolean", @@ -3248,7 +3238,7 @@ false ], "default": false, - "order": 6 + "order": 5 } }, "output": [ @@ -3266,12 +3256,6 @@ "data_path": "action_result.parameter.lite", "data_type": "boolean", "column_name": "Lite", - "column_order": 6 - }, - { - "data_path": "action_result.parameter.all_reuslts", - "data_type": "boolean", - "column_name": "All Results", "column_order": 5 }, { diff --git a/zscaler_connector.py b/zscaler_connector.py index a495112..3e9e1ca 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1080,7 +1080,6 @@ def _handle_list_destination_group(self, param): :param include_ipv6: Retrieve IPv6 groups :param limit: Number of groups to retrieve :param lite: Retrieve limited information for each group - :param all_results: :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) """ self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) @@ -1093,7 +1092,6 @@ def _handle_list_destination_group(self, param): category_type_list = [item.strip() for item in category_type.split(',') if item.strip()] include_ipv6 = param.get("include_ipv6", False) limit = param.get("limit", 50) - # all_results = param.get("all_results", False) lite = param.get("lite", False) params = {} From b875ce5584b13038c4e1ded2314e918d9584aa3a Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Wed, 7 Aug 2024 19:37:19 +0000 Subject: [PATCH 16/53] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 9506fe8..5db35b3 100644 --- a/README.md +++ b/README.md @@ -805,7 +805,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS **category_type** | optional | Comma seperated list of IP group types to be filtered from results. This argument is only supported when the 'lite' argument is set to True | string | **include_ipv6** | optional | Retrieve IPv6 destination groups | boolean | **limit** | optional | Limit of the results to be retrieved | numeric | -**all_results** | optional | Whether to retrieve all results at once | boolean | **lite** | optional | Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups | boolean | #### Action Output @@ -813,7 +812,6 @@ DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | test success test failed action_result.parameter.lite | boolean | | -action_result.parameter.all_reuslts | boolean | | action_result.parameter.limit | numeric | | action_result.parameter.include_ipv6 | boolean | | action_result.parameter.category_type | string | | From bfe732a51d91b53bc797c0ac0b6b28099fb710f8 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 12 Aug 2024 09:19:20 -0700 Subject: [PATCH 17/53] PAPP-34460: category actions completed --- zscaler.json | 500 +++++++++++++++++++++++++++++++++++++++++-- zscaler_connector.py | 167 +++++++++++++-- 2 files changed, 635 insertions(+), 32 deletions(-) diff --git a/zscaler.json b/zscaler.json index 4e234ef..0abf6c9 100644 --- a/zscaler.json +++ b/zscaler.json @@ -316,7 +316,19 @@ "description": "List all URL categories", "type": "investigate", "read_only": true, - "parameters": {}, + "parameters": { + "get_ids_and_names_only": { + "description": "Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned", + "data_type": "boolean", + "order": 0, + "default": false, + "example_values": [ + true, + false + ], + "primary": true + } + }, "output": [ { "data_path": "action_result.status", @@ -326,6 +338,13 @@ "test failed" ] }, + { + "data_path": "action_result.parameter.get_ids_and_names_only", + "data_type": "string", + "example_values": [ + "RADIO_STATIONS" + ] + }, { "data_path": "action_result.data.*.configuredName", "data_type": "string", @@ -3055,13 +3074,81 @@ "data_path": "action_result.parameter.retaining-parent-category-url", "data_type": "string" }, + { + "data_path": "action_result.data.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.val", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.scopes.*.Type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.editable", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.keywords", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.configuredName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customCategory", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.customUrlsCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.dbCategorizedUrls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customIpRangesCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.keywordsRetainingParentCategory", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", + "data_type": "numeric" + }, { "data_path": "action_result.message", "data_type": "string", "example_values": [ - "Total messages returned: 1" + "Message: Category urs updated" ] }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -3083,22 +3170,33 @@ "versions": "EQ(*)" }, { - "action": "get categories", - "description": "Retrieve categories", - "type": "investigative", - "identifier": "get_categories", + "action": "add category ip", + "description": "Add IPs to a cetgory", + "type": "generic", + "identifier": "add_category_ip", "read_only": false, "parameters": { - "get_ids_and_names_only": { - "description": "Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned", - "data_type": "boolean", + "category_id": { + "description": "The ID of the category to add the specified URLs to", + "data_type": "string", "order": 0, - "default": false, "example_values": [ - true, - false + "RADIO_STATIONS" ], + "primary": true, + "required": true + }, + "ips": { + "description": "A comma-separated list of IP addresses to add to the specified category", + "data_type": "string", + "order": 1, "primary": true + }, + "retaining-parent-category-ip": { + "description": "A comma-separated list of IPs to add to the retaining parent category section inside the specified category", + "data_type": "string", + "primary": true, + "order": 2 } }, "output": [ @@ -3111,19 +3209,393 @@ ] }, { - "data_path": "action_result.parameter.get_ids_and_names_only", + "data_path": "action_result.parameter.category_id", + "data_type": "string", + "example_values": [ + "RADIO_STATIONS" + ] + }, + { + "data_path": "action_result.parameter.ips", + "data_type": "string" + }, + { + "data_path": "action_result.parameter.retaining-parent-category-ip", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.val", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.scopes.*.Type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.editable", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.keywords", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.configuredName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customCategory", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.customUrlsCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.dbCategorizedUrls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customIpRangesCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.keywordsRetainingParentCategory", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Message: Category ips updated" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "remove category url", + "description": "Add urls to a cetgory", + "type": "generic", + "identifier": "remove_category_url", + "read_only": false, + "parameters": { + "category_id": { + "description": "The ID of the category to add the specified URLs to", + "data_type": "string", + "order": 0, + "example_values": [ + "RADIO_STATIONS" + ], + "primary": true, + "required": true + }, + "urls": { + "description": "A comma-separated list of URLs to remove from the specified category", + "data_type": "string", + "order": 1, + "primary": true + }, + "retaining-parent-category-url": { + "description": "A comma-separated list of URLs to remove from the retaining parent category section inside the specified category", + "data_type": "string", + "primary": true, + "order": 2 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.category_id", + "data_type": "string", + "example_values": [ + "RADIO_STATIONS" + ] + }, + { + "data_path": "action_result.parameter.urls", + "data_type": "string" + }, + { + "data_path": "action_result.parameter.retaining-parent-category-url", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.val", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.scopes.*.Type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.editable", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.keywords", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.configuredName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customCategory", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.customUrlsCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.dbCategorizedUrls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customIpRangesCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.keywordsRetainingParentCategory", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Message: Category urls removed" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "remove category ip", + "description": "Remove IPs to a cetgory", + "type": "generic", + "identifier": "remove_category_ip", + "read_only": false, + "parameters": { + "category_id": { + "description": "The ID of the category to add the specified URLs to", + "data_type": "string", + "order": 0, + "example_values": [ + "RADIO_STATIONS" + ], + "primary": true, + "required": true + }, + "ips": { + "description": "A comma-separated list of IP addresses to add to the specified category", + "data_type": "string", + "order": 1, + "primary": true + }, + "retaining-parent-category-ip": { + "description": "A comma-separated list of IPs to add to the retaining parent category section inside the specified category", + "data_type": "string", + "primary": true, + "order": 2 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.category_id", "data_type": "string", "example_values": [ "RADIO_STATIONS" ] }, + { + "data_path": "action_result.parameter.ips", + "data_type": "string" + }, + { + "data_path": "action_result.parameter.retaining-parent-category-ip", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.val", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.scopes.*.Type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.editable", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.keywords", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.configuredName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customCategory", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.customUrlsCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.dbCategorizedUrls", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.customIpRangesCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.keywordsRetainingParentCategory", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", + "data_type": "numeric" + }, { "data_path": "action_result.message", "data_type": "string", "example_values": [ - "Total messages returned: 1" + "Message: Category ips removed" ] }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "summary.total_objects", "data_type": "numeric", diff --git a/zscaler_connector.py b/zscaler_connector.py index 675d162..24106e7 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -739,8 +739,17 @@ def _handle_list_url_categories(self, param): if phantom.is_fail(ret_val): return action_result.get_status() + get_ids_and_names_only = param["get_ids_and_names_only"] + for url_category in list_url_categories: - action_result.add_data(url_category) + if get_ids_and_names_only: + category_lite = {} + category_lite["id"] = url_category["id"] + if "configuredName" in url_category: + category_lite["configuredName"] = url_category["configuredName"] + action_result.add_data(category_lite) + else: + action_result.add_data(url_category) summary = action_result.update_summary({}) summary['total_url_categories'] = action_result.get_data_size() @@ -989,36 +998,152 @@ def _handle_remove_group_user(self, param): summary['message'] = "User removed from group" return action_result.set_status(phantom.APP_SUCCESS) - + def _get_category_details(self, id, action_result): ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{id}', action_result) if phantom.is_fail(ret_val): return action_result.get_status(), None return phantom.APP_SUCCESS, response + def _add_to_category(self, data, parent_data, category_details, category_id, action_result): + new_data = category_details.get("urls", []) + new_data.extend(data) + if new_data: + category_details["urls"] = new_data + self.debug_print("add_to_category new data {0}".format(category_details["urls"])) + + new_parent_data = category_details.get("dbCategorizedUrls", []) + new_parent_data.extend(parent_data) + if new_parent_data: + category_details["dbCategorizedUrls"] = new_parent_data + self.debug_print("add_to_category new parent data {0}".format(category_details["dbCategorizedUrls"])) + + ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=category_details, method='put') + return ret_val, response + def _handle_add_category_url(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) category_id = param["category_id"] - + ret_val, category_details = self._get_category_details(category_id, action_result) if phantom.is_fail(ret_val): return action_result.get_status() - - configuredName = category_details["configuredName"] - urls = param["urls"] + + is_custom_category = category_details.get("customCategory", False) + + if not is_custom_category: + action_result.set_status(phantom.APP_ERROR, "Category with {0} is a default category, which cannot be modified" + .format(category_id)) + return action_result.get_status() + + urls = param.get("urls", "") urls_list = [item.strip() for item in urls.split(',') if item.strip()] - retaining_parent_category_url = param["retaining-parent-category-url"] + retaining_parent_category_url = param.get("retaining-parent-category-url", "") parent_urls = [item.strip() for item in retaining_parent_category_url.split(',') if item.strip()] - data = {} - data["configuredName"] = configuredName - data["urls"] = urls_list - #do get_categories because custom categories need name so just pass name with every call - - def _handle_get_categories(self, param): + ret_val, response = self._add_to_category(urls_list, parent_urls, category_details, category_id, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Category urls updated" + + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_add_category_ips(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - get_ids_and_names_only = param["get_ids_and_names_only"] + category_id = param["category_id"] + + ret_val, category_details = self._get_category_details(category_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + ips = param.get("ips", "") + ips_list = [item.strip() for item in ips.split(',') if item.strip()] + retaining_parent_category_ip = param.get("retaining-parent-category-ip", "") + parent_ips = [item.strip() for item in retaining_parent_category_ip.split(',') if item.strip()] + ret_val, response = self._add_to_category(ips_list, parent_ips, category_details, category_id, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Category ips updated" + + return action_result.set_status(phantom.APP_SUCCESS) + + def _remove_from_category(self, data, parent_data, category_details, category_id, action_result): + data_set = set(data) + new_data = [] + for point in category_details.get("urls", []): + if point not in data_set: + new_data.append(point) + + parent_data_set = set(parent_data) + new_parent_data = [] + for point in category_details.get("dbCategorizedUrls", []): + if point not in parent_data_set: + new_parent_data.append(point) + + category_details["urls"] = new_data + category_details["dbCategorizedUrls"] = new_parent_data + + ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=category_details, method='put') + return ret_val, response + + def _handle_remove_category_urls(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + category_id = param["category_id"] + + ret_val, category_details = self._get_category_details(category_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + urls = param.get("urls", "") + urls_to_remove = [item.strip() for item in urls.split(',') if item.strip()] + retaining_parent_category_url = param.get("retaining-parent-category-url", "") + parent_urls_to_remove = [item.strip() for item in retaining_parent_category_url.split(',') if item.strip()] + + ret_val, response = self._remove_from_category(urls_to_remove, parent_urls_to_remove, category_details, category_id, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Category urls removed" + + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_remove_category_ips(self, param): + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + category_id = param["category_id"] + + ret_val, category_details = self._get_category_details(category_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + ips = param.get("ips", "") + ips_to_remove = [item.strip() for item in ips.split(',') if item.strip()] + retaining_parent_category_ips = param.get("retaining-parent-category-ip", "") + parent_ips_to_remove = [item.strip() for item in retaining_parent_category_ips.split(',') if item.strip()] + + ret_val, response = self._remove_from_category(ips_to_remove, parent_ips_to_remove, category_details, category_id, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + summary = action_result.update_summary({}) + summary['message'] = "Category ips removed" + + return action_result.set_status(phantom.APP_SUCCESS) def handle_action(self, param): @@ -1085,12 +1210,18 @@ def handle_action(self, param): elif action_id == 'remove_group_user': ret_val = self._handle_remove_group_user(param) - + elif action_id == 'add_category_url': ret_val = self._handle_add_category_url(param) - - elif action_id == 'get_categories': - ret_val = self._handle_get_categories(param) + + elif action_id == 'add_category_ip': + ret_val = self._handle_add_category_ips(param) + + elif action_id == 'remove_category_url': + ret_val = self._handle_remove_category_urls(param) + + elif action_id == 'remove_category_ip': + ret_val = self._handle_remove_category_ips(param) return ret_val From f261c81ddfad4b30464f8718cb6c3d4de4de1ed8 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 12 Aug 2024 16:20:11 +0000 Subject: [PATCH 18/53] Update README.md --- README.md | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 134 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ec4a31a..66d068c 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,9 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [add group user](#action-add-group-user) - Add user to group [remove group user](#action-remove-group-user) - Remove user from group [add category url](#action-add-category-url) - Add urls to a cetgory -[get categories](#action-get-categories) - Retrieve categories +[add category ip](#action-add-category-ip) - Add IPs to a cetgory +[remove category url](#action-remove-category-url) - Add urls to a cetgory +[remove category ip](#action-remove-category-ip) - Remove IPs to a cetgory ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -187,12 +189,15 @@ Type: **investigate** Read only: **True** #### Action Parameters -No parameters are required for this action +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**get_ids_and_names_only** | optional | Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned | boolean | #### Action Output DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | test success test failed +action_result.parameter.get_ids_and_names_only | string | | RADIO_STATIONS action_result.data.\*.configuredName | string | | test Test-Caution action_result.data.\*.customCategory | boolean | | True False action_result.data.\*.customIpRangesCount | numeric | | 0 @@ -769,26 +774,146 @@ action_result.status | string | | success failed action_result.parameter.category_id | string | | RADIO_STATIONS action_result.parameter.urls | string | | action_result.parameter.retaining-parent-category-url | string | | -action_result.message | string | | Total messages returned: 1 +action_result.data.\*.id | string | | +action_result.data.\*.val | numeric | | +action_result.data.\*.type | string | | +action_result.data.\*.urls | string | | +action_result.data.\*.scopes.\*.Type | string | | +action_result.data.\*.editable | boolean | | +action_result.data.\*.keywords | string | | +action_result.data.\*.description | string | | +action_result.data.\*.configuredName | string | | +action_result.data.\*.customCategory | boolean | | +action_result.data.\*.customUrlsCount | numeric | | +action_result.data.\*.dbCategorizedUrls | string | | +action_result.data.\*.customIpRangesCount | numeric | | +action_result.data.\*.keywordsRetainingParentCategory | string | | +action_result.data.\*.urlsRetainingParentCategoryCount | numeric | | +action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | +action_result.message | string | | Message: Category urs updated +action_result.summary | string | | summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 -## action: 'get categories' -Retrieve categories +## action: 'add category ip' +Add IPs to a cetgory -Type: **investigative** +Type: **generic** Read only: **False** #### Action Parameters PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- -**get_ids_and_names_only** | optional | Whether to retrieve only a list containing URL category IDs and names. Even if displayURL is set to true, URLs will not be returned | boolean | +**category_id** | required | The ID of the category to add the specified URLs to | string | +**ips** | optional | A comma-separated list of IP addresses to add to the specified category | string | +**retaining-parent-category-ip** | optional | A comma-separated list of IPs to add to the retaining parent category section inside the specified category | string | #### Action Output DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | success failed -action_result.parameter.get_ids_and_names_only | string | | RADIO_STATIONS -action_result.message | string | | Total messages returned: 1 +action_result.parameter.category_id | string | | RADIO_STATIONS +action_result.parameter.ips | string | | +action_result.parameter.retaining-parent-category-ip | string | | +action_result.data.\*.id | string | | +action_result.data.\*.val | numeric | | +action_result.data.\*.type | string | | +action_result.data.\*.urls | string | | +action_result.data.\*.scopes.\*.Type | string | | +action_result.data.\*.editable | boolean | | +action_result.data.\*.keywords | string | | +action_result.data.\*.description | string | | +action_result.data.\*.configuredName | string | | +action_result.data.\*.customCategory | boolean | | +action_result.data.\*.customUrlsCount | numeric | | +action_result.data.\*.dbCategorizedUrls | string | | +action_result.data.\*.customIpRangesCount | numeric | | +action_result.data.\*.keywordsRetainingParentCategory | string | | +action_result.data.\*.urlsRetainingParentCategoryCount | numeric | | +action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | +action_result.message | string | | Message: Category ips updated +action_result.summary | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'remove category url' +Add urls to a cetgory + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**category_id** | required | The ID of the category to add the specified URLs to | string | +**urls** | optional | A comma-separated list of URLs to remove from the specified category | string | +**retaining-parent-category-url** | optional | A comma-separated list of URLs to remove from the retaining parent category section inside the specified category | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.category_id | string | | RADIO_STATIONS +action_result.parameter.urls | string | | +action_result.parameter.retaining-parent-category-url | string | | +action_result.data.\*.id | string | | +action_result.data.\*.val | numeric | | +action_result.data.\*.type | string | | +action_result.data.\*.urls | string | | +action_result.data.\*.scopes.\*.Type | string | | +action_result.data.\*.editable | boolean | | +action_result.data.\*.keywords | string | | +action_result.data.\*.description | string | | +action_result.data.\*.configuredName | string | | +action_result.data.\*.customCategory | boolean | | +action_result.data.\*.customUrlsCount | numeric | | +action_result.data.\*.dbCategorizedUrls | string | | +action_result.data.\*.customIpRangesCount | numeric | | +action_result.data.\*.keywordsRetainingParentCategory | string | | +action_result.data.\*.urlsRetainingParentCategoryCount | numeric | | +action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | +action_result.message | string | | Message: Category urls removed +action_result.summary | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'remove category ip' +Remove IPs to a cetgory + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**category_id** | required | The ID of the category to add the specified URLs to | string | +**ips** | optional | A comma-separated list of IP addresses to add to the specified category | string | +**retaining-parent-category-ip** | optional | A comma-separated list of IPs to add to the retaining parent category section inside the specified category | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.category_id | string | | RADIO_STATIONS +action_result.parameter.ips | string | | +action_result.parameter.retaining-parent-category-ip | string | | +action_result.data.\*.id | string | | +action_result.data.\*.val | numeric | | +action_result.data.\*.type | string | | +action_result.data.\*.urls | string | | +action_result.data.\*.scopes.\*.Type | string | | +action_result.data.\*.editable | boolean | | +action_result.data.\*.keywords | string | | +action_result.data.\*.description | string | | +action_result.data.\*.configuredName | string | | +action_result.data.\*.customCategory | boolean | | +action_result.data.\*.customUrlsCount | numeric | | +action_result.data.\*.dbCategorizedUrls | string | | +action_result.data.\*.customIpRangesCount | numeric | | +action_result.data.\*.keywordsRetainingParentCategory | string | | +action_result.data.\*.urlsRetainingParentCategoryCount | numeric | | +action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | +action_result.message | string | | Message: Category ips removed +action_result.summary | string | | summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From d85615dc8455354dbc930be96e3e430a3869349e Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 12 Aug 2024 16:44:08 +0000 Subject: [PATCH 19/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9569872..26b8ed7 100644 --- a/README.md +++ b/README.md @@ -920,7 +920,7 @@ action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | action_result.message | string | | Message: Category ips removed action_result.summary | string | | summary.total_objects | numeric | | 1 -summary.total_objects_successful | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'create destination group' Create destination group From 6b62c2f5c638a750064dc6c7ac8a364ac6fa706c Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 12 Aug 2024 11:21:15 -0700 Subject: [PATCH 20/53] PAPP-34457: param change --- zscaler_connector.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index 6cac669..d8de1d7 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1010,13 +1010,11 @@ def _add_to_category(self, data, parent_data, category_details, category_id, act new_data.extend(data) if new_data: category_details["urls"] = new_data - self.debug_print("add_to_category new data {0}".format(category_details["urls"])) new_parent_data = category_details.get("dbCategorizedUrls", []) new_parent_data.extend(parent_data) if new_parent_data: category_details["dbCategorizedUrls"] = new_parent_data - self.debug_print("add_to_category new parent data {0}".format(category_details["dbCategorizedUrls"])) ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=category_details, method='put') return ret_val, response @@ -1075,7 +1073,7 @@ def _handle_add_category_ips(self, param): summary['message'] = "Category ips updated" return action_result.set_status(phantom.APP_SUCCESS) - + def _handle_remove_category_ips(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) @@ -1135,7 +1133,7 @@ def _handle_remove_category_urls(self, param): parent_urls_to_remove = [item.strip() for item in retaining_parent_category_url.split(',') if item.strip()] ret_val, response = self._remove_from_category(urls_to_remove, parent_urls_to_remove, category_details, category_id, action_result) - + if phantom.is_fail(ret_val): return action_result.get_status() @@ -1143,6 +1141,8 @@ def _handle_remove_category_urls(self, param): summary = action_result.update_summary({}) summary['message'] = "Category urls removed" + return action_result.set_status(phantom.APP_SUCCESS) + def _handle_create_destination_group(self, param): """ This action is used to create an IP Destination Group @@ -1168,7 +1168,7 @@ def _handle_create_destination_group(self, param): data["addresses"] = [item.strip() for item in addresses.split(',')] data["description"] = param.get("description", "") if ip_categories: - data["ip_categories"] = [item.strip() for item in ip_categories.split(',')] + data["ipCategories"] = [item.strip() for item in ip_categories.split(',')] if countries: data["countries"] = [item.strip() for item in countries.split(',')] @@ -1310,16 +1310,16 @@ def _handle_edit_destination_group(self, param): if param.get("name"): group_resp["name"] = param["name"] if param.get('addresses'): - addresses = param["addresses"] - group_resp["addresses"] = [item.strip() for item in addresses.split(',') if item.strip()] + new_addresses = [item.strip() for item in param["addresses"].split(',') if item.strip()] + group_resp["addresses"] = new_addresses if param.get("description"): group_resp["description"] = param["description"] if param.get("ip_categories"): - ip_categories = param["ip_categories"] - group_resp["ip_categories"] = [item.strip() for item in ip_categories.split(',') if item.strip()] + new_ip_categories = [item.strip() for item in param["ip_categories"].split(',') if item.strip()] + group_resp["ipCategories"] = new_ip_categories if param.get("countries"): - countries = param["countries"] - group_resp["countries"] = [item.strip() for item in countries.split(',') if item.strip()] + new_countries = [item.strip() for item in param["countries"].split(',') if item.strip()] + group_resp["countries"] = new_countries group_resp["isNonEditable"] = param["is_non_editable"] ret_val, response = self._make_rest_call_helper(f'/api/v1/ipDestinationGroups/{group_id}', action_result, data=group_resp, method='put') From 741403e43e3bf1af569e74e98638292b72c6039a Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 12 Aug 2024 18:35:13 +0000 Subject: [PATCH 21/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f53d1f..63491f0 100644 --- a/README.md +++ b/README.md @@ -792,7 +792,7 @@ action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group summary.message | string | | summary.total_objects | numeric | | 1 -summary.total_objects_successful | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'add category url' Add urls to a cetgory From 6dd48ece34499fc2071af6370bd17950f5067a8a Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 12 Aug 2024 11:40:22 -0700 Subject: [PATCH 22/53] PAPP-34457: liniting changes --- zscaler_connector.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index 967793b..87a7dba 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1013,10 +1013,10 @@ def _handle_update_user(self, param): ) ret_val, response = self._make_rest_call_helper(f'/api/v1/users/{user_id}', action_result, data=data, method='put') - + if phantom.is_fail(ret_val): return action_result.get_status() - + self.debug_print(response) action_result.add_data(response) summary = action_result.update_summary({}) @@ -1446,7 +1446,7 @@ def handle_action(self, param): elif action_id == "update_user": ret_val = self._handle_update_user(param) - + elif action_id == 'add_category_url': ret_val = self._handle_add_category_url(param) From 8484f703221248f55534e618ee7752061ac9618f Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 12 Aug 2024 19:29:14 +0000 Subject: [PATCH 23/53] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4674e26..345fc17 100644 --- a/README.md +++ b/README.md @@ -802,7 +802,7 @@ action_result.data.\*.blacklistUrl | string | | action_result.summary.message | string | | Blacklist retrieved action_result.summary.total_blacklist_items | numeric | | 10 summary.total_objects | numeric | | 1 -summary.total_objects_successful | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'update user' Update user with given id From bee09927913f56c37328095b2a2147a9ddad4894 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Mon, 12 Aug 2024 14:32:05 -0700 Subject: [PATCH 24/53] PAPP-34457: linitng changes --- zscaler_connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index 6a5a4a3..02cec49 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1321,7 +1321,7 @@ def _handle_list_destination_group(self, param): """ self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - + ip_group_ids = param.get("ip_group_ids", "") ip_ids_lst = [item.strip() for item in ip_group_ids.split(',') if item.strip()] exclude_type = param.get("exclude_type", "") From 0c9cae5ef2da7cb7d428c9df2a216ea4d5040ad0 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Wed, 14 Aug 2024 11:28:23 -0700 Subject: [PATCH 25/53] PAPP-34457: adding get departments action and fromatting table output --- zscaler.json | 404 ++++++++++++++++++++++++++++++------------- zscaler_connector.py | 39 ++++- 2 files changed, 323 insertions(+), 120 deletions(-) diff --git a/zscaler.json b/zscaler.json index f14b789..06ee6d4 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3038,7 +3038,8 @@ }, { "data_path": "action_result.data.*.whitelistUrl", - "data_type": "string" + "data_type": "string", + "column_order": 0 }, { "data_path": "action_result.summary.total_whitelist_items", @@ -3117,8 +3118,7 @@ "column_name": "Query", "example_values": [ "8...8" - ], - "column_order": 1 + ] }, { "data_path": "action_result.parameter.filter", @@ -3127,12 +3127,12 @@ "value_list": [ "url", "ip" - ], - "column_order": 0 + ] }, { "data_path": "action_result.data.*.blacklistUrl", - "data_type": "string" + "data_type": "string", + "column_order": 0 }, { "data_path": "action_result.summary.message", @@ -3201,7 +3201,6 @@ "data_path": "action_result.status", "data_type": "string", "column_name": "Status", - "column_order": 2, "example_values": [ "test success", "test failed" @@ -3210,8 +3209,7 @@ { "data_path": "action_result.parameter.user", "data_type": "string", - "column_name": "User", - "column_order": 1 + "column_name": "User" }, { "data_path": "action_result.parameter.user_id", @@ -3220,7 +3218,6 @@ "zscaler user id" ], "column_name": "User ID", - "column_order": 0, "example_values": [ 889814 ] @@ -3231,14 +3228,16 @@ "example_values": [ true, false - ] + ], + "column_order": 9 }, { "data_path": "action_result.data.*.comments", "data_type": "string", "example_values": [ "test This is test user" - ] + ], + "column_order": 8 }, { "data_path": "action_result.data.*.deleted", @@ -3246,21 +3245,24 @@ "example_values": [ true, false - ] + ], + "column_order": 7 }, { "data_path": "action_result.data.*.department.id", "data_type": "numeric", "example_values": [ 81896690 - ] + ], + "column_order": 6 }, { "data_path": "action_result.data.*.department.name", "data_type": "string", "example_values": [ "test IT" - ] + ], + "column_order": 5 }, { "data_path": "action_result.data.*.email", @@ -3272,7 +3274,7 @@ "test first.last@domain.com" ], "column_name": "User Email", - "column_order": 2 + "column_order": 4 }, { "data_path": "action_result.data.*.groups.*.id", @@ -3293,7 +3295,7 @@ "test Super Admin" ], "column_name": "Group Name", - "column_order": 4 + "column_order": 2 }, { "data_path": "action_result.data.*.id", @@ -3414,67 +3416,83 @@ }, { "data_path": "action_result.data.*.id", - "data_type": "string" + "data_type": "string", + "column_order": 0 }, { "data_path": "action_result.data.*.val", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 1 }, { "data_path": "action_result.data.*.type", - "data_type": "string" + "data_type": "string", + "column_order": 2 }, { "data_path": "action_result.data.*.urls", - "data_type": "string" + "data_type": "string", + "column_order": 3 }, { "data_path": "action_result.data.*.scopes.*.Type", - "data_type": "string" + "data_type": "string", + "column_order": 4 }, { "data_path": "action_result.data.*.editable", - "data_type": "boolean" + "data_type": "boolean", + "column_order": 5 }, { "data_path": "action_result.data.*.keywords", - "data_type": "string" + "data_type": "string", + "column_order": 6 }, { "data_path": "action_result.data.*.description", - "data_type": "string" + "data_type": "string", + "column_order": 7 }, { "data_path": "action_result.data.*.configuredName", - "data_type": "string" + "data_type": "string", + "column_order": 8 }, { "data_path": "action_result.data.*.customCategory", - "data_type": "boolean" + "data_type": "boolean", + "column_order": 9 }, { "data_path": "action_result.data.*.customUrlsCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 10 }, { "data_path": "action_result.data.*.dbCategorizedUrls", - "data_type": "string" + "data_type": "string", + "column_order": 11 }, { "data_path": "action_result.data.*.customIpRangesCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 12 }, { "data_path": "action_result.data.*.keywordsRetainingParentCategory", - "data_type": "string" + "data_type": "string", + "column_order": 13 }, { "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 14 }, { "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 15 }, { "data_path": "action_result.message", @@ -3563,67 +3581,83 @@ }, { "data_path": "action_result.data.*.id", - "data_type": "string" + "data_type": "string", + "column_order": 0 }, { "data_path": "action_result.data.*.val", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 1 }, { "data_path": "action_result.data.*.type", - "data_type": "string" + "data_type": "string", + "column_order": 2 }, { "data_path": "action_result.data.*.urls", - "data_type": "string" + "data_type": "string", + "column_order": 3 }, { "data_path": "action_result.data.*.scopes.*.Type", - "data_type": "string" + "data_type": "string", + "column_order": 4 }, { "data_path": "action_result.data.*.editable", - "data_type": "boolean" + "data_type": "boolean", + "column_order": 5 }, { "data_path": "action_result.data.*.keywords", - "data_type": "string" + "data_type": "string", + "column_order": 6 }, { "data_path": "action_result.data.*.description", - "data_type": "string" + "data_type": "string", + "column_order": 7 }, { "data_path": "action_result.data.*.configuredName", - "data_type": "string" + "data_type": "string", + "column_order": 8 }, { "data_path": "action_result.data.*.customCategory", - "data_type": "boolean" + "data_type": "boolean", + "column_order": 9 }, { "data_path": "action_result.data.*.customUrlsCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 10 }, { "data_path": "action_result.data.*.dbCategorizedUrls", - "data_type": "string" + "data_type": "string", + "column_order": 11 }, { "data_path": "action_result.data.*.customIpRangesCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 12 }, { "data_path": "action_result.data.*.keywordsRetainingParentCategory", - "data_type": "string" + "data_type": "string", + "column_order": 13 }, { "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 14 }, { "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 15 }, { "data_path": "action_result.message", @@ -3693,7 +3727,8 @@ "example_values": [ "success", "failed" - ] + ], + "column_order": 0 }, { "data_path": "action_result.parameter.category_id", @@ -3842,7 +3877,8 @@ "example_values": [ "success", "failed" - ] + ], + "column_order": 0 }, { "data_path": "action_result.parameter.category_id", @@ -4016,46 +4052,42 @@ { "data_path": "action_result.parameter.countries", "data_type": "string", - "column_name": "Countries", - "column_order": 5 + "column_name": "Countries" }, { "data_path": "action_result.parameter.ip_categories", "data_type": "string", - "column_name": "Ip Categories", - "column_order": 4 + "column_name": "Ip Categories" }, { "data_path": "action_result.parameter.description", "data_type": "string", - "column_name": "Description", - "column_order": 3 + "column_name": "Description" }, { "data_path": "action_result.parameter.addresses", "data_type": "string", - "column_name": "Addresses", - "column_order": 2 + "column_name": "Addresses" }, { "data_path": "action_result.parameter.type", "data_type": "string", - "column_name": "Type", - "column_order": 1 + "column_name": "Type" }, { "data_path": "action_result.parameter.name", "data_type": "string", - "column_name": "Name", - "column_order": 0 + "column_name": "Name" }, { "data_path": "action_result.data.*.id", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 0 }, { "data_path": "action_result.data.*.name", - "data_type": "string" + "data_type": "string", + "column_order": 1 }, { "data_path": "action_result.data.*.type", @@ -4065,29 +4097,39 @@ "DSTN_FQDN", "DSTN_DOMAIN", "DSTN_OTHER" - ] + ], + "column_order": 2 }, { "data_path": "action_result.data.*.addresses", "data_type": "string", "example_values": [ "192.168.1.1" - ] + ], + "column_order": 3 }, { "data_path": "action_result.data.*.countries", - "data_type": "string" + "data_type": "string", + "column_order": 4 }, { "data_path": "action_result.data.*.description", - "data_type": "string" + "data_type": "string", + "column_order": 5 }, { "data_path": "action_result.data.*.ipCategories", "data_type": "string", "example_values": [ "TRADING_BROKARAGE_INSURANCE" - ] + ], + "column_order": 6 + }, + { + "data_path": "action_result.data.*.creatorContext", + "data_type": "string", + "column_order": 7 }, { "data_path": "action_result.summary", @@ -4199,7 +4241,6 @@ "data_path": "action_result.status", "data_type": "string", "column_name": "Status", - "column_order": 2, "example_values": [ "test success", "test failed" @@ -4208,46 +4249,42 @@ { "data_path": "action_result.parameter.lite", "data_type": "boolean", - "column_name": "Lite", - "column_order": 5 + "column_name": "Lite" }, { "data_path": "action_result.parameter.limit", "data_type": "numeric", - "column_name": "Limit", - "column_order": 4 + "column_name": "Limit" }, { "data_path": "action_result.parameter.include_ipv6", "data_type": "boolean", - "column_name": "Include Ipv6", - "column_order": 3 + "column_name": "Include Ipv6" }, { "data_path": "action_result.parameter.category_type", "data_type": "string", - "column_name": "Category Type", - "column_order": 2 + "column_name": "Category Type" }, { "data_path": "action_result.parameter.exclude_type", "data_type": "string", - "column_name": "Exclude Type", - "column_order": 1 + "column_name": "Exclude Type" }, { "data_path": "action_result.parameter.ip_group_id", "data_type": "string", - "column_name": "Ip Group ID", - "column_order": 0 + "column_name": "Ip Group ID" }, { "data_path": "action_result.data.*.id", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 0 }, { "data_path": "action_result.data.*.name", - "data_type": "string" + "data_type": "string", + "column_order": 1 }, { "data_path": "action_result.data.*.type", @@ -4257,29 +4294,39 @@ "DSTN_FQDN", "DSTN_DOMAIN", "DSTN_OTHER" - ] + ], + "column_order": 2 }, { "data_path": "action_result.data.*.addresses", "data_type": "string", "example_values": [ "192.168.1.1" - ] + ], + "column_order": 3 }, { "data_path": "action_result.data.*.countries", - "data_type": "string" + "data_type": "string", + "column_order": 4 }, { "data_path": "action_result.data.*.description", - "data_type": "string" + "data_type": "string", + "column_order": 5 }, { "data_path": "action_result.data.*.ipCategories", "data_type": "string", "example_values": [ "TRADING_BROKARAGE_INSURANCE" - ] + ], + "column_order": 6 + }, + { + "data_path": "action_result.data.*.creatorContext", + "data_type": "string", + "column_order": 7 }, { "data_path": "action_result.summary", @@ -4388,52 +4435,48 @@ { "data_path": "action_result.parameter.is_non_editable", "data_type": "boolean", - "column_name": "Is Non Editab;e", - "column_order": 6 + "column_name": "Is Non Editable" }, { "data_path": "action_result.parameter.countries", "data_type": "string", - "column_name": "Countries", - "column_order": 5 + "column_name": "Countries" }, { "data_path": "action_result.parameter.ip_categories", "data_type": "string", - "column_name": "Ip Categories", - "column_order": 4 + "column_name": "Ip Categories" }, { "data_path": "action_result.parameter.description", "data_type": "string", - "column_name": "Description", - "column_order": 3 + "column_name": "Description" }, { "data_path": "action_result.parameter.addresses", "data_type": "string", - "column_name": "Addresses", - "column_order": 2 + "column_name": "Addresses" }, { "data_path": "action_result.parameter.name", "data_type": "string", - "column_name": "Name", - "column_order": 1 + "column_name": "Name" }, { "data_path": "action_result.parameter.ip_group_id", "data_type": "numeric", - "column_name": "IP Group Id", - "column_order": 1 + "column_name": "IP Group Id" + }, { "data_path": "action_result.data.*.id", - "data_type": "numeric" + "data_type": "numeric", + "column_order": 0 }, { "data_path": "action_result.data.*.name", - "data_type": "string" + "data_type": "string", + "column_order": 1 }, { "data_path": "action_result.data.*.type", @@ -4443,33 +4486,39 @@ "DSTN_FQDN", "DSTN_DOMAIN", "DSTN_OTHER" - ] + ], + "column_order": 2 }, { "data_path": "action_result.data.*.addresses", "data_type": "string", "example_values": [ "192.168.1.1" - ] + ], + "column_order": 3 }, { "data_path": "action_result.data.*.countries", - "data_type": "string" + "data_type": "string", + "column_order": 4 }, { "data_path": "action_result.data.*.description", - "data_type": "string" + "data_type": "string", + "column_order": 5 }, { "data_path": "action_result.data.*.ipCategories", "data_type": "string", "example_values": [ "TRADING_BROKARAGE_INSURANCE" - ] + ], + "column_order": 6 }, { "data_path": "action_result.data.*.creatorContext", - "data_type": "string" + "data_type": "string", + "column_order": 7 }, { "data_path": "action_result.summary", @@ -4479,14 +4528,14 @@ "data_path": "action_result.summary.message", "data_type": "string", "example_values": [ - "test User removed from group" + "Destination group edited" ] }, { "data_path": "action_result.message", "data_type": "string", "example_values": [ - "test User removed from group" + "Destination group edited" ] }, { @@ -4532,7 +4581,7 @@ "data_path": "action_result.status", "data_type": "string", "column_name": "Status", - "column_order": 2, + "column_order": 0, "example_values": [ "test success", "test failed" @@ -4541,8 +4590,7 @@ { "data_path": "action_result.parameter.ip_group_ids", "data_type": "string", - "column_name": "IP Group Ids", - "column_order": 0 + "column_name": "IP Group Ids" }, { "data_path": "action_result.data.*.ip_group_ids", @@ -4556,14 +4604,132 @@ "data_path": "action_result.summary.message", "data_type": "string", "example_values": [ - "test User removed from group" + "Destination group deleted" ] }, { "data_path": "action_result.message", "data_type": "string", "example_values": [ - "test User removed from group" + "Destination group deleted" + ] + }, + { + "data_path": "summary.message", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "get departments", + "identifier": "get_departments", + "description": "Get a list of departments", + "type": "investigate", + "read_only": true, + "parameters": { + "name": { + "description": "Filter by department name", + "data_type": "string", + "primary": true, + "order": 0 + }, + "page": { + "description": "Specifies the page offset", + "data_type": "numeric", + "primary": true, + "order": 1 + }, + "pageSize": { + "description": "Specifies the page size", + "default": 100, + "data_type": "numeric", + "primary": true, + "order": 2 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "column_name": "Status", + "column_order": 2, + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.pageSize", + "data_type": "string", + "column_name": "Page Size" + }, + { + "data_path": "action_result.parameter.page", + "data_type": "string", + "column_name": "Page" + }, + { + "data_path": "action_result.parameter.name", + "data_type": "string", + "column_name": "Name" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "numeric", + "column_order": 0 + + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.isNonEditable", + "data_type": "boolean", + "column_order": 2 + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "Departments Retrieved" + ] + }, + { + "data_path": "action_result.summary.total_deparments", + "data_type": "numeric", + "example_values": [ + 97 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Departments Retrieved" ] }, { diff --git a/zscaler_connector.py b/zscaler_connector.py index 02cec49..d176a30 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1058,7 +1058,7 @@ def _handle_get_blacklist(self, param): summary['total_blacklist_items'] = action_result.get_data_size() return action_result.set_status(phantom.APP_SUCCESS) - + def _handle_update_user(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) @@ -1437,6 +1437,40 @@ def _handle_delete_destination_group(self, param): summary = action_result.update_summary({}) summary['message'] = "Destination groups deleted" return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_get_departments(self, param): + """ + This action is used to get departments + :param name: Filter by department name + :param page: Specifies the page offset + :param pageSize: Specifies the page size. Defaul is 100 + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + name = param.get("name") + page_size = param.get("pageSize") + page_num = param.get("page", 1) + + endpoint = f"/api/v1/departments?page={page_num}&pageSize={page_size}" + + if name: + endpoint = f"/api/v1/departments?page={page_num}&pageSize={page_size}&search={name}&limitSearch=true" + + ret_val, response = self._make_rest_call_helper(endpoint, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + for department in response: + action_result.add_data(department) + + summary = action_result.update_summary({}) + summary['message'] = "Departments retrieved" + summary['total_deparments'] = action_result.get_data_size() + return action_result.set_status(phantom.APP_SUCCESS) + def handle_action(self, param): @@ -1537,6 +1571,9 @@ def handle_action(self, param): elif action_id == 'delete_destination_group': ret_val = self._handle_delete_destination_group(param) + elif action_id == 'get_departments': + ret_val = self._handle_get_departments(param) + return ret_val def initialize(self): From 60360bfd41b199d2a84f5f5989c9987cd70c7ddd Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Wed, 14 Aug 2024 18:29:22 +0000 Subject: [PATCH 26/53] Update README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 345fc17..5bc37cc 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [list destination group](#action-list-destination-group) - List destination group [edit destination group](#action-edit-destination-group) - Edit destination group [delete destination group](#action-delete-destination-group) - Delete destination group +[get departments](#action-get-departments) - Get a list of departments ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -1036,6 +1037,7 @@ action_result.data.\*.addresses | string | | 192.168.1.1 action_result.data.\*.countries | string | | action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.creatorContext | string | | action_result.summary | string | | action_result.summary.message | string | | test User removed from group action_result.message | string | | test User removed from group @@ -1076,6 +1078,7 @@ action_result.data.\*.addresses | string | | 192.168.1.1 action_result.data.\*.countries | string | | action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.creatorContext | string | | action_result.summary | string | | action_result.summary.message | string | | Retreived Destination Groups action_result.message | string | | Retreived Destination Groups @@ -1120,8 +1123,8 @@ action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE action_result.data.\*.creatorContext | string | | action_result.summary | string | | -action_result.summary.message | string | | test User removed from group -action_result.message | string | | test User removed from group +action_result.summary.message | string | | Destination group edited +action_result.message | string | | Destination group edited summary.message | string | | summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 @@ -1144,8 +1147,39 @@ action_result.status | string | | test success test failed action_result.parameter.ip_group_ids | string | | action_result.data.\*.ip_group_ids | string | | action_result.summary | string | | -action_result.summary.message | string | | test User removed from group -action_result.message | string | | test User removed from group +action_result.summary.message | string | | Destination group deleted +action_result.message | string | | Destination group deleted +summary.message | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get departments' +Get a list of departments + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**name** | optional | Filter by department name | string | +**page** | optional | Specifies the page offset | numeric | +**pageSize** | optional | Specifies the page size | numeric | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.pageSize | string | | +action_result.parameter.page | string | | +action_result.parameter.name | string | | +action_result.data.\*.id | numeric | | +action_result.data.\*.name | string | | +action_result.data.\*.isNonEditable | boolean | | +action_result.summary | string | | +action_result.summary.message | string | | Departments Retrieved +action_result.summary.total_deparments | numeric | | 97 +action_result.message | string | | Departments Retrieved summary.message | string | | summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From 8504654addfa6112f2d94d1de9c22be4fbeb785b Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Thu, 15 Aug 2024 14:00:06 -0700 Subject: [PATCH 27/53] PAPP-34457: using gets to access params --- zscaler_connector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index d176a30..cfaeb25 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -739,7 +739,7 @@ def _handle_list_url_categories(self, param): if phantom.is_fail(ret_val): return action_result.get_status() - get_ids_and_names_only = param["get_ids_and_names_only"] + get_ids_and_names_only = param.get("get_ids_and_names_only", False) for url_category in list_url_categories: if get_ids_and_names_only: @@ -1404,7 +1404,7 @@ def _handle_edit_destination_group(self, param): if param.get("countries"): new_countries = [item.strip() for item in param["countries"].split(',') if item.strip()] group_resp["countries"] = new_countries - group_resp["isNonEditable"] = param["is_non_editable"] + group_resp["isNonEditable"] = param.get("is_non_editable", False) ret_val, response = self._make_rest_call_helper(f'/api/v1/ipDestinationGroups/{group_id}', action_result, data=group_resp, method='put') if phantom.is_fail(ret_val): From c4cef616b33d993453df09f1b758728a8edd3343 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Thu, 15 Aug 2024 18:05:18 -0700 Subject: [PATCH 28/53] PAPP-34457: logic change to edit destination group --- zscaler_connector.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index cfaeb25..92348d4 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1390,14 +1390,11 @@ def _handle_edit_destination_group(self, param): ret_val, group_resp = self._get_destination_group(group_id, action_result) if phantom.is_fail(ret_val): return action_result.get_status() - self.debug_print("handle edit response {0}".format(group_resp)) - if param.get("name"): - group_resp["name"] = param["name"] + group_resp["name"] = param.get("name", group_resp["name"]) if param.get('addresses'): new_addresses = [item.strip() for item in param["addresses"].split(',') if item.strip()] group_resp["addresses"] = new_addresses - if param.get("description"): - group_resp["description"] = param["description"] + group_resp["description"] = param.get("description", group_resp["description"]) if param.get("ip_categories"): new_ip_categories = [item.strip() for item in param["ip_categories"].split(',') if item.strip()] group_resp["ipCategories"] = new_ip_categories From a8e996c9619c027295e7ff2559ac21eead45d337 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Fri, 16 Aug 2024 10:59:04 -0700 Subject: [PATCH 29/53] PAPP-34457: adding column names --- zscaler.json | 116 +++++++++++++++++++++++++++++++++++++++---- zscaler_connector.py | 8 +-- 2 files changed, 111 insertions(+), 13 deletions(-) diff --git a/zscaler.json b/zscaler.json index 06ee6d4..df78356 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3037,8 +3037,9 @@ ] }, { - "data_path": "action_result.data.*.whitelistUrl", + "data_path": "action_result.data.*.url", "data_type": "string", + "column_name": "whitelist url", "column_order": 0 }, { @@ -3071,7 +3072,7 @@ } ], "render": { - "title": "List URL Categories", + "title": "Whitelist", "type": "table" }, "versions": "EQ(*)" @@ -3130,8 +3131,9 @@ ] }, { - "data_path": "action_result.data.*.blacklistUrl", + "data_path": "action_result.data.*.url", "data_type": "string", + "column_name": "blacklist url", "column_order": 0 }, { @@ -3164,7 +3166,7 @@ } ], "render": { - "title": "List URL Categories", + "title": "Blacklist", "type": "table" }, "versions": "EQ(*)" @@ -3229,6 +3231,7 @@ true, false ], + "column_name": "Is Admin User", "column_order": 9 }, { @@ -3237,6 +3240,7 @@ "example_values": [ "test This is test user" ], + "column_name": "Comments", "column_order": 8 }, { @@ -3246,6 +3250,7 @@ true, false ], + "column_name": "Is Deleted", "column_order": 7 }, { @@ -3254,6 +3259,7 @@ "example_values": [ 81896690 ], + "column_name": "Department ID", "column_order": 6 }, { @@ -3262,6 +3268,7 @@ "example_values": [ "test IT" ], + "column_name": "Department name", "column_order": 5 }, { @@ -3417,81 +3424,97 @@ { "data_path": "action_result.data.*.id", "data_type": "string", + "column_name": "URL category", "column_order": 0 }, { "data_path": "action_result.data.*.val", "data_type": "numeric", + "column_name": "Value", "column_order": 1 }, { "data_path": "action_result.data.*.type", "data_type": "string", + "column_name": "Category type", "column_order": 2 }, { "data_path": "action_result.data.*.urls", "data_type": "string", + "column_name": "URLs added", "column_order": 3 }, { "data_path": "action_result.data.*.scopes.*.Type", "data_type": "string", + "column_name": "Category scope", "column_order": 4 }, { "data_path": "action_result.data.*.editable", "data_type": "boolean", + "column_name": "Is editable", "column_order": 5 }, { "data_path": "action_result.data.*.keywords", "data_type": "string", + "date_type": "Category keywords", "column_order": 6 }, { "data_path": "action_result.data.*.description", "data_type": "string", + "column_name": "Category description", "column_order": 7 }, { "data_path": "action_result.data.*.configuredName", "data_type": "string", + "column_name": "Configured Name", "column_order": 8 }, { "data_path": "action_result.data.*.customCategory", "data_type": "boolean", + "column_name": "Is Custom Category", "column_order": 9 }, { "data_path": "action_result.data.*.customUrlsCount", "data_type": "numeric", + "column_name": "Custom url count", "column_order": 10 }, { "data_path": "action_result.data.*.dbCategorizedUrls", "data_type": "string", + "column_name": "Parent urls", "column_order": 11 }, { "data_path": "action_result.data.*.customIpRangesCount", "data_type": "numeric", + "column_name": "Custom ip ranges count", "column_order": 12 }, { "data_path": "action_result.data.*.keywordsRetainingParentCategory", "data_type": "string", + "column_name": "Parent url keywords", "column_order": 13 }, { "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", "data_type": "numeric", + "column_name": "Number of parent urls", "column_order": 14 }, { "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", "data_type": "numeric", + "column_name": "Number of parent ips", "column_order": 15 }, { @@ -3582,81 +3605,97 @@ { "data_path": "action_result.data.*.id", "data_type": "string", + "column_name": "URL category", "column_order": 0 }, { "data_path": "action_result.data.*.val", "data_type": "numeric", + "column_name": "Value", "column_order": 1 }, { "data_path": "action_result.data.*.type", "data_type": "string", + "column_name": "Category type", "column_order": 2 }, { "data_path": "action_result.data.*.urls", "data_type": "string", + "column_name": "URLs added", "column_order": 3 }, { "data_path": "action_result.data.*.scopes.*.Type", "data_type": "string", + "column_name": "Category scope", "column_order": 4 }, { "data_path": "action_result.data.*.editable", "data_type": "boolean", + "column_name": "Is editable", "column_order": 5 }, { "data_path": "action_result.data.*.keywords", "data_type": "string", + "date_type": "Category keywords", "column_order": 6 }, { "data_path": "action_result.data.*.description", "data_type": "string", + "column_name": "Category description", "column_order": 7 }, { "data_path": "action_result.data.*.configuredName", "data_type": "string", + "column_name": "Configured Name", "column_order": 8 }, { "data_path": "action_result.data.*.customCategory", "data_type": "boolean", + "column_name": "Is Custom Category", "column_order": 9 }, { "data_path": "action_result.data.*.customUrlsCount", "data_type": "numeric", + "column_name": "Custom url count", "column_order": 10 }, { "data_path": "action_result.data.*.dbCategorizedUrls", "data_type": "string", + "column_name": "Parent urls", "column_order": 11 }, { "data_path": "action_result.data.*.customIpRangesCount", "data_type": "numeric", + "column_name": "Custom ip ranges count", "column_order": 12 }, { "data_path": "action_result.data.*.keywordsRetainingParentCategory", "data_type": "string", + "column_name": "Parent url keywords", "column_order": 13 }, { "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", "data_type": "numeric", + "column_name": "Number of parent urls", "column_order": 14 }, { "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", "data_type": "numeric", + "column_name": "Number of parent ips", "column_order": 15 }, { @@ -3728,7 +3767,8 @@ "success", "failed" ], - "column_order": 0 + "column_order": 0, + "column_name": "Status" }, { "data_path": "action_result.parameter.category_id", @@ -3878,7 +3918,8 @@ "success", "failed" ], - "column_order": 0 + "column_order": 0, + "column_name": "Status" }, { "data_path": "action_result.parameter.category_id", @@ -4082,11 +4123,13 @@ { "data_path": "action_result.data.*.id", "data_type": "numeric", + "column_name": "Group ID", "column_order": 0 }, { "data_path": "action_result.data.*.name", "data_type": "string", + "column_name": "Group name", "column_order": 1 }, { @@ -4098,6 +4141,7 @@ "DSTN_DOMAIN", "DSTN_OTHER" ], + "column_name": "Group type", "column_order": 2 }, { @@ -4106,16 +4150,19 @@ "example_values": [ "192.168.1.1" ], + "column_name": "Destination addresses", "column_order": 3 }, { "data_path": "action_result.data.*.countries", "data_type": "string", + "column_name": "Destination countries", "column_order": 4 }, { "data_path": "action_result.data.*.description", "data_type": "string", + "column_name": "Description", "column_order": 5 }, { @@ -4124,12 +4171,24 @@ "example_values": [ "TRADING_BROKARAGE_INSURANCE" ], + "column_name": "Destination categories", "column_order": 6 }, + { + "data_path": "action_result.data.*.isNonEditable", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "column_name": "Is editable", + "column_order": 7 + }, { "data_path": "action_result.data.*.creatorContext", "data_type": "string", - "column_order": 7 + "column_name": "Creator Context", + "column_order": 8 }, { "data_path": "action_result.summary", @@ -4279,11 +4338,13 @@ { "data_path": "action_result.data.*.id", "data_type": "numeric", + "column_name": "Group ID", "column_order": 0 }, { "data_path": "action_result.data.*.name", "data_type": "string", + "column_name": "Group name", "column_order": 1 }, { @@ -4295,6 +4356,7 @@ "DSTN_DOMAIN", "DSTN_OTHER" ], + "column_name": "Group type", "column_order": 2 }, { @@ -4303,16 +4365,19 @@ "example_values": [ "192.168.1.1" ], + "column_name": "Destination addresses", "column_order": 3 }, { "data_path": "action_result.data.*.countries", "data_type": "string", + "column_name": "Destination countries", "column_order": 4 }, { "data_path": "action_result.data.*.description", "data_type": "string", + "column_name": "Description", "column_order": 5 }, { @@ -4321,12 +4386,24 @@ "example_values": [ "TRADING_BROKARAGE_INSURANCE" ], + "column_name": "Destination categories", "column_order": 6 }, + { + "data_path": "action_result.data.*.isNonEditable", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "column_name": "Is editable", + "column_order": 7 + }, { "data_path": "action_result.data.*.creatorContext", "data_type": "string", - "column_order": 7 + "column_name": "Creator Context", + "column_order": 8 }, { "data_path": "action_result.summary", @@ -4471,11 +4548,13 @@ { "data_path": "action_result.data.*.id", "data_type": "numeric", + "column_name": "Group ID", "column_order": 0 }, { "data_path": "action_result.data.*.name", "data_type": "string", + "column_name": "Group name", "column_order": 1 }, { @@ -4487,6 +4566,7 @@ "DSTN_DOMAIN", "DSTN_OTHER" ], + "column_name": "Group type", "column_order": 2 }, { @@ -4495,16 +4575,19 @@ "example_values": [ "192.168.1.1" ], + "column_name": "Destination addresses", "column_order": 3 }, { "data_path": "action_result.data.*.countries", "data_type": "string", + "column_name": "Destination countries", "column_order": 4 }, { "data_path": "action_result.data.*.description", "data_type": "string", + "column_name": "Description", "column_order": 5 }, { @@ -4513,12 +4596,24 @@ "example_values": [ "TRADING_BROKARAGE_INSURANCE" ], + "column_name": "Destination categories", "column_order": 6 }, + { + "data_path": "action_result.data.*.isNonEditable", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "column_name": "Is editable", + "column_order": 7 + }, { "data_path": "action_result.data.*.creatorContext", "data_type": "string", - "column_order": 7 + "column_name": "Creator Context", + "column_order": 8 }, { "data_path": "action_result.summary", @@ -4694,17 +4789,20 @@ { "data_path": "action_result.data.*.id", "data_type": "numeric", + "column_name": "Department Id", "column_order": 0 }, { "data_path": "action_result.data.*.name", "data_type": "string", + "column_name": "Department Name", "column_order": 1 }, { "data_path": "action_result.data.*.isNonEditable", "data_type": "boolean", + "column_name": "Is editable", "column_order": 2 }, { diff --git a/zscaler_connector.py b/zscaler_connector.py index 92348d4..1e02a8c 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1013,7 +1013,7 @@ def _handle_get_whitelist(self, param): whitelist = response.get('whitelistUrls', []) for allowed in whitelist: - action_result.add_data(allowed) + action_result.add_data({"url": allowed}) summary = action_result.update_summary({}) summary['total_whitelist_items'] = action_result.get_data_size() summary['message'] = "Whitelist retrieved" @@ -1054,7 +1054,7 @@ def _handle_get_blacklist(self, param): continue if query and not re.fullmatch(query, blocked): continue - action_result.add_data(blocked) + action_result.add_data({"url": blocked}) summary['total_blacklist_items'] = action_result.get_data_size() return action_result.set_status(phantom.APP_SUCCESS) @@ -1262,7 +1262,7 @@ def _handle_create_destination_group(self, param): action_result.add_data(response) summary = action_result.update_summary({}) - summary['message'] = "Destination IP added" + summary['message'] = "Destination Group Created" return action_result.set_status(phantom.APP_SUCCESS) @@ -1409,7 +1409,7 @@ def _handle_edit_destination_group(self, param): action_result.add_data(response) summary = action_result.update_summary({}) - summary['message'] = "Destination IP edited" + summary['message'] = "Destination Group Edited" return action_result.set_status(phantom.APP_SUCCESS) From 10a3d1265fbda272505eebc102aa7cc90ba8c71d Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Fri, 16 Aug 2024 17:59:53 +0000 Subject: [PATCH 30/53] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5bc37cc..c80069e 100644 --- a/README.md +++ b/README.md @@ -775,7 +775,7 @@ No parameters are required for this action DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | test success test failed -action_result.data.\*.whitelistUrl | string | | +action_result.data.\*.url | string | | action_result.summary.total_whitelist_items | numeric | | 10 action_result.summary.message | string | | Whitelist retrieved summary.total_objects | numeric | | 1 @@ -799,7 +799,7 @@ DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES action_result.status | string | | test success test failed action_result.parameter.query | string | | 8...8 action_result.parameter.filter | string | | -action_result.data.\*.blacklistUrl | string | | +action_result.data.\*.url | string | | action_result.summary.message | string | | Blacklist retrieved action_result.summary.total_blacklist_items | numeric | | 10 summary.total_objects | numeric | | 1 @@ -1037,6 +1037,7 @@ action_result.data.\*.addresses | string | | 192.168.1.1 action_result.data.\*.countries | string | | action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.isNonEditable | boolean | | True False action_result.data.\*.creatorContext | string | | action_result.summary | string | | action_result.summary.message | string | | test User removed from group @@ -1078,6 +1079,7 @@ action_result.data.\*.addresses | string | | 192.168.1.1 action_result.data.\*.countries | string | | action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.isNonEditable | boolean | | True False action_result.data.\*.creatorContext | string | | action_result.summary | string | | action_result.summary.message | string | | Retreived Destination Groups @@ -1121,6 +1123,7 @@ action_result.data.\*.addresses | string | | 192.168.1.1 action_result.data.\*.countries | string | | action_result.data.\*.description | string | | action_result.data.\*.ipCategories | string | | TRADING_BROKARAGE_INSURANCE +action_result.data.\*.isNonEditable | boolean | | True False action_result.data.\*.creatorContext | string | | action_result.summary | string | | action_result.summary.message | string | | Destination group edited From abf7a2fe295fe953b9a966c9155824894cf4467e Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Fri, 16 Aug 2024 17:17:59 -0700 Subject: [PATCH 31/53] PAPP-34457: fixing flake error --- zscaler_connector.py | 54 +++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/zscaler_connector.py b/zscaler_connector.py index 1e02a8c..42a51cf 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1434,7 +1434,7 @@ def _handle_delete_destination_group(self, param): summary = action_result.update_summary({}) summary['message'] = "Destination groups deleted" return action_result.set_status(phantom.APP_SUCCESS) - + def _handle_get_departments(self, param): """ This action is used to get departments @@ -1445,29 +1445,48 @@ def _handle_get_departments(self, param): """ self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) - + name = param.get("name") page_size = param.get("pageSize") page_num = param.get("page", 1) - + endpoint = f"/api/v1/departments?page={page_num}&pageSize={page_size}" - + if name: endpoint = f"/api/v1/departments?page={page_num}&pageSize={page_size}&search={name}&limitSearch=true" - + ret_val, response = self._make_rest_call_helper(endpoint, action_result) - + if phantom.is_fail(ret_val): return action_result.get_status() - + for department in response: action_result.add_data(department) - + summary = action_result.update_summary({}) summary['message'] = "Departments retrieved" summary['total_deparments'] = action_result.get_data_size() return action_result.set_status(phantom.APP_SUCCESS) - + + def _handle_additional_actions(self, action_id, param): + ret_val = phantom.APP_SUCCESS + + if action_id == 'create_destination_group': + ret_val = self._handle_create_destination_group(param) + + elif action_id == 'list_destination_group': + ret_val = self._handle_list_destination_group(param) + + elif action_id == 'edit_destination_group': + ret_val = self._handle_edit_destination_group(param) + + elif action_id == 'delete_destination_group': + ret_val = self._handle_delete_destination_group(param) + + elif action_id == 'get_departments': + ret_val = self._handle_get_departments(param) + + return ret_val def handle_action(self, param): @@ -1556,20 +1575,9 @@ def handle_action(self, param): elif action_id == 'remove_category_ip': ret_val = self._handle_remove_category_ips(param) - elif action_id == 'create_destination_group': - ret_val = self._handle_create_destination_group(param) - - elif action_id == 'list_destination_group': - ret_val = self._handle_list_destination_group(param) - - elif action_id == 'edit_destination_group': - ret_val = self._handle_edit_destination_group(param) - - elif action_id == 'delete_destination_group': - ret_val = self._handle_delete_destination_group(param) - - elif action_id == 'get_departments': - ret_val = self._handle_get_departments(param) + else: + # passing the action handling to another function to decrease FLAKE_8 complexity + ret_val = self._handle_additional_actions(action_id, param) return ret_val From 45f301a43821969fcc102c0f236ebd458d1b8736 Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Wed, 28 Aug 2024 14:13:42 -0700 Subject: [PATCH 32/53] PAPP-34457: new get details action --- zscaler.json | 191 ++++++++++++++++++++++++++++++++++++++++++- zscaler_connector.py | 26 ++++++ 2 files changed, 215 insertions(+), 2 deletions(-) diff --git a/zscaler.json b/zscaler.json index df78356..efa2f97 100644 --- a/zscaler.json +++ b/zscaler.json @@ -3460,7 +3460,7 @@ { "data_path": "action_result.data.*.keywords", "data_type": "string", - "date_type": "Category keywords", + "column_name": "Category keywords", "column_order": 6 }, { @@ -3641,7 +3641,7 @@ { "data_path": "action_result.data.*.keywords", "data_type": "string", - "date_type": "Category keywords", + "column_name": "Category keywords", "column_order": 6 }, { @@ -4853,6 +4853,193 @@ "type": "table" }, "versions": "EQ(*)" + }, + { + "action": "get category details", + "identifier": "get_category_details", + "description": "Get the urls and keywords of a category", + "type": "investigate", + "read_only": true, + "parameters": { + "category_ids": { + "description": "Comma seperated string of category id's to query", + "data_type": "string", + "order": 0, + "example_values": [ + "CUSTOM_001, CUSTOM_002" + ], + "primary": true + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "test success", + "test failed" + ] + }, + { + "data_path": "action_result.parameter.category_ids", + "data_type": "string", + "example_values": [ + "CUSTOM_001, CUSTOM_002" + ] + }, + { + "data_path": "action_result.data.*.configuredName", + "data_type": "string", + "example_values": [ + "test Test-Caution" + ], + "column_order": 2, + "column_name": "Configured Name" + }, + { + "data_path": "action_result.data.*.customCategory", + "data_type": "boolean", + "column_name": "Is Custom Category", + "column_order": 4, + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.keywords", + "data_type": "string", + "column_order": 5, + "column_name": "Category Keywords" + }, + { + "data_path": "action_result.data.*.urls", + "data_type": "string", + "column_order": 6, + "column_name": "Category Urls" + }, + { + "data_path": "action_result.data.*.customIpRangesCount", + "data_type": "numeric", + "example_values": [ + 0 + ] + }, + { + "data_path": "action_result.data.*.customUrlsCount", + "data_type": "numeric", + "example_values": [ + 0 + ] + }, + { + "data_path": "action_result.data.*.dbCategorizedUrls", + "data_type": "string", + "example_values": [ + "test 6.5.3.2.4" + ] + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string", + "column_name": "Description", + "column_order": 3, + "example_values": [ + "test OTHER_RESTRICTED_WEBSITE_DESC" + ] + }, + { + "data_path": "action_result.data.*.editable", + "data_type": "boolean", + "column_name": "Editable", + "column_order": 7, + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "column_name": "Category ID", + "column_order": 0, + "contains": [ + "zscaler url category" + ], + "example_values": [ + "test OTHER_RESTRICTED_WEBSITE" + ] + }, + { + "data_path": "action_result.data.*.ipRangesRetainingParentCategoryCount", + "data_type": "numeric", + "example_values": [ + 0 + ] + }, + { + "data_path": "action_result.data.*.scopes.*.Type", + "data_type": "string", + "example_values": [ + "test ORGANIZATION" + ] + }, + { + "data_path": "action_result.data.*.type", + "data_type": "string", + "example_values": [ + "test URL_CATEGORY" + ], + "column_order": 1, + "column_name": "Type" + }, + { + "data_path": "action_result.data.*.urlsRetainingParentCategoryCount", + "data_type": "numeric", + "example_values": [ + 0 + ] + }, + { + "data_path": "action_result.data.*.val", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "action_result.summary.total_categories", + "data_type": "numeric", + "example_values": [ + 97 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Category details recieved" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" } ], "pip_dependencies": { diff --git a/zscaler_connector.py b/zscaler_connector.py index 42a51cf..5f752d9 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1435,6 +1435,29 @@ def _handle_delete_destination_group(self, param): summary['message'] = "Destination groups deleted" return action_result.set_status(phantom.APP_SUCCESS) + def _handle_get_category_details(self, param): + """ + This action is used to get category details of specfic categories + :param category_ids: Ids of category's to query + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + group_ids = param.get("category_ids", "") + list_category_ids = [item.strip() for item in group_ids.split(',') if item.strip()] + + for category_id in list_category_ids: + ret_val, category_details = self._get_category_details(category_id, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + action_result.add_data(category_details) + + summary = action_result.update_summary({}) + summary['message'] = "Category details recieved" + summary['total_categories'] = action_result.get_data_size() + return action_result.set_status(phantom.APP_SUCCESS) + def _handle_get_departments(self, param): """ This action is used to get departments @@ -1486,6 +1509,9 @@ def _handle_additional_actions(self, action_id, param): elif action_id == 'get_departments': ret_val = self._handle_get_departments(param) + elif action_id == 'get_category_details': + ret_val = self._handle_get_category_details(param) + return ret_val def handle_action(self, param): From a46ada55cc1f8b02dc0c922b0b3c8fd34b762bca Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Wed, 28 Aug 2024 21:14:28 +0000 Subject: [PATCH 33/53] Update README.md --- README.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/README.md b/README.md index c80069e..5623a75 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [edit destination group](#action-edit-destination-group) - Edit destination group [delete destination group](#action-delete-destination-group) - Delete destination group [get departments](#action-get-departments) - Get a list of departments +[get category details](#action-get-category-details) - Get the urls and keywords of a category ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -1185,4 +1186,40 @@ action_result.summary.total_deparments | numeric | | 97 action_result.message | string | | Departments Retrieved summary.message | string | | summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get category details' +Get the urls and keywords of a category + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**category_ids** | optional | Comma seperated string of category id's to query | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | test success test failed +action_result.parameter.category_ids | string | | CUSTOM_001, CUSTOM_002 +action_result.data.\*.configuredName | string | | test Test-Caution +action_result.data.\*.customCategory | boolean | | True False +action_result.data.\*.keywords | string | | +action_result.data.\*.urls | string | | +action_result.data.\*.customIpRangesCount | numeric | | 0 +action_result.data.\*.customUrlsCount | numeric | | 0 +action_result.data.\*.dbCategorizedUrls | string | | test 6.5.3.2.4 +action_result.data.\*.description | string | | test OTHER_RESTRICTED_WEBSITE_DESC +action_result.data.\*.editable | boolean | | True False +action_result.data.\*.id | string | `zscaler url category` | test OTHER_RESTRICTED_WEBSITE +action_result.data.\*.ipRangesRetainingParentCategoryCount | numeric | | 0 +action_result.data.\*.scopes.\*.Type | string | | test ORGANIZATION +action_result.data.\*.type | string | | test URL_CATEGORY +action_result.data.\*.urlsRetainingParentCategoryCount | numeric | | 0 +action_result.data.\*.val | numeric | | 1 +action_result.summary.total_categories | numeric | | 97 +action_result.message | string | | Category details recieved +summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 \ No newline at end of file From 0228effb3d3b5f68e5b89f392cb7201b6d39135a Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Wed, 11 Sep 2024 14:25:36 -0700 Subject: [PATCH 34/53] PAPP-34457: removing get ipv6 destination groups --- zscaler.json | 14 ++------------ zscaler_connector.py | 11 ----------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/zscaler.json b/zscaler.json index efa2f97..890c376 100644 --- a/zscaler.json +++ b/zscaler.json @@ -4268,21 +4268,11 @@ ], "order": 2 }, - "include_ipv6": { - "description": "Retrieve IPv6 destination groups", - "data_type": "boolean", - "example_values": [ - true, - false - ], - "default": false, - "order": 3 - }, "limit": { "description": "Limit of the results to be retrieved", "data_type": "numeric", "default": 50, - "order": 4 + "order": 3 }, "lite": { "description": "Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups", @@ -4292,7 +4282,7 @@ false ], "default": false, - "order": 5 + "order": 4 } }, "output": [ diff --git a/zscaler_connector.py b/zscaler_connector.py index 5f752d9..c8ea91e 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1314,7 +1314,6 @@ def _handle_list_destination_group(self, param): :param ip_group_ids: Destination groups to retrieve :param exclude_type: Group types to exclude from search :param category_type: Destination types to filter by - :param include_ipv6: Retrieve IPv6 groups :param limit: Number of groups to retrieve :param lite: Retrieve limited information for each group :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) @@ -1327,7 +1326,6 @@ def _handle_list_destination_group(self, param): exclude_type = param.get("exclude_type", "") category_type = param.get("category_type", "") category_type_list = [item.strip() for item in category_type.split(',') if item.strip()] - include_ipv6 = param.get("include_ipv6", False) limit = param.get("limit", 50) lite = param.get("lite", False) @@ -1356,15 +1354,6 @@ def _handle_list_destination_group(self, param): if phantom.is_fail(ret_val): return action_result.get_status() - if include_ipv6: - self.save_progress("Retrieving ipv6 destination groups") - params['page'] = 1 - params['pageSize'] = limit - endpoint = '/ipDestinationGroups/ipv6DestinationGroups/lite' if lite else '/ipDestinationGroups/ipv6DestinationGroups' - ret_val = self._get_batched_groups(endpoint, params, action_result) - if phantom.is_fail(ret_val): - return action_result.get_status() - # action_result.add_data(destination_groups) summary = action_result.update_summary({}) summary['message'] = "Destination groups retrieved" From ebdbf1d3cb30ffa69604846c68a6fe97cb6a7fa2 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Wed, 11 Sep 2024 21:26:33 +0000 Subject: [PATCH 35/53] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 5623a75..5fa9b11 100644 --- a/README.md +++ b/README.md @@ -1059,7 +1059,6 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS **ip_group_ids** | optional | A comma-separated list of unique identifiers for the IP destination groups | string | **exclude_type** | optional | The IP group type to be excluded from the results | string | **category_type** | optional | Comma seperated list of IP group types to be filtered from results. This argument is only supported when the 'lite' argument is set to True | string | -**include_ipv6** | optional | Retrieve IPv6 destination groups | boolean | **limit** | optional | Limit of the results to be retrieved | numeric | **lite** | optional | Whether to retrieve only limited information of IP destination groups. Includes ID, name and type of the IP destination groups | boolean | From aea41da5bb616845e7f5b8599f50c6820306c74d Mon Sep 17 00:00:00 2001 From: Tapish Jain Date: Thu, 12 Sep 2024 09:10:42 -0700 Subject: [PATCH 36/53] PAPP-34457: fixing static test and linting failures --- LICENSE | 2 +- manual_readme_content.md | 2 +- zscaler.json | 58 ++++++++++++++++++++---------------- zscaler_connector.py | 46 ++++++++++++++-------------- zscaler_consts.py | 2 +- zscaler_get_admin_users.html | 2 +- zscaler_submit_file.html | 2 +- zscaler_view.py | 2 +- 8 files changed, 62 insertions(+), 54 deletions(-) diff --git a/LICENSE b/LICENSE index fe5e893..d0f6848 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2017-2023 Splunk Inc. + Copyright (c) 2017-2024 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/manual_readme_content.md b/manual_readme_content.md index 6d52965..26220a8 100644 --- a/manual_readme_content.md +++ b/manual_readme_content.md @@ -1,5 +1,5 @@ [comment]: # " File: README.md" -[comment]: # " Copyright (c) 2017-2023 Splunk Inc." +[comment]: # " Copyright (c) 2017-2024 Splunk Inc." [comment]: # "" [comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');" [comment]: # "you may not use this file except in compliance with the License." diff --git a/zscaler.json b/zscaler.json index 890c376..6e46680 100644 --- a/zscaler.json +++ b/zscaler.json @@ -9,13 +9,13 @@ "product_name": "Zscaler", "product_version_regex": ".*", "publisher": "Splunk", - "license": "Copyright (c) 2017-2023 Splunk Inc.", + "license": "Copyright (c) 2017-2024 Splunk Inc.", "app_version": "2.4.0", "utctime_updated": "2022-01-24T06:29:48.000000Z", "package_name": "phantom_zscaler", "main_module": "zscaler_connector.py", "python_version": "3", - "min_phantom_version": "6.0.0", + "min_phantom_version": "6.2.1", "fips_compliant": true, "latest_tested_versions": [ "Cloud v6.2, 29th June 2023" @@ -3023,7 +3023,7 @@ { "action": "get whitelist", "identifier": "get_whitelist", - "description": "get urls on the allow list", + "description": "Get urls on the allow list", "type": "investigate", "read_only": true, "parameters": {}, @@ -3056,6 +3056,13 @@ "Whitelist retrieved" ] }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Whitelist retrieved" + ] + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -3080,7 +3087,7 @@ { "action": "get blacklist", "identifier": "get_blacklist", - "description": "get urls on the deny list", + "description": "Get urls on the deny list", "type": "investigate", "read_only": true, "parameters": { @@ -3143,6 +3150,13 @@ "Blacklist retrieved" ] }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Blacklist retrieved" + ] + }, { "data_path": "action_result.summary.total_blacklist_items", "data_type": "numeric", @@ -4142,7 +4156,7 @@ "DSTN_OTHER" ], "column_name": "Group type", - "column_order": 2 + "column_order": 3 }, { "data_path": "action_result.data.*.addresses", @@ -4151,19 +4165,19 @@ "192.168.1.1" ], "column_name": "Destination addresses", - "column_order": 3 + "column_order": 4 }, { "data_path": "action_result.data.*.countries", "data_type": "string", "column_name": "Destination countries", - "column_order": 4 + "column_order": 5 }, { "data_path": "action_result.data.*.description", "data_type": "string", "column_name": "Description", - "column_order": 5 + "column_order": 6 }, { "data_path": "action_result.data.*.ipCategories", @@ -4172,7 +4186,7 @@ "TRADING_BROKARAGE_INSURANCE" ], "column_name": "Destination categories", - "column_order": 6 + "column_order": 7 }, { "data_path": "action_result.data.*.isNonEditable", @@ -4182,13 +4196,13 @@ false ], "column_name": "Is editable", - "column_order": 7 + "column_order": 8 }, { "data_path": "action_result.data.*.creatorContext", "data_type": "string", "column_name": "Creator Context", - "column_order": 8 + "column_order": 9 }, { "data_path": "action_result.summary", @@ -4305,11 +4319,6 @@ "data_type": "numeric", "column_name": "Limit" }, - { - "data_path": "action_result.parameter.include_ipv6", - "data_type": "boolean", - "column_name": "Include Ipv6" - }, { "data_path": "action_result.parameter.category_type", "data_type": "string", @@ -4321,7 +4330,7 @@ "column_name": "Exclude Type" }, { - "data_path": "action_result.parameter.ip_group_id", + "data_path": "action_result.parameter.ip_group_ids", "data_type": "string", "column_name": "Ip Group ID" }, @@ -4557,7 +4566,7 @@ "DSTN_OTHER" ], "column_name": "Group type", - "column_order": 2 + "column_order": 3 }, { "data_path": "action_result.data.*.addresses", @@ -4566,19 +4575,19 @@ "192.168.1.1" ], "column_name": "Destination addresses", - "column_order": 3 + "column_order": 4 }, { "data_path": "action_result.data.*.countries", "data_type": "string", "column_name": "Destination countries", - "column_order": 4 + "column_order": 5 }, { "data_path": "action_result.data.*.description", "data_type": "string", "column_name": "Description", - "column_order": 5 + "column_order": 6 }, { "data_path": "action_result.data.*.ipCategories", @@ -4587,7 +4596,7 @@ "TRADING_BROKARAGE_INSURANCE" ], "column_name": "Destination categories", - "column_order": 6 + "column_order": 7 }, { "data_path": "action_result.data.*.isNonEditable", @@ -4597,13 +4606,13 @@ false ], "column_name": "Is editable", - "column_order": 7 + "column_order": 8 }, { "data_path": "action_result.data.*.creatorContext", "data_type": "string", "column_name": "Creator Context", - "column_order": 8 + "column_order": 9 }, { "data_path": "action_result.summary", @@ -4755,7 +4764,6 @@ "data_path": "action_result.status", "data_type": "string", "column_name": "Status", - "column_order": 2, "example_values": [ "test success", "test failed" diff --git a/zscaler_connector.py b/zscaler_connector.py index c8ea91e..03e5c46 100644 --- a/zscaler_connector.py +++ b/zscaler_connector.py @@ -1,6 +1,6 @@ # File: zscaler_connector.py # -# Copyright (c) 2017-2023 Splunk Inc. +# Copyright (c) 2017-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -1065,7 +1065,7 @@ def _handle_update_user(self, param): user_id = param['user_id'] try: - data = json.loads(param["user"]) + data = json.loads(param.get("user", '{}')) except Exception as e: return action_result.set_status( phantom.APP_ERROR, @@ -1089,18 +1089,18 @@ def _get_category_details(self, id, action_result): return action_result.get_status(), None return phantom.APP_SUCCESS, response - def _add_to_category(self, data, parent_data, category_details, category_id, action_result): - new_data = category_details.get("urls", []) + def _add_to_category(self, data, parent_data, cat_details, category_id, action_result): + new_data = cat_details.get("urls", []) new_data.extend(data) if new_data: - category_details["urls"] = new_data + cat_details["urls"] = new_data - new_parent_data = category_details.get("dbCategorizedUrls", []) + new_parent_data = cat_details.get("dbCategorizedUrls", []) new_parent_data.extend(parent_data) if new_parent_data: - category_details["dbCategorizedUrls"] = new_parent_data + cat_details["dbCategorizedUrls"] = new_parent_data - ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=category_details, method='put') + ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=cat_details, method='put') return ret_val, response def _handle_add_category_url(self, param): @@ -1134,7 +1134,7 @@ def _handle_add_category_url(self, param): return action_result.set_status(phantom.APP_SUCCESS) - def _handle_add_category_ips(self, param): + def _handle_add_category_ip(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) category_id = param["category_id"] @@ -1158,7 +1158,7 @@ def _handle_add_category_ips(self, param): return action_result.set_status(phantom.APP_SUCCESS) - def _handle_remove_category_ips(self, param): + def _handle_remove_category_ip(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) category_id = param["category_id"] @@ -1183,26 +1183,26 @@ def _handle_remove_category_ips(self, param): return action_result.set_status(phantom.APP_SUCCESS) - def _remove_from_category(self, data, parent_data, category_details, category_id, action_result): + def _remove_from_category(self, data, parent_data, cat_details, category_id, action_result): data_set = set(data) new_data = [] - for point in category_details.get("urls", []): + for point in cat_details.get("urls", []): if point not in data_set: new_data.append(point) parent_data_set = set(parent_data) new_parent_data = [] - for point in category_details.get("dbCategorizedUrls", []): + for point in cat_details.get("dbCategorizedUrls", []): if point not in parent_data_set: new_parent_data.append(point) - category_details["urls"] = new_data - category_details["dbCategorizedUrls"] = new_parent_data + cat_details["urls"] = new_data + cat_details["dbCategorizedUrls"] = new_parent_data - ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=category_details, method='put') + ret_val, response = self._make_rest_call_helper(f'/api/v1/urlCategories/{category_id}', action_result, data=cat_details, method='put') return ret_val, response - def _handle_remove_category_urls(self, param): + def _handle_remove_category_url(self, param): self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) action_result = self.add_action_result(ActionResult(dict(param))) category_id = param["category_id"] @@ -1381,14 +1381,14 @@ def _handle_edit_destination_group(self, param): return action_result.get_status() group_resp["name"] = param.get("name", group_resp["name"]) if param.get('addresses'): - new_addresses = [item.strip() for item in param["addresses"].split(',') if item.strip()] + new_addresses = [item.strip() for item in param.get("addresses", "").split(',') if item.strip()] group_resp["addresses"] = new_addresses group_resp["description"] = param.get("description", group_resp["description"]) if param.get("ip_categories"): - new_ip_categories = [item.strip() for item in param["ip_categories"].split(',') if item.strip()] + new_ip_categories = [item.strip() for item in param.get("ip_categories", "").split(',') if item.strip()] group_resp["ipCategories"] = new_ip_categories if param.get("countries"): - new_countries = [item.strip() for item in param["countries"].split(',') if item.strip()] + new_countries = [item.strip() for item in param.get("countries", "").split(',') if item.strip()] group_resp["countries"] = new_countries group_resp["isNonEditable"] = param.get("is_non_editable", False) @@ -1582,13 +1582,13 @@ def handle_action(self, param): ret_val = self._handle_add_category_url(param) elif action_id == 'add_category_ip': - ret_val = self._handle_add_category_ips(param) + ret_val = self._handle_add_category_ip(param) elif action_id == 'remove_category_url': - ret_val = self._handle_remove_category_urls(param) + ret_val = self._handle_remove_category_url(param) elif action_id == 'remove_category_ip': - ret_val = self._handle_remove_category_ips(param) + ret_val = self._handle_remove_category_ip(param) else: # passing the action handling to another function to decrease FLAKE_8 complexity diff --git a/zscaler_consts.py b/zscaler_consts.py index d34a5c4..68e627e 100644 --- a/zscaler_consts.py +++ b/zscaler_consts.py @@ -1,6 +1,6 @@ # File: zscaler_consts.py # -# Copyright (c) 2017-2023 Splunk Inc. +# Copyright (c) 2017-2024 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/zscaler_get_admin_users.html b/zscaler_get_admin_users.html index 0bad440..ac3779d 100644 --- a/zscaler_get_admin_users.html +++ b/zscaler_get_admin_users.html @@ -10,7 +10,7 @@ {% block widget_content %}