cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
7125
Views
2
Helpful
0
Comments
thomas
Cisco Employee
Cisco Employee
 

Cisco Platform Exchange Grid (pxGrid) in ISE Tutorial

 

Contents

 

 

Introduction

 

Cisco pxGrid Client Software

The official Cisco Platform Exchange Grid (pxGrid) account in GitHub, cisco-pxgrid, contains multiple repositories of example code to connect, discover, subcribe, and publish with pxGrid. There are two repositories that we will use in this tutorial with the Python programming language:

Repository Description
pxgrid-rest-ws The official pxGrid client source code, available in Golang, Java , and Python
python-advanced-examples Contains the source code for a number of advanced pxGrid examples written in python that extend the examples found in pxgrid-rest-ws

 

Resources

 

Requirements

All of the examples in the tutorial assume that you have an ISE 3.x node and a Linux/Unix environment for running curl, git and other commands. Windows users should consider installing Windows Subsystem for Linux (WSL), a Linux VM, or Linux container (Podman / Docker).

 

ISE Configuration

These instructions provide the bare minimum requirements to enable ISE for doing pxGrid with a single internal test account. You may skip steps if you have already configured these options in your lab or production ISE deployment.

 

Create Default Network Device

If you do not want to create individual network device entries for testing the fastest option is to use the Default Network Device Option.

  1. In ISE, navigate to Administration > Network Resources > Network Devices 
  2. Select Default Device from the left menu
    • Default Network Device Status : Enable
    • Enable RADIUS
    • Shared Secret: ISEisC00L (or your preferred shared secret)
  3. Select Save

 

Create Internal User

You will want a simple test user account for generating RADIUS sessions with pxGrid if you do not already have one or more that you can use.

  1. In ISE, navigate to Administration > Identity Management > Identities
  2. Select +Add
    • Username: employee
    • Login Password: ISEisC00L (or your preferred test password)
    • User Groups: Employee
  3. Select Submit

 

Enable pxGrid

  1. In ISE, navigate to Administration > pxGrid Services > Summary
  2. Notice that pxGrid is Disabled by default
  3. Navigate to Administration > System > Deployment
    1. Choose your ISE node
    2. Scroll down and enable pxGrid
    3. Select Save
ISE requires one or more active Advanced licenses for pxGrid entitlement.

 

Enable ISE ERS and Open API

  1. In ISE, navigate to Administration > Settings > API Settings and enable the ERS and Open API
  2. Select the API Service Settings tab
  3. ERS (Read/Write)
  4. Open API (Read/Write)
  5. Ignore CSRF Check and keep it Disabled unless you know what you are doing and why
  6. Select Save

 

Create a Virtual Environment

Virtual environments with Python allow you to create multiple development environments for your projects that will not conflict with each other. This allows you to clearly understand your dependencies and keep from bloating your workstation with random packages.

Create a project directory for playing with pxGrid and change directory (cd) into it :

mkdir ISE_pxGrid_Tutorial
cd ISE_pxGrid_Tutorial

 

Create a Python environment with `pipenv` and install the necessary Python packages :

python -m ensurepip --upgrade
Spoiler
If Ubuntu, this command might give No module named ensurepip, so do the following, instead:

curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10  # Install the latest
python3.10 -m pip --version                                 # test the result
python3.10 -m pip install --upgrade pip                     # test upgrade

pip3 install pipenv           # Install virtual environment utility
pipenv install --python 3.11  # 3.8 or later should work
pipenv install pxgrid-util    # Install cisco-pxgrid/python-advanced-examples
pipenv install requests       # HTTP
pipenv install websockets # websockets pipenv shell # launch virtual environment

If you have any problems installing Python, see the Python Beginner's Guide.

You may verify your installed packages in your virtual environment :

pip list

 

cURL

Our ISE API examples will utilize the command line utility cURL. This is because cURL is the most universal and flexible choice for quickly doing HTTP/S-based REST calls.

To quickly test if curl and your ISE APIs are working with your ISE node, try the following :

curl --insecure \
--header 'Accept: application/json' \
--user admin:ISEisC00L \
--request GET https://ise.securitydemo.net/api/v1/deployment/node
Be sure to use your ISE admin username and password or you will get a 401 error.
ISE versions < 3.1 should use the REST endpoint /ers/config/node instead of /api/v1/deployment/node  .

Your response should look something like this and you definitely want to see pxGrid as one of the services:

