From b801b6ecb662dd19222d3fab29c300201028f48c Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 18 Jul 2022 09:52:05 -0700 Subject: [PATCH 01/10] Adding workflow file for release review --- .github/workflows/review-release.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/review-release.yml diff --git a/.github/workflows/review-release.yml b/.github/workflows/review-release.yml new file mode 100644 index 0000000..6f3bf31 --- /dev/null +++ b/.github/workflows/review-release.yml @@ -0,0 +1,22 @@ +name: Review Release +concurrency: + group: app-release + cancel-in-progress: true +permissions: + contents: read + id-token: write + statuses: write +on: + workflow_dispatch: + inputs: + task_token: + description: 'StepFunction task token' + required: true + +jobs: + review: + uses: 'phantomcyber/dev-cicd-tools/.github/workflows/review-release.yml@main' + with: + task_token: ${{ inputs.task_token }} + secrets: + resume_release_role_arn: ${{ secrets.RESUME_RELEASE_ROLE_ARN }} From 32f5b6c80dff2856dd5a0bc0c722d1ddcf6d8342 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Thu, 21 Jul 2022 20:08:39 -0700 Subject: [PATCH 02/10] 'stop maintaining and delete release_notes.html' --- release_notes/release_notes.html | 50 -------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 release_notes/release_notes.html diff --git a/release_notes/release_notes.html b/release_notes/release_notes.html deleted file mode 100644 index 9fa8c01..0000000 --- a/release_notes/release_notes.html +++ /dev/null @@ -1,50 +0,0 @@ -Cisco ISE Release Notes - Published by Splunk March 11, 2022 -

