cancel
Showing results for 
Search instead for 
Did you mean: 

Pulse Secure vADC

Sort by:
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
In October 2014, Google published details of a vulnerability in the SSL 3.0 protocol - named "POODLE" - which makes it possible for an attacker to decrypt messages between client and server in some circumstances. Because this is a problem with the protocol itself, rather than with a specific implementation of the protocol, this means that any client-server transaction which supports SSL 3.0 is at risk. Even if the client-server supports higher levels of security (such as TLS 1.2), it is possible for an attacker to force a downgrade to SSL 3.0 using a man-in-the-middle attack - which means that systems should disable SSL 3.0 to protect against this kind of attack, and use more recent security handshake protocols such as TLS.   How to Disable SSL 3.0 Completely   With SteelApp Traffic Manager, it is easy to disable SSL v3.0 completely from the system console. Navigate to System->Global settings->SSL Configuration, and you can control how SteelApp manages SSL transactions:     How to Trap SSL Requests:   So we can disable SSL 3.0 completely, but some browsers will show an unhelpful error message: ideally, we would provide some extra feedback to the user to show what the problem is, and how to resolve it. Attach this TrafficScript rule to your virtual server: if you leave SSL 3.0 enabled, this rule permits any transaction using TLS, but traps SSL requests and returns a custom error message to the user:   $cipher = ssl.clientCipher(); if (string.len($cipher) > 0) { if (string.contains($cipher, "version=TLS")) { # this is the good case, incrementing the user SNMP counter counter64.increment(1,1); break; } else { # logic for the SSL (insecure) cases counter64.increment(2,1); # increment a counter for bad cases event.emit ("ssl request", "IP: ".request.getRemoteIP()." User-agent: ".http.getHeader("User-Agent")); http.sendResponse( "400 Bad request", "text/plain", "This service requires TLS security, and is using SSL security. \ Please verify your SSL/TLS settings and try again", "" ); } }   This TrafficScript rule will write an event message to the SteelApp log file, identifying the client IP and User Agent, and we also increment a user-defined counter to help track how often attempts are made to open an SSL transaction. These counters can be graphed on the SteelApp Activity Monitor, or retrieved remotely as user-defined SNMP variables, (use index 1 for good TLS requests, and index 2 for SSL requests that were rejected). The rule also raises a custom event named "ssl request" which can be used to trigger external actions if needed.   To test the script using Firefox, go to the "about:config" page, and change the value "security.tls.version.max" from the default of "3" to "0" This will force SSL 3.0 to be used instead of TLS. In newer versions of Firefox, you may also need to set "security.tls.version.min" to "0" - but don't forget to set these values back to a secure setting after testing.   Poodle icon designed by http://www.thenounproject.com/edward from the http://www.thenounproject.com.
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 Stingray 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
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
With the evolution of social media as a tool for marketing and current events, we commonly see the Twitter feed updated long before the website. It’s not surprising for people to rely on these outlets for information. Fortunately Twitter provides a suite of widgets and scripting t ools to integrate Twitter information for your application. The tools available can be implemented with little code changes and support many applications. Unfortunately the same reason a website is not as fresh as social media is because of the code changes required. The code could be owned by different people in the organization or you may have limited access to the code due to security or CMS environment. Traffic Manager provides the ability to insert the required code into your site with no changes to the application.   Twitter Overview "Embeddable timelines make it easy to syndicate any public Twitter timeline to your website with one line of code. Create an embedded timeline from your widgets settings page on twitter.com, or choose “Embed this…” from the options menu on profile, search and collection pages.   Just like timelines on twitter.com, embeddable timelines are interactive and enable your visitors to reply, Retweet, and favorite Tweets directly from your pages. Users can expand Tweets to see Cards inline, as well as Retweet and favorite counts. An integrated Tweet box encourages users to respond or start new conversations, and the option to auto-expand media brings photos front and center.   These new timeline tools are built specifically for the web, mobile web, and touch devices. They load fast, scale with your traffic, and update in real-time." -twitter.com   Thank you Faisal Memon for the original article Using TrafficScript to add a Twitter feed to your web site   As happens more often than than not, platform access changes. This time twitter is our prime example. When loading Twiter js, http://widgets.twimg.com/j/2/widget.js you can see the following notice:   The Twitter API v1.0 is deprecated, and this widget has ceased functioning.","You can replace it with a new, upgraded widget from <https://twitter.com/settings/widgets/new/"+H+">","For more information on alternative Twitter tools, see <https://dev.twitter.com/docs/twitter-for-websites>   To save you some time, Twitter really means deprecated and the information link is broken. For more information on alternative Twitter tools the Twitter for Websites | Home. For information related to the information in this article, please see Embedded Timelines | Home   One of the biggest changes in the current twitter platform is the requirement for a "data-widget-id". The data-widget-id is unique, and is used by the twitter platform to provide information to generate the data. Before getting started with the Traffic Manager and Web application you will have to create a new widget using your twitter account https://twitter.com/settings/widgets/new/. Once you create your widget, will see the "Copy and paste the code into the HTML of your site." section on the twitter website. Along with other information, this code contains your "data-widget-id". See Create widget image.   Create widget (click to zoom)   This example uses a Traffic Script response rule to rewrite the HTTP body from the application. Specifically I know the body for my application includes a html comment <!--SIDEBAR-->. This rule will insert the required client side code into the HTTP body and send the updated body in to complete the request.  The $inserttag variable can be just about anything in the body itself  i.e. the " MORE LIKE THIS " text on the side of this page. Simply change the code below to      $inserttag = "MORE LIKE THIS";   Some of the values used in the example (i.e. width, data-theme, data-link-color, data-tweet-limit) are not required. They have been included to demonstrate customization. When you create/save the widget on the twitter website, the configuration options (See the Create widget image above) are associated with the "data-widget-id". For example "data-theme", if you saved the widget with light and you want the light theme, it can be excluded. Alternatively if you saved the widget with light, you can use "data-theme=dark" and over ride the value saved with the widget.  In the example time line picture the data-link-color value is used to over ride the value provided with the saved "data-widget-id".   Example Response Rule, *line spaced for splash readability and use of variables for easy customization. 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 # Only modify text/html pages    if ( !string.startsWith( http.getResponseHeader( "Content-Type" ), "text/html" )) break;         $inserttag = "<!--SIDEBAR-->" ;       # create a widget ID @ https://twitter.com/settings/widgets/new  #This is the id used by riverbed.com   $ttimelinedataid = "261517019072040960" ;  $ttimelinewidth = "520" ; # max could be limited by ID config.  $ttimelineheight = "420" ;  $ttimelinelinkcolor = "#0080ff" ; #0 for default or ID config, #0080ff & #0099cc are nice  $ttimelinetheme = "dark" ; #"light" or "dark"  $ttimelinelimit = "0" ; #0 = unlimited with scroll. >=1 will ignore height.  #See https://dev.twitter.com/web/embedded-timelines#customization for other options.       $ttimelinehtml = "<a class=\"twitter-timeline\" " .                   "width=\"" . $ttimelinewidth . "" .                     "\" height=\"" . $ttimelineheight . "" .                     "\" data-theme=\"" . $ttimelinetheme . "" .                   "\" data-link-color=\"" . $ttimelinelinkcolor . "" .                   "\" data-tweet-limit=\"" . $ttimelinelimit . "" .                   "\" data-widget-id=\"" . $ttimelinedataid . "" .                    "\"></a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)" .                     "[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id))" .                     "{js=d.createElement(s);js.id=id;js.src=p+" .                   "\"://platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js," .                   "fjs);}}(document,\"script\",\"twitter-wjs\");" .                     "</script><br>" . $inserttag . "" ;         $body = http.getResponseBody();    $body = string.replace( $body , $inserttag , $ttimelinehtml );  http.setResponseBody( $body );    A short version of the rule above, still with line breaks for readability.   1 2 3 4 5 6 7 8 9 if ( !string.startsWith( http.getResponseHeader( "Content-Type" ), "text/html" )) break;         http.setResponseBody(string.replace( http.getResponseBody(), "<!--SIDEBAR-->" ,   "<a class=\"twitter-timeline\" width=\"520\" height=\"420\" data-theme=\"dark\" " .  "data-link-color=\"#0080ff\" data-tweet-limit=\"0\" data-widget-id=\"261517019072040960\">" .  "</a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test" .  "(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;" .  "js.src=p+\"://platform.twitter.com/widgets.js\";fjs.parentNode.insertBefore(js,fjs);}}" .  "(document,\"script\",\"twitter-wjs\");</script><br><!--SIDEBAR-->" ));    Result from either rule:  
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
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.   SteelApp can extend protection for your applications with unmatched software flexibility and scale. Utilize existing investments by installing SteelApp on your infrastructure (Linux, Solaris, VMWare, Hyper-V, etc.) and integrate with existing antivirus scanners. Deploy SteelApp (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 SteelApp can be used to mitigate virus propagation by scanning outbound content.   The SteelApp 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 SteelApp 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 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 SteelApp Traffic Manager SteelApp Web App Firewall SteelApp Documentation RFC 3507 - Internet Content Adaptation Protocol (ICAP) The c-icap project Clam AntiVirus  
View full article
For versions of the SteelApp Traffic Manager Appliance before 9.7, we support customers installing software only via our standard APIs/interfaces (using extra files, custom action scripts).   This constraint has been relaxed at version 9.7. We still do not support customers modifying the tested software shipped with the appliance, but we do allow installation of additional software.   Examples of where this might be useful include:   Installing monitoring agents that customers use to monitor the rest of their infrastructure (e.g. Nagios) Installing software such as BIND to avoid having to deploy an extra host when setting up GLB.   Operating system   SteelApp 9.7 appliances use a customized build of Ubuntu 12.04LTS, with an optimized kernel from which some unused features have been removed.   What you may change   You may install additional software not shipped with the appliance, but note that some Ubuntu packages may rely on kernel features not available on the appliance.   You may modify configuration not managed by the appliance.   What you may not change   You may not install a different kernel.   You may not install different versions of any debian packages that were installed on the appliance as shipped, nor remove any of these packages (see the licence acknowledgements doc for a list).   You may not directly modify configuration that is managed from the traffic manager (e.g. sysctl values, network configuration).   You may not change configuration explicitly set by the appliance (usually marked with a comment containing ZOLD or  BEGIN_STINGRAY_BLOCK).   What happens when you need support   You should mention any additional software you have installed when requesting support, the Technical Support Report will also contain information about it. If the issue is found to be caused by interaction with the additional software we will ask you to remove it, or to seek advice or a remedy from its supplier.   What happens on reset or upgrade   z-reset-to-factory-defaults will not remove additional software but may rewrite some system configuration files.   An incremental upgrade (from 9.7 to 9.7r1 for example) may upgrade some installed packages, and may rewrite system configuration files.   A full upgrade will install a fresh appliance image on a separate disk partition, and will not copy additional software or configuration changes across. The /logs partition will be preserved.   Note that future appliance versions may change the set of installed packages, or even the underlying operating system.
View full article
In many cases, it is desirable to upgrade a virtual appliance by deploying a virtual appliance at the newer version and importing the old configuration.  For example, the size of the traffic manager disk image was increased in version 9.7, and deploying a new virtual appliance lets a customer take advantage of this larger disk.  This article documents the procedure for deploying a new virtual appliance with the old configuration in common scenarios.   These instructions describe how to upgrade and reinstall Brocade Virtual Traffic Manager appliance instances (either in a cluster or standalone appliances). For instructions on upgrading on other platforms, please refer to Upgrading Stingray Traffic Manager.   Upgrading a standalone Virtual Appliance   This process will replace a standalone virtual appliance with another virtual appliance with the same configuration (including migrating network configuration). Note that the Brocade Virtual Traffic Manager Cloud Getting Started Guide contains instructions for upgrading a standalone EC2 instance from version 9.7 onwards; if upgrading from a version prior to 9.7 and using the Stingray Application Firewall (now Brocade Virtual Web Application Firewall) these instructions must be followed to correctly back up and restore any firewall configuration.   Make a backup of the traffic manager configuration (See section "System > Backups" in the Brocade Virtual Traffic Manager User Manual), and export it. If you are upgrading from a  version prior to 9.7 and are using the Stingray Application Firewall, back up the Stingray Application Firewall configuration Log on to a command line Run /opt/zeus/stop-zeus Copy /opt/zeus/zeusafm/current/var/lib/config.db off the appliance. Shut down the original appliance. Deploy a new appliance with the same network interfaces as the original. If you backed up the application firewall configuration earlier, restore it here onto the new appliance, before you restore the traffic manager configuration: Copy the config.db file to /opt/zeus/stingrayafm/current/var/lib/config.db (overwriting the original) Check that the owner on the config.db file is root, and the mode is 0644. Import and restore the traffic manager configuration via the UI. If you have application firewall errors Use the Diagnose page to automatically fix any configuration errors Reset the Traffic Manager software.   Upgrading a cluster of Virtual Appliances (except Amazon EC2)   This process will replace the appliances in the cluster, one at a time, maintaining the same IP addresses. As the cluster will be reduced by one at points in the upgrade process, you should ensure that this is carried out at a time when the cluster is otherwise healthy, and of the n appliances in the cluster, the load can be handled by (n-1) appliances.   Before beginning the process, ensure that any cluster errors have been resolved. Nominate the appliance which will be the last to be upgraded (call it the final appliance).  When any of the other machines needs to be removed from the cluster, it should be done using the UI on this appliance, and when a hostname and port are required to join the cluster, this appliance's hostname should be used. If you are using the Brocade Virtual Web Application Firewall first ensure that vWAF on the final appliance in the cluster is upgraded to the most recent version, using the vWAF updater. Choose an appliance to be upgraded, and remove the machine from the cluster: If it is not the final appliance (nominated in step 2), this should be done via the UI on the final appliance If it is the final appliance, the UI on any other machine may be used. Make a backup of the traffic manager configuration (System > Backups) on the appliance being upgraded, and export the backup.  This backup only contains the machine specific info for that appliance (networking config etc). Shut down the appliance, and deploy a new appliance at the new version.  When deploying, it needs to be given the identical hostname to the machine it's replacing. Log on to the admin UI of the new appliance, and import and restore the backup from step 5. If you are using the Brocade Virtual Web Application Firewall, accessing the Application Firewall tab in the UI will fail and there will be an error on the Diagnose page and an 'Update Configuration' button. Click the Update Configuration button once, then wait for the error to clear.  The configuration is now correct, but the admin server still needs to be restarted to pick up the configuration: # $ZEUSHOME/admin/rc restart Now, upgrade the application firewall on the new appliance to the latest version. Join into the cluster: For all appliances except the final appliance, you must not select any of the auto-detected existing clusters.  Instead manually specify the hostname and port of the final appliance. If you are using Brocade Virtual Web Application Firewall, there may be an issue where the config on the new machine hasn't synced the vWAF config from the old machine, and clicking the 'Update Application Firewall Cluster Status' button on the Diagnose page doesn't fix the problem. If this happens, firstly get the clusterPwd from the final appliance: # grep clusterPwd /opt/zeus/zxtm/conf/zeusafm.conf clusterPwd = <your cluster pwd> On the new appliance, edit /opt/zeus/zxtm/conf/zeusafm.conf (with e.g. nano or vi), and replace the clusterPwd with the final appliance's clusterPwd. The moment that file is saved, Brocade vWAF should get restarted, and the config should get synced to the new machine correctly. When you are upgrading the final appliance, you should select the auto-detected existing cluster entry, which should now list all the other cluster peers. Once a cluster contains multiple versions, configuration changes must not be made until the upgrade has been completed, and 'Cluster conflict' errors are expected until the end of the process. Repeat steps 4-9 until all appliances have been upgraded.   Upgrading a cluster of STM EC2 appliances   Because EC2 licenses are not tied to the IP address, it is recommended that new EC2 instances are deployed into a cluster before removing old instances.  This ensures that the capacity of the cluster is not reduced during the upgrade process.  This process is documented in the "Creating a Traffic Manager Instances on Amazon EC2" chapter in the Brocade Virtual Traffic Manager Cloud Getting Started Guide.  The clusterPwd may also need to be fixed as above.
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
This document covers updating the built-in GeoIP database. See TechTip: Extending the Brocade vTM GeoIP database for instructions on adding custom entries to the database.  
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
The following code uses Stingray's RESTful API to a file to the extra directory.   The code is written in PHP and uses STMRESTClient.  This program adds the file 'validserialnumbers' to the extra directory and if the file already exists it will be overwrite it.  If this is not the desired behavior, code can be added to to check for the existence of the file as was done in the addpool example.   addextrafile.   <?php require_once 'stmrestclient.inc'; $fileName = 'validserialnumbers'; $validSerialNumbers = "123456\n234567\n345678\n"; try { # Set up the connection $client = new STMRestClient(); $client->put("extra/$fileName", $validSerialNumbers, 'application/octet-stream'); # If the file already exists, it will be replaced with this version and 204 will be returned # otherwise 201 will be returned. print("<br>statusCode=" . $client->statusCode . "<br><br>"); if ($client->statusCode == 201) { print("File $fileName added"); } else { print("File $fileName replaced"); } } 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()); } ?>   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:   File validserialnumbers added   or   File validserialnumbers replaced   Notes   Since this is a file and not a configuration resource, JSON will not be used and the MIME type will be "application/octet-stream".  Another difference when dealing with files is how Stingray handles adding a file that already exists.  If the file already exists, Stingray will overwrite the it and return a HTTP status code of 204.  If the file doesn't already exist, the HTTP status code will be a 201.   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
The following code uses Stingray's RESTful API to delete a pool.  The code is written in PHP and uses STMRESTClient.  This program deletes the "phptest" pool created by the addpool.php example.  To delete a resource you do a HTTP DELETE on the URI for the resource.  If the delete is successful a 204 HTTP status code will be returned.   deletepool.php   <?php # Delete a pool require_once 'stmrestclient.inc'; $poolName = 'phptest'; try { # Set up the connection $client = new STMRestClient(); /* Check to see if the pool exists. If it doesn't exist, then a * ResourceNotFoundException exception will be thrown. */ $response = $client->get("pools/$poolName"); $client->delete("pools/$poolName"); print("Pool $poolName deleted"); } catch (STMResourceNotFoundException $e) { # The pool doesn't exist print("Pool $poolName not found"); } 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:   Pool phptest deleted   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
The following code uses Stingray's RESTful API to add a pool.   The code is written in PHP and uses STMRESTClient. This program creates a new pool, "phptest", first doing a GET to make sure the pool doesn't already exist, and if the pool doesn't exist, the pool is created by doing a PUT with just the minimum data needed to create a pool.  In this case the program creates a properties object with just one node.  All other values will get default values when Stingray creates the pool.   addpool.php   <?php # Add a pool require_once 'stmrestclient.inc'; $poolName = 'phptest'; $node = '192.168.168.135:80'; try { # Set up the connection $client = new STMRestClient(); /* Check to see if the pool already exist. If it does not yet exist, then a * ResourceNotFoundException exception will be thrown. */ $response = $client->get("pools/$poolName"); print("Pool $poolName already exists"); } catch (STMResourceNotFoundException $e) { # The pool doesn't exist, so it can be created $poolConfig->properties->basic->nodes = array($node); #$poolConfig = array('properties' => array('basic' => array('nodes' => array($node)))); try { $response = $client->put("pools/$poolName", $poolConfig); print("Pool $poolName added"); } catch (Exception $e) { print ("Error creating Pool $poolName: " . $e->getMessage()); } } 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:   Pool phptest added   Notes   The only difference between doing a PUT to change a resource and a PUT to add a resource is the HTTP status code returned.  When changing a resource 200 is the expected status code and when adding a resource, 201 is the expected status code.   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