Ansible URI Module Breakdown & ISE Example

"The What?" - In this blog I want to cover an important Ansible module for those looking to gain an understanding of how to use Ansible to consume APIs without the need for custom modules. The URI module is part of the ansible-base and is included with all Ansible installations. This module allows interactions with HTTP & HTTPS web services.

"The Why?" - Learning how to automate mundane tasks is important, automation saves time, & for the general understanding of how components interact with each other to accomplish your end goal. Network automation is the future.

"The How?" - In the example below I will breakdown an Ansible playbook that I created that allows you to consume ISE APIs specifically using the Ansible URI module to automagically update a network device configuration settings within the ISE database.

This playbook is specifically intended to automatically update the following settings for an individual Network Device IP Address:

  • Device Owner

  • Device Location

  • TrustSec Notification & Updates CoA 'Send From' PSN

- name: ISE
  hosts: localhost
  connection: local
  gather_facts: false
    ise_user: XXXX  
    ise_pass: XXXX  

  - name: Get Existing NAD ID string
      url: https://XXXX:9060/ers/config/networkdevice?filter=ipaddress.EQ.{{ ip_addr }}    
      user: "{{ ise_user }}"
      password: "{{ ise_pass }}"
        Accept: application/json
        content-type: application/json
        ers-media-type: network.networkdevice.1.1
      status_code: 200
      method: GET
      validate_certs: no
    register: nad_id

  - name: Print returned ISE json data
     msg: "{{ nad_id.json }}"
  - name: Get ISE ID String
     id: "{{ nad_id | json_query(jmesquery) }}"
      jmesquery: '*.SearchResult.resources[*].id'

  - name: Extract NAD ID from Nested List
     id: "{{ id[0][0] }}"

  - name: Print ISE NAD ID
     msg: "{{ id }}"

  - name: Update NAD Details in ISE DB
      url: https://XXXX:9060/ers/config/networkdevice/{{ id }}
      user: "{{ ise_user }}"
      password: "{{ ise_pass }}"
        Accept: application/json
        content-type: application/json
        ers-media-type: network.networkdevice.1.1
      status_code: 200
      method: PUT
      body_format: json
      body: '{"NetworkDevice": {"id": "{{ id }}","name": "XXXX{{ site_id }}","profileName": "Cisco","coaPort": "1700","authenticationSettings" : {},"snmpsettings" : {"pollingInterval" : 3600,"linkTrapQuery" : "false","macTrapQuery" : "false",},"trustsecsettings" : {"deviceAuthenticationSettings" :{},"sgaNotificationAndUpdates" : {"downlaodEnvironmentDataEveryXSeconds" : 86400,"downlaodPeerAuthorizationPolicyEveryXSeconds" : 86400,"reAuthenticationEveryXSeconds" : 86400,"downloadSGACLListsEveryXSeconds" : 86400,"otherSGADevicesToTrustThisDevice" : "true","sendConfigurationToDevice" : "true","sendConfigurationToDeviceUsing" : "ENABLE_USING_COA","coaSourceHost" : "{{ ise_coa_node }}"
},"deviceConfigurationDeployment" : {"includeWhenDeployingSGTUpdates" : "true",}},"NetworkDeviceIPList": [{"ipaddress": "{{ ip_addr }}","mask": 32,}],"NetworkDeviceGroupList": ["Location#All Locations#{{ location }}","Device Type#All Device Types#SDA#{{ owner }}","IPSEC#Is IPSEC Device#No"]}}'
      validate_certs: no
    register: ise_update

  - name: Print ISE Update Notification
     msg: "{{ ise_update }}"

From the top:

  • The connection is actually set to execute locally since we are actually specifying an API to consume in the individual tasks/plays further in the playbook via the uri module with the url information.

  • It is important to note that the headers for all the APIs and requirements can be found/pulled from the SDK (see below for more info)

  • The first task (- name: Get Existing NAD ID string) is using a GET call (in relation to CRUD it would be a READ) to get the given IP Address ID string from ISE. This ID String will be appended to the following REST call to update the resource in the ISE DB

  • The succeeding tasks do the following:

  • parse the returned data to extract the ID string and store as variable (- name: Get ISE ID String).

  • Then do to how the string is nested we extract the ID string & set it as a new variable (- name: Extract NAD ID from Nested List)

  • Now that we have the extracted ID string from the original GET call we are ready to update the NAD in the ISE DB via (- name: Update NAD Details in ISE DB)

  • This is where testing to understand the JSON body syntax requirements can be hectic at first, but once you get a feel (LOOK AT THE SDK for other examples regarding requirements) you can really rock n roll

  • The final task prints the returned data from ISE which will show you old & new config. Essentially what the old config was & what is was changed to allowing you to confirm on the Ansible side that everything worked as expected.

NOTE: Important to know that the following vars are required via user input or survey if using tower:

  • {{ ip_addr }} = network device IP that you wish to update

  • {{ site_id }} = site identifier that appends to device hostname (this is optional; you can just update the code to have your full NAD name)

  • {{ location }} = location of the device based on your ISE location groups

  • {{ owner }} = who owns the device based on your ISE NAD device type groups

  • {{ ise_coa_node }} = PSN you wish ISE to use to send CTS updates via CoA

Remember that the variable {{ id }} is discovered during playbook execution.

If testing this: Be sure to have ERS enabled, update the user/pass, & url location. Test on a non-production device.

Lastly, to cover some additional information:

To understand more on Ansible modules check out their documentation here: Ansible Module Documentation

As for gaining more information on ISE APIs to include functionality, consuming, & required syntax use the ISE SDK. The SDK can be found via https://<you ise pan ip>:9060/ers/sdk#

The online SDK aides in explaining operations, parameters, & responses in relation to the ISE ERS API. ERS or External REST Services is for external clients to perform CRUD operations. See more on CRUD here: CURL, REST, & CRUD Tidbit.

That wraps this up. See more under the Automation tab. Cheers!


Recent Posts

See All

Linux AnyConnect Overview & Ansible Automation

"The What?" - In this blog I want to cover a brief overview of one way to install AnyConnect (AC) on a linux client running a supported OS. Once I cover the overview I intend on covering a few Ansibl

Using a Custom Ansible Module for ISE API Interaction

"The What?" - In this post I am going to provide a general understanding on how to use a custom Ansible module. A module is essentially a reusable standalone script that Ansible will run on your beha