REST API Builder

This tutorial describes how to construct a REST API so that traffic queries and other scriptable features can be invoked remotely. Before proceeding with this tutorial it is worth studying the Scripting Queries tutorial since it introduces the scripting capabilities of Traffic Sentinel.

Note: This tutorial describes a feature that was added in Traffic Sentinel 6.0.39. If you are running an older version of Traffic Sentinel you will need to upgrade before you can use this.

Query Scripts Directory

REST-API query scripts should be added to:

/usr/local/inmsf/queries
You may need to log in to the server and create this directory before you start.

Example

Below is a simple example of a REST API query script:

// author: Neil McKee
// date: 2/12/2013
// version: 1.0
// description: query for host location
// ttl: 60
// resultFormat: json

if(!address) throw("missing address");
var net = Network.current();
var loc = net.locationMap([ address ]);
var locationZone = null;
var locationGroup = null;
var locationIF = null;
if(loc) {
  locationIF = loc[0];
  net.path = locationIF;
  locationZone = net.zone();
  locationGroup = net.group();
}
var ans = {
   "address": address,
      "zone": locationZone,
     "group": locationGroup,
      "port": locationIF,
};
println(JSON.stringify(ans));

Save this as /usr/local/inmsf/queries/location.js and then you can invoke it immediately like this:

http://<server>/inmsf/Q/location.js?address=<address>

where <server> is your traffic sentinel server and <address> can be any address (IP, MAC, IPv6, ...). The output should look like this:

{"address":"10.0.0.70","zone":"SF","group":"Lab","port":"10.0.0.239>2"}

Result Caching

The ttl: 60 comment at the top of the script directs the server to cache the result for 60 seconds.

Access Control

A comment such as AuthClients: 10.1.1.0/24,10.2.2.0/24 will restrict access to client IPs in those CIDRs.

Alternatively, comments authUser: user and authPasswd: pass will require the client to supply that user and password via HTTP basic authentication. The use of basic authentication may imply that only https should be used to access the API. If so, that can be controlled in the apache config (see /etc/httpd/conf.d/inmsf_httpd.conf). For example to force all REST API calls to use https:

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/inmsf/Q/(.*) https://%{SERVER_NAME}/inmsf/Q/$1 [L,R]

You may need to install the apache mod_ssl package first.

Output Format

The resultFormat: <format> comment announces the output format, which controls the mime-type of the page. Options are txt,csv,json or html.

Traffic Query Example

Below is another example. This time it is a real-time traffic query that can only be accessed from client 10.0.0.114. The ttl is set to 60 seconds but the view: rttraffic comment means the server will invalidate the cache if new data is available for the rttraffic view.

// author: Peter Phaal
// date: 10/12/2012
// version: 1.0
// description: csv Query(view, select, where, interval, sort, n, group, headers)
// ttl: 60
// view: rttraffic
// resultFormat: csv
// authClients: 10.0.0.114

var view = "rttraffic";
var select   = typeof(select)   != 'undefined' ? select   : "sourceaddress,bytes";
var where    = typeof(where)    != 'undefined' ? where    : "";
var interval = typeof(interval) != 'undefined' ? interval : "last60minutes";
var sort     = typeof(sort)     != 'undefined' ? sort     : "bytes";
var n        = typeof(n)        != 'undefined' ? n        : "10";
var group    = typeof(group)    != 'undefined' ? group    : "";
var headers  = typeof(headers)  != 'undefined' ? headers  : false;

var max_n     = 100;
var max_range = 180;

try {
  if(!select) throw "missing select";
  if(!interval) throw "missing interval";
  if(!sort) throw "missing sort";
  if(!n) throw "missing n";

  if(n <= 0) throw "error n <= 0";
  if(n > max_n) throw "error n > " + max_n;

  var q = Query.topN(view,select,where,interval,sort,n);
  q.group = group;

  var times = q.timeRange();
  var now = (new Date()).getTime();
  if((Math.abs((now - times[0].getTime()) / 60000)) > max_range) throw "interval range";
  if((Math.abs((now - times[1].getTime()) / 60000)) > max_range) throw "interval range";

  var table = q.run();
  table.printCSV(headers);
} catch(err) {
  println("error = " + err);
}

Related Topics