{
"response" : [ {
"hostname" : "ise",
"fqdn" : "ise.securitydemo.net",
"ipAddress" : "198.18.133.27",
"roles" : [ "Standalone" ],
"services" : [ "Session", "Profiler", "pxGrid" ],
"nodeStatus" : "Connected"
} ],
"version" : "1.0.0"
}

Frequently used command line options with curl:

cURL Option Description
-k, --insecure Accept insecure connections. Useful if you are playing with a demo installation of ISE using a self-signed certificate.
-H, --header {header}

Header to include in the request. Use one per header.

-i, --include Include the HTTP result headers in the output.
-s, --silent Disable the progress bar output for clean output when piping the output to other utilities like xq
-u, --user {username:password} Specify the username & password to authenticate the API user
-d, --data '{content}' The data payload to send, as a string or file, typically with JSON or XML content.
-X, --request <method> Specify a custom HTTP request method.
-L, --location Follow the redirected URL in the location header.

 

Environment Variables

In the above example, we showed you the ISE admin username and password ISEisC00L in the clear on the command line. It is a bad security practice to do API work with your passwords to security applications like ISE exposed for anyone to see over your shoulder or in your command line history. For this reason, we will utilize environment variables in our command line work as a best practice with our ISE REST API usernames and passwords for all further examples. We will also use variables for our hostname (ISE_HOSTNAME) to generalize the scripts so you may copy and paste them to your command line.

The fastest to use environment variables in your command line scripts is to create temporary environment variables using the export command (or set command on Windows) in your terminal:

export ISE_HOSTNAME=ise.securitydemo.net  # for small ISE deployments
export ISE_PAN=ise-ppan.example.com # large ISE deployments use the PAN node for ERS APIs
export ISE_MNT=ise-pmnt.example.com # large ISE deployments use the MNT node for MNT APIs
export ISE_PXG=ise-pxg1.example.com # large ISE deployments use the PXG node for pxGrid
export ISE_ERS_USERNAME=admin
export ISE_ERS_PASSWORD=ISEisC00L
export ISE_CERT_VERIFY=false
export PXGRID_CLIENT_USERNAME=pxgrid_demo_user
export PXGRID_CLIENT_PASSWORD=

You may also add the lines above to an ise.sh file in a .secrets folder in your home directory then, when you want to use them in your terminal session, run:

source ~/.secrets/ise.sh

You may view and verify your current environment variables using the following commands and access them in scripts or on the command line by prefixing them with a `$`:

env                            
printenv ISE_ERS_USERNAME
echo $ISE_ERS_USERNAME

The same example cURL command above using environment variables would look like this:

curl --insecure \
--header 'Accept: application/json' \
--user $ISE_ERS_USERNAME:$ISE_ERS_PASSWORD \
--request GET https://$ISE_HOSTNAME/api/v1/deployment/node

If you want to verify your environment variable values, use the echo command to help you troubleshoot!

> echo https://$ISE_HOSTNAME/api/v1/deployment/node

https://ise.securitydemo.net/api/v1/deployment/node

 

jq (JSON Query)

Many of the examples below will also utilize the command line utility jq to pretty-print the JSON output of the REST APIs. It may even be used to filter the output.

Pipe the output of curl into jq (" | jq"):

curl --insecure --silent \
--header 'Accept: application/json' \
--user $ISE_ERS_USERNAME:$ISE_ERS_PASSWORD \
--request GET https://$ISE_HOSTNAME/api/v1/deployment/node \
| jq -C .

 

pxGrid Authentication & Authorization

Enable Username:Password Authentication

  1. Go to Administration > pxGrid Services > Settings
    1. Allow password based account creation
    2. Click Save
  2. Go to Administration > pxGrid Services > Client Management > Clients to see there are no clients

 

pxGrid Settings

To make an ISE ERS call, the ISE ERS API must be enabled under Administration > System > Settings > API Settings > API Service Settings. An example REST call with curl is below to enable the basic user auth for pxGrid clients. You could also use Postman, Python, Ansible or some other mechanism to make the REST call.

curl \
  --insecure --include \
  --header 'Content-Type:application/json' \
  --header 'Accept: application/json' \
  --user $ISE_ERS_USERNAME:$ISE_ERS_PASSWORD \
  --request PUT https://$ISE_HOSTNAME/ers/config/pxgridsettings/autoapprove \
  --data '
{
  "PxgridSettings" : {
    "autoApproveCertBasedAccounts" : true,
    "allowPasswordBasedAccounts" : true
  }
}
'

 

