cancel
Showing results for 
Search instead for 
Did you mean: 

Pulse Secure vADC

Sort by:
Java Extensions are one of the 'data plane' APIs provided by Traffic Manager to process network transactions.  Java Extensions are invoked from TrafficScript using the java.run() function.   This article contains a selection of technical tips and solutions to illustrate the use of Java Extensions.   Basic Language Examples   Writing Java Extensions - an introduction (presenting a template and 'Hello World' application) Writing TrafficScript functions in Java (illustrating how to use the GenericServlet interface) Tech Tip: Prompting for Authentication in a Java Extension Tech Tip: Reading HTTP responses in a Java Extension   Advanced Language Examples   Apache Commons Logging (TODO) Authenticating users with Active Directory and Stingray Java Extensions Watermarking Images with Traffic Manager and Java Extensions Watermarking PDF documents with Traffic Manager and Java Extensions Being Lazy with Java Extensions XML, TrafficScript and Java Extensions Merging RSS feeds using Java Extensions (12/17/2008) Serving Web Content from Traffic Manager using Java Stingray-API.jar: A Java Interface Library for Traffic Manager's SOAP Control API TrafficManager Status - Using the Control API from a Java Extension   Java Extensions in other languages   PyRunner.jar: Running Python code in Traffic Manager Making Traffic Manager more RAD with Jython! Scala, Traffic Manager and Java Extensions (06/30/2009)   More information   Feature Brief: Java Extensions in Traffic Manager Java Development Guide documentation in the Product Documentation
View full article
With more services being delivered through a browser, it's safe to say web applications are here to stay. The rapid growth of web enabled applications and an increasing number of client devices mean that organizations are dealing with more document transfer methods than ever before. Providing easy access to these applications (web mail, intranet portals, document storage, etc.) can expose vulnerable points in the network.   When it comes to security and protection, application owners typically cover the common threats and vulnerabilities. What is often overlooked happens to be one of the first things we learned about the internet, virus protection. Some application owners consider the response “We have virus scanners running on the servers” sufficient. These same owners implement security plans that involve extending protection as far as possible, but surprisingly allow a virus sent several layers within the architecture.   Pulse vADC can extend protection for your applications with unmatched software flexibility and scale. Utilize existing investments by installing Pulse vADC on your infrastructure (Linux, Solaris, VMWare, Hyper-V, etc.) and integrate with existing antivirus scanners. Deploy Pulse vADC (available with many providers: Amazon, Azure, CoSentry, Datapipe, Firehost, GoGrid, Joyent, Layered Tech, Liquidweb, Logicworks, Rackspace, Sungard, Xerox, and many others) and externally proxy your applications to remove threats before they are in your infrastructure. Additionally, when serving as a forward proxy for clients, Pulse vADC can be used to mitigate virus propagation by scanning outbound content.   The Pulse Web Application Firewall ICAP Client Handler provides the possibility to integrate with an ICAP server. ICAP (Internet Content Adaption Protocol) is a protocol aimed at providing simple object-based content vectoring for HTTP services. The Web Application Firewall acts as an ICAP client and passes requests to a specified ICAP server. This enables you to integrate with third party products, based on the ICAP protocol. In particular, you can use the ICAP Client Handler as a virus scanner interface for scanning uploads to your web application.   Example Deployment   This deployment uses version 9.7 of the Pulse Traffic Manager with open source applications ClamAV and c-icap installed locally. If utilizing a cluster of Traffic Managers, this deployment should be performed on all nodes of the cluster. Additionally, Traffic Manager could be utilized as an ADC to extend availability and performance across multiple external ICAP application servers. I would also like to credit Thomas Masso, Jim Young, and Brian Gautreau - Thank you for your assistance!   "ClamAV is an open source (GPL) antivirus engine designed for detecting Trojans, viruses, malware and other malicious threats." - http://www.clamav.net/   "c-icap is an implementation of an ICAP server. It can be used with HTTP proxies that support the ICAP protocol to implement content adaptation and filtering services." - The c-icap project   Installation of ClamAV, c-icap, and libc-icap-mod-clamav   For this example, public repositories are used to install the packages on version 9.7 of the Traffic Manager virtual appliance with the default configuration. To install in a different manner or operating system, consult the ClamAV and c-icap documentation.   Run the following commands (copy and paste) to backup and update sources.list file cp /etc/apt/sources.list /etc/apt/sources.list.rvbdbackup   Run the following commands to update the sources.list file. *Tested with Traffic Manager virtual appliance version 9.7. For other Ubuntu releases replace the 'precise' with the current version installed. Run "lsb_release -sc" to find out your release. cat <> /etc/apt/sources.list deb http://ch.archive.ubuntu.com/ubuntu/ precise main restricted deb-src http://ch.archive.ubuntu.com/ubuntu/ precise main restricted deb http://us.archive.ubuntu.com/ubuntu/ precise universe deb-src http://us.archive.ubuntu.com/ubuntu/ precise universe deb http://us.archive.ubuntu.com/ubuntu/ precise-updates universe deb-src http://us.archive.ubuntu.com/ubuntu/ precise-updates universe EOF   Run the following command to retrieve the updated package lists   apt-get update   Run the following command to install ClamAV, c-icap, and libc-icap-mod-clamav.   apt-get install clamav c-icap libc-icap-mod-clamav   Run the following command to restore your sources.list.   cp /etc/apt/sources.list.rvbdbackup /etc/apt/sources.list   Configure the c-icap ClamAV service   Run the following commands to add lines to the /etc/c-icap/c-icap.conf   cat <> /etc/c-icap/c-icap.conf Service clamav srv_clamav.so ServiceAlias avscan srv_clamav?allow204=on&sizelimit=off&mode=simple srv_clamav.ScanFileTypes DATA EXECUTABLE ARCHIVE GIF JPEG MSOFFICE srv_clamav.MaxObjectSize 100M EOF   *Consult the ClamAV and c-icap documentation and customize the configuration and settings for ClamAV and c-icap (i.e. definition updates, ScanFileTypes, restricting c-icap access, etc.) for your deployment.   Just for fun run the following command to manually update the clamav database. /usr/bin/freshclam   Configure the ICAP Server to Start   This process can be completed a few different ways, for this example we are going to use the Event Alerting functionality of Traffic Manager to start i-cap server when the Web Application Firewall is started.   Save the following bash script (for this example start_icap.sh) on your computer. #!/bin/bash /usr/bin/c-icap #END   Upload the script via the Traffic Manager UI under Catalogs > Extra Files > Action Programs. (see Figure 1) Figure 1      Create a new event type (for this example named "Firewall Started") under System > Alerting > Manage Event Types. Select "appfirewallcontrolstarted: Application firewall started" and click update to save. (See Figure 2) Figure 2      Create a new action (for this example named "Start ICAP") under System > Alerting > Manage Actions. Select the "Program" radio button and click "Add Action" to save. (See Figure 3) Figure 3     Configure the "Start ICAP" Action Program to use the "start_icap.sh" script, and for this example we will adjust the timeout setting to 300. Click Update to save. (See Figure 4) Figure 4      Configure the Alert Mapping under System > Alerting to use the Event type and Action previously created. Click Update to save your changes. (See Figure 5) Figure 5      Restart the Application Firewall or reboot to automatically start i-cap server. Alternatively you can run the /usr/bin/c-icap command from the console or select "Update and Test" under the "Start ICAP" alert configuration page of the UI to manually start c-icap.   Configure the Web Application Firewall Within the Web Application Firewall UI, Add and configure the ICAPClientHandler using the following attribute and values.   icap_server_location - 127.0.0.1 icap_server_resource - /avscan   Testing Notes   Check the WAF application logs. Use Full logging for the Application configuration and enable_logging for the ICAPClientHandler. As with any system use full logging with caution, they could fill fast! Check the c-icap logs ( cat /var/log/c-icap/access.log & server.log). Note: Changing the /etc/c-icap/c-icap.conf "DebugLevel" value to 9 is useful for testing and recording to the /var/log/c-icap/server.log. *You may want to change this back to 1 when you are done testing. The Action Settings page in the Traffic Manager UI (for this example  Alerting > Actions > Start ICAP) also provides an "Update and Test" that allows you to trigger the action and start the c-icap server. Enable verbose logging for the "Start ICAP" action in the Traffic Manager for more information from the event mechanism. *You may want to change this setting back to disable when you are done testing.   Additional Information Pulse Secure Virtual Traffic Manager Pulse Secure Virtual Web Application Firewall Product Documentation RFC 3507 - Internet Content Adaptation Protocol (ICAP) The c-icap project Clam AntiVirus  
View full article
When deploying applications using content management systems, application owners are typically limited to the functionality of the CMS application in use or third party add-on's available. Unfortunately, these components alone may not deliver the application requirements.  Leaving the application owner to dedicate resources to develop a solution that usually ends up taking longer than it should, or not working at all. This article addresses some hypothetical production use cases, where the application does not provide the administrators an easy method to add a timer to the website.   This solution builds upon the previous articles (Embedded Google Maps - Augmenting Web Applications with Traffic Manager and Embedded Twitter Timeline - Augmenting Web Applications with Traffic Manager). "Using" a solution from Owen Garrett (See Instrument web content with Traffic Manager),This example will use a simple CSS overlay to display the added information.   Basic Rule   As a starting point to understand the minimum requirements, and to customize for your own use. I.E. Most people want to use "text-align:center". Values may need to be added to the $style or $html for your application, see examples.   1 2 3 4 5 6 7 8 9 10 11 if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;       $timer =  ( "366" - ( sys. gmtime . format ( "%j" ) ) );       $html =  '<div class="Countdown">' . $timer . ' DAYS UNTIL THE END OF THE YEAR</div>' ;       $style = '<style type="text/css">.Countdown{z-index:100;background:white}</style>' ;       $body = http.getResponseBody();  $body = string.regexsub( $body , "(<body[^>]*>)" , $style . "$1\n" . $html . "\n" , "i" );  http.setResponseBody( $body );   Example 1 - Simple Day Countdown Timer   This example covers a common use case popular with retailers, a countdown for the holiday shopping season. This example also adds font formatting and additional text with a link.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #Only process text/html content  if ( !string.startsWith (http.getResponseHeader ( "Content-Type" ), "text/html" )) break;       #Countdown target  #Julian day of the year "001" to "366"  $targetday = "359" ;  $bgcolor = "#D71920" ;  $labelday = "DAYS" ;  $title = "UNTIL CHRISTMAS" ;  $titlecolor = "white" ;  $link = "/dept.jump?id=dept20020200034" ;  $linkcolor = "yellow" ;  $linktext = "VISIT YOUR ONE-STOP GIFT SHOP" ;       #Calculate days between today and targetday  $timer = ( $targetday - ( sys. gmtime . format ( "%j" ) ) );       #Remove the S from "DAYS" if only 1 day left  if ( $timer == 1 ){     $labelday = string.drop( $label , 1 );  };       $html = '  <div class= "TrafficScriptCountdown" >     <h3>       <font color= "'.$titlecolor.'" >         '.$timer.' '.$labelday.' '.$title.'        </font>       <a href= "'.$link.'" >         <font color= "'.$linkcolor.'" >           '.$linktext.'          </font>       </a>     </h3>  </div>  ';       $style = '  <style type= "text/css" >  .TrafficScriptCountdown {     position:relative;     top:0;     width:100%;     text-align:center;     background: '.$bgcolor.' ;     opacity:100%;     z- index :1000;     padding:0  }  </style>  ';       $body = http.getResponseBody();       $body = string.regexsub( $body , "(<body[^>]*>)" , $style . "$1\n" . $html . "\n" , "i" );       http.setResponseBody( $body );?    Example 1 in Action     Example 2 - Ticking countdown timer with second detail   This example covers how to dynamically display the time down to seconds. Opposed to sending data to the client every second, I chose to use a client side java script found @ HTML Countdown to Date v3 (Javascript Timer)  | ricocheting.com   Example 2 Response Rule   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;       #Countdown target  $year = "2014" ;  $month = "11" ;  $day = "3" ;  $hr = "8" ;  $min = "0" ;  $sec = "0" ;  #number of hours offset from UTC  $utc = "-8" ;       $labeldays = "DAYS" ;  $labelhrs = "HRS" ;  $labelmins = "MINS" ;  $labelsecs = "SECS" ;  $separator = ", " ;       $timer = '<script type= "text/javascript" >  var CDown=function(){this.state=0,this.counts=[],this.interval=null};CDown. prototype =\  {init:function(){this.state=1;var t=this;this.interval=window.setInterval(function()\  {t.tick()},1e3)},add:function(t,s){tzOffset= '.$utc.' ,dx=t.toGMTString(),dx=dx. substr \  (0,dx. length -3),tzCurrent=t.getTimezoneOffset()/60*-2,t.setTime(Date.parse(dx)),\  t.setHours(t.getHours()+tzCurrent-tzOffset),this.counts. push ({d:t,id:s}),this.tick(),\  0==this.state&&this.init()},expire:function(t){ for (var s in t)this.display\  (this.counts[t[s]], "Now!" ),this.counts. splice (t[s],1)}, format :function(t){var s= "" ;\  return 0!=t.d&&(s+=t.d+ " " +(1==t.d? "'.string.drop( $labeldays, 1 ).'" :" '.$labeldays.' \  ")+" '.$separator.' "),0!=t.h&&(s+=t.h+" "+(1==t.h?" '.string.drop( $labelhrs, 1 ).' ":\  "'.$labelhrs.'" )+ "'.$separator.'" ),s+=t.m+ " " +(1==t.m?"\  '.string.drop( $labelmins, 1 ).' ":" '.$labelmins.' ")+" '.$separator.' ",s+=t.s+" "\  +(1==t.s? "'.string.drop( $labelsecs, 1 ).'" : "'.$labelsecs.'" )+ "'.$separator.'" \  ,s. substr (0,s. length -2)},math:function(t){var i=w=d=h=m=s=ms=0; return ms=( "" +\  (t %1e3 +1e3)). substr (1,3),t=Math.floor(t/1e3),i=Math.floor(t/31536e3),w=Math.floor\  (t/604800),d=Math.floor(t/86400),t%=86400,h=Math.floor(t/3600),t%=3600,m=Math.floor\  (t/60),t%=60,s=Math.floor(t),{y:i,w:w,d:d,h:h,m:m,s:s,ms:ms}},tick:function()\  {var t=(new Date).getTime(),s=[],i=0,n=0; if (this.counts) for (var e=0,\  o=this.counts. length ;o>e;++e)i=this.counts[e],n=i.d.getTime()-t,0>n?s. push (e):\  this.display(i,this. format (this.math(n)));s. length >0&&this.expire(s),\  0==this.counts. length &&window.clearTimeout(this.interval)},display:function(t,s)\  {document.getElementById(t.id).innerHTML=s}},window.onload=function()\  {var t=new CDown;t.add(new Date\  ( '.$year.' , '.--$month.' , '.$day.' , '.$hr.' , '.$min.' , '.$sec.' ), "countbox1" )};  </script><span id= "countbox1" ></span>';       $html =  '<div class= "TrafficScriptCountdown" ><center><h3><font color= "white" >\  COUNTDOWN TO RIVERBED FORCE '.$timer.' </font>\  <a href= "https://secure3.aetherquest.com/riverbedforce2014/" ><font color= "yellow" >\  REGISTER NOW</a></h3></font></center></div>';       $style = '<style type= "text/css" >.TrafficScriptCountdown{position:relative;top:0;\  width:100%;background: #E9681D;opacity:100%;z-index:1000;padding:0}</style>';       http.setResponseBody( string.regexsub( http.getResponseBody(),  "(<body[^>]*>)" , $style . "$1\n" . $html . "\n" , "i" ) );    Example 2 in action     Notes   Example 1 results in faster page load time than Example 2. Example 1 can be easily extended to enable Traffic Script to set $timer to include detail down to the second as in example 2. Be aware of any trailing space(s) after the " \ " line breaks when copy and paste is used to import the rule. Incorrect spacing can stop the JS and the HTML from functioning. You may have to adjust the elements for your web application. (i.e. z-index, the regex sub match, div class, etc.).   This is a great example of using Traffic Manager to deliver a solution in minutes that could otherwise could take hours.
View full article
The SOAP Control API is one of the 'Control Plane' APIs provided by Pulse Traffic Manager (see also REST and SNMP).   This article contains a selection of simple technical tips and solutions that use the SOAP Control API to manage and query Traffic Manager.   Basic language examples   Tech Tip: Using the SOAP Control API with Perl Tech Tip: Using the SOAP Control API with C# Tech Tip: Using the SOAP Control API with Java Tech Tip: Using the SOAP Control API with Python Tech Tip: Using the SOAP Control API with PHP Tech Tip: Using the SOAP Control API with Ruby Tech Tip: Ruby and SOAP revisited Tech Tip: Ruby and SOAP - a rubygems implementation   More sophisticated tips and examples   Tech Tip: Running Perl code on the Pulse vADC Virtual Appliance Tech Tip: using Perl SOAP::Lite with Traffic Manager's SOAP Control API Tech Tip: Using Perl/SOAP to list recent connections in Pulse Traffic Manager Gathering statistics from a cluster of Traffic Managers   More information   For a more rigorous introduction to the SOAP Control API, please refer to the Control API documentation in the  Product Documentation
View full article
Feature Brief: Pulse Traffic Manager RESTful Control API is one of the 'Control Plane' APIs provided by Pulse Traffic Manager (see also Feature Brief: Pulse Traffic Manager SOAP API). This article contains a selection of simple technical tips and solutions that use the REST Control API to manage and query Pulse Traffic Manager.   Overview Tech Tip: Using the RESTful Control API with Python Tech Tip: Using the RESTful Control API with Perl Tech Tip: Using the RESTful Control API with Ruby Tech Tip: Using the RESTful Control API with TrafficScript Tech Tip: Using the RESTful Control API with PHP   Example programs   Retrieving resource configuration data Tech Tip: Using the RESTful Control API with Python - listpools Tech Tip: Using the RESTful Control API with Perl - listpools Tech Tip: Using the RESTful Control API with Ruby - listpools Tech Tip: Using the RESTful Control API with TrafficScript - listpools Tech Tip: Using the RESTful Control API with PHP - listpools Tech Tip: Using the RESTful Control API with Python - listpoolnodes Tech Tip: Using the RESTful Control API with Perl - listpoolnodes Tech Tip: Using the RESTful Control API with Ruby - listpoolnodes Tech Tip: Using the RESTful Control API with TrafficScript - listpoolnodes Tech Tip: Using the RESTful Control API with PHP - listpoolnodes   Changing resource configuration data Tech Tip: Using the RESTful Control API with Python - startstopvs Tech Tip: Using the RESTful Control API with Perl - startstopvs Tech Tip: Using the RESTful Control API with Ruby - startstopvs Tech Tip: Using the RESTful Control API with TrafficScript - startstopvs Tech Tip: Using the RESTful Control API with PHP - startstopvs Adding a resource Tech Tip: Using the RESTful Control API with Python - addpool Tech Tip: Using the RESTful Control API with Perl - addpool Tech Tip: Using the RESTful Control API with Ruby - addpool Tech Tip: Using the RESTful Control API with TrafficScript - addpool Tech Tip: Using the RESTful Control API with PHP - addpool Tech Tip: Creating a new service with the REST API and Python   Deleting a resource Tech Tip: Using the RESTful Control API with Python - deletepool Tech Tip: Using the RESTful Control API with Perl - deletepool Tech Tip: Using the RESTful Control API with Ruby - deletepool Tech Tip: Using the RESTful Control API with TrafficScript - deletepool Tech Tip: Using the RESTful Control API with PHP - deletepool   Adding a file Tech Tip: Using the RESTful Control API with Python - addextrafile Tech Tip: Using the RESTful Control API with Perl - addextrafile Tech Tip: Using the RESTful Control API with Ruby - addextrafile Tech Tip: Using the RESTful Control API with PHP - addextrafile   Other Examples HowTo: List all of the draining nodes in Traffic Manager using Python and REST HowTo: Drain a node in multiple pools (Python REST API example) Deploying Python code to Pulse Traffic Manager Slowing down busy users - driving the REST API from TrafficScript Tech Tip: Using the RESTful Control API to get pool statistics with PHP Read More   The REST API Guide in the Product Documentation Feature Brief: Pulse Traffic Manager RESTful Control API
View full article
TrafficScript is the programming language that is built into the Traffic Manager.  With TrafficScript, you can create traffic management 'rules' to control the behaviour of Traffic Manager in a wide manner of ways, inspecting, modifying and routing any type of TCP or UDP traffic.   The language is a simple, procedural one - the style and syntax will be familiar to anyone who has used Perl, PHP, C, BASIC, etc. Its strength comes from its integration with Traffic Manager, allowing you to perform complex traffic management tasks simply, such as controlling traffic flow, reading and parsing HTTP requests and responses, and managing XML data.   This article contains a selection of simple technical tips to illustrate how to perform common tasks using TrafficScript.   TrafficScript Syntax   HowTo: TrafficScript Syntax HowTo: TrafficScript variables and types HowTo: if-then-else conditions in TrafficScript HowTo: loops in TrafficScript HowTo: TrafficScript rules processing and flow control HowTo: TrafficScript String Manipulation HowTo: TrafficScript Libraries and Subroutines HowTo: TrafficScript Arrays and Hashes   HTTP operations   HowTo: Techniques to read HTTP headers HowTo: Set an HTTP Response Header HowTo: Inspect HTTP Request Parameters HowTo: Rewriting HTTP Requests HowTo: Rewriting HTTP Responses HowTo: Redirect HTTP clients HowTo: Inspect and log HTTP POST data HowTo: Handle cookies in TrafficScript   XML processing   HowTo: Inspect XML and route requests Managing XML SOAP data with TrafficScript   General examples   HowTo: Controlling Session Persistence HowTo: Control Bandwidth Management HowTo: Monitor the response time of slow services HowTo: Query an external datasource using HTTP HowTo: Techniques for inspecting binary protocols HowTo: Spoof Source IP Addresses with IP Transparency HowTo: Use low-bandwidth content during periods of high load HowTo: Log slow connections in Stingray Traffic Manager HowTo: Inspect and synchronize SMTP HowTo: Write Health Monitors in TrafficScript HowTo: Delete Session Persistence records   More information   For a more rigorous introduction to the TrafficScript language, please refer to the TrafficScript guide in the Product Documentation
View full article
This article explains how to use Pulse vADC RESTful Control API with Perl.  It's a little more work than with Tech Tip: Using the RESTful Control API with Python - Overview but once the basic environment is set up and the framework in place, you can rapidly create scripts in Perl to manage the configuration.   Getting Started   The code examples below depend on several Perl modules that may not be installed by default on your client system: REST::Client, MIME::Base64 and JSON.   On a Linux system, the best way to pull these in to the system perl is by using the system package manager (apt or rpm). On a Mac (or a home-grown perl instance), you can install them using CPAN   Preparing a Mac to use CPAN   Install the package 'Command Line Tools for Xcode' either from within the Xcode or directly from https://developer.apple.com/downloads/.   Some of the CPAN build scripts indirectly seek out /usr/bin/gcc-4.2 and won't build if /usr/bin/gcc-4.2 is missing.  If gcc-4.2 is missing, the following should help:   $ ls -l /usr/bin/gcc-4.2 ls: /usr/bin/gcc-4.2: No such file or directory $ sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2   Installing the perl modules   It may take 20 minutes for CPAN to initialize itself, download, compile, test and install the necessary perl modules:   $ sudo perl –MCPAN –e shell cpan> install Bundle::CPAN cpan> install REST:: Client cpan> install MIME::Base64 cpan> install JSON   Your first Perl REST client application   This application looks for a pool named 'Web Servers'.  It prints a list of the nodes in the pool, and then sets the first one to drain.   #!/usr/bin/perl use REST::Client; use MIME::Base64; use JSON; # Configurables $poolname = "Web Servers"; $endpoint = "stingray:9070"; $userpass = "admin:admin"; # Older implementations of LWP check this to disable server verification $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; # Set up the connection my $client = REST::Client->new( ); # Newer implementations of LWP use this to disable server verification # Try SSL_verify_mode => SSL_VERIFY_NONE. 0 is more compatible, but may be deprecated $client->getUseragent()->ssl_opts( SSL_verify_mode => 0 ); $client->setHost( "https://$endpoint" ); $client->addHeader( "Authorization", "Basic ".encode_base64( $userpass ) ); # Perform a HTTP GET on this URI $client->GET( "/api/tm/1.0/config/active/pools/$poolname" ); die $client->responseContent() if( $client->responseCode() >= 300 ); # Add the node to the list of draining nodes my $r = decode_json( $client->responseContent() ); print "Pool: $poolname:\n"; print " Nodes: " . join( ", ", @{$r->{properties}->{basic}->{nodes}} ) . "\n"; print " Draining: " . join( ", ", @{$r->{properties}->{basic}->{draining}} ) . "\n"; # If the first node is not already draining, add it to the draining list $node = $r->{properties}->{basic}->{nodes}[0]; if( ! ($node ~~ @{$r->{properties}->{basic}->{draining}}) ) { print " Planning to drain: $node\n"; push @{$r->{properties}->{basic}->{draining}}, $node; } # Now put the updated configuration $client->addHeader( "Content-Type", "application/json" ); $client->PUT( "/api/tm/1.0/config/active/pools/$poolname", encode_json( $r ) ); die $client->responseContent() if( $client->responseCode() >= 300 ); my $r = decode_json( $client->responseContent() ); print " Now draining: " . join( ", ", @{$r->{properties}->{basic}->{draining}} ) . "\n";   Running the script   $ perl ./pool.pl Pool: Web Servers: Nodes: 192.168.207.101:80, 192.168.207.103:80, 192.168.207.102:80 Draining: 192.168.207.102:80 Planning to drain: 192.168.207.101:80 Now draining: 192.168.207.101:80, 192.168.207.102:80   Notes   This script was tested against two different installations of perl, with different versions of the LWP library.  It was necessary to disable SSL certificate checking using:   $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;   ... with the older, and:   # Try SSL_verify_mode => SSL_VERIFY_NONE. 0 is more compatible, but may be deprecated $client->getUseragent()->ssl_opts( SSL_verify_mode => 0 );   with the new.  The older implementation failed when using SSL_VERIFY_NONE.  YMMV.
View full article
Pulse Virtual Traffic Manager contains a GeoIP database that maps IP addresses to location - longitude and latitude, city, county and country.  The GeoIP database is used by the Global Load Balancing capability to estimate distances between remote users and local datacenters, and it is accessible using the  geo.*  TrafficScript and Java functions.  
View full article
The following code uses Stingray's RESTful API to list all the pools defined for a cluster and for each pool it lists the nodes defined for that pool, including draining and disabled nodes. The code is written in Python. This example builds on the previous listpools.py example.  This program does a GET request for the list of pool and then while looping through the list of pools, a GET is done for each pool to retrieve the configuration parameters for that pool.   listpoolnodes.py #! /usr/bin/env python import requests import json import sys print "Pools:\n" url = 'https://stingray.example.com:9070/api/tm/1.0/config/active/pools' jsontype = {'content-type': 'application/json'} client = requests.Session() client.auth = ('admin', 'admin') client.verify = False try: # Do the HTTP GET to get the lists of pools. We are only putting this client.get within a try # because if there is no error connecting on this one there shouldn't be an error connnecting # on later client.get so that would be an unexpected exception. response = client.get(url) except requests.exceptions.ConnectionError: print "Error: Unable to connect to " + url sys.exit(1) data = json.loads(response.content) if response.status_code == 200: if data.has_key('children'): pools = data['children'] for i, pool in enumerate(pools): poolName = pool['name'] # Do the HTTP GET to get the properties of a pool response = client.get(url + "/" + poolName) poolConfig = json.loads(response.content) if response.status_code == 200: # Since we are getting the properties for a pool we expect the first element to be 'properties' if poolConfig.has_key('properties'): # The value of the key 'properties' will be a dictionary containing property sections # All the properties that this program cares about are in the 'basic' section # nodes is the list of all active or draining nodes in this pool # draining the list of all draining nodes in this pool # disabled is the list of all disabled nodes in this pool nodes = poolConfig['properties']['basic']['nodes'] draining = poolConfig['properties']['basic']['draining'] disabled = poolConfig['properties']['basic']['disabled'] print pool['name'] print " Nodes: ", for n, node in enumerate(nodes): print node + " ", print "" if len(draining) > 0: print " Draining Nodes: ", for n, node in enumerate(draining): print node + " ", print "" if len(disabled) > 0: print " Disabled Nodes: ", for n, node in enumerate(disabled): print node + " ", print "" else: print "Error: No properties found for pool " + poolName print "" else: print "Error getting pool config: URL=%s Status=%d Id=%s: %s" %(url + "/" + poolName, response.status_code, poolConfig['error_id'], poolConfig['error_text']) else: print 'Error: No chidren found' else: print "Error getting pool list: URL=%s Status=%d Id=%s: %s" %(url, response.status_code, data['error_id'], data['error_text']) Running the example   This code was tested with Python 2.7.3 and version 1.1.0 of the requests library.   Run the Python script as follows:   $ listpoolnodes.py Pools:   Pool1     Nodes:  192.168.1.100 192.168.1.101     Draining:  192.168.1.101     Disabled:  192.168.1.102   Pool2     Nodes:  192.168.1.103 192.168.1.104   Read More   REST API Guide in the vADC Product Documentation Tech Tip: Using the RESTful Control API Collected Tech Tips: Using the RESTful Control API
View full article
The following code uses the RESTful API to list all the pools defined for a cluster and for each pool it lists the nodes defined for that pool, including draining and disabled nodes. The code is written in TrafficScript. This example builds on the previous stmrest_listpools example.  This rule does a GET request for the list of pools and then while looping through the list of pools, a GET is done for each pool to retrieve the configuration parameters for that pool.  A subroutine in stmrestclient is used to do the actual RESTful API call.  stmrestclient is attached to the article Tech Tip: Using the RESTful Control API with TrafficScript - Overview.   stmrest_listpoolnodes   ################################################################################ # stmrest_listpoolnodes # # This rule lists the names of all pools and also the nodes, draining nodes # and disable nodes in each pool. # # To run this rule add it as a request rule to an HTTP Virtual Server and in a # browser enter the path /rest/listpoolnodes. # # It uses the subroutines in stmrestclient ################################################################################ import stmrestclient; if (http.getPath() != "/rest/listpoolnodes") break; $resource = "pools"; $accept = "json"; $html = "<br><b>Pools:</b><br>"; $response = stmrestclient.stmRestGet($resource, $accept); if ($response["rc"] == 1) { $pools = $response["data"]["children"]; foreach ($pool in $pools) { $poolName = $pool["name"]; $response = stmrestclient.stmRestGet($resource. "/" . string.escape($poolName), $accept); if ($response["rc"] == 1) { $poolConfig = $response["data"]; $nodes = $poolConfig["properties"]["basic"]["nodes"]; $draining = $poolConfig["properties"]["basic"]["draining"]; $disabled = $poolConfig["properties"]["basic"]["disabled"]; $html = $html . "<br>" . $poolName . ":<br>"; $html = $html . "<br> Nodes: "; foreach ($node in $nodes) { $html = $html . $node . " "; } $html = $html . "\n"; if (array.length($draining) > 0) { $html = $html . "<br> Draining Nodes: "; foreach ($node in $draining) { $html = $html . $node . " "; } $html = $html . "\n"; } if (array.length($disabled) > 0) { $html = $html . "<br> Disabled Nodes: "; foreach ($node in $disabled) { html = $html . $node . " "; } $html = $html . "\n"; } $html = $html . "<br>\n"; } else { $html = $html . "There was an error getting the pool configuration for pool . " . $poolName . ": " . $response['info']; } } } else { $html = $html . "<br>There was an error getting the pool list: " . $response['info']; } http.sendResponse("200 OK", "text/html", $html, "");   Running the example   This rule should be added as a request rule to a Virtual Server and run with the URL:   http://<hostname>/rest/listpoolnodes   Pools:   Pool1     Nodes:  192.168.1.100 192.168.1.101     Draining:  192.168.1.101     Disabled:  192.168.1.102   Pool2     Nodes:  192.168.1.103 192.168.1.104   Read More   REST API Guide in the vADC Product Documentation Tech Tip: Using the RESTful Control API with TrafficScript - Overview Feature Brief: RESTful Control API Collected Tech Tips: Using the RESTful Control API
View full article
A selection of SteelApp security articles, for SteelApp Traffic Manager and SteelApp Web App Firewall. Listed from the most recent to the oldest, let me know if you have other articles to add to this list.   Poodle 2.0:   SteelApp not vulnerable to POODLE 2.0 (CVE 2014-8730) CVE-2014-8730   Poodle:   Disabling SSL v3.0 for SteelApp Re: Assuming TLS, what ciphers does SteelApp 9.8 support? CVE-2014-3566   ShellShock/Bash:   TrafficScript rule to protect against "Shellshock" bash vulnerability (CVE-2014-6271) CVE-2014-6271   Heartbleed:   Heartbleed: Using TrafficScript to detect TLS heartbeat records Would Stingray automatically protect servers from Heartbleed? CVE-2014-0160   Whitepapers:   Global-scale Web Application Security for DOD Why Web Application Firewalls Matter   Miscellaneous Articles:   The "Contact Us" attack against mail servers Protecting against Java and PHP floating point bugs Managing DDoS attacks with Stingray Traffic Manager Enhanced anti-DDoS using TrafficScript, Event Handlers and iptables How to stop 'login abuse', using TrafficScript Bind9 Exploit in the Wild... Protecting against the range header denial-of-service in Apache HTTPD Checking IP addresses against a DNS blacklist with Stingray Traffic Manager SteelApp TrafficManager SAML 2.0 Protocol Validation with TrafficScript
View full article
The SteelApp GLB (Global Load Balancer) performs global load balancing by manipulating DNS responses to clients. The load balancing algorithms available include round-robin, weighted, active/passive and load based. SteelApp also supports making the decision based on geographic proximity.   An extension to DNS known as the Client Subnet Option (CSO) has been drafted by the IETF. The draft: draft-vandergaast-edns-client-subnet-02 is now at version 2.0 and is currently being used by Google and some other large DNS providers. The Client Subnet Option adds an additional DNS Extension record (EDNS0) into requests which are sent to authoritative name servers. This additional record allows recursive DNS servers to add in the originating client IP subnet into the request. The authoritative name server may then provide an optimized response.   The SteelApp GLB does not natively understand  EDNS0 records at present, but we can detect the presence of the CSO extension using a simple TrafficScript. The script can then modify the request in such a way that the GLB will use the CSO in its decision making process.   Here's the TrafficScript:   #=-To log resolver, use macro: %t %v %h %A:%p %n %B %b %T %{resolver}d # Set verbose to 1 to enable logging to event log, 0 to disable. $verbose = 0; # EDNS0 OPT Code 0x0 0x08, Len 0x0 0x07, IPv4 family 0x01, length 24bits 0x18, mask 0x0 $csoBytes = string.hexdecode("0008000700011800"); $resolver = "-"; $data = request.get( request.getLength() ); $end = string.skip( $data, string.length($data) - 11 ); if ( string.startswith($end, $csoBytes ) ) { $cs = string.skip($end,8); $client = string.bytesToInt(string.substring($cs,0,0)) . "." . string.bytesToInt(string.substring($cs,1,1)) . "." . string.bytesToInt(string.substring($cs,2,2)) . "."; $resolver = request.getRemoteIP(); $resolverOctets = string.split($resolver, "."); if ( $verbose ) log.info("DNS Request with CSO. Resolver: " . $resolver . ", Using Address: [" . $client . "]" . $resolverOctets[0]); request.setRemoteIP( $client . $resolverOctets[0]); connection.data.set("resolver", $resolver); }   The script looks for the CSO data at the end of the incoming DNS request. If a record is found, then we use the address specified as the client IP when making our GLB decision. However the CSO only includes the first three octets of the clients address. The idea is for the resolver to give the name server enough information about the client to determine its region, without divulging the full IPv4 address. Unfortunately we need a full IP address for GLB, so the script uses the first octet of the resolvers IP as the last octet of the clients IP. Why not? If you prefer you could just hard code the last octet. An exercise for the reader.   The rule stores the resolver address in connection memory so that you can log both the resolver and the address from the CSO by using the following request log log!format macro:   %t %v %h %A:%p %n %B %b %T %{resolver}d   Optionally, enabling $verbose will cause the script to write an event to the standard event log whenever it receives a request containing CSO information.   This rule needs to be applied to your GLB DNS service as a request rule.   Enjoy!
View full article
Dynamic information is more abundant now than ever, but we still see web applications provide static content. Unfortunately many websites are still using a static picture for a location map because of application code changes required. Traffic Manager provides the ability to insert the required code into your site with no changes to the application. This simplifies the ability to provide users dynamic and interactive content tailored for them.  Fortunately, Google provides an API to use embedded Google maps for your application. These maps can be implemented with little code changes and support many applications. This document will focus on using the Traffic Manager to provide embedded Google Maps without configuration or code changes to the application.   "The Google Maps Embed API uses a simple HTTP request to return a dynamic, interactive map. The map can be easily embedded in your web page by setting the Embed API URL as the src attribute of an iframe...   Google Maps Embed API maps are easy to add to your webpage—just set the URL you build as the value of an iframe's src attribute. Control the size of the map with the iframe's height and width attributes. No JavaScript required. "... -- Google Maps Embed API — Google Developers   Google Maps Embedded API Notes   Please reference the Google Documentation at Google Maps Embed API — Google Developers for additional information and options not covered in this document.   Google API Key   Before you get started with the Traffic Script, your need to get a Google API Key. Requests to the Google Embed API must include a free API key as the value of the URL key parameter. Your key enables you to monitor your application's Maps API usage, and ensures that Google can contact you about your website/application if necessary. Visit Google Maps Embed API — Google Developers to for directions to obtain an API key.   By default, a key can be used on any site. We strongly recommend that you restrict the use of your key to domains that you administer, to prevent use on unauthorized sites. You can specify which domains are allowed to use your API key by clicking the Edit allowed referrers... link for your key. -- Google Maps Embed API — Google Developers   The API key is included in clear text to the client ( search nerdydata for "https://www.google.com/maps/embed/v1/place?key=" ). I also recommend you restrict use of your key to your domains.   Map Modes   Google provides four map modes available for use,and the mode is specified in the request URL.   Place mode displays a map pin at a particular place or address, such as a landmark, business, geographic feature, or town. Directions mode displays the path between two or more specified points on the map, as well as the distance and travel time. Search mode displays results for a search across the visible map region. It's recommended that a location for the search be defined, either by including a location in the search term (record+stores+in+Seattle) or by including a center and zoom parameter to bound the search. View mode returns a map with no markers or directions.   A few use cases:   Display a map of a specific location with labels using place mode (Covered in this document). Display Parking and Transit information for a location with Search Mode.(Covered in this document). Provide directions (between locations or from the airport to a location) using Directions mode Display nearby Hotels or tourist information with Search mode using keywords or "lodging" or "landmarks" Use geo location and Traffic Script and provide a dynamic Search map of Gym's local to each visitor for your fitness blog. My personal favorite for Intranets Save time figuring out where to eat lunch around the office and use Search Mode with keyword "restaurant" Improve my Traffic Script productivity and use Search Mode with keyword "coffee+shops"   Traffic Script Examples   Example 1: Place Map (Replace a string)   This example covers a basic method to replace a string in the HTML code. This rule will replace a string within the existing HTML with Google Place map iframe HTML, and has been formatted for easy customization and readability.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #Only process text/html content  if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;        $nearaddress = "680+Folsom+St.+San+Francisco,+CA+94107" ;   $googleapikey = "YOUR_KEY_HERE" ;   $googlemapurl = "https://www.google.com/maps/embed/v1/place" ;   #Map height and width   $mapheight = "420" ;   $mapwidth = "420" ;        #String of HTML to be replaced   $insertstring = "<!-- TAB 2 Content (Office Locations) -->" ;        #Replacement HTML   $googlemaphtml = "<iframe width=\"" . $mapwidth . "\" height=\"" . $mapheight . "\" " .   "frameborder=\"0\" style=\"border:0\" src=\"" . $googlemapurl . "?q=" .   "" . $nearaddress . "&key=" . $googleapikey . "\"></iframe>" .        #Get the existing HTTP Body for modification   $body = http.getResponseBody();        #Regex sub against the body looking for the defined string   $body = string.replaceall( $body , $insertstring , $googlemaphtml );   http.setResponseBody( $body );    Example 2: Search Map (Replace a string) This example is the same as Example 1, but a change in the map type (note the change in the $googlemapurl?q=parking+near). This rule will replace a string within the existing HTML with Google Search map iframe HTML, and has been formatted for easy customization and readability.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #Only process text/html content  if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;           $nearaddress = "680+Folsom+St.+San+Francisco,+CA+94107" ;    $googleapikey = "YOUR_KEY_HERE" ;    $googlemapurl = "https://www.google.com/maps/embed/v1/search" ;    #Map height and width    $mapheight = "420" ;    $mapwidth = "420" ;           #String of HTML to be replaced    $insertstring = "<!-- TAB 2 Content (Office Locations) -->" ;           #Replacement HTML    $googlemaphtml = "<iframe width=\"" . $mapwidth . "\" height=\"" . $mapheight . "\" " .    "frameborder=\"0\" style=\"border:0\" src=\"" . $googlemapurl . "?q=parking+near+" .    "" . $nearaddress . "&key=" . $googleapikey . "\"></iframe>" .           #Get the existing HTTP Body for modification    $body = http.getResponseBody();           #Regex sub against the body looking for the defined string    $body = string.replaceall( $body , $insertstring , $googlemaphtml );    http.setResponseBody( $body );    Example 3: Search Map (Replace a section)   This example provides a different method to insert code into the existing HTML. This rule uses regex to replace a section of the existing HTML with Google map iframe HTML, and has also been formatted for easy customization and readability. The change from Example 2 can be noted (See $insertstring and string.regexsub).   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #Only process text/html content       if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;           $nearaddress = "680+Folsom+St.+San+Francisco,+CA+94107" ;    $googleapikey = "YOUR_KEY_HERE" ;    $googlemapurl = "https://www.google.com/maps/embed/v1/search" ;    #Map height and width    $mapheight = "420" ;    $mapwidth = "420" ;          #String of HTML to be replaced    $insertstring = "</a>Parking</h4>(?s)(.*)<!-- TAB 2 Content \\(Office Locations\\) -->" ;          #Replacement HTML    $googlemaphtml = "<iframe width=\"" . $mapwidth . "\" height=\"" . $mapheight . "\" " .    "frameborder=\"0\" style=\"border:0\" src=\"" . $googlemapurl . "?q=parking+near+" .    "" . $nearaddress . "&key=" . $googleapikey . "\"></iframe>" .          #Get the existing HTTP Body for modification    $body = http.getResponseBody();          #Regex sub against the body looking for the defined string    $body = string.regexsub( $body , $insertstring , $googlemaphtml );    http.setResponseBody( $body );     Example 3.1 (Shortened)   For reference a shortened version of the Example 3 Rule above (with line breaks for readability):   1 2 3 4 5 6 7 8 if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" ) ) break;                http.setResponseBody ( string.regexsub( http.getResponseBody(),      "</a>Parking</h4>(?s)(.*)<!-- TAB 2 Content \\(Office Locations\\) -->" ,      "<iframe width=\"420\" height=\"420\" frameborder=\"0\" style=\"border:0\" " .      "src=\"https://www.google.com/maps/embed/v1/search?" .      "q=parking+near+680+Folsom+St.+San+Francisco,+CA+94107" .      "&key=YOUR_KEY_HERE\"></iframe>" ) );     Example 4: Search Map ( Replace a section with formatting, select URL, & additional map)   This example is closer to a production use case. Specifically this was created with www.riverbed.com as my pool nodes. This rule has the following changes from Example 3: use HTML formatting to visually integrate with an existing application (<div class=\"six columns\">), only process for the desired URL path of contact (line #3), and provides an additional Transit Stop map (lines 27-31).   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #Only process text/html content in the contact path  if (!string.startsWith(http.getResponseHeader( "Content-Type" ), "text/html" )       || http.getpath() == "contact" ) break;       $nearaddress = "680+Folsom+St.+San+Francisco,+CA+94107" ;  $mapcenter = string.urlencode( "37.784465,-122.398570" );  $mapzoom = "14" ;  #Google API key  $googleapikey = "YOUR_KEY_HERE" ;  $googlemapurl = "https://www.google.com/maps/embed/v1/search" ;  #Map height and width  $mapheight = "420" ;  $mapwidth = "420" ;       #Regex match for the HTML section to be replaced  $insertstring = "</a>Parking</h4>(?s)(.*)<!-- TAB 2 Content \\(Office Locations\\) -->" ;       #Replacment HTML  $googlemapshtml =   #HTML cleanup (2x "</div>") and New Section title  "</div></div></a><h4>Parking and Transit Information</h4>" .  #BEGIN Parking Map. Using existing css for layout  "<div class=\"six columns\"><h5>Parking Map</h5>" .  "<iframe width=\"" . $mapwidth . "\" height=\"" . $mapheight . "\" frameborder=\"0\" " .  "style=\"border:0\" src=\"" . $googlemapurl . "?q=parking+near+" . $nearaddress . "" .  "&key=" . $googleapikey . "\"></iframe></div>" .  #BEGIN Transit Map. Using existing css for layout  "<div class=\"six columns\"><h5>Transit Stop's</h5>" .  "<iframe width=\"" . $mapwidth . "\" height=\"" . $mapheight . "\" frameborder=\"0\" " .  "style=\"border:0\" src=\"" . $googlemapurl . "?q=Transit+Stop+near+" . $nearaddress . "" .  "&center=" . $mapcenter . "&zoom=" . $mapzoom . "&key=" . $googleapikey . "\"></iframe></div>" .  #Include the removed HTML comment  "<!-- TAB 2 Content (Office Locations) -->" ;       #Get the existing HTTP Body for modification  $body = http.getResponseBody();       #Regex sub against the body looking for the defined string  $body = string.regexsub( $body , $insertstring , $googlemapshtml );  http.setResponseBody( $body );    Example 4.1 (Shortened)   For reference a shortened version of the Example 4 Rule above (with line breaks for readability):   1 2 3 4 5 6 7 8 9 10 11 12 13 14 if ( !string.startsWith ( http.getResponseHeader( "Content-Type" ), "text/html" )         || http.getpath() == "contact" ) break;           http.setResponseBody( string.regexsub(  http.getResponseBody() ,    "</a>Parking</h4>(?s)(.*)<!-- TAB 2 Content \\(Office Locations\\) -->" ,     "</div></div></a><h4>Parking and Transit Information</h4><div class=\"six columns\">" .    "<h5>Parking Map</h5><iframe width=\"420\" height=\"420\" frameborder=\"0\" " .    "style=\"border:0\" src=\"https://www.google.com/maps/embed/v1/search" .    "?q=parking+near+680+Folsom+St.+San+Francisco,+CA+94107&key=YOU_KEY_HERE\"></iframe>" .  "</div><div class=\"six columns\"><h5>Transit Stop's</h5><iframe width=\"420\" " .  "height=\"420\" frameborder=\"0\" style=\"border:0\" " .  "src=\"https://www.google.com/maps/embed/v1/search?q=Transit+Stop+near+" .  "680+Folsom+St.+San+Francisco,+CA+94107&center=37.784465%2C-122.398570&zoom=14" .  "&key=YOUR_KEY_HERE\"></iframe></div><!-- TAB 2 Content (Office Locations) -->" ) );  
View full article
SteelApp includes some great tools for graphical analysis, and for drilling down into the details of individual transaction connections. But when you are trying to debug high-throughput production applications, the number of connections in the log history can make it very difficult to trace and identify critical transactions on the Activity > Connections GUI on the user interface.     Although you can use the “Filter” option to track down particular types of transaction, there is now a new way to include or exclude just the transactions you want to be stored in the connection history!   From SteelApp Traffic Manager 9.8, TrafficScript includes two new functions connection.getCompletionReasonCode() and connection.getCompletionReasonInfo() which are designed to be used in transaction completion rules to give information about why a transaction ended. For example, it might have completed normally, or it might have timed out, or there may even have been a client or server error.   By using these two functions to identify specific transaction faults, you can use recentconns.include() and recentconns.exclude() to save only the trace information for connections that encountered problems that need further analysis: these two functions allow close control of which transactions should be retained, which means that the Activity > Connections page will only show the transactions you specifically wanted to trace.   connection.getCompletionReasonCode() This function returns a single reason code for the transaction, which could include “COMPLETE” if the transaction was successful, or “TIMEOUT” or a number of other potential problems. Other reason codes include “NODE_LOST” and “BAD_REQUEST” – see the user documentation for a complete list. In the following example, we would trace all transactions which did not complete for any reason.   1 2 3 4 5 6 $reasonCode = connection.getCompletionReasonCode();       if ( $reasonCode != "COMPLETE" ) {        # Failed transaction        recentconns.include();  }    connection.getCompletionReasonInfo() However, there is a way of extracting even more detailed information about the completion: this function contains information about whether the transaction ended due to client error, or to server error and other, all encoded in a hash returned by the function:   Key Details code Reason (from connection.getCompletionReasonCode(); message A detailed message describing the reason code. Iserror 1 if the transaction ended due to an error. Isservererror 1 if the transaction ended due to a server error. Isclienterror 1 if the transaction ended due to a client error. Istimeout 1 if the transaction ended because it exceeding any timeout duration. isprocessingtimeout 1 if the transaction ended because it exceeded rule or optimization processing timeouts.   Using this detailed information, we can pick out particular types of failure in the Activity > Connections page. Alternatively, we could raise an external event or create a log record. In this example, instead of sending the transaction detail to the Activity > Connections display, we emit a log record with detailed information about this transaction, inserting the “code” and “message” into the log file:   1 2 3 4 5 6 7 8 $info = connection.getCompletionReasonInfo();       if ( $info [ 'iserror' ] ) {        log .info( "Transaction error detected. Code: " .                 $info [ 'code' ] . " Message: " .                 $info [ 'message' ]                 );  }    For more information on these new TrafficScript functions, as well as how to use with recentconns.include() and recentconns.exclude() to control capture of transaction information in functions in the Activity > Connections display, see the SteelApp TrafficScript Guide in the User Documentation.   The SteelApp Developer Edition allows you to use Riverbed SteelApp Traffic Manager completely free within your test and development environments to experiment with this and other TrafficScript features, and to support the applications that you're building before you put them into production.   Find out more - and download your free trial here.
View full article
SteelApp TrafficScript is a simple, yet powerful programming language, which gives you full control over applications, and is embedded right within the kernel of SteelApp Traffic Manager to run with the highest possible performance. And in SteelApp Traffic Manager 9.8 [URL], we have introduced a new switch() statement to help build complex rules which are easier to maintain and understand.   Let’s imagine you have an ecommerce application, which serves a number of different domains, and you have independent application nodes (resource pools) reserved for each domain. You want to inspect each request, and direct it to the nodes that are reserved for the desired domain. A simple way to do this would be to create a series of if/then statements:   $host = http.getHeader( “Host” ); if ( !$host ) break; if ( $host == “www.mystore.com”) { # Direct all requests for this host # to a pool reserved for this domain pool.use( “mybank” ); } else if ($host == “www.store-bbb.com”) { ... } else if ($host == “www.store-ccc.com”) { ... } else { # All other requests go to shared pool pool.use( “generic” ); }   TrafficScript now provides a "switch" statement for cases where one if-else expression can evaluate to a number of different values, each requiring Traffic Manager to take a different action. By checking the host value of the HTTP header, you can use the switch statement to select the correct host using a number of cases. The syntax for the switch statement is:   switch( [, ] ) { case : ; case : ; case : ; ... [default: ;] }   By default, the Traffic Manager executes the first case containing an expression that evaluates to be equal ("==") to the switch <expression>. There is also an optional default statement must only be used as the last case, and is always executed if no previous cases have been executed.   So using the switch() statement, our example now becomes:   $host = http.getHeader( “Host” ); switch( $host ) { case “www.mybank.com”: # Direct all requests for this host # to a pool reserved for this domain pool.use( “mybank” ); case “www.store-bbb.com”, “www.store-ccc.com”: pool.use( “store-bbb-ccc” ); default: # All other requests go to shared pool if ( $host ) { pool.use( “generic” ); } }   User-defined comparator function:   There is even an option to provide a user-defined comparator function for complex rules using the optional <function name> argument. This argument accepts the name of a user defined or built in function, declared without any brackets or arguments. The function must accept two arguments - each case statement will then be assessed by invoking the comparator function with the value being switched on as the first argument and the value in the case statement as the second. The function should evaluate to TRUE for a match in order to execute the corresponding case statement.   For example, to perform matches on regular expressions, we could set <function name> to the TrafficScript function "string.regexmatch". Then, for each case statement, you can specify either a single expression or a comma-separated list of multiple expressions to be used in the comparison. A case is executed if the evaluation function returns true for any of the case's expressions. In this case, the commas in the expression list act as the "or" logical operator.   In this example, we are selecting a resource pool depending on whether the host header starts with “secure” or “ssl” and discarding any other request which does not start with “www”   $host = http.getHostHeader(); switch( $host, string.startsWith ) { case "secure", "ssl": pool.use( "secure pool" ); case "www": pool.use( "non-secure pool ); default: pool.use( "discard" ); }   For more information on this new switch() statement, including use of the break keyword, see the SteelApp TrafficScript Guide in the User Documentation.   And our Developer Edition allows you to use Riverbed SteelApp Traffic Manager completely free within your test and development environments to experiment with this and other TrafficScript features, and to support the applications that you're building before you put them into production.   Find out more - and download your free trial here.
View full article
SAML is the Security Assertion Markup Language, used for example in Web Single Sign on scenarios. The current version 2.0 is specified at OASIS Open: SAML Specifications | SAML XML.org   SAML uses XML documents to transfer information, defined in assertion documents, protocol definitions and bindings how the protocol is transferred. The assertions and protocol is defined as XML Schema.   The protocol can be validated in SteelApp TrafficManager with the XML Schema validation as additional security measure for example to protect SAML Identity Providers (IdP).   This article explains a use case of validating SAML 2.0 for the HTTP POST binding, where the protocol is transferred as HTTP body, Base64 encoded. The rule checks an endpoint URL, where SAML validation should be performed and if the HTTP method is "POST".   Base64-encoded SAML request can be encoded and decoded for example with this online tool or with the offline tools "base64" on Linux systems. https://rnd.feide.no/simplesaml/module.php/saml2debug/debug.php   To test the SAML validation, "curl" can be used to post the encoded data&colon;   curl -X POST -H "Content-Type: text/plain" --data-binary "@SAML-example.txt" http://192.168.42.21/auth/test.php   Result of the validation can be observed in the STM event log.   xml.validate.xsd() returns the following test result:   1, then the validation is successful, the transfer is a well-formed and valid SAML protocol document 0, the document is not valid, containing illegal attributes but the document is well formed XML -1, the document is not well-formed (XML document errors)   # Validate HTTP POST body against the SAML Protocol schema # (c) Riverbed Technology GmbH, Juergen Luksch, # only run rule, if path is SAML endpoint $path = http.getPath(); if(!string.startsWithI($path, "/auth/")) break; # only POST binding supported in example if(http.getMethod() != "POST") break; #standard base64 encoded saml message decode: $samlAuth = string.base64decode(http.getBody(0)); $samlProtocolSchema = resource.get("saml-schema-protocol-2.0.xsd"); $result = xml.validate.xsd($samlAuth, $samlProtocolSchema); #log.info ("XML Validation: " . $result); if( $result != 1 ) { log.warn("XML Validation failed!"); # connection.discard(); # response with HTTP http.sendResponse("500 Server error", "text/plain", "XML Validation failed", ""); }   To be able to validate a SAML document, the XML schema definition (XSD) needs to be present on the STM in the extra files catalog. For the SAML protocol, there’s two schemas needed: saml-schema-protocol and saml-schema-assertion. These additionally import the XML signatures schema and XML encryption schema.   The schema documents can be downloaded from OASIS Open (Index of /security/saml/v2.0/) and the W3 consortium (http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd, http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd). As the imports refer to external resources in the original documents, the „schemaLocation=“ needs to be changed to the local file before uploading to STM.   When the document is checked and recognized as invalid, a HTTP error code could be returned or the connection discarded.   So, with downloading schemas, creating a XML validation rule and adding this rule to the virtual server, SAML protocol requests can be validated and actioned on.
View full article
  1. The Issue   When using perpetual licensing on a Traffic Manager, it is restricted to a throughput licensing limitation as per the license.  If this limitation is reached, traffic will be queued and in extreme situations, if the throughput reaches much higher than expected levels, some traffic could be dropped because of the limitation.   2. The Solution   Automatically increase the allocated bandwidth for the Traffic Manager!!   3. A Brief Overview of the Solution   An SSC holds the licensed bandwidth configuration for the Traffic Manager instance.   The Traffic Manager is configured to execute a script on an event being raised, the bwlimited event.   The script makes REST calls to the SSC in order to obtain and then increment if necessary, the Traffic Manager's bandwidth allocation.   I have written the script used here, to only increment if the resulting bandwidth allocation is 5Mbps or under, but this restriction could be removed if it's not required.  The idea behind this was to allow the Traffic Manager to increment it's allocation, but to only let it have a certain maximum amount of bandwidth from the SSC bandwidth "bucket".   4. The Solution in a Little More Detail   4.1. Move to an SSC Licensing Model   If you're currently running Traffic Managers with perpetual licenses, then you'll need to move from the perpetual licensing model to the SSC licensing model.  This effectively allows you to allocate bandwidth and features across multiple Traffic Managers within your estate.  The SSC has a "bucket" of bandwidth along with configured feature sets which can be allocated and distributed across the estate as required, allowing for right-sizing of instances, features and also allowing multi-tenant access to various instances as required throughout the organisation.   Instance Hosts and Instance resources are configured on the SSC, after which a Flexible License is uploaded on each of the Traffic Manager instances which you wish to be licensed by the SSC, and those instances "call home" to the SSC regularly in order to assess their licensing state and to obtain their feature set.   For more information on SSC, visit the Riverbed website pages covering this product, here - SteelCentral Services Controller for SteelApp Software.   There's also a Brochure attached to this article which covers the basics of the SSC.   4.2. Traffic Manager Configuration and a Bit of Bash Scripting!   The SSC has a REST API that can be accessed from external platforms able to send and receive REST calls.  This includes the Traffic Manager itself.   To carry out the automated bandwidth allocation increase on the Traffic Manager, we'll need to carry out the following;   a. Create a script which can be executed on the Traffic Manager, which will issue REST calls in order to change the SSC configuration for the instance in the event of a bandwidth limitation event firing. b. Upload the script to be used, on to the Traffic Manager. c. Create a new event and action on the Traffic Manager which will be initiated when the bandwidth limitation is hit, calling the script mentioned in point a above.   4.2.a. The Script to increment the Traffic Manager Bandwidth Allocation   This script, called  and attached, is shown below.   Script Function:   Obtain the Traffic Manager instance configuration from the SSC. Extract the current bandwidth allocation for the Traffic Manager instance from the information obtained. If the current bandwidth is less then 5Mbps, then increment the allocation by 1Mbps and issue the REST call to the SSC to make the changes to the instance configuration as required.  If the bandwidth is currently 5Mbps, then do nothing, as we've hit the limit for this particular Traffic Manager instance.   #!/bin/bash # # Bandwidth_Increment # ------------------- # Called on event: bwlimited # # Request the current instance information requested_instance_info=$(curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" \ -X GET -u admin:password https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-1.example.com-00002) # Extract the current bandwidth figure for the instance current_instance_bandwidth=$(echo $requested_instance_info | sed -e 's/.*"bandwidth": \(\S*\).*/\1/g' | tr -d \,) # Add 1 to the original bandwidth figure, imposing a 5Mbps limitation on this instance bandwidth entry if [ $current_instance_bandwidth -lt 5 ] then new_instance_bandwidth=$(expr $current_instance_bandwidth + 1) # Set the instance bandwidth figure to the new bandwidth figure (original + 1) curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \ '{"bandwidth":'"${new_instance_bandwidth}"'}' \ https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-1.example.com-00002 fi   There are some obvious parts to the script that will need to be changed to fit your own environment.  The admin username and password in the REST calls and the SSC name, port and path used in the curl statements.  Hopefully from this you will be able to see just how easy the process is, and how the SSC can be manipulated to contain the configuration that you require.   This script can be considered a skeleton which you can use to carry out whatever configuration is required on the SSC for a particular Traffic Manager.  Events and actions can be set up on the Traffic Manager which can then be used to execute scripts which can access the SSC and make the changes necessary based on any logic you see fit.   4.2.b. Upload the Bash Scripts to be Used   On the Traffic Manager, upload the bash script that will be needed for the solution to work.  The scripts are uploaded in the Catalogs > Extra Files > Action Programs section of the Traffic Manager, and can then be referenced from the Actions when they are created later.   4.2.c. Create a New Event and Action for the Bandwidth Limitation Hit   On the Traffic Manager, create a new event type as shown in the screenshot below - I've created Bandwidth_Increment, but this event could be called anything relevant.  The important factor here is that the event is raised from the bwlimited event.     Once this event has been created, an action must be associated with it.   Create a new external program action as shown in the screenshot below - I've created one called Bandwidth_Increment, but again this could be called anything relevant.  The important factor for the action is that it's an external program action and that it calls the correct bash script, in my case called SSC_Bandwidth_Increment.     5. Testing   In order to test the solution, on the SSC, set the initial bandwidth for the Traffic Manager instance to 1Mbps.   Generate some traffic through to a service on the Traffic Manager that will force the Traffic Manager to hit it's 1Mbps limitation for a succession of time.  This will cause the bwlimited event to fire and for the Bandwidth_Increment action to be executed, running the SSC_Bandwidth_Increment script.   The script will increment the Traffic Manager bandwidth by 1Mbps.   Check and confirm this on the SSC.   Once confirmed, stop the traffic generation.   Note: As the Flexible License on the Traffic Manager polls the SSC every 3 minutes for an update on it's licensed state, you may not see an immediate change to the bandwidth allocation of the Traffic Manager.   You can force the Traffic Manager to poll the SSC by removing the Flexible License and re-adding the license again - the re-configuration of the Flexible License will then force the Traffic Manager to re-poll the SSC and you should then see the updated bandwidth in the System > Licenses (after expanding the license information) page of the Traffic Manager as shown in the screenshot below;     6. Summary   Please feel free to use the information contained within this post to experiment!!!   If you do not yet have an SSC deployment, then an Evaluation can be arranged by contacting your Partner or Riverbed Salesman.  They will be able to arrange for the Evaluation, and will be there to support you if required.
View full article
  1. The Issue   When using perpetual licensing on Traffic Manager instances which are clustered, the failure of one of the instances results in licensed throughput capability being lost until that instance is recovered.   2. The Solution   Automatically adjust the bandwidth allocation across cluster members so that wasted or unused bandwidth is used effectively.   3. A Brief Overview of the Solution   An SSC holds the configuration for the Traffic Manager cluster members. The Traffic Managers are configured to execute scripts on two events being raised, the machinetimeout event and the allmachinesok event.   Those scripts make REST calls to the SSC in order to dynamically and automatically amend the Traffic Manager instance configuration held for the two cluster members.   4. The Solution in a Little More Detail   4.1. Move to an SSC Licensing Model   If you're currently running Traffic Managers with perpetual licenses, then you'll need to move from the perpetual licensing model to the SSC licensing model.  This effectively allows you to allocate bandwidth and features across multiple Traffic Managers within your estate.  The SSC has a "bucket" of bandwidth along with configured feature sets which can be allocated and distributed across the estate as required, allowing for right-sizing of instances, features and also allowing multi-tenant access to various instances as required throughout the organisation.   Instance Hosts and Instance resources are configured on the SSC, after which a Flexible License is uploaded on each of the Traffic Manager instances which you wish to be licensed by the SSC, and those instances "call home" to the SSC regularly in order to assess their licensing state and to obtain their feature set. For more information on SSC, visit the Riverbed website pages covering this product, here - SteelCentral Services Controller for SteelApp Software.   There's also a Brochure attached to this article which covers the basics of the SSC.   4.2. Traffic Manager Configuration and a Bit of Bash Scripting!   The SSC has a REST API that can be accessed from external platforms able to send and receive REST calls.  This includes the Traffic Manager itself.   To carry out automated bandwidth allocation on cluster members, we'll need to carry out the following;   a. Create a script which can be executed on the Traffic Manager, which will issue REST calls in order to change the SSC configuration for the cluster members in the event of a cluster member failure. b. Create another script which can be executed on the Traffic Manager, which will issue REST calls to reset the SSC configuration for the cluster members when all of the cluster members are up and operational. c. Upload the two scripts to be used, on to the Traffic Manager cluster. d. Create a new event and action on the Traffic Manager cluster which will be initiated when a cluster member fails, calling the script mentioned in point a above. e. Create a new event and action on the Traffic Manager cluster which will be initiated when all of the cluster members are up and operational, calling the script mentioned in point b above.   4.2.a. The Script to Re-allocate Bandwidth After a Cluster Member Failure This script, called Cluster_Member_Fail_Bandwidth_Allocation and attached, is shown below.   Script Function:   Determine which cluster member has executed the script. Make REST calls to the SSC to allocate bandwidth according to which cluster member is up and which is down.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #!/bin/bash  #  # Cluster_Member_Fail_Bandwidth_Allocation  # ----------------------------------------  # Called on event: machinetimeout  #  # Checks which host calls this script and assigns bandwidth in SSC accordingly  # If demo-1 makes the call, then demo-1 gets 999 and demo-2 gets 1  # If demo-2 makes the call, then demo-2 gets 999 and demo-1 gets 1  #       # Grab the hostname of the executing host  Calling_Hostname=$(hostname -f)       # If demo-1.example.com is executing then issue REST calls accordingly  if [ $Calling_Hostname == "demo-1.example.com" ]  then           # Set the demo-1.example.com instance bandwidth figure to 999 and           # demo-2.example.com instance bandwidth figure to 1           curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                              '{"bandwidth":999}' \                              https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-1.example.com           curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                              '{"bandwidth":1}' \                              https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-2.example.com  fi       # If demo-2.example.com is executing then issue REST calls accordingly  if [ $Calling_Hostname == "demo-2.example.com" ]  then           # Set the demo-2.example.com instance bandwidth figure to 999 and           # demo-1.example.com instance bandwidth figure to 1           curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                              '{"bandwidth":999}' \                              https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-2.example.com           curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                              '{"bandwidth":1}' \                              https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-1.example.com  fi    There are some obvious parts to the script that will need to be changed to fit your own environment.  The hostname validation, the admin username and password in the REST calls and the SSC name, port and path used in the curl statements.  Hopefully from this you will be able to see just how easy the process is, and how the SSC can be manipulated to contain the configuration that you require.   This script can be considered a skeleton, as can the other script for resetting the bandwidth, shown later.   4.2.b. The Script to Reset the Bandwidth   This script, called Cluster_Member_All_Machines_OK and attached, is shown below.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #!/bin/bash  #  # Cluster_Member_All_Machines_OK  # ------------------------------  # Called on event: allmachinesok  #  # Resets bandwidth for demo-1.example.com and demo-2.example.com - both get 500  #       # Set both demo-1.example.com and demo-2.example.com bandwidth figure to 500  curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                      '{"bandwidth":500}' \                      https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-1.example.com-00002  curl -k --basic -H "Content-Type: application/json" -H "Accept: application/json" -u adminuser:adminpassword -d \                      '{"bandwidth":500}' \                      https://ssc.example.com:8000/api/tmcm/1.1/instance/demo-2.example.com-00002    Again, there are some parts to the script that will need to be changed to fit your own environment.  The admin username and password in the REST calls and the SSC name, port and path used in the curl statements.   4.2.c. Upload the Bash Scripts to be Used   On one of the Traffic Managers, upload the two bash scripts that will be needed for the solution to work.  The scripts are uploaded in the Catalogs > Extra Files > Action Programs section of the Traffic Manager, and can then be referenced from the Actions when they are created later.     4.2.d. Create a New Event and Action for a Cluster Member Failure   On the Traffic Manager (any one of the cluster members), create a new event type as shown in the screenshot below - I've created Cluster_Member_Down, but this event could be called anything relevant.  The important factor here is that the event is raised from the machinetimeout event.   Once this event has been created, an action must be associated with it. Create a new external program action as shown in the screenshot below - I've created one called Cluster_Member_Down, but again this could be called anything relevant.  The important factor for the action is that it's an external program action and that it calls the correct bash script, in my case called Cluster_Member_Fail_Bandwidth_Allocation.   4.2.e. Create a New Event and Action for All Cluster Members OK   On the Traffic Manager (any one of the cluster members), create a new event type as shown in the screenshot below - I've created All_Cluster_Members_OK, but this event could be called anything relevant.  The important factor here is that the event is raised from the allmachinesok event.   Once this event has been created, an action must be associated with it. Create a new external program action as shown in the screenshot below - I've created one called All_Cluster_Members_OK, but again this could be called anything relevant.  The important factor for the action is that it's an external program action and that it calls the correct bash script, in my case called Cluster_Member_All_Machines_OK.   5. Testing   In order to test the solution, simply DOWN Traffic Manager A from an A/B cluster.  Traffic Manager B should raise the machinetimeout event which will in turn execute the Cluster_Member_Down event and associated action and script, Cluster_Member_Fail_Bandwidth_Allocation.   The script should allocate 999Mbps to Traffic Manager B, and 1Mbps to Traffic Manager A within the SSC configuration.   As the Flexible License on the Traffic Manager polls the SSC every 3 minutes for an update on it's licensed state, you may not see an immediate change to the bandwidth allocation of the Traffic Managers in questions. You can force the Traffic Manager to poll the SSC by removing the Flexible License and re-adding the license again - the re-configuration of the Flexible License will then force the Traffic Manager to re-poll the SSC and you should then see the updated bandwidth in the System > Licenses (after expanding the license information) page of the Traffic Manager as shown in the screenshot below;     To test the resetting of the bandwidth allocation for the cluster, simply UP Traffic Manager B.  Once Traffic Manager B re-joins the cluster communications, the allmachinesok event will be raised which will execute the All_Cluster_Members_OK event and associated action and script, Cluster_Member_All_Machines_OK. The script should allocate 500Mbps to Traffic Manager B, and 500Mbps to Traffic Manager A within the SSC configuration.   Just as before for the failure event and changes, the Flexible License on the Traffic Manager polls the SSC every 3 minutes for an update on it's licensed state so you may not see an immediate change to the bandwidth allocation of the Traffic Managers in questions.   You can force the Traffic Manager to poll the SSC once again, by removing the Flexible License and re-adding the license again - the re-configuration of the Flexible License will then force the Traffic Manager to re-poll the SSC and you should then see the updated bandwidth in the System > Licenses (after expanding the license information) page of the Traffic Manager as before (and shown above).   6. Summary   Please feel free to use the information contained within this post to experiment!!!   If you do not yet have an SSC deployment, then an Evaluation can be arranged by contacting your Partner or Brocade Salesman.  They will be able to arrange for the Evaluation, and will be there to support you if required.
View full article
When using PHP to access the Stingray Traffic Manager (STM) RESTful API you can choose to interact directly with the API using cURL, or you can use one of the PHP REST Clients that are available.  I decided to create my own PHP REST Client, STMRESTClient, and instructions for using STMRESTClient are included in this article and the code is attached.   Overview   STMRestClient is a PHP class written specifically to work with the STM RESTful API.  So for example, it handles JSON conversions, authorization and understands the path hierarchy of the API.  The attached code has extensive comments that contain more detailed information then is included in this article.  The class contains default values for the hostname:port, user name, password and API version so the class can be edited to change these default values.  Any of these values can also be set when the class is instantiated by passing in an associative array with one or more of:   'STMHost' => '<host>:<port>' 'UserId' => '<user name>, 'Password' => '<password>' 'APIVersion' => '<version>'   The default value will be used for any of the values not specified.  So for example, all of the following are correct:   $client = new STMRestClient() $client = new STMRESTClient(array('UserId' => 'user', 'Password' => 'password'); $client = new STMRESTClient(array('STMHost' => 'stm.example.com:9070', 'UserId' => 'user',                                   'Password' => 'password', 'APIVersion' => '1.1'));   Once the class has been instantiated, any of the class methods can be invoked.  The following three methods are likely to be the most commonly used:   get: This method is used to get data for a resource. It takes two input parameters: resource: The end of the URI path for the resource.  So for example, to get the list of pools this would be "pools" and to get data for the pool, "testpool", it would be "pools/testpool". resource type: This parameter is optional.  It specifies the type of resource and can be one of the following constants: TYPE_CONFIG: causes the path to be /api/tm/<version>/config/active/<resource> TYPE_INFO: causes the path to be /api/tm/<version>/status/local_tm/information/<resource> TYPE_STATS: causes the path to be /api/tm/<version>/status/local_tm/statistics/<resource> The default is TYPE_CONFIG   For configuration resources, an object will be returned that has been created by decoding the JSON response.  For file resources, the file text will be returned.   Examples:   $pools = $client->get("pools"); $poolStats = $client->get("pools/testpool", TYPE_STATS);   put: This method is used to add or change a configuration resource. It takes two input parameters: resource: The end of the URI path for the resource. resource data&colon; An object or an associative array containing the resource data or file text.  For configuration resources, the data will be JSON encoded by STMRestClient. content type: The Content-Type header to use for this data.  This should be "application/octet-stream" for files and                      "application/json" for all other resources.  It defaults to "application/json".   For configuration resources, the new or changed resource is returned as an object.  For files, nothing is returned.   Example:   $vsData->properties->basic->pool = 'testpool'; $vsData->properties->basic->port = '80'; $newVS = $client->put("virtual_servers/newvs", $vsData);   $poolData->properties->basic->nodes = array('192.168.168.168:80'); $poolData = array('properties' => array('basic' => array('nodes' =>                   array('192.168.168.168:80'))));   $client->put("rules/newrule", "#test rule", "application/octet-stream");   delete: This method is used to delete a configuration resource. It takes one input parameter: resource: The end of the URI for the resource.   It returns true if the resource was deleted.   Example:   $client->delete("virtual_servers/newvs");   All three of these methods return the following exceptions:   STMAuthException: If there was an error logging into the STM STMConnectException: If there was error connecting to the STM STMResourceNotFoundException: If the resource requested is not found Exception: Any other errors   There are other methods that can be accessed and there are properties that can be set or retrieved and these are all documented in the class code.  The two public properties that are available are:   returnedContentType: This is the ContentType header returned by the last REST API request statusCode: This is the HTTP status code returned on the last REST API request   Examples   Several examples using STMRestClient can be found at: Read More   The REST API Guide in the Stingray Product Documentation Feature Brief: Stingray's RESTful Control API Collected Tech Tips: Using the RESTful Control API Tech Tip: Using the RESTful Control API with PHP - Overview
View full article
The following code uses Stingray's RESTful API to retrieve the statistics for a pool. The code is written in PHP and uses STMRESTClient.  This program does a single GET request for the statistics for the pool and then loops through response printing out each property and its value.   getpoolstats.php   <?php # Display the statistics for a pool require_once 'stmrestclient.inc'; $pool = "testpool"; print("<html><body>\n<br><b>Statistics for Pool $pool</b><br><br>\n"); print("<table>\n"); try { $client = new STMRestClient(); $response = $client->get("pools/$pool", TYPE_STATS); $stats = $response->statistics; foreach ($stats as $field => $value) { print("<tr><td>$field:</td><td>$value</td></tr>\n"); } print("</table>\n"); } catch (STMConnectException $e) { print ("Error connecting to the REST API: " . $e->getMessage()); } catch (STMAuthException $e) { print ("Error logging into the REST API: " . $e->getMessage()); } catch (exception $e) { print ('Error: ' . $e->getMessage()); } print("</body></html>\n"); ?>   Running the example   This code was tested with PHP 5.3.3 and uses the STMRestClient class that can be found here: Tech Tip: A Stingray Traffic Manager REST Client for PHP   To run this program, Make it available via a web server and the output should be:   Statistics for Pool testpool   algorithm:        roundrobin bytes_in:         16114052 bytes_out:        276005 conns_queued:     0 disabled:         1 draining:         1 max_queue_time:   0 mean_queue_time:  0 min_queue_time:   0 nodes:            2 persistence:      none queue_timeouts:   0 session_migrated: 0 state:            active total_conn:       4076   Read More   Stingray REST API Guide in the Stingray Product Documentation Feature Brief: Stingray's RESTful Control API Tech Tip: Using Stingray's RESTful Control API Tech Tip: Using the RESTful Control API with PHP - Overview Collected Tech Tips: Using the RESTful Control API
View full article