-Version 3.0.1 - Released March 11, 2022 - -Version 3.0.0 - Released March 03, 2022 - -Version 2.0.5 - Released December 21, 2021 - -Version 1.2.17 - Released February 07, 2018 - -Version 1.2.14 - Released August 23, 2017 - -Version 1.2.12 - Released July 27, 2017 - -Version 1.2.11 - Released October 14, 2016 - From 64d629da928629098d36c9b0f445d9e13fb1fc13 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Thu, 2 Mar 2023 20:00:36 -0800 Subject: [PATCH 03/10] 'create generate-doc.yml file' --- .github/workflows/generate-doc.yml | 14 ++++++++++++++ .pre-commit-config.yaml | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/generate-doc.yml diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml new file mode 100644 index 0000000..4661718 --- /dev/null +++ b/.github/workflows/generate-doc.yml @@ -0,0 +1,14 @@ +name: Generate Readme Doc +on: + workflow_dispatch: + push: + paths: + - '*.json' + - 'readme.html' +jobs: + generate-doc: + runs-on: ubuntu-latest + steps: + - uses: 'phantomcyber/dev-cicd-tools/github-actions/generate-doc@main' + with: + GITHUB_TOKEN: ${{ secrets.SOAR_APPS_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa97c3c..827b060 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/phantomcyber/dev-cicd-tools - rev: v1.11 + rev: v1.16 hooks: - id: org-hook - id: package-app-dependencies - repo: https://github.com/Yelp/detect-secrets - rev: v1.1.0 + rev: v1.4.0 hooks: - id: detect-secrets args: ['--no-verify', '--exclude-files', '^ciscoise.json$'] From 076c02a85cdef7604055255d544c2bdddc0c6499 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Mon, 6 Mar 2023 20:18:33 -0800 Subject: [PATCH 04/10] 'update generate-doc.yml file' --- .github/workflows/generate-doc.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml index 4661718..e63a4cd 100644 --- a/.github/workflows/generate-doc.yml +++ b/.github/workflows/generate-doc.yml @@ -5,6 +5,11 @@ on: paths: - '*.json' - 'readme.html' + tags-ignore: + - '*-beta*' + branches-ignore: + - next + - main jobs: generate-doc: runs-on: ubuntu-latest From 6a6825e7e53a9a19eb6f19969b1a0256254fda2a Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Tue, 7 Mar 2023 14:22:38 -0800 Subject: [PATCH 05/10] 'update generate-doc.yml file' --- .github/workflows/generate-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml index e63a4cd..7a3ba90 100644 --- a/.github/workflows/generate-doc.yml +++ b/.github/workflows/generate-doc.yml @@ -6,7 +6,7 @@ on: - '*.json' - 'readme.html' tags-ignore: - - '*-beta*' + - '**' branches-ignore: - next - main From ba93690a714b49b34a0aa8e583bce1225d5f9ecf Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Fri, 21 Apr 2023 23:36:10 -0700 Subject: [PATCH 06/10] 'update generate-doc.yml file with manual_readme_content.md' --- .github/workflows/generate-doc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml index 7a3ba90..9284f9d 100644 --- a/.github/workflows/generate-doc.yml +++ b/.github/workflows/generate-doc.yml @@ -5,6 +5,7 @@ on: paths: - '*.json' - 'readme.html' + - 'manual_readme_content.md' tags-ignore: - '**' branches-ignore: From c400f4e9bc981524b0dc5d1a9a3541cc3804eead Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Fri, 14 Jul 2023 14:21:03 -0700 Subject: [PATCH 07/10] 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 e6814816c7e83066d00c86c29aa67376cc314453 Mon Sep 17 00:00:00 2001 From: splunk-soar-connectors-admin Date: Tue, 1 Aug 2023 12:08:43 -0700 Subject: [PATCH 08/10] 'convert readme.html to manual_readme_content.md' --- manual_readme_content.md | 183 ++++++++++++++++++++++++++++++++++++++ readme.html | 187 --------------------------------------- 2 files changed, 183 insertions(+), 187 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..6d14ff0 --- /dev/null +++ b/manual_readme_content.md @@ -0,0 +1,183 @@ +[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 + +- 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 3.0.0. + 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 | diff --git a/readme.html b/readme.html deleted file mode 100644 index 8cdf51a..0000000 --- a/readme.html +++ /dev/null @@ -1,187 +0,0 @@ - - -

Asset Configuration For Authentication

-
    -
  • 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 3.0.0. Users are advised to use "apply policy" and "clear policy" actions to achieve the same objective
  2. -
  3. 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
    • -
    -
  4. -
  5. An ISE node can assume any or all of the following personas: Administration, Policy Service, and Monitoring. For detailed info: - Types of nodes -
      -
    • 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
    • -
    -
  6. -
  7. 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). Examples as below
  8. -
      -
    • 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 NameTransport ProtocolPort
httptcp80
httpstcp443
-

From d5de11cb87b121439fd85447177b8026d47f5fbb Mon Sep 17 00:00:00 2001 From: achandya-crest <70213464+achandya-crest@users.noreply.github.com> Date: Wed, 20 Dec 2023 19:07:32 +0530 Subject: [PATCH 09/10] PAPP-30822: Updated requests modules (#12) * Updated requests modules * Update README.md * updated copyright right version and constant names for static failures * updated json data * updated notice file * pre-commit chnages * empty commit * updated release notes * empty commit * empty commit to trigger pipelines --------- Co-authored-by: splunk-soar-connectors-admin Co-authored-by: hardik-crest --- LICENSE | 4 +- NOTICE | 7 +- README.md | 480 +++++++++--------- __init__.py | 2 +- ciscoise.json | 48 +- ciscoise_connector.py | 38 +- ciscoise_consts.py | 24 +- manual_readme_content.md | 8 +- release_notes/unreleased.md | 1 + requirements.txt | 1 - tox.ini | 2 +- wheels/py3/setuptools-60.8.2-py3-none-any.whl | Bin 1060226 -> 0 bytes wheels/py3/setuptools-69.0.2-py3-none-any.whl | Bin 0 -> 819519 bytes .../certifi-2021.10.8-py2.py3-none-any.whl | Bin 149195 -> 0 bytes .../shared/chardet-3.0.4-py2.py3-none-any.whl | Bin 133356 -> 0 bytes wheels/shared/idna-2.10-py2.py3-none-any.whl | Bin 58811 -> 0 bytes .../requests-2.25.0-py2.py3-none-any.whl | Bin 61132 -> 0 bytes .../urllib3-1.26.8-py2.py3-none-any.whl | Bin 138699 -> 0 bytes 18 files changed, 288 insertions(+), 327 deletions(-) delete mode 100644 wheels/py3/setuptools-60.8.2-py3-none-any.whl create mode 100644 wheels/py3/setuptools-69.0.2-py3-none-any.whl delete mode 100644 wheels/shared/certifi-2021.10.8-py2.py3-none-any.whl delete mode 100644 wheels/shared/chardet-3.0.4-py2.py3-none-any.whl delete mode 100644 wheels/shared/idna-2.10-py2.py3-none-any.whl delete mode 100644 wheels/shared/requests-2.25.0-py2.py3-none-any.whl delete mode 100644 wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl diff --git a/LICENSE b/LICENSE index e6f5c5c..21ab60a 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) 2014-2022 Splunk Inc. + Copyright (c) 2014-2023 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. \ No newline at end of file + limitations under the License. diff --git a/NOTICE b/NOTICE index debfd39..734fbd3 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Splunk SOAR Cisco ISE -Copyright (c) 2014-2022 Splunk Inc. +Copyright (c) 2014-2023 Splunk Inc. Third-party Software Attributions: @@ -8,11 +8,6 @@ Version: 1.3.4 License: ISC Copyright 2012-2016 Nicola Iarocci -Library: requests -Version: 2.25.0 -License: Apache 2.0 -Kenneth Reitz - Library: xmltodict Version: 0.12.0 License: MIT diff --git a/README.md b/README.md index a4d94af..ef8dd95 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ # Cisco ISE Publisher: Splunk -Connector Version: 3\.0\.1 +Connector Version: 3.0.2 Product Vendor: Cisco Systems Product Name: Cisco ISE -Product Version Supported (regex): "/\(\[2\]\.\[67\]\)\|\(\[3\]\.\[01\]\)/" -Minimum Product Version: 5\.1\.0 +Product Version Supported (regex): "/([2].[67])|([3].[01])/" +Minimum Product Version: 5.1.0 This app implements investigative and containment actions on a Cisco ISE device [comment]: # " File: README.md" -[comment]: # " Copyright (c) 2014-2022 Splunk Inc." +[comment]: # " Copyright (c) 2014-2023 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." @@ -94,7 +94,7 @@ This app implements investigative and containment actions on a Cisco ISE device "name": "guestUser", "guestInfo": { "userName": "DS3ewdsa34wWE", - "password": "asdlkj324ew", + "password": "asdlkj324ew", # pragma: allowlist secret "enabled": true }, "guestAccessInfo": { @@ -122,7 +122,7 @@ This app implements investigative and containment actions on a Cisco ISE device "enabled": true, "password": "*******", "changePassword": true, - "passwordIDStore": "Internal Users" + "passwordIDStore": "Internal Users" # pragma: allowlist secret } } @@ -152,7 +152,7 @@ This app implements investigative and containment actions on a Cisco ISE device "pushIdSupport": false }, "tacacsSettings": { - "sharedSecret": "aaa" + "sharedSecret": "aaa" # pragma: allowlist secret }, "profileName": "Cisco", "NetworkDeviceIPList": [ @@ -201,22 +201,22 @@ The below configuration variables are required for this Connector to operate. T VARIABLE | REQUIRED | TYPE | DESCRIPTION -------- | -------- | ---- | ----------- **device** | required | string | Device IP/Hostname -**ha\_device** | optional | string | Device IP/Hostname for a High Availability node if available +**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 +**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 +[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 +[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 @@ -227,7 +227,7 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [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 +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** @@ -247,24 +247,24 @@ 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.mac_address | string | `mac address` | 11:11:11:11:11:11 +action_result.data.\*.SearchResult.resources.\*.id | string | `ise endpoint id` `ise resource id` | d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.SearchResult.resources.\*.link.href | string | `url` | https://10.16.0.92:9060/ers/config/endpoint/d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.SearchResult.resources.\*.link.rel | string | | self +action_result.data.\*.SearchResult.resources.\*.link.type | string | | application/xml +action_result.data.\*.SearchResult.resources.\*.name | string | | 8C:85:90:17:D6:39 +action_result.data.\*.SearchResult.total | numeric | | 1 +action_result.summary.Endpoints found | string | | 9 1 +action_result.summary.endpoints_found | numeric | | 1 +action_result.message | string | | 9 Endpoints found 1 Endpoints found +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'get device info' Get information about a specific endpoint @@ -275,32 +275,32 @@ 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.endpoint_id | string | `ise endpoint id` `ise resource id` | 59985000-712d-11e6-9062-000c29bea319 d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.ERSEndPoint.customAttributes.customAttributes.ITSecurityBlock | string | | true +action_result.data.\*.ERSEndPoint.description | string | | description +action_result.data.\*.ERSEndPoint.groupId | string | | aa10ae00-8bff-11e6-996c-525400b48521 +action_result.data.\*.ERSEndPoint.id | string | `ise endpoint id` `ise resource id` | d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.ERSEndPoint.identityStore | string | | +action_result.data.\*.ERSEndPoint.identityStoreId | string | | +action_result.data.\*.ERSEndPoint.link.href | string | `url` | https://10.16.0.92:9060/ers/config/endpoint/d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.ERSEndPoint.link.rel | string | | self +action_result.data.\*.ERSEndPoint.link.type | string | | application/xml +action_result.data.\*.ERSEndPoint.mac | string | | 8C:85:90:17:D6:39 +action_result.data.\*.ERSEndPoint.name | string | | 8C:85:90:17:D6:39 +action_result.data.\*.ERSEndPoint.portalUser | string | | +action_result.data.\*.ERSEndPoint.profileId | string | | 09663280-8c00-11e6-996c-525400b48521 +action_result.data.\*.ERSEndPoint.staticGroupAssignment | boolean | | True False +action_result.data.\*.ERSEndPoint.staticProfileAssignment | boolean | | True False +action_result.summary | string | | +action_result.message | string | | Endpoint found +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'update device info' Update information or attributes for a specific endpoint @@ -311,28 +311,28 @@ 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` +**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 | +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.attribute | string | | ITSecurityBlock +action_result.parameter.attribute_value | string | | True +action_result.parameter.custom_attribute | string | | CustomAttribute +action_result.parameter.custom_attribute_value | string | | True +action_result.parameter.endpoint_id | string | `ise endpoint id` `ise resource id` | d0337940-a86f-11e7-b6e9-000c29d5f0ea +action_result.data.\*.UpdatedFieldsList.updatedField.\*.field | string | | customAttributes +action_result.data.\*.UpdatedFieldsList.updatedField.\*.newValue | string | | {ITSecurityBlock=True} +action_result.data.\*.UpdatedFieldsList.updatedField.\*.oldValue | string | | {ITSecurityBlock=False} +action_result.summary | string | | +action_result.message | string | | Endpoint Updated +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'list sessions' List the sessions currently available on the Monitoring node @@ -344,23 +344,23 @@ Read only: **True** 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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +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 | | 0 +action_result.message | string | | +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'terminate session' Terminate sessions @@ -374,15 +374,15 @@ 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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.macaddress | string | `mac address` | 11:11:11:11:11:11 +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 @@ -394,27 +394,27 @@ Read only: **True** 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 | +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.max_results | numeric | | 2 +action_result.parameter.resource | string | | Endpoints +action_result.data.\*.description | string | | Default portal used by sponsors to create and manage accounts for authorized visitors to securely access the network +action_result.data.\*.id | string | `ise resource id` | 40963c00-2e02-11e8-ba71-005056872c7f +action_result.data.\*.link.href | string | `url` | https://10.1.16.169:9060/ers/config/portal/40963c00-2e02-11e8-ba71-005056872c7f +action_result.data.\*.link.rel | string | | self +action_result.data.\*.link.type | string | | application/xml +action_result.data.\*.name | string | | Sponsor Portal (default) +action_result.summary.resources_returned | numeric | | 5 +action_result.message | string | | Resources returned: 5 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'get resources' -Get the information about resource if resource\_id is provided\. Fetch the list of resources match with the key\-value filter +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** @@ -423,37 +423,37 @@ Read only: **True** PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- **resource** | required | Resource type of the resource to fetch | string | -**resource\_id** | optional | Resource ID | string | `ise resource id` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.key | string | | mac +action_result.parameter.resource | string | | Endpoints +action_result.parameter.resource_id | string | `ise resource id` | 2e9cf1c0-30b6-11ea-8f06-ce112ec9f8fa +action_result.parameter.value | string | | 00:00:00:00:00:00 +action_result.data.\*.description | string | | This endpoint for test +action_result.data.\*.groupId | string | | aa10ae00-8bff-11e6-996c-525400b48521 +action_result.data.\*.id | string | `ise resource id` | d335f970-10e0-11ea-8f06-ce112ec9f8fa +action_result.data.\*.identityStore | string | | +action_result.data.\*.identityStoreId | string | | +action_result.data.\*.link.href | string | `url` | https://10.1.16.169:9060/ers/config/endpoint/d335f970-10e0-11ea-8f06-ce112ec9f8fa +action_result.data.\*.link.rel | string | | self +action_result.data.\*.link.type | string | | application/xml +action_result.data.\*.mac | string | | 00:00:00:00:00:00 +action_result.data.\*.name | string | | 00:00:00:00:00:00 +action_result.data.\*.portalUser | string | | +action_result.data.\*.profileId | string | | 44031480-8c00-11e6-996c-525400b48521 +action_result.data.\*.staticGroupAssignment | boolean | | True False +action_result.data.\*.staticProfileAssignment | boolean | | True False +action_result.summary.resource_id | string | `ise resource id` | d335f970-10e0-11ea-8f06-ce112ec9f8fa +action_result.summary.resources_returned | numeric | | 0 +action_result.message | string | | Resource id: d335f970-10e0-11ea-8f06-ce112ec9f8fa +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'delete resource' Delete a resource @@ -465,19 +465,19 @@ Read only: **False** 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.resource | string | | Endpoints +action_result.parameter.resource_id | string | `ise resource id` | 2e9cf1c0-30b6-11ea-8f06-ce112ec9f8fa +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Resource deleted successfully +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'create resource' Create a resource @@ -489,19 +489,25 @@ Read only: **False** 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 | +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.resource | string | | Endpoints +action_result.parameter.resource_json | string | | { +"ERSEndPoint": { +"name": "name", +"description": "MyEndpoint", +"mac": "11:22:33:44:55:66" +} +} +action_result.data | string | | +action_result.summary | string | | Resource created successfully +action_result.message | string | | Resource created successfully +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'update resource' Update a resource @@ -513,23 +519,23 @@ Read only: **False** 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.key | string | | mac +action_result.parameter.resource | string | | Endpoints +action_result.parameter.resource_id | string | `ise resource id` | 2e9cf1c0-30b6-11ea-8f06-ce112ec9f8fa +action_result.parameter.value | string | | 11:11:11:11:11:11 +action_result.data | string | | +action_result.summary | string | | Resource created successfully +action_result.message | string | | Resource updated successfully +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'apply policy' Apply policy on selected Ip address or MAC address @@ -540,20 +546,20 @@ 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.ip_mac_address | string | `mac address` `ip` | 11:11:11:11:11:11 +action_result.parameter.policy_name | string | | testPolicy +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Policy applied +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'clear policy' Clear policy on selected Ip address or MAC address @@ -564,20 +570,20 @@ 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` +**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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.ip_mac_address | string | `mac address` `ip` | 11:11:11:11:11:11 +action_result.parameter.policy_name | string | | testPolicy +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Policy cleared +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'list policies' Lists all the ANC policies available @@ -589,20 +595,20 @@ Read only: **True** 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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.data.\*.actions | string | | +action_result.data.\*.id | string | `ise policy id` | policy_name +action_result.data.\*.link.href | string | | https://10.0.0.0:9060/ers/config/ancpolicy/policy_name +action_result.data.\*.link.rel | string | | self +action_result.data.\*.link.type | string | | application/json +action_result.data.\*.name | string | | policy_name +action_result.summary | string | | +action_result.summary.policies_found | numeric | | +action_result.message | string | | Policies found: 1 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'add policy' Add a new ANC Policy @@ -614,19 +620,19 @@ Read only: **False** PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- **name** | required | Policy Name | string | -**action\_type** | required | Policy action type | 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 | +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.action_type | string | | QUARANTINE +action_result.parameter.name | string | | policy_name +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Policy created +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 ## action: 'delete policy' Delete a policy @@ -637,15 +643,15 @@ Read only: **False** #### Action Parameters PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS --------- | -------- | ----------- | ---- | -------- -**policy\_name** | required | Policy Name | string | `ise policy id` +**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 +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.policy_name | string | `ise policy id` | +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Policy deleted +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 \ No newline at end of file diff --git a/__init__.py b/__init__.py index 77b1650..445e59b 100644 --- a/__init__.py +++ b/__init__.py @@ -1,6 +1,6 @@ # File: __init__.py # -# Copyright (c) 2014-2022 Splunk Inc. +# Copyright (c) 2014-2023 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 1798639..127614d 100644 --- a/ciscoise.json +++ b/ciscoise.json @@ -5,7 +5,7 @@ "publisher": "Splunk", "type": "network security", "main_module": "ciscoise_connector.py", - "app_version": "3.0.1", + "app_version": "3.0.2", "utctime_updated": "2022-03-11T04:16:56.000000Z", "package_name": "phantom_ciscoise", "product_vendor": "Cisco Systems", @@ -14,7 +14,7 @@ "min_phantom_version": "5.1.0", "logo": "logo_cisco.svg", "logo_dark": "logo_cisco_dark.svg", - "license": "Copyright (c) 2014-2022 Splunk Inc.", + "license": "Copyright (c) 2014-2023 Splunk Inc.", "python_version": "3", "fips_compliant": true, "latest_tested_version": [ @@ -1903,30 +1903,10 @@ "module": "Cerberus", "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" @@ -1939,29 +1919,9 @@ "module": "Cerberus", "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-60.8.2-py3-none-any.whl" - }, - { - "module": "urllib3", - "input_file": "wheels/shared/urllib3-1.26.8-py2.py3-none-any.whl" + "input_file": "wheels/py3/setuptools-69.0.2-py3-none-any.whl" }, { "module": "xmltodict", @@ -1969,4 +1929,4 @@ } ] } -} \ No newline at end of file +} diff --git a/ciscoise_connector.py b/ciscoise_connector.py index 9e28670..67d32b8 100644 --- a/ciscoise_connector.py +++ b/ciscoise_connector.py @@ -1,6 +1,6 @@ # File: ciscoise_connector.py # -# Copyright (c) 2014-2022 Splunk Inc. +# Copyright (c) 2014-2023 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -87,11 +87,11 @@ def _validate_integers(self, action_result, parameter, key, allow_zero=False): 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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_INVALID_PARAM.format(key)), None if parameter < 0: return action_result.set_status(phantom.APP_ERROR, @@ -132,7 +132,7 @@ def _call_ers_api(self, endpoint, action_result, data=None, allow_unknown=True, 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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_REST_API, e), ret_data try: headers = {"Content-Type": "application/json", "ACCEPT": "application/json"} resp = request_func( # nosemgrep: python.requests.best-practice.use-timeout.use-timeout @@ -144,7 +144,7 @@ def _call_ers_api(self, endpoint, action_result, data=None, allow_unknown=True, ) 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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_REST_API, e), ret_data if not (200 <= resp.status_code < 399): error_message = resp.text @@ -156,7 +156,7 @@ def _call_ers_api(self, endpoint, action_result, data=None, allow_unknown=True, return ( action_result.set_status( phantom.APP_ERROR, - CISCOISE_ERR_REST_API_ERR_CODE, + CISCOISE_REST_API_ERROR_CODE, code=resp.status_code, message=error_message ), @@ -190,13 +190,13 @@ def _call_rest_api(self, endpoint, action_result, schema=None, data=None, allow_ 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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_REST_API, e), ret_data if resp.status_code != 200: return ( action_result.set_status( phantom.APP_ERROR, - CISCOISE_ERR_REST_API_ERR_CODE, + CISCOISE_REST_API_ERROR_CODE, code=resp.status_code, message=resp.text, ), @@ -210,14 +210,14 @@ def _call_rest_api(self, endpoint, action_result, schema=None, data=None, allow_ 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 + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_UNABLE_TO_PARSE_REPLY, e), ret_data ret_data = response_dict if schema is not None: v = Validator(schema, allow_unknown=allow_unknown) if v.validate(ret_data) is False: - action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_UNABLE_TO_PARSE_REPLY) + action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_UNABLE_TO_PARSE_REPLY) action_result.append_to_message(v.errors) return action_result.get_status(), ret_data @@ -372,15 +372,15 @@ def _logoff_system(self, param): remote_coa = ret_data.get("remoteCoA") if remote_coa is None: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_PARSE_REPLY) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_PARSE_REPLY) result = remote_coa.get("results") if result is None: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_PARSE_REPLY) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_PARSE_REPLY) if result == "false": - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_LOGOFF_SYSTEM) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_LOGOFF_SYSTEM) return action_result.set_status(phantom.APP_SUCCESS) @@ -412,15 +412,15 @@ def _terminate_session(self, param): remote_coa = ret_data.get("remoteCoA") if remote_coa is None: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_PARSE_REPLY) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_PARSE_REPLY) result = remote_coa.get("results") if result is None: - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_PARSE_REPLY) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_PARSE_REPLY) if result == "false": - return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_TERMINATE_SESSION) + return action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_TERMINATE_SESSION) return action_result.set_status(phantom.APP_SUCCESS, CISCOISE_SUCC_SESSION_TERMINATED) @@ -602,7 +602,7 @@ def _handle_policy_change(self, action_result, param, change_type="apply"): payload["OperationAdditionalData"]["additionalData"][0]["name"] = "ipAddress" else: return ( - action_result.set_status(phantom.APP_ERROR, CISCOISE_ERR_MAC_AND_IP_NOT_SPECIFIED), + action_result.set_status(phantom.APP_ERROR, CISCOISE_ERROR_MAC_AND_IP_NOT_SPECIFIED), ret_data, ) @@ -708,14 +708,14 @@ def _test_connectivity_to_device(self, base_url, verify=True): verify=verify) except Exception as e: self.debug_print("Exception is test connectivity: {}".format(e)) - return self.set_status_save_progress(phantom.APP_ERROR, CISCOISE_ERR_TEST_CONNECTIVITY_FAILED) + return self.set_status_save_progress(phantom.APP_ERROR, CISCOISE_ERROR_TEST_CONNECTIVITY_FAILED) if resp.status_code == 200: return self.set_status_save_progress(phantom.APP_SUCCESS, CISCOISE_SUCC_TEST_CONNECTIVITY_PASSED) else: return self.set_status_save_progress( phantom.APP_ERROR, - CISCOISE_ERR_TEST_CONNECTIVITY_FAILED_ERR_CODE, + CISCOISE_TEST_CONNECTIVITY_FAILED_ERROR_CODE, code=resp.status_code ) diff --git a/ciscoise_consts.py b/ciscoise_consts.py index 9dab218..dd95e0c 100644 --- a/ciscoise_consts.py +++ b/ciscoise_consts.py @@ -1,6 +1,6 @@ # File: ciscoise_consts.py # -# Copyright (c) 2014-2022 Splunk Inc. +# Copyright (c) 2014-2023 Splunk Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -33,22 +33,22 @@ ERS_POLICIES = ":9060/ers/config/ancpolicy" # Error/Success -CISCOISE_ERR_TEST_CONNECTIVITY_FAILED = "Test connectivity failed" -CISCOISE_ERR_TEST_CONNECTIVITY_FAILED_ERR_CODE = "Test connectivity failed with status code: '{code}'" +CISCOISE_ERROR_TEST_CONNECTIVITY_FAILED = "Test connectivity failed" +CISCOISE_TEST_CONNECTIVITY_FAILED_ERROR_CODE = "Test connectivity failed with status code: '{code}'" CISCOISE_SUCC_TEST_CONNECTIVITY_PASSED = "Test connectivity passed" -CISCOISE_ERR_REST_API = "REST Api error" -CISCOISE_ERR_REST_API_ERR_CODE = "REST Api error with status code: {code}, Message from server: {message}" -CISCOISE_ERR_UNABLE_TO_PARSE_REPLY = "Parsing error, Unable to convert xml reply to json" +CISCOISE_ERROR_REST_API = "REST Api error" +CISCOISE_REST_API_ERROR_CODE = "REST Api error with status code: {code}, Message from server: {message}" +CISCOISE_ERROR_UNABLE_TO_PARSE_REPLY = "Parsing error, Unable to convert xml reply to json" CISCOISE_SUCC_SESSION_TERMINATED = "Session terminated" -CISCOISE_ERR_PARSE_REPLY = "Error parsing reply" -CISCOISE_ERR_TERMINATE_SESSION = "Session termination failed. Session possibly not found" -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_ERROR_PARSE_REPLY = "Error parsing reply" +CISCOISE_ERROR_TERMINATE_SESSION = "Session termination failed. Session possibly not found" +CISCOISE_ERROR_LOGOFF_SYSTEM = "System Logoff failed" +CISCOISE_ERROR_MAC_AND_IP_NOT_SPECIFIED = "Please specify a valid mac or ip address to execute action" +CISCOISE_ERROR_ACTION_FAILED = "Action failed with error code: {error_code}" CISCOISE_SUCC_LIST_ENDPOINTS = "{0} Endpoints found" CISCOISE_SUCC_GET_ENDPOINT = "Endpoint found" CISCOISE_SUCC_UPDATE_ENDPOINT = "Endpoint updated" -CISCOISE_ERR_INVALID_PARAM = "Please provide a non-zero positive integer in {param}" +CISCOISE_ERROR_INVALID_PARAM = "Please provide a non-zero positive integer in {param}" CISCOISE_MAP_IP_ABSENT_ERROR = "Please provide either mac address or ip address" CISCOISE_ERS_CRED_MISSING = "ERS credentials in asset configuration are required for this action" DEFAULT_MAX_RESULTS = 7 diff --git a/manual_readme_content.md b/manual_readme_content.md index 6d14ff0..4cc9e20 100644 --- a/manual_readme_content.md +++ b/manual_readme_content.md @@ -1,5 +1,5 @@ [comment]: # " File: README.md" -[comment]: # " Copyright (c) 2014-2022 Splunk Inc." +[comment]: # " Copyright (c) 2014-2023 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." @@ -82,7 +82,7 @@ "name": "guestUser", "guestInfo": { "userName": "DS3ewdsa34wWE", - "password": "asdlkj324ew", + "password": "asdlkj324ew", # pragma: allowlist secret "enabled": true }, "guestAccessInfo": { @@ -110,7 +110,7 @@ "enabled": true, "password": "*******", "changePassword": true, - "passwordIDStore": "Internal Users" + "passwordIDStore": "Internal Users" # pragma: allowlist secret } } @@ -140,7 +140,7 @@ "pushIdSupport": false }, "tacacsSettings": { - "sharedSecret": "aaa" + "sharedSecret": "aaa" # pragma: allowlist secret }, "profileName": "Cisco", "NetworkDeviceIPList": [ diff --git a/release_notes/unreleased.md b/release_notes/unreleased.md index fbcb2fd..96e416d 100644 --- a/release_notes/unreleased.md +++ b/release_notes/unreleased.md @@ -1 +1,2 @@ **Unreleased** +* Updated requests and certifi dependencies in order to use platform packages [PAPP-30822,PAPP-31096] diff --git a/requirements.txt b/requirements.txt index 20258f1..757f9df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ Cerberus==1.3.4 -requests==2.25.0 xmltodict==0.12.0 diff --git a/tox.ini b/tox.ini index 127a08b..c4644ad 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [flake8] max-line-length = 145 max-complexity = 28 -ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 +extend-ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 [isort] line_length = 145 diff --git a/wheels/py3/setuptools-60.8.2-py3-none-any.whl b/wheels/py3/setuptools-60.8.2-py3-none-any.whl deleted file mode 100644 index a64ea495410d288540b80b0d76dec76d1b75ea9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1060226 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