AccountCreate

Now that password-based authentication is enabled for pxGrid, you may create an account and password. Export an environment variable with your ISE pxGrid node’s name or IP address :

Submit a request for a nodeName (username) and retrieve a randomly generated password for your pxGrid client :

⚠ Do NOT include any username:password credentials for the AccountCreate request!
⚠ Allows <= 100 case-insensitive characters in the nodeName: [a-z0-9_.-]
curl \
  --include  --insecure \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --request POST https://$ISE_PXG:8910/pxgrid/control/AccountCreate \
  --data '{ "nodeName":"'$PXGRID_CLIENT_USERNAME'" }'

The REST response will show your pxGrid client username with a unique, random password:

HTTP/1.1 200
{"nodeName":"pxgrid_demo_user","password":"15ozVGARjkZJMCLN","userName":"pxgrid_demo_user"}

Update your PXGRID_CLIENT_PASSWORD environment variable with random password assigned to your account :

export PXGRID_CLIENT_PASSWORD='HjERBEHfkqqXWCpp'

In the ISE GUI, navigate to Administration > pxGrid Services > Client Management > Clients to see your pxGrid client registered the Initialized state. You must still activate and approve it.

Name Description Client Groups Status
pxgrid_demo_user     Initialized

 

AccountActivate

You have requested a pxGrid client account and now you must activate it :

curl \
  --include  --insecure \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
--user $PXGRID_CLIENT_USERNAME:$PXGRID_CLIENT_PASSWORD \ --request POST https://$ISE_PXG:8910/pxgrid/control/AccountActivate \ --data '{ "description": "My pxGrid Client" }'

The response will show the accountState as PENDING :

{"accountState":"PENDING","version":"2.0"}

Refresh the pxGrid Clients table in the ISE GUI to see the updated Status and the Description you specified in the AccountActivate body :

Name Description Client Groups Status
pxgrid_demo_user My pxGrid Client   Pending

Select the row for your pxgrid_demo_user then select the Approve button above the table and you will see the Status change to Enabled.

Name Description Client Groups Status
pxgrid_demo_user My pxGrid Client   Enabled

After being Approved in the ISE GUI, the same AccountActivate REST API request shows you are Enabled :

HTTP/1.1 200
{"accountState":"ENABLED","version":"2.0"}

If your request was declined in the ISE GUI, the AccountActivate REST API returns a 401 Unauthorized response :

HTTP/1.1 401

 

Authorization

You may be authorized by the ISE Administrator to retrieve certain services but not others. Use the /pxgrid/control/Authorization REST endpoint to verify your capabilities.

Request:

curl \
  --include  --insecure \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --user $PXGRID_CLIENT_USERNAME:$PXGRID_CLIENT_PASSWORD \
  --request POST https://$ISE_PXG:8910/pxgrid/control/Authorization \
  --data '
{
  "requestNodeName":"'$PXGRID_CLIENT_USERNAME'",
  "serviceName":"com.cisco.ise.sessiondirectory",
  "serviceOperation":"gets"
}'

Response:

HTTP/1.1 200
{"authorization":"PERMIT"}

 

Service Discovery

There are many different services within ISE :

  • com.cisco.ise.echo
  • com.cisco.ise.system
  • com.cisco.ise.mdm
  • com.cisco.ise.config.profiler
  • com.cisco.ise.config.anc
  • com.cisco.endpointanalytics
  • com.cisco.ise.dnac
  • com.cisco.ise.pubsub
  • com.cisco.ise.session
  • com.cisco.ise.sxp
  • com.cisco.ise.config.trustsec
  • com.cisco.ise.endpoint
  • com.cisco.ise.posture
  • com.cisco.ise.pxcloud
  • com.cisco.ise.telemetry
  • com.cisco.ise.aiagent
  • com.cisco.ise.radius
  • com.cisco.ise.pxgrid.admin
  • com.cisco.ise.config.deployment.node
  • com.cisco.ise.trustsec
  • com.cisco.ise.config.upn

 

ServiceLookup

Request:

curl --silent --insecure \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --user $PXGRID_CLIENT_USERNAME:$PXGRID_CLIENT_PASSWORD \
  --request POST https://$ISE_PXG:8910/pxgrid/control/ServiceLookup \
--data '{ "name":"com.cisco.ise.session" }' \
| jq -C .

Response:

{
"services": [
{
"name": "com.cisco.ise.session",
"nodeName": "~ise-mnt-ise",
"properties": {
"sessionTopic": "/topic/com.cisco.ise.session",
"groupTopic": "/topic/com.cisco.ise.session.group",
"wsPubsubService": "com.cisco.ise.pubsub",
"restBaseURL": "https://ise.securitydemo.net:8910/pxgrid/mnt/sd",
"restBaseUrl": "https://ise.securitydemo.net:8910/pxgrid/mnt/sd"
}
}
]
}

 

AccessSecret

Ue the nodeName from the ServiceLookup to get the AccessSecret for that service on that node.

curl --silent --insecure \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--user $PXGRID_CLIENT_USERNAME:$PXGRID_CLIENT_PASSWORD \
--request POST https://$ISE_PXG:8910/pxgrid/control/AccessSecret \
--data '{ "peerNodeName":"~ise-admin-ise" }' \

Response:

{
"secret": "8AF7vMB6hga2pdrq"
}

You may now perform REST API queries with that service.

 

pxgrid-util

This is an installable Python package (pip install pxgrid-util) that is hosted in the python-advanced-examples GitHub repository. The package has many tools for testing pxGrid but all of them may have examples here.

  • anc-policy : Download ANC policies, endpoints with ANC policies applied, and apply ANC policy
  • create-new-pxgrid-account : Create a simple password authentication pxGrid client if you have an ISE admin username and password
  • matrix-query-all : Download all cells of the TrustSec policy matrix
  • profiles-query-all : Download all ISE Profiler profiles
  • px-subscribe : General purpose utility to display details on multiple services and to allow subscriptions to topics of named services
  • session-query-all : Download all current sessions
  • session-query-by-ip : Perform a query on the session topic using a given IP address
  • sgacls-query-all : Download all current SG-ACL definitions
  • sgts-query-all : Download all SGT definitions
  • sxp-query-bindings : Download all SXP bindings
  • system-query-all : Download performance or health metrics from an ISE installation
  • user-groups-query : Query for the groups associated with users authenticated to ISE

 

session-query-all

Downloads all current sessions

Request:

session-query-all \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C .

Response:

{"sessions":[]} 

Filtering responses with jq 

Request:

session-query-all \
--hostname $ISE_PXG \
--nodename $PXGRID_CLIENT_USERNAME \
--password $PXGRID_CLIENT_PASSWORD \
--insecure \
| jq -C '[ .sessions[] | select(.state == "STARTED") | .macAddress ]'

Response:

[
  "00:50:56:94:39:9F",
  "00:50:56:94:6F:90",
  "00:50:56:94:91:67",
  "00:50:56:94:AA:9B",
  "00:50:56:94:D8:7E",
  "00:50:56:94:DF:7D",
  "00:50:56:94:E4:31",
  "00:50:56:94:E7:97"
]

 

session-query-by-ip

Performs a query on the session topic using a given IP address.

session-query-by-ip \
--hostname $ISE_PXG \
--nodename $PXGRID_CLIENT_USERNAME \
--password $PXGRID_CLIENT_PASSWORD \
--insecure

 

px-subscribe

Run px-subscribe to connect to ISE with a websocket and observe any new RADIUS session updates :

px-subscribe \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  --service com.cisco.ise.session \
  --topic sessionTopic \
  | jq -C .

You may observe the px-subscribe websocket connection in the ISE GUI under Administration > pxGrid Services > Diagnostics > WebSocket Connection.

To see a new session, authenticate a user or endpoint to create a new RADIUS session which you should see in the px-subscribe output within ~5 seconds :

{
  "sequence": 1,
  "sessions": [
    {
      "adNormalizedUser": "thomas",
      "authMethod": "dot1x",
      "authProtocol": "PEAP (EAP-MSCHAPv2)",
      "calledStationId": "2C-3F-0B-56-E3-6C:ISECorp",
      "callingStationId": "56:5B:EE:FE:7C:34",
      "ctsSecurityGroup": "Employees",
      "endpointCheckResult": "none",
      "endpointProfile": "Unknown",
      "identitySourcePortEnd": 0,
      "identitySourcePortFirst": 0,
      "identitySourcePortStart": 0,
      "ipAddresses": [
        "10.80.60.151"
      ],
      "macAddress": "56:5B:EE:FE:7C:34",
      "mdmCompliant": false,
      "mdmDiskEncrypted": false,
      "mdmJailBroken": false,
      "mdmPinLocked": false,
      "mdmRegistered": false,
      "nasIdentifier": "2C-3F-0B-56-E3-6C:vap1",
      "nasIpAddress": "10.80.60.150",
      "nasPortType": "Wireless - IEEE 802.11",
      "networkDeviceProfileName": "Cisco",
      "providers": [
        "None"
      ],
      "radiusFlowType": "Wireless802_1x",
      "selectedAuthzProfiles": [
        "PermitAccess"
      ],
      "serviceType": "Framed",
      "ssid": "2C-3F-0B-56-E3-6C:ISECorp",
      "state": "STARTED",
      "timestamp": "2022-03-22T03:44:12.445Z",
      "userName": "thomas"
    }
  ]
}

