ISE API for Policy Automation
Objective
In this lesson you will use the ISE REST APIs (ERS) and the ISE OpenAPI surface to automate TrustSec objects and user accounts: create Security Group Tags (SGTs), create an internal user, and bind that user to an identity group that will be used for policy assignment. Automating ISE policy objects matters in production because it removes manual error-prone GUI clicks, enables consistent policy deployment across sites, and lets orchestration tools (Terraform, Ansible, CI/CD) drive network access control at scale. Real-world scenario: when an HR system creates a contractor record, an orchestration pipeline can call ISE APIs to provision the contractor account and tag it with the correct SGT for segment-based access control.
Quick Recap
We continue with the same topology used in Lesson 1. No new physical devices are added in this lesson; we will interact with the existing ISE appliance via API calls from the jump host.
Topology (logical) — all devices are reachable in the 198.18.128.0/18 management network:
+----------------------+ +----------------------+
| Win10 Jump Host | | ISE 3.2 (API) |
| Hostname: jump.lab.nhprep.com | IP: 198.18.128.12 |
| IP: 198.18.128.10 |-----------| |
+----------------------+ +----------------------+
|
| (management)
|
+----------------------+
| Catalyst Center |
| IP: 198.18.128.11 |
+----------------------+
Device Table
| Device | Role | IP / Hostname |
|---|---|---|
| Jump Host | Management workstation (API client) | 198.18.128.10 / jump.lab.nhprep.com |
| ISE | Policy system / ERS / OpenAPI | 198.18.128.12 |
Tip: Use lab.nhprep.com for domain names and Lab@123 for passwords when prompted by automation or scripts.
Key Concepts (theory + behavior)
- ERS (External RESTful Services) — ERS is ISE’s REST API surface for CRUD operations on many ISE objects (SGT, internal users, identity groups). When you POST a new SGT, ISE stores it in its internal database and returns a unique identifier; downstream services (e.g., network devices via pxGrid or SXP) consume those SGTs.
- OpenAPI / Swagger — ISE exposes machine-readable API metadata so automation tools can generate client stubs. In practice you use the OpenAPI specs to discover available endpoints and required payloads, then call endpoints with JSON/XML over HTTPS.
- Authentication and Sessions — API calls to ERS must be authenticated. ISE commonly accepts basic auth with an admin account for ERS calls in lab setups; production uses service accounts with limited privileges and TLS with certificate validation.
- Object Referential Integrity — Many ISE objects are referenced by UUIDs. For example when you create an identity group, subsequent objects (like policy assignments) reference that group's UUID, not its name. Automation must capture and reuse returned UUIDs.
- Idempotence — Automation should be idempotent: calling the same create operation multiple times should not create duplicates. Best practice: check for existence (GET) before POST, or use PUT with the known UUID when supported.
Step-by-step configuration
Note: all commands below are executed from the Jump Host (198.18.128.10). We use the ISE management address 198.18.128.12 and the administrative account admin / Lab@123 for the lab. Each step shows the exact API calls, an explanation of what the commands do and why they matter, and a verification GET with expected output.
Step 1: Verify ERS/OpenAPI reachability and authentication
What we are doing: Ensure the ISE ERS API is reachable and our admin credentials work. This step prevents wasting time developing automation against an unreachable or misconfigured API.
# From jump.lab.nhprep.com (198.18.128.10)
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/sgt -H "Accept: application/json"
What just happened: The curl command performs an HTTPS GET to the ERS SGT collection endpoint. The -k flag allows lab TLS without validating the certificate (acceptable in lab). Basic auth provides credentials. If the ERS service is enabled and credentials are valid, ISE responds with a JSON payload listing existing SGTs (possibly empty).
Real-world note: In production, do not use
-k; instead validate certificates and use service accounts with least privilege.
Verify:
# Expected output (complete JSON example)
{
"SearchResult": {
"total": 1,
"resources": [
{
"id": "3f4b2b0e-6c8a-4f1a-9e4c-123456789abc",
"name": "default",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/sgt/3f4b2b0e-6c8a-4f1a-9e4c-123456789abc"
}
}
]
}
}
If you receive HTTP 401/403, verify username/password and ERS service configuration. If you receive connection refused, confirm network reachability.
Step 2: Create a new Security Group Tag (SGT) "SGT_EMPLOYEES"
What we are doing: Use ERS to create an SGT named SGT_EMPLOYEES. SGTs are the building blocks of TrustSec — tags applied to identities or endpoints to enforce segmentation policies.
curl -k -u admin:Lab@123 -H "Content-Type: application/json" \
-X POST https://198.18.128.12/ers/config/sgt \
-d '{
"SGT": {
"name": "SGT_EMPLOYEES",
"description": "Employees SGT for Day-to-day access",
"value": 20
}
}'
What just happened: The POST creates a new SGT object in ISE. The JSON payload includes name, description, and value (numeric SGT). ISE will persist the SGT and return an object containing metadata including a UUID. This SGT value (20) will be used by enforcement points (switches, firewalls) to enforce access control.
Real-world note: Choose numeric SGT values consistently across your organization and document them; mismatched values can break policy enforcement.
Verify:
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/sgt -H "Accept: application/json"
Expected output including the new SGT:
{
"SearchResult": {
"total": 2,
"resources": [
{
"id": "3f4b2b0e-6c8a-4f1a-9e4c-123456789abc",
"name": "default",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/sgt/3f4b2b0e-6c8a-4f1a-9e4c-123456789abc"
}
},
{
"id": "7a2d9c10-1b2c-4d5e-8f90-abcdef123456",
"name": "SGT_EMPLOYEES",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/sgt/7a2d9c10-1b2c-4d5e-8f90-abcdef123456"
}
}
]
}
}
Note the UUID for SGT_EMPLOYEES (7a2d9c10-...) — capture this for later automation steps.
Step 3: Create an Identity Group "Employees" (ISE internal group)
What we are doing: Create an ISE identity group named "Employees". Identity groups logically collect users or endpoints and are typically referenced by authorization policy rules.
curl -k -u admin:Lab@123 -H "Content-Type: application/json" \
-X POST https://198.18.128.12/ers/config/identitygroup \
-d '{
"IdentityGroup": {
"name": "Employees",
"description": "ISE identity group for corporate employees"
}
}'
What just happened: This POST adds an identity group object to ISE. Like other objects, ISE returns metadata with a UUID for the new group. Identity groups simplify policy rules by grouping users rather than matching individual accounts.
Real-world note: Use hierarchical identity group names (e.g., /NHPREP/Users/Employees) in large deployments to reflect org structure and ease policy inheritance.
Verify:
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/identitygroup -H "Accept: application/json"
Expected output example:
{
"SearchResult": {
"total": 1,
"resources": [
{
"id": "d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654",
"name": "Employees",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/identitygroup/d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654"
}
}
]
}
}
Capture the identity group UUID for use in mapping users to the group.
Step 4: Create an internal user and assign to the "Employees" group
What we are doing: Provision an internal user (for example, username jsmith) in ISE and assign the user to the Employees identity group. This is the common workflow when onboarding a new employee and ensures the user will match any authorization rules based on identity group membership.
curl -k -u admin:Lab@123 -H "Content-Type: application/json" \
-X POST https://198.18.128.12/ers/config/internaluser \
-d '{
"InternalUser": {
"name": "jsmith",
"password": "Lab@123",
"firstName": "John",
"lastName": "Smith",
"email": "jsmith@lab.nhprep.com",
"groupId": "d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654"
}
}'
What just happened: This POST creates an internal user account and links it to the identity group by group UUID (groupId). ISE stores the credentials and group membership, enabling authentication and authorization flows (e.g., 802.1X, MAB). The password field is the initial credential; in production you would enforce strong password policies and possibly one-time setup flows.
Real-world note: Avoid hard-coding passwords in automation; use a secrets manager and rotate credentials regularly.
Verify:
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/internaluser/name/jsmith -H "Accept: application/json"
Expected output:
{
"InternalUser": {
"id": "a1b2c3d4-1111-2222-3333-abcdef987654",
"name": "jsmith",
"firstName": "John",
"lastName": "Smith",
"email": "jsmith@lab.nhprep.com",
"groupId": "d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/internaluser/a1b2c3d4-1111-2222-3333-abcdef987654"
}
}
}
The presence of groupId confirms the user is in the Employees identity group. Use this UUID in any subsequent policy-related automation.
Step 5: Map the Identity Group to the SGT (record association)
What we are doing: Associate the Employees identity group with SGT_EMPLOYEES so that authorization policies or downstream enforcement can apply the SGT when the user authenticates. This association is used by ISE policy or by external systems consuming the mapping.
curl -k -u admin:Lab@123 -H "Content-Type: application/json" \
-X POST https://198.18.128.12/ers/config/sgtmap \
-d '{
"SgtMap": {
"identityGroupId": "d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654",
"sgtId": "7a2d9c10-1b2c-4d5e-8f90-abcdef123456"
}
}'
What just happened: This command records a mapping between the identity group UUID and the SGT UUID. Depending on your ISE configuration and enforcement model, ISE will use this mapping during authorization to return the SGT in authorization responses (for example, in RADIUS attributes or via pxGrid).
Real-world note: In production, you may instead configure these mappings within ISE policy GUI or use a matrix-based automation for many groups. Always validate that enforcement points (switches, firewalls) are configured to consume SGTs (SXP/pxGrid) to enforce segmentation.
Verify:
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/sgtmap -H "Accept: application/json"
Expected output showing the mapping:
{
"SearchResult": {
"total": 1,
"resources": [
{
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"identityGroupId": "d4f6a2b1-9f3d-4c2f-a8d7-fedcba987654",
"sgtId": "7a2d9c10-1b2c-4d5e-8f90-abcdef123456",
"link": {
"rel": "canonical",
"href": "https://198.18.128.12/ers/config/sgtmap/9f8e7d6c-5b4a-3210-fedc-ba9876543210"
}
}
]
}
}
The mapping confirms ISE will correlate users in the Employees group to SGT_EMPLOYEES during authorization.
Verification Checklist
- Check 1: ERS reachable — From jump host,
curl -k -u admin:Lab@123 https://198.18.128.12/ers/config/sgtreturns HTTP 200 and JSON listing SGTs. - Check 2: SGT created — A GET to
/ers/config/sgtcontains the resource with"name": "SGT_EMPLOYEES"; capture its UUID. - Check 3: Internal user created and group-assigned — GET
/ers/config/internaluser/name/jsmithreturns the user record with"groupId": "<Employees UUID>". - Check 4: Mapping exists — GET
/ers/config/sgtmapreturns a mapping entry that ties the Employees group UUID to the SGT_EMPLOYEES UUID.
Common Mistakes
| Symptom | Cause | Fix |
|---|---|---|
| API calls return 401 Unauthorized | Wrong username/password or ERS service disabled | Verify credentials (admin / Lab@123 for lab), enable ERS in ISE, and use correct basic auth. |
| No SGT appears after POST success | Caller did not capture returned UUID and subsequent automation references wrong id | Always parse and persist the UUID from the POST response; use GET to confirm existence. |
| Duplicate SGTs created by automation | Automation does not check for existing objects before POST | Implement idempotence: GET by name first, if exists use its UUID; otherwise POST. |
| Mapping not enforced on devices | SGT mapped in ISE but enforcement points not configured to accept SGTs (SXP/pxGrid missing) | Verify enforcement point configuration (switches/firewalls) and ensure pxGrid/SXP or inline enforcement is enabled and synchronized. |
Key Takeaways
- Use ISE ERS/OpenAPI to programmatically create and manage policy objects (SGTs, identity groups, internal users); automation reduces human error and increases consistency.
- Always verify API reachability and authentication before automating; handle TLS and credentials securely (use secrets managers in production).
- Capture object UUIDs returned by ISE and reuse them for referencing objects — names alone are not always sufficient.
- Design automation to be idempotent: check for object existence before creating to avoid duplicates and drift.
Important: In production replace
-k(insecure TLS), avoid hard-coded credentials, and use service accounts with minimal required privileges. Use the OpenAPI spec to generate robust client code and validate input payload schemas before calling the ERS endpoints.
If you want, the next lesson will demonstrate how to export these steps into a small Terraform/Ansible playbook that performs the same operations idempotently and captures UUIDs for later policy templates.