Feb
1
2016

Using Cisco ISE API to write web interface

In the last three months, I was involved in a project concerning the migration of the authentication system (dot1x) from Cisco ACS to Cisco ISE (1.4). At the end of this work, the account told me if it is possible to have a web interface with the active sessions, the devices authenticated via Dot1x and the devices authenticated via MAB.

Reading the official guide, I found that Cisco ISE has embedded API. Cool! This what I needed!

There are two different API:

  • REST API: it allow you to gather session and node-specific information; for instance: session management, troubleshooting, change of authorization (CoA).
  • External RESTful API: it allows to perform Create, Read, Update, Delete (CRUD) operations. These APIs provide an interface to the ISE configuration data by enabling users, endpoints, endpoint groups, identity groups and SGTs to perform CRUD operations on the ISE data. It uses port 9060.

In this article, only the REST APIs are used.

As you can read on the official guide, there are several type of REST APIs, but only one will be used:

  • https://< ISE-Management-Node >/admin/API/mnt/Session/ActiveList

Remember: To be able to use a public Monitoring REST API, you must first authenticate with Cisco ISE using valid credentials (for instance the admin account).

Note: This article requires minimum programming knowledge: PHP, CSS, JS and Html will be used.

 

Step 1: Test the API

Open a browser and copy the link:

https://< ISE-Management-Node >/API/mnt/Session/ActiveList

Enter valid login credentials. The result is an XML file with several values for each active session: user_name, calling_station_id, nas_ip_address, acct_session_id, audit_session_id, server and framed_ip_address.

 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
 <activeList noOfActiveSession="4">
  <activeSession>
   <user_name>CLIENT9757.ciscozine.com</user_name> 
   <calling_station_id>00:1F:00:2F:30:1F</calling_station_id> 
   <nas_ip_address>172.20.1.10</nas_ip_address> 
   <acct_session_id>0000001B</acct_session_id> 
   <audit_session_id>BC9903DE0000001200064295</audit_session_id> 
   <server>ciscozinesrv1</server> 
   <framed_ip_address>172.26.8.163</framed_ip_address> 
  </activeSession>
  <activeSession>
   <user_name>CLIENT8731.ciscozine.com</user_name> 
   <calling_station_id>11:31:50:78:45:08</calling_station_id> 
   <nas_ip_address>172.20.2.10</nas_ip_address> 
   <acct_session_id>00000003</acct_session_id> 
   <audit_session_id>BC9903DE000000010002666E</audit_session_id> 
   <server>ciscozinesrv2</server> 
   <framed_ip_address>192.168.77.78</framed_ip_address> 
  </activeSession>
  <activeSession>
   <user_name>22:15:99:C9:FE:1C</user_name> 
   <calling_station_id>22:15:99:C9:FE:1C</calling_station_id> 
   <nas_ip_address>172.20.1.10</nas_ip_address> 
   <acct_session_id>000008F8</acct_session_id> 
   <audit_session_id>BC9903DE000004EC0902160D</audit_session_id> 
   <server>ciscozinesrv1</server> 
   <framed_ip_address>172.17.1.78</framed_ip_address> 
  </activeSession>
  <activeSession>
   <user_name>CLIENT3377.ciscozine.com</user_name> 
   <calling_station_id>D0:BF:9C:DD:0B:4F</calling_station_id> 
   <nas_ip_address>172.20.1.10</nas_ip_address> 
   <acct_session_id>000008FB</acct_session_id> 
   <audit_session_id>BC9903DE000004EF0902160D</audit_session_id> 
   <server>ciscozinesrv1</server> 
   <framed_ip_address>172.26.8.198</framed_ip_address> 
  </activeSession>
 </activeList>

Note: In the PHP script only “user_name” and “calling_station_id” are extracted.

 

Step 2: Using PHP to manipulate XML

The script is based on three parts:

2a. Load the XML (you must change the $username, $password and $ISE_server variables).

<?PHP
//Your settings
$username = "admin";
$password = "C1sc0z!n3";
$ISE_server = "1.1.1.1";
 
// Create a stream
$opts = array('http'=>array('method'=>"GET",'header' => "Authorization: Basic " . base64_encode("$username:$password")));
$context = stream_context_create($opts);

// Open the file using the HTTP headers set above
$remote_url = 'https://'.$ISE_server.'/admin/API/mnt/Session/ActiveList';
$xmlstr = @file_get_contents($remote_url, false, $context);
if ($xmlstr===false){
        exit("I can't load the page!");
}
$XML = new SimpleXMLElement($xmlstr);

2b. Manipulate the XML.

$MAB='0';
$DOT1X='0';

foreach( $XML as $activeSession ){
 if (strcmp($activeSession->calling_station_id, $activeSession->user_name)==0){
  $MAB++;
 }
 else{
  $DOT1X++;
 }
}

$Active_Session=$MAB+$DOT1X;

2c. Print the result:

echo "<div id=\"STAT\"><div id=\"title\">Ciscozine DOT1X<br /><span id=\"last_update\">Last update: ".date("H:i:s - j F Y")."</span></div>";
echo "<div id=\"Total\">Active sessions<br /><span class=\"value\">$Active_Session</span></div>";
echo "<div id=\"DOT1X\">DOT1X<br /><span class=\"value\">$DOT1X</span></div>";
echo "<div id=\"MAB\">MAB<br /><span class=\"value\">$MAB</span></div></div>";
?>

Copy these three parts in the stats.php file and load it in a browser. The result is something like that:

Ciscozine DOT1X
Last update: 21:20:12 - 30 January 2016
Sessioni attive
4
DOT1X
3
MAB
1

Note: Obviously, there are several ways to manipulate XML with PHP.

 

3. JQuery and CSS

For a better user experience, Jquery and CSS are used:

3a. Download the last compressed release of jquery (https://jquery.com/download/) and save it as “jquery.min.js”.

3b. Save the CSS as style.css:

* {
 margin: 0;
 padding: 0;
}

body{
 font-family:Verdana, Arial, Helvetica, sans-serif;
 background-color: #323B55;
 color:#373739;
 font-size:20px;
 margin:5px 0 5px 0;
}

#container{
 text-align: center;
 display:table;
 background-color:#FFFFFF;
 margin:0 auto;
 padding: 5px 20px 5px 20px;
 text-align:center;
 border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; -khtml-border-radius: 10px; 
box-shadow: 0 5px 12px rgba(0,0,0,.4); -webkit-box-shadow: 0 5px 12px rgba(0,0,0,.4); -moz-box-shadow: 0 5px 12px 
rgba(0,0,0,.4); -khtml-box-shadow: 0 5px 12px rgba(0,0,0,.4); 
 clear:both;
 width:960px;
}

div#title{
 font-size:36px;
 margin-bottom:30px;
}

div#title span#last_update{
 font-size:14px;
}

div#Total, div#DOT1X, div#MAB{
 float:left;
 font-size:24px;
 padding:30px 40px 20px 40px;
 min-width: 220px;
 margin: 10px;
 border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; -khtml-border-radius: 10px; 
box-shadow: 0 5px 12px rgba(0,0,0,.4); -webkit-box-shadow: 0 5px 12px rgba(0,0,0,.4); -moz-box-shadow: 0 5px 12px 
rgba(0,0,0,.4); -khtml-box-shadow: 0 5px 12px rgba(0,0,0,.4);
 background-color:#BFFF80;
}

span.value{
 font-size:82px;
 font-weight:bold;
}

div#connection_problem{
 width: 320px;
 background-color: #FFFFFF;
 font-weight:bold;
 border: 1px solid #666666;
 color:red;
 padding: 5px 10px 5px 10px;
 text-align:center;
 border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; -khtml-border-radius: 10px; 
box-shadow: 0 5px 12px rgba(0,0,0,.4); -webkit-box-shadow: 0 5px 12px rgba(0,0,0,.4); -moz-box-shadow: 0 5px 12px 
rgba(0,0,0,.4); -khtml-box-shadow: 0 5px 12px rgba(0,0,0,.4); 
 position: absolute;
 top: 135px;
 left: 50%;
 margin-left: -175px;
 z-index:2;
}

3c. Save this html code as index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
<script src="jquery.min.js" type="text/javascript"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
<title>Ciscozine DOT1X</title>

<script type="text/javascript">
//<![CDATA[//><!--
$(document).ready(function(){

var refresh_time=1000;

var dot1x = function(){
 clearInterval(interval);
 interval = setInterval(dot1x, refresh_time);


 $("#container").load('stats.php', function( response, status, xhr ){
 if ( status == "error" ) {
 $("#connection_problem").slideDown("slow");
 }
 else{
 $("#connection_problem").slideUp("slow");
 }
 //Page refresh time (milliseconds)
 refresh_time=30000;
 });
}


 var interval = setInterval(dot1x, refresh_time);
 $.ajaxSetup({ cache: false });
 
});
//--><!]]>
</script>

</head>

<body>
<div id="container"><br /><br />Loading...<br /><br /></div>
<div id="connection_problem" style="display: none">Connection problem.<br />Check your web server or your connection!</div>
</body>
</html>

Open the index.html:

Cisco-ISE-API-write-web-interface

Note: the refresh_time variables is expressed in milliseconds and define the page refresh time  (by default 30 seconds).

You can download the script here.

 

Consideration: This article is a simple demonstration of what API can do. There can be many other implementations based on your configuration and you goal.

References:

Summary
Article Name
Using Cisco ISE API to write web interface
Description
Reading the official guide, I found that the Cisco ISE have embedded API. Cool! This what I needed! There are two different API: REST API, RESTful API.
Author
  • Iarno Pagliani

    Hi Fabio,
    great post. I’ve tested on Cisco ISE 2.0 and it works as well.

  • Good news Iarno!
    Thank you.