Disconnect the endpoint session and wait 5 seconds to see updated session information.

 

matrix-query-all

Download all cells of the TrustSec policy matrix.

matrix-query-all \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure

Response:

{
"deletedEgressPolicies": [],
"egressPolicies": [
{
"description": "Default egress rule",
"destinationSecurityGroupId": "92bb1950-8c01-11e6-996c-525400b48521",
"id": "92c1a900-8c01-11e6-996c-525400b48521",
"matrixId": "9fa3a33a-329e-43cb-a4cf-7bd38df16e7b",
"name": "ANY-ANY",
"sgaclIds": [
"92951ac0-8c01-11e6-996c-525400b48521"
],
"sourceSecurityGroupId": "92bb1950-8c01-11e6-996c-525400b48521",
"status": "ENABLED",
"timestamp": "2016-10-06T20:15:06.714861Z"
}
],
"totalCount": "1",
"version": "1.0.0"
}

 

sgts-query-all

Download all SGT definitions.

sgts-query-all \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C .

Show the tag number and name :

sgts-query-all \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C '[ .securityGroups[] | .tag, .name ]' 

 

sgacls-query-all

sgacls-query-all \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C .

 

sxp-query-bindings

Download all SXP bindings.

sxp-query-bindings \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C .

Response:

{
"bindings": []
}

 

user-groups-query

user-groups-query \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  | jq -C .

Response:

{
"userGroups": [
{
"adUserQualifiedName": "thomas",
"adUserSamAccountName": "thomas",
"groups": [
{
"name": "null",
"type": "IDENTITY"
},
{
"name": "S-1-5-21-3064548688-3193819538-1298560677-513",
"type": "EXTERNAL"
},
{
"name": "dcloud.cisco.com/Users/Domain Users",
"type": "INTERESTING_ACTIVE_DIRECTORY"
}
],
"userName": "thomas"
}
]
}

 

anc-policy

Download ANC policies, endpoints with ANC policies applied, and apply ANC policies.

 

getPolicies

Get all defined ANC policies:

anc-policy \
  --hostname $ISE_PXG \
  --nodename $PXGRID_CLIENT_USERNAME \
  --password $PXGRID_CLIENT_PASSWORD \
  --insecure \
  --get-anc-policies

Response:

{
"policies": [
{
"actions": [
"PORT_BOUNCE"
],
"name": "ANC-Destroy"
},
{
"actions": [
"SHUT_DOWN"
],
"name": "ANC-NukeFromOrbit"
},
{
"actions": [
"QUARANTINE"
],
"name": "pxGridQRadarQuarantine"
},
{
"actions": [
"SHUT_DOWN"
],
"name": "pxGridQRadarShutDown"
},
{
"actions": [
"PORT_BOUNCE"
],
"name": "pxGridQRadarPortBounce"
},
{
"actions": [
"QUARANTINE"
],
"name": "ANC-Investigate"
}
]
}

 

Certificates

Generate pxGrid Certificates from ISE

  1. In the ISE Admin GUI, login and navigate to Administration > pxGrid Services > Client Management > Certificates
  2. Fill in the form to generate a certificate for pxGrid communication :
    • I want to: Generate a single certificate (without a certificate signing request)
    • Common Name (CN): {fill in any name, e.g. pxgrid-consumer}
    • Certificate Download Format: Certificate in Privacy Enhanced Electronic Mail (PEM) format
    • Certificate Password: {fill in a password, e.g. C1sco12345}
    • Confirm Password: {fill in the same password as above}
  3. Select the ‘Create’ button. A zip file should download to your machine
  4. Extract the downloaded file. In the rest of this document, we’ll refer to the extracted folder as /path/to/12345678_cert/

 

 

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: