diff --git a/.github/workflows/start-release.yml b/.github/workflows/start-release.yml index 7d47230..7bbce79 100644 --- a/.github/workflows/start-release.yml +++ b/.github/workflows/start-release.yml @@ -1,5 +1,9 @@ name: Start Release -on: workflow_dispatch +on: + workflow_dispatch: + push: + tags: + - '*-beta*' jobs: start-release: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f4494f..fa97c3c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/phantomcyber/dev-cicd-tools - rev: v1.5 + rev: v1.11 hooks: - id: org-hook - id: package-app-dependencies diff --git a/LICENSE b/LICENSE index 56c8192..e6f5c5c 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2021 Splunk Inc. + Copyright (c) 2014-2022 Splunk Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/NOTICE b/NOTICE index d60bbde..debfd39 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Splunk SOAR Cisco ISE -Copyright (c) 2014-2021 Splunk Inc. +Copyright (c) 2014-2022 Splunk Inc. Third-party Software Attributions: diff --git a/README.md b/README.md index 6367564..2d77404 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,651 @@ -# Splunk> Phantom +[comment]: # "Auto-generated SOAR connector documentation" +# Cisco ISE -Welcome to the open-source repository for Splunk> Phantom's ciscoise App. +Publisher: Splunk +Connector Version: 3\.0\.0 +Product Vendor: Cisco Systems +Product Name: Cisco ISE +Product Version Supported (regex): "/\(\[2\]\.\[67\]\)\|\(\[3\]\.\[01\]\)/" +Minimum Product Version: 5\.1\.0 -Please have a look at our [Contributing Guide](https://github.com/Splunk-SOAR-Apps/.github/blob/main/.github/CONTRIBUTING.md) if you are interested in contributing, raising issues, or learning more about open-source Phantom apps. +This app implements investigative and containment actions on a Cisco ISE device -## Legal and License +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2014-2022 Splunk Inc." +[comment]: # "" +[comment]: # " SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part" +[comment]: # " without a valid written license from Splunk Inc. is PROHIBITED." +[comment]: # "" +[comment]: # " pragma: allowlist secret " +[comment]: # " pragma: allowlist secret " +[comment]: # " pragma: allowlist secret " +## Asset Configuration For Authentication -This Phantom App is licensed under the Apache 2.0 license. Please see our [Contributing Guide](https://github.com/Splunk-SOAR-Apps/.github/blob/main/.github/CONTRIBUTING.md#legal-notice) for further details. +- ERS uses HTTPS port 9060 which is closed by default. Clients trying to access this port without + enabling ERS first will face a timeout from the server. Therefore, the first requirement is to + enable ERS from the Cisco ISE admin UI. Go to Administration \> Settings \> ERS Settings and + enable the Enable ERS for Read/Write radio button +- Go to Administration \> System \> Admin Users. Now add an account by clicking Add \> Create an + admin user. Then enter name and password and select ERS Admin in Admin Group and then press + save. +- Go to Administration \> System \> Admin Users. Now add an account by clicking Add \> Create an + admin user. Then enter name and password and select MnT Admin in Admin Group and then press + save. +- Configurations expect user with MnT Admin Access group in username/password fields and user in + ERS Admin group in ERS username/password fields or user with both MnT Admin or ERS Admin access + group in username/password field. +- Also, you can add both MnT Admin and ERS Admin Access groups to a user and use that credentials + in username/password. The App will use username/password if ERS username/password is not + provided + +## Note + +1. The actions "quarantine system" and "unquarantine system" are removed in the version X.X.X. + Users are advised to use "apply policy" and "clear policy" actions to achieve the same objective +2. ERS credentials are required for actions + - list endpoints + - get device info + - update device info + - get resources + - delete resource + - create resource + - update resource + - apply policy + - create policy +3. An ISE node can assume any or all of the following personas: Administration, Policy Service, and + Monitoring. For detailed info: [Types of + nodes](https://www.cisco.com/en/US/docs/security/ise/1.0/user_guide/ise10_dis_deploy.html#wp1123452) + - All actions can run on Administration node. + - Actions create resource, update resource, delete resource, list resource, get resources, + list sessions, update device info, get device info, and list endpoints can run on Monitoring + node + - Actions quarantine device, unquarantine device, apply policy, clear policy, and terminate + session can run on Policy Service node +4. For create resource action, user needs to provide valid json with required fields of that + specified resource (For more details head over to [API + Reference](https://developer.cisco.com/docs/identity-services-engine/v1/#!endpoint) ). Examples + as below + - Endpoint + + { + "ERSEndPoint": { + "name": "name", + "description": "MyEndpoint", + "mac": "11:22:33:44:55:66" + } + } + + + - Endpoint identity groups + + { + "EndPointGroup": { + "name": "Cisco-Meraki-Device", + "description": "Identity Group for Profile: Cisco-Meraki-Device", + "systemDefined": "true" + } + } + + + - Guest users + + { + "GuestUser": { + "name": "guestUser", + "guestInfo": { + "userName": "DS3ewdsa34wWE", + "password": "asdlkj324ew", + "enabled": true + }, + "guestAccessInfo": { + "validDays": 90 + } + } + } + + + - User identity groups + + { + "IdentityGroup": { + "name": "GuestType_Weekly (default)", + "parent": "NAC Group:NAC:IdentityGroups:User Identity Groups" + } + } + + + - Internal users + + { + "InternalUser": { + "name": "name", + "enabled": true, + "password": "*******", + "changePassword": true, + "passwordIDStore": "Internal Users" + } + } + + + - Network devices + + { + "NetworkDevice": { + "name": "ISE_EST_Local_Host", + "authenticationSettings": { + "enableKeyWrap": true, + "enableMultiSecret": true, + "keyEncryptionKey": 1234567890123456, + "keyInputFormat": "ASCII" + }, + "coaPort": 0, + "snmpsettings": { + "pollingInterval": 3600, + "linkTrapQuery": true, + "macTrapQuery": true, + "originatingPolicyServicesNode": "Auto" + }, + "trustsecsettings": { + "deviceAuthenticationSettings": {}, + "sgaNotificationAndUpdates": {}, + "deviceConfigurationDeployment": {}, + "pushIdSupport": false + }, + "tacacsSettings": { + "sharedSecret": "aaa" + }, + "profileName": "Cisco", + "NetworkDeviceIPList": [ + { + "ipaddress": "127.0.0.1", + "mask": 32 + } + ] + } + } + + + - Network device groups + + { + "NetworkDeviceGroup": { + "name": "Device Type#All Device Types" + } + } + + + - Security groups + + { + "Sgt": { + "name": "Employees", + "value": 4 + } + } + + +## Port Information + +The app uses HTTP/ HTTPS protocol for communicating with the Cisco ISE server. Below are the default +ports used by Splunk SOAR. + +| Service Name | Transport Protocol | Port | +|--------------|--------------------|------| +| http | tcp | 80 | +| https | tcp | 443 | + + +### Configuration Variables +The below configuration variables are required for this Connector to operate. These variables are specified when configuring a Cisco ISE asset in SOAR. + +VARIABLE | REQUIRED | TYPE | DESCRIPTION +-------- | -------- | ---- | ----------- +**device** | required | string | Device IP/Hostname +**ha\_device** | optional | string | Device IP/Hostname for a High Availability node if available +**username** | required | string | Username +**password** | required | password | Password +**ers\_user** | optional | string | Username for ERS APIs +**ers\_password** | optional | password | Password for ERS APIs +**verify\_server\_cert** | optional | boolean | Verify server certificate + +### Supported Actions +[test connectivity](#action-test-connectivity) - Validate the asset configuration for connectivity\. This action logs into the device using a REST API call to check the connection and credentials +[list endpoints](#action-list-endpoints) - List the endpoints configured on the system +[get device info](#action-get-device-info) - Get information about a specific endpoint +[update device info](#action-update-device-info) - Update information or attributes for a specific endpoint +[list sessions](#action-list-sessions) - List the sessions currently available on the Monitoring node +[terminate session](#action-terminate-session) - Terminate sessions +[list resources](#action-list-resources) - Lists all the resources configured on the system of a particular resource +[get resources](#action-get-resources) - Get the information about resource if resource\_id is provided\. Fetch the list of resources match with the key\-value filter +[delete resource](#action-delete-resource) - Delete a resource +[create resource](#action-create-resource) - Create a resource +[update resource](#action-update-resource) - Update a resource +[apply policy](#action-apply-policy) - Apply policy on selected Ip address or MAC address +[clear policy](#action-clear-policy) - Clear policy on selected Ip address or MAC address +[list policies](#action-list-policies) - Lists all the ANC policies available +[add policy](#action-add-policy) - Add a new ANC Policy +[delete policy](#action-delete-policy) - Delete a policy + +## action: 'test connectivity' +Validate the asset configuration for connectivity\. This action logs into the device using a REST API call to check the connection and credentials + +Type: **test** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +No Output + +## action: 'list endpoints' +List the endpoints configured on the system + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**mac\_address** | optional | Mac Address to filter on \(6 bytes, colon separated\) | string | `mac address` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.mac\_address | string | `mac address` +action\_result\.data\.\*\.SearchResult\.resources\.\*\.id | string | `ise endpoint id` `ise resource id` +action\_result\.data\.\*\.SearchResult\.resources\.\*\.link\.href | string | `url` +action\_result\.data\.\*\.SearchResult\.resources\.\*\.link\.rel | string | +action\_result\.data\.\*\.SearchResult\.resources\.\*\.link\.type | string | +action\_result\.data\.\*\.SearchResult\.resources\.\*\.name | string | +action\_result\.data\.\*\.SearchResult\.total | numeric | +action\_result\.summary\.Endpoints found | string | +action\_result\.summary\.endpoints\_found | numeric | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'get device info' +Get information about a specific endpoint + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**endpoint\_id** | required | ISE Endpoint ID for device | string | `ise endpoint id` `ise resource id` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.endpoint\_id | string | `ise endpoint id` `ise resource id` +action\_result\.data\.\*\.ERSEndPoint\.customAttributes\.customAttributes\.ITSecurityBlock | string | +action\_result\.data\.\*\.ERSEndPoint\.description | string | +action\_result\.data\.\*\.ERSEndPoint\.groupId | string | +action\_result\.data\.\*\.ERSEndPoint\.id | string | `ise endpoint id` `ise resource id` +action\_result\.data\.\*\.ERSEndPoint\.identityStore | string | +action\_result\.data\.\*\.ERSEndPoint\.identityStoreId | string | +action\_result\.data\.\*\.ERSEndPoint\.link\.href | string | `url` +action\_result\.data\.\*\.ERSEndPoint\.link\.rel | string | +action\_result\.data\.\*\.ERSEndPoint\.link\.type | string | +action\_result\.data\.\*\.ERSEndPoint\.mac | string | +action\_result\.data\.\*\.ERSEndPoint\.name | string | +action\_result\.data\.\*\.ERSEndPoint\.portalUser | string | +action\_result\.data\.\*\.ERSEndPoint\.profileId | string | +action\_result\.data\.\*\.ERSEndPoint\.staticGroupAssignment | boolean | +action\_result\.data\.\*\.ERSEndPoint\.staticProfileAssignment | boolean | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'update device info' +Update information or attributes for a specific endpoint + +Type: **contain** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**endpoint\_id** | required | ISE Endpoint ID for device | string | `ise endpoint id` `ise resource id` +**attribute** | optional | Attribute to update for the Endpoint | string | +**attribute\_value** | optional | Value to put in the attribute for the Endpoint | string | +**custom\_attribute** | optional | Custom attribute to update for the Endpoint | string | +**custom\_attribute\_value** | optional | Value to put in the custom attribute for the Endpoint | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.attribute | string | +action\_result\.parameter\.attribute\_value | string | +action\_result\.parameter\.custom\_attribute | string | +action\_result\.parameter\.custom\_attribute\_value | string | +action\_result\.parameter\.endpoint\_id | string | `ise endpoint id` `ise resource id` +action\_result\.data\.\*\.UpdatedFieldsList\.updatedField\.\*\.field | string | +action\_result\.data\.\*\.UpdatedFieldsList\.updatedField\.\*\.newValue | string | +action\_result\.data\.\*\.UpdatedFieldsList\.updatedField\.\*\.oldValue | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'list sessions' +List the sessions currently available on the Monitoring node + +Type: **investigate** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.data\.\*\.acct\_session\_id | string | +action\_result\.data\.\*\.audit\_session\_id | string | `ise session id` +action\_result\.data\.\*\.calling\_station\_id | string | `mac address` +action\_result\.data\.\*\.framed\_ip\_address | string | `ip` +action\_result\.data\.\*\.framed\_ipv6\_address | string | +action\_result\.data\.\*\.is\_quarantined | string | +action\_result\.data\.\*\.nas\_ip\_address | string | `nas server` +action\_result\.data\.\*\.server | string | `ise server` +action\_result\.data\.\*\.user\_name | string | `user name` +action\_result\.summary | string | +action\_result\.summary\.sessions\_found | numeric | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'terminate session' +Terminate sessions + +Type: **contain** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**macaddress** | required | MAC address of device to terminate sessions of | string | `mac address` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.macaddress | string | `mac address` +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'list resources' +Lists all the resources configured on the system of a particular resource + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**resource** | required | Resource type of the resources to fetch | string | +**max\_results** | optional | Total number of observables to return | numeric | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.max\_results | numeric | +action\_result\.parameter\.resource | string | +action\_result\.data\.\*\.description | string | +action\_result\.data\.\*\.id | string | `ise resource id` +action\_result\.data\.\*\.link\.href | string | `url` +action\_result\.data\.\*\.link\.rel | string | +action\_result\.data\.\*\.link\.type | string | +action\_result\.data\.\*\.name | string | +action\_result\.summary\.resources\_returned | numeric | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'get resources' +Get the information about resource if resource\_id is provided\. Fetch the list of resources match with the key\-value filter + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**resource** | required | Resource type of the resource to fetch | string | +**resource\_id** | optional | Resource ID | string | `ise resource id` +**key** | optional | Key | string | +**value** | optional | Value | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.key | string | +action\_result\.parameter\.resource | string | +action\_result\.parameter\.resource\_id | string | `ise resource id` +action\_result\.parameter\.value | string | +action\_result\.data\.\*\.description | string | +action\_result\.data\.\*\.groupId | string | +action\_result\.data\.\*\.id | string | `ise resource id` +action\_result\.data\.\*\.identityStore | string | +action\_result\.data\.\*\.identityStoreId | string | +action\_result\.data\.\*\.link\.href | string | `url` +action\_result\.data\.\*\.link\.rel | string | +action\_result\.data\.\*\.link\.type | string | +action\_result\.data\.\*\.mac | string | +action\_result\.data\.\*\.name | string | +action\_result\.data\.\*\.portalUser | string | +action\_result\.data\.\*\.profileId | string | +action\_result\.data\.\*\.staticGroupAssignment | boolean | +action\_result\.data\.\*\.staticProfileAssignment | boolean | +action\_result\.summary\.resource\_id | string | `ise resource id` +action\_result\.summary\.resources\_returned | numeric | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'delete resource' +Delete a resource + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**resource** | required | Resource type of the resource to be deleted | string | +**resource\_id** | required | Resource ID | string | `ise resource id` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.resource | string | +action\_result\.parameter\.resource\_id | string | `ise resource id` +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'create resource' +Create a resource + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**resource** | required | Resource type of the resource to be created | string | +**resource\_json** | required | JSON which contains all values needed to create a resource | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.resource | string | +action\_result\.parameter\.resource\_json | string | +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'update resource' +Update a resource + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**resource** | required | Resource type of the resource to be created | string | +**resource\_id** | required | ID of resource | string | `ise resource id` +**key** | required | Key of resource which needs to be updated | string | +**value** | required | New value of key | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.key | string | +action\_result\.parameter\.resource | string | +action\_result\.parameter\.resource\_id | string | `ise resource id` +action\_result\.parameter\.value | string | +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'apply policy' +Apply policy on selected Ip address or MAC address + +Type: **investigate** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**policy\_name** | required | Policy Name | string | +**ip\_mac\_address** | required | MAC or IP Address of the device | string | `mac address` `ip` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.ip\_mac\_address | string | `mac address` `ip` +action\_result\.parameter\.policy\_name | string | +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'clear policy' +Clear policy on selected Ip address or MAC address + +Type: **investigate** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**policy\_name** | required | Policy Name | string | +**ip\_mac\_address** | required | MAC or IP Address of the device | string | `mac address` `ip` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.ip\_mac\_address | string | `mac address` `ip` +action\_result\.parameter\.policy\_name | string | +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'list policies' +Lists all the ANC policies available + +Type: **investigate** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.data\.\*\.actions | string | +action\_result\.data\.\*\.id | string | `ise policy id` +action\_result\.data\.\*\.link\.href | string | +action\_result\.data\.\*\.link\.rel | string | +action\_result\.data\.\*\.link\.type | string | +action\_result\.data\.\*\.name | string | +action\_result\.summary | string | +action\_result\.summary\.policies\_found | numeric | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'add policy' +Add a new ANC Policy + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**name** | required | Policy Name | string | +**action\_type** | required | Policy action type | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.action\_type | string | +action\_result\.parameter\.name | string | +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'delete policy' +Delete a policy + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**policy\_name** | required | Policy Name | string | `ise policy id` + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.policy\_name | string | `ise policy id` +action\_result\.data | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | \ No newline at end of file diff --git a/__init__.py b/__init__.py index 48163fc..77b1650 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,6 @@ # File: __init__.py # -# Copyright (c) 2014-2021 Splunk Inc. +# Copyright (c) 2014-2022 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/ciscoise.json b/ciscoise.json index dfb5f44..38e5491 100644 --- a/ciscoise.json +++ b/ciscoise.json @@ -5,20 +5,20 @@ "publisher": "Splunk", "type": "network security", "main_module": "ciscoise_connector.py", - "app_version": "2.0.5", - "utctime_updated": "2021-12-20T10:42:25.000000Z", + "app_version": "3.0.0", + "utctime_updated": "2022-01-07T20:54:18.000000Z", "package_name": "phantom_ciscoise", "product_vendor": "Cisco Systems", "product_name": "Cisco ISE", "product_version_regex": "/([2].[67])|([3].[01])/", - "min_phantom_version": "5.0.0", + "min_phantom_version": "5.1.0", "logo": "logo_cisco.svg", "logo_dark": "logo_cisco_dark.svg", - "license": "Copyright (c) 2014-2021 Splunk Inc.", + "license": "Copyright (c) 2014-2022 Splunk Inc.", "python_version": "3", "fips_compliant": true, "latest_tested_version": [ - "Cisco ISE version 3.0.0.458, 9th Dec 2021" + "Cisco ISE version 3.0.0.458, 22th Feb 2022" ], "configuration": { "device": { @@ -667,208 +667,6 @@ ], "versions": "EQ(*)" }, - { - "action": "quarantine device", - "description": "Quarantine the device", - "type": "contain", - "identifier": "quarantine_device", - "read_only": false, - "parameters": { - "ip_macaddress": { - "description": "MAC or IP address of device to quarantine", - "data_type": "string", - "order": 0, - "contains": [ - "mac address", - "ip" - ], - "primary": true, - "required": true - } - }, - "undo": "unquarantine device", - "render": { - "width": 12, - "title": "Quarantine Device", - "type": "table", - "height": 5 - }, - "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, - { - "data_path": "action_result.parameter.ip_macaddress", - "data_type": "string", - "column_name": "Device MAC/IP", - "example_values": [ - "11:11:11:11:11:11" - ], - "contains": [ - "mac address", - "ip" - ], - "column_order": 0 - }, - { - "data_path": "action_result.data", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.EPS_RESULT.errorCode", - "data_type": "string", - "example_values": [ - "0" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.operationID", - "data_type": "string", - "example_value": [ - "0" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.requestID", - "data_type": "string", - "example_value": [ - "-1" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.status", - "data_type": "string", - "example_values": [ - "Success" - ] - }, - { - "data_path": "action_result.summary", - "data_type": "string" - }, - { - "data_path": "action_result.message", - "data_type": "string", - "column_name": "Message", - "column_order": 1 - }, - { - "data_path": "summary.total_objects", - "data_type": "numeric" - }, - { - "data_path": "summary.total_objects_successful", - "data_type": "numeric" - } - ], - "versions": "EQ(*)" - }, - { - "action": "unquarantine device", - "description": "Unquarantine the device", - "type": "correct", - "identifier": "unquarantine_device", - "read_only": false, - "undo": "quarantine device", - "parameters": { - "ip_macaddress": { - "description": "MAC or IP address of device to unquarantine", - "data_type": "string", - "order": 0, - "contains": [ - "mac address", - "ip" - ], - "primary": true, - "required": true - } - }, - "render": { - "width": 12, - "title": "Unquarantine Device", - "type": "table", - "height": 5 - }, - "output": [ - { - "data_path": "action_result.status", - "data_type": "string", - "example_values": [ - "success", - "failed" - ] - }, - { - "data_path": "action_result.parameter.ip_macaddress", - "data_type": "string", - "column_name": "Device MAC/IP", - "contains": [ - "mac address", - "ip" - ], - "example_values": [ - "11:11:11:11:11:11" - ], - "column_order": 0 - }, - { - "data_path": "action_result.data", - "data_type": "string" - }, - { - "data_path": "action_result.data.*.EPS_RESULT.errorCode", - "data_type": "string", - "example_values": [ - "0" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.operationID", - "data_type": "string", - "example_values": [ - "90" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.requestID", - "data_type": "string", - "example_values": [ - "-1" - ] - }, - { - "data_path": "action_result.data.*.EPS_RESULT.status", - "data_type": "string", - "example_values": [ - "Success" - ] - }, - { - "data_path": "action_result.summary", - "data_type": "string" - }, - { - "data_path": "action_result.message", - "data_type": "string", - "column_name": "Message", - "column_order": 1 - }, - { - "data_path": "summary.total_objects", - "data_type": "numeric" - }, - { - "data_path": "summary.total_objects_successful", - "data_type": "numeric" - } - ], - "versions": "EQ(*)" - }, { "action": "terminate session", "description": "Terminate sessions", @@ -1110,7 +908,8 @@ "order": 1, "contains": [ "ise resource id" - ] + ], + "primary": true }, "key": { "description": "Key", @@ -1343,7 +1142,8 @@ "order": 1, "contains": [ "ise resource id" - ] + ], + "primary": true } }, "output": [ @@ -1538,7 +1338,8 @@ "order": 1, "contains": [ "ise resource id" - ] + ], + "primary": true }, "key": { "description": "Key of resource which needs to be updated", @@ -1648,7 +1449,6 @@ "description": "Policy Name", "data_type": "string", "order": 0, - "primary": false, "required": true }, "ip_mac_address": { @@ -1670,6 +1470,14 @@ "title": "Endpoints" }, "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, { "data_path": "action_result.parameter.ip_mac_address", "data_type": "string", @@ -1680,7 +1488,7 @@ "example_values": [ "11:11:11:11:11:11" ], - "column_name": "IP MAC address", + "column_name": "IP MAC Address", "column_order": 0 }, { @@ -1692,15 +1500,6 @@ ], "column_order": 1 }, - { - "data_path": "action_result.message", - "data_type": "string", - "example_values": [ - "Policy applied" - ], - "column_name": "Status", - "column_order": 2 - }, { "data_path": "action_result.data", "data_type": "string" @@ -1710,12 +1509,13 @@ "data_type": "string" }, { - "data_path": "action_result.status", + "data_path": "action_result.message", "data_type": "string", "example_values": [ - "success", - "failed" - ] + "Policy applied" + ], + "column_name": "Status", + "column_order": 2 }, { "data_path": "summary.total_objects", @@ -1766,6 +1566,14 @@ "title": "Endpoints" }, "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, { "data_path": "action_result.parameter.ip_mac_address", "data_type": "string", @@ -1776,7 +1584,7 @@ "example_values": [ "11:11:11:11:11:11" ], - "column_name": "IP MAC address", + "column_name": "IP MAC Address", "column_order": 0 }, { @@ -1788,6 +1596,14 @@ "column_name": "Policy Name", "column_order": 1 }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, { "data_path": "action_result.message", "data_type": "string", @@ -1797,6 +1613,181 @@ "column_name": "Status", "column_order": 2 }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "versions": "EQ(*)" + }, + { + "action": "list policies", + "description": "Lists all the ANC policies available", + "type": "investigate", + "identifier": "list_policies", + "read_only": true, + "parameters": {}, + "render": { + "type": "table", + "width": 12, + "height": 5, + "title": "Policies" + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.data.*.actions", + "data_type": "string", + "example_value": "SHUTDOWN", + "column_name": "Action Type", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "policy_name" + ], + "column_name": "Policy Name", + "column_order": 0, + "contains": [ + "ise policy id" + ] + }, + { + "data_path": "action_result.data.*.link.href", + "data_type": "string", + "example_values": [ + "https://10.0.0.0:9060/ers/config/ancpolicy/policy_name" + ] + }, + { + "data_path": "action_result.data.*.link.rel", + "data_type": "string", + "example_values": [ + "self" + ] + }, + { + "data_path": "action_result.data.*.link.type", + "data_type": "string", + "example_values": [ + "application/json" + ] + }, + { + "data_path": "action_result.data.*.name", + "data_type": "string", + "example_values": [ + "policy_name" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.policies_found", + "data_type": "numeric", + "example_value": 6 + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Policies found: 1" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "versions": "EQ(*)" + }, + { + "action": "add policy", + "description": "Add a new ANC Policy", + "type": "generic", + "identifier": "add_policy", + "read_only": false, + "parameters": { + "name": { + "data_type": "string", + "description": "Policy Name", + "order": 0, + "default": false, + "required": true + }, + "action_type": { + "data_type": "string", + "description": "Policy action type", + "order": 1, + "value_list": [ + "QUARANTINE", + "SHUTDOWN", + "PORTBOUNCE" + ], + "required": true, + "default": "QUARANTINE" + } + }, + "render": { + "type": "table", + "width": 12, + "height": 5, + "title": "Results" + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.action_type", + "data_type": "string", + "example_values": [ + "QUARANTINE" + ] + }, + { + "data_path": "action_result.parameter.name", + "data_type": "string", + "example_values": [ + "policy_name" + ] + }, { "data_path": "action_result.data", "data_type": "string" @@ -1805,6 +1796,57 @@ "data_path": "action_result.summary", "data_type": "string" }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Policy created" + ], + "column_name": "Status", + "column_order": 0 + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "versions": "EQ(*)" + }, + { + "action": "delete policy", + "description": "Delete a policy", + "type": "generic", + "identifier": "delete_policy", + "read_only": false, + "parameters": { + "policy_name": { + "description": "Policy Name", + "data_type": "string", + "order": 0, + "required": true, + "contains": [ + "ise policy id" + ], + "primary": true + } + }, + "render": { + "type": "table", + "width": 12, + "height": 5, + "title": "Results" + }, + "output": [ { "data_path": "action_result.status", "data_type": "string", @@ -1813,6 +1855,30 @@ "failed" ] }, + { + "data_path": "action_result.parameter.policy_name", + "data_type": "string", + "contains": [ + "ise policy id" + ] + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Policy deleted" + ], + "column_name": "Status", + "column_order": 0 + }, { "data_path": "summary.total_objects", "data_type": "numeric", @@ -1835,36 +1901,72 @@ "wheel": [ { "module": "Cerberus", - "input_file": "wheels/Cerberus-1.3.4-py3-none-any.whl" + "input_file": "wheels/py3/Cerberus-1.3.4-py3-none-any.whl" + }, + { + "module": "certifi", + "input_file": "wheels/shared/certifi-2021.10.8-py2.py3-none-any.whl" + }, + { + "module": "chardet", + "input_file": "wheels/shared/chardet-3.0.4-py2.py3-none-any.whl" + }, + { + "module": "idna", + "input_file": "wheels/shared/idna-2.10-py2.py3-none-any.whl" + }, + { + "module": "requests", + "input_file": "wheels/shared/requests-2.25.0-py2.py3-none-any.whl" + }, + { + "module": "setuptools", + "input_file": "wheels/py3/setuptools-59.6.0-py3-none-any.whl" + }, + { + "module": "urllib3", + "input_file": "wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl" + }, + { + "module": "xmltodict", + "input_file": "wheels/shared/xmltodict-0.12.0-py2.py3-none-any.whl" + } + ] + }, + "pip39_dependencies": { + "wheel": [ + { + "module": "Cerberus", + "input_file": "wheels/py3/Cerberus-1.3.4-py3-none-any.whl" }, { "module": "certifi", - "input_file": "wheels/certifi-2021.10.8-py2.py3-none-any.whl" + "input_file": "wheels/shared/certifi-2021.10.8-py2.py3-none-any.whl" }, { "module": "chardet", - "input_file": "wheels/chardet-3.0.4-py2.py3-none-any.whl" + "input_file": "wheels/shared/chardet-3.0.4-py2.py3-none-any.whl" }, { "module": "idna", - "input_file": "wheels/idna-2.10-py2.py3-none-any.whl" + "input_file": "wheels/shared/idna-2.10-py2.py3-none-any.whl" }, { "module": "requests", - "input_file": "wheels/requests-2.25.0-py2.py3-none-any.whl" + "input_file": "wheels/shared/requests-2.25.0-py2.py3-none-any.whl" }, { "module": "setuptools", - "input_file": "wheels/setuptools-59.6.0-py3-none-any.whl" + "input_file": "wheels/py3/setuptools-60.8.2-py3-none-any.whl" }, { "module": "urllib3", - "input_file": "wheels/urllib3-1.26.7-py2.py3-none-any.whl" + "input_file": "wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl" }, { "module": "xmltodict", - "input_file": "wheels/xmltodict-0.12.0-py2.py3-none-any.whl" + "input_file": "wheels/shared/xmltodict-0.12.0-py2.py3-none-any.whl" } ] } -} \ No newline at end of file +} diff --git a/ciscoise_connector.py b/ciscoise_connector.py index 2e86278..9e28670 100644 --- a/ciscoise_connector.py +++ b/ciscoise_connector.py @@ -1,6 +1,6 @@ # File: ciscoise_connector.py # -# Copyright (c) 2014-2021 Splunk Inc. +# Copyright (c) 2014-2022 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -30,13 +30,10 @@ class CiscoISEConnector(BaseConnector): - # actions supported by this script ACTION_ID_LIST_SESSIONS = "list_sessions" ACTION_ID_TERMINATE_SESSION = "terminate_session" ACTION_ID_LOGOFF_SYSTEM = "logoff_system" - ACTION_ID_QUARANTINE_SYSTEM = "quarantine_device" - ACTION_ID_UNQUARANTINE_SYSTEM = "unquarantine_device" ACTION_ID_LIST_ENDPOINTS = "list_endpoints" ACTION_ID_GET_ENDPOINT = "get_endpoint" ACTION_ID_UPDATE_ENDPOINT = "update_endpoint" @@ -47,6 +44,9 @@ class CiscoISEConnector(BaseConnector): ACTION_ID_UPDATE_RESOURCE = "update_resource" ACTION_ID_APPLY_POLICY = "apply_policy" ACTION_ID_CLEAR_POLICY = "clear_policy" + ACTION_ID_LIST_POLICIES = "list_policies" + ACTION_ID_CREATE_POLICY = "add_policy" + ACTION_ID_DELETE_POLICY = "delete_policy" def __init__(self): @@ -76,6 +76,32 @@ def initialize(self): return phantom.APP_SUCCESS + def _validate_integers(self, action_result, parameter, key, allow_zero=False): + """ This method is to check if the provided input parameter value + is a non-zero positive integer and returns the integer value of the parameter itself. + :param action_result: Action result or BaseConnector object + :param parameter: input parameter + :return: integer value of the parameter or None in case of failure + """ + + if parameter is not None: + try: + if not float(parameter).is_integer(): + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_INVALID_PARAM.format(key)), None + parameter = int(parameter) + + except Exception: + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_INVALID_PARAM.format(key)), None + + if parameter < 0: + return action_result.set_status(phantom.APP_ERROR, + "Please provide a valid non-negative integer value in the {} parameter".format(key)), None + if not allow_zero and parameter == 0: + return action_result.set_status(phantom.APP_ERROR, + "Please provide non-zero positive integer in {}".format(key)), None + + return phantom.APP_SUCCESS, parameter + def _ha_device_wrapper(self, func): def make_another_call(*args, **kwargs): self.debug_print("Making call to primary device") @@ -91,7 +117,8 @@ def make_another_call(*args, **kwargs): return make_another_call def _call_ers_api(self, endpoint, action_result, data=None, allow_unknown=True, method="get", try_ha_device=False): - if self._ers_auth is None: + auth_method = self._ers_auth or self._auth + if not auth_method: return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERS_CRED_MISSING), None url = "{0}{1}".format(self._base_url, endpoint) if try_ha_device: @@ -104,11 +131,19 @@ def _call_ers_api(self, endpoint, action_result, data=None, allow_unknown=True, try: request_func = getattr(requests, method) except AttributeError as e: + self.debug_print("Exception occurred: {}".format(e)) return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_REST_API, e), ret_data try: headers = {"Content-Type": "application/json", "ACCEPT": "application/json"} - resp = request_func(url, json=data, verify=verify, headers=headers, auth=self._ers_auth) + resp = request_func( # nosemgrep: python.requests.best-practice.use-timeout.use-timeout + url, + json=data, + verify=verify, + headers=headers, + auth=auth_method + ) except Exception as e: + self.debug_print("Exception occurred: {}".format(e)) return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_REST_API, e), ret_data if not (200 <= resp.status_code < 399): @@ -154,6 +189,7 @@ def _call_rest_api(self, endpoint, action_result, schema=None, data=None, allow_ verify=verify, auth=self._auth) except Exception as e: + self.debug_print("Exception occurred: {}".format(e)) return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_REST_API, e), ret_data if resp.status_code != 200: @@ -173,6 +209,7 @@ def _call_rest_api(self, endpoint, action_result, schema=None, data=None, allow_ try: response_dict = xmltodict.parse(xml) except Exception as e: + self.debug_print("Exception occurred: {}".format(e)) return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_UNABLE_TO_PARSE_REPLY, e), ret_data ret_data = response_dict @@ -194,14 +231,10 @@ def _map_resource_type(self, resource_type, action_result, *args): def _list_sessions(self, param): - ret_val = phantom.APP_SUCCESS - action_result = self.add_action_result(ActionResult(dict(param))) summary = action_result.update_summary({CISCOISE_JSON_TOTAL_SESSIONS: 0}) - ret_data = None - ret_val, ret_data = self._call_rest_api(ACTIVE_LIST_REST, action_result) if phantom.is_fail(ret_val): @@ -246,14 +279,11 @@ def _list_sessions(self, param): def _list_endpoints(self, param): - ret_val = phantom.APP_SUCCESS - action_result = self.add_action_result(ActionResult(dict(param))) - ret_data = None endpoint = ERS_ENDPOINT_REST - mac_filter = param.get("mac_address", None) + mac_filter = param.get("mac_address") if mac_filter is not None: endpoint = ERS_ENDPOINT_REST + "?filter=mac.EQ." + mac_filter @@ -272,11 +302,8 @@ def _list_endpoints(self, param): def _get_endpoint(self, param): - ret_val = phantom.APP_SUCCESS - action_result = self.add_action_result(ActionResult(dict(param))) - ret_data = None endpoint = ERS_ENDPOINT_REST + "/" + param["endpoint_id"] ret_val, ret_data = self._call_ers_api(endpoint, action_result) @@ -325,118 +352,10 @@ def _update_endpoint(self, param): return action_result.set_status(phantom.APP_SUCCESS, "Endpoint Updated") - def _quarantine_system(self, param): - - ret_val = phantom.APP_SUCCESS - - action_result = self.add_action_result(ActionResult(dict(param))) - - ret_data = None - - mac_ip_address = param[phantom.APP_JSON_IP_MACADDRESS] - - if phantom.is_mac(mac_ip_address): - endpoint = "{0}/{1}".format(QUARANTINE_MAC_REST, mac_ip_address) - elif phantom.is_ip(mac_ip_address): - endpoint = "{0}/{1}".format(QUARANTINE_IP_REST, mac_ip_address) - else: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_MAC_AND_IP_NOT_SPECIFIED) - - ret_val, ret_data = self._call_rest_api(endpoint, action_result, QUARANTINE_RESP_SCHEMA) - - if phantom.is_fail(ret_val): - return action_result.get_status() - - action_result.add_data(ret_data) - - # Can safely access the members of ret_data, since they have been parsed as by the rules of - # QUARANTINE_RESP_SCHEMA - status = ret_data["EPS_RESULT"]["status"] - - if status == "Failure": - return action_result.set_status( - phantom.APP_ERROR, - CISCOISE_ERR_ACTION_FAILED, - error_code=ret_data["EPS_RESULT"]["errorCode"] - ) - - # In cases where the radius authentication failed, the status is STILL set to success, - # but failureType and failureMessage keys are added to the ret_data, so need to check for those - failure_type = phantom.get_value(ret_data["EPS_RESULT"], "failureType") - failure_msg = phantom.get_value(ret_data["EPS_RESULT"], "failureMessage") - - if (failure_type is not None) or (failure_msg is not None): - action_result.set_status( - phantom.APP_ERROR, CISCOISE_ERR_ACTION_FAILED, error_code=ret_data["EPS_RESULT"]["errorCode"] - ) - if failure_type is not None: - action_result.append_to_message(failure_type) - if failure_msg is not None: - action_result.append_to_message(failure_msg) - return action_result.get_status() - - return action_result.set_status(phantom.APP_SUCCESS, CISCOISE_SUCC_SYSTEM_QUARANTINED) - - def _unquarantine_system(self, param): - - ret_val = phantom.APP_SUCCESS - - action_result = self.add_action_result(ActionResult(dict(param))) - - ret_data = None - - mac_ip_address = param[phantom.APP_JSON_IP_MACADDRESS] - - if phantom.is_mac(mac_ip_address): - endpoint = "{0}/{1}".format(UNQUARANTINE_MAC_REST, mac_ip_address) - elif phantom.is_ip(mac_ip_address): - endpoint = "{0}/{1}".format(UNQUARANTINE_IP_REST, mac_ip_address) - else: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_MAC_AND_IP_NOT_SPECIFIED) - - ret_val, ret_data = self._call_rest_api(endpoint, action_result, QUARANTINE_RESP_SCHEMA) - - if phantom.is_fail(ret_val): - return action_result.get_status() - - action_result.add_data(ret_data) - - status = ret_data["EPS_RESULT"]["status"] - - if status == "Failure": - return action_result.set_status( - phantom.APP_ERROR, CISCOISE_ERR_ACTION_FAILED, error_code=ret_data["EPS_RESULT"]["errorCode"] - ) - - # In cases where the radius authentication failed, the status is STILL set to success, - # but failureType and failureMessage keys are added to the ret_data, so need to check for those - failure_type = phantom.get_value(ret_data["EPS_RESULT"], "failureType") - failure_msg = phantom.get_value(ret_data["EPS_RESULT"], "failureMessage") - - if (failure_type is not None) or (failure_msg is not None): - action_result.set_status( - phantom.APP_ERROR, - CISCOISE_ERR_ACTION_FAILED, - error_code=ret_data["EPS_RESULT"]["errorCode"], - ) - if failure_type is not None: - action_result.append_to_message(failure_type) - if failure_msg is not None: - action_result.append_to_message(failure_msg) - return action_result.get_status() - - return action_result.set_status( - phantom.APP_SUCCESS, CISCOISE_SUCC_SYSTEM_UNQUARANTINED - ) - def _logoff_system(self, param): - ret_val = phantom.APP_SUCCESS - action_result = self.add_action_result(ActionResult(dict(param))) - ret_data = None - server = param[CISCOISE_JSON_SERVER] mac_address = param[CISCOISE_JSON_MACADDR] port = 2 # 0 is default, 1 is bounce, 2 is shutdown @@ -467,12 +386,8 @@ def _logoff_system(self, param): def _terminate_session(self, param): - ret_val = phantom.APP_SUCCESS - action_result = self.add_action_result(ActionResult(dict(param))) - ret_data = None - mac_address = param[phantom.APP_JSON_MACADDRESS] port = 2 # 0 is default, 1 is bounce, 2 is shutdown @@ -546,17 +461,12 @@ def _list_resources(self, param): action_result = self.add_action_result(ActionResult(dict(param))) resource = self._map_resource_type(param["resource"], action_result) - max_result = param.get("max_results") - endpoint = ERS_RESOURCE_REST.format(resource=resource) + ret_val, max_result = self._validate_integers(action_result, param.get("max_results"), 'max_result') - try: - if max_result: - max_result = int(max_result) - except ValueError as ex: # noqa: F841 - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_INVALID_PARAM.format(param="max_result")) + if phantom.is_fail(ret_val): + return action_result.get_status() - if max_result is not None and max_result <= 0: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_INVALID_PARAM.format(param="max_result")) + endpoint = ERS_RESOURCE_REST.format(resource=resource) resources = self._paginator(endpoint, action_result, limit=max_result) @@ -727,6 +637,67 @@ def _clear_policy(self, param): action_result.add_data(ret_data) return action_result.set_status(phantom.APP_SUCCESS, "Policy cleared") + def _list_policies(self, param): + + action_result = self.add_action_result(ActionResult(dict(param))) + + endpoint = ERS_POLICIES + + ret_val, ret_data = self._call_ers_api(endpoint, action_result) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + total = ret_data["SearchResult"]["total"] + policies = ret_data["SearchResult"]["resources"] + + for policy in policies: + endpoint = f"{ERS_POLICIES}/{policy['id']}" + + ret_val, ret_data = self._call_ers_api(endpoint, action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + data = ret_data["ErsAncPolicy"] + data['actions'] = ', '.join(data['actions']) + action_result.add_data(data) + + action_result.update_summary({"policies_found": total}) + + return action_result.set_status(phantom.APP_SUCCESS) + + def _delete_policy(self, param): + + action_result = self.add_action_result(ActionResult(dict(param))) + + endpoint = f"{ERS_POLICIES}/{param['policy_name']}" + + ret_val, ret_data = self._call_ers_api(endpoint, action_result, method="delete") + + if phantom.is_fail(ret_val): + return action_result.get_status() + + return action_result.set_status(phantom.APP_SUCCESS, "Policy deleted") + + def _add_policy(self, param): + + action_result = self.add_action_result(ActionResult(dict(param))) + + body = { + "ErsAncPolicy": { + "name": param["name"], + "actions": [param["action_type"]] + } + } + + endpoint = f"{ERS_POLICIES}" + + ret_val, ret_data = self._call_ers_api(endpoint, action_result, method="post", data=body) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + return action_result.set_status(phantom.APP_SUCCESS, 'Policy created') + def _test_connectivity_to_device(self, base_url, verify=True): try: rest_endpoint = "{0}{1}".format(base_url, ACTIVE_LIST_REST) @@ -774,10 +745,6 @@ def handle_action(self, param): result = self._terminate_session(param) elif action == self.ACTION_ID_LOGOFF_SYSTEM: result = self._logoff_system(param) - elif action == self.ACTION_ID_QUARANTINE_SYSTEM: - result = self._quarantine_system(param) - elif action == self.ACTION_ID_UNQUARANTINE_SYSTEM: - result = self._unquarantine_system(param) elif action == self.ACTION_ID_LIST_ENDPOINTS: result = self._list_endpoints(param) elif action == self.ACTION_ID_GET_ENDPOINT: @@ -798,6 +765,12 @@ def handle_action(self, param): result = self._apply_policy(param) elif action == self.ACTION_ID_CLEAR_POLICY: result = self._clear_policy(param) + elif action == self.ACTION_ID_LIST_POLICIES: + result = self._list_policies(param) + elif action == self.ACTION_ID_CREATE_POLICY: + result = self._add_policy(param) + elif action == self.ACTION_ID_DELETE_POLICY: + result = self._delete_policy(param) return result diff --git a/ciscoise_consts.py b/ciscoise_consts.py index d141e81..9dab218 100644 --- a/ciscoise_consts.py +++ b/ciscoise_consts.py @@ -1,6 +1,6 @@ # File: ciscoise_consts.py # -# Copyright (c) 2014-2021 Splunk Inc. +# Copyright (c) 2014-2022 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,15 +25,12 @@ DISCONNECT_MAC_REST = "/ise/mnt/CoA/Disconnect" REAUTH_MAC_REST = "/ise/mnt/CoA/Reauth" IS_MAC_QUARANTINED_REST = "/ise/eps/isQuarantineByMAC" -QUARANTINE_MAC_REST = "/ise/eps/QuarantineByMAC_S" -QUARANTINE_IP_REST = "/ise/eps/QuarantineByIP_S" -UNQUARANTINE_MAC_REST = "/ise/eps/UnQuarantineByMAC_S" -UNQUARANTINE_IP_REST = "/ise/eps/UnQuarantineByIP_S" MAC_SESSION_DETAILS_REST = "/ise/mnt/Session/MACAddress" ERS_ENDPOINT_REST = ":9060/ers/config/endpoint" ERS_RESOURCE_REST = ":9060/ers/config/{resource}" ERS_ENDPOINT_ANC_APPLY = ":9060/ers/config/ancendpoint/apply" ERS_ENDPOINT_ANC_CLEAR = ":9060/ers/config/ancendpoint/clear" +ERS_POLICIES = ":9060/ers/config/ancpolicy" # Error/Success CISCOISE_ERR_TEST_CONNECTIVITY_FAILED = "Test connectivity failed" @@ -48,8 +45,6 @@ CISCOISE_ERR_LOGOFF_SYSTEM = "System Logoff failed" CISCOISE_ERR_MAC_AND_IP_NOT_SPECIFIED = "Please specify a valid mac or ip address to execute action" CISCOISE_ERR_ACTION_FAILED = "Action failed with error code: {error_code}" -CISCOISE_SUCC_SYSTEM_QUARANTINED = "System Quarantined" -CISCOISE_SUCC_SYSTEM_UNQUARANTINED = "System unquarantined" CISCOISE_SUCC_LIST_ENDPOINTS = "{0} Endpoints found" CISCOISE_SUCC_GET_ENDPOINT = "Endpoint found" CISCOISE_SUCC_UPDATE_ENDPOINT = "Endpoint updated" @@ -62,11 +57,7 @@ IS_MAC_QUARAN_RESP_SCHEMA = { "EPS_RESULT": {"type": "dict", "schema": {"status": {"type": "string"}, "userData": {"type": "string"}}} } -QUARANTINE_RESP_SCHEMA = { - "EPS_RESULT": {"type": "dict", "schema": {"status": {"type": "string"}, "errorCode": {"type": "string"}}} -} MAC_SESSION_RESP_SCHEMA = {"sessionParameters": {"type": "dict", "schema": {"acs_server": {"type": "string"}}}} -DISCONNECT_MAC_SESS_RESP_SCHEMA = {"remoteCoA": {"type": "dict", "schema": {"results": {"type": "string"}}}} ERS_UPDATE_ENDPOINT_SCHEMA = { "updatedField": {"type": "dict", "schema": {"newValue": {"type": "string"}, "oldValue": {"type": "string"}}} } diff --git a/readme.html b/readme.html index fca0233..47f5f35 100644 --- a/readme.html +++ b/readme.html @@ -1,29 +1,34 @@ -
ERS uses on HTTPS port 9060 which is by default closed. Clients trying to access this port without enabling ERS first, will face a timeout from the server. - Therefore, the first requirement is to enable ERS from the Cisco ISE admin UI. Go to Administration > Settings > ERS Settings and enable the Enable ERS - for Read/Write radio button
-Go to Administration > Settings > ERS Settings and then from the panel on the left select Admin Users under administrators. - Now add an account by clicking Add > Create an admin user. Then enter name and password and select ERS Admin in Admin Group and then press save.
-