10-26-2011 07:26 AM - last edited on 10-26-2011 07:28 AM
10-25-2011 06:03 AM - last edited on 10-28-2011 03:56 AM
We have many backend servers that present a "choose a digital certificate" box/prompt to the client before presenting a page. I would like to set up a monitor that could use that same process to determine if a node is alive or not. The perl scripts look promising... any suggestions, canned scripts you could point me to?
© Copyright 2012 Riverbed Technology. All rights reserved Riverbed.com | Contact Us | Technical Support | Terms & Conditions | Privacy Policy
Response from Michael Granzow, Member of Technical Staff, Riverbed Technology
The standard monitors do not support client certificates, unfortunately.
As part of the traffic manager installation, you can find a command-line HTTP client in
$ZEUSHOME/admin/bin/httpclient
This tool also supports HTTPS and can be told to present a certificate should the server ask for one.
I've written a small wrapper around this program that can be used as a monitor of type 'external program', see below. Please download the file and save it on your computer under the name 'client_cert'.
The most convenient way to install it into your system is to use 'zcli'. Create a file called 'zcli_commands' with the necessary commands, like this:
1. Catalog.Monitor.uploadMonitorProgram client_cert client_cert 2. Conf.Extra.uploadFile client_cert.private ~/certs/client_cert.private 3. Conf.Extra.uploadFile client_cert.public ~/certs/client_cert.public 4. Catalog.Monitor.addMonitors client_cert 5. Catalog.Monitor.setType client_cert program 6. Catalog.Monitor.setProgram client_cert client_cert 7. Catalog.Monitor.addProgramArguments client_cert {description:"The certificate to use", name: "cert", value:"zxtm/conf/extra/client_cert.public"} 8. Catalog.Monitor.addProgramArguments client_cert {description:"The private key",name:"key",value:"zxtm/conf/extra/client_cert .private"}
9. Catalog.Monitor.addProgramArguments client_cert {description:"The Host header", name:"hostheader", value:"my.domain.com"}This assumes that the certificate and corresponding private key you want to use are located in certs/client_cert.public and certs/client_cert.private under your home directory.
Obviously you'll have to replace 'my.domain.com' with the host header your web servers expect.
Then invoke zcli:
# $ZEUSHOME/zxtm/bin/zcli < zcli_commands
Now you have to make the installed program executable:
# chmod +x $ZEUSHOME/zxtm/conf/scripts/client_cert
and you should be able to use your new monitor with your pools. If you only want to consider certain http response codes successful, you can add another argument to the program, 'responsecode'.
This is the program (similar to dns.pl that comes with the software):
1. #!/bin/sh 2. # Bootstrap into the version of perl provided by Zeus 3. exec $ZEUSHOME/perl/miniperl -wx $0 ${1+"$@"} 4. if0; 5. # -*- perl -*- 6. #!/usr/bin/perl 7. #line9 8. # This monitor will contact an https server, and 9. # provide an ssl client cert during the handshake if 10. # the server requests it. The program then checks 11. # for a valid HTTP response and optionally for 12. # certain response codes (regex). 13. BEGIN{ unshift @INC,"$ENV{ZEUSHOME}/zxtm/lib/perl", 14. "$ENV{ZEUSHOME}/zxtmadmin/lib/perl";} 15. useZeus::ZXTM::Monitor qw(ParseArgumentsMonitorWorkedMonitorFailedLog); 16. # Process the arguments 17. my%args =ParseArguments(); 18. if(! $args{ipaddr}){ 19. MonitorFailed("No 'ipaddr' to contact specified"); 20. } 21. my $ipaddr = $args{ipaddr}; 22. my $cmd ="$ENV{ZEUSHOME}/admin/bin/httpclient "; 23. if(defined( $args{hostheader})){ 24. $cmd .="--hostheader=$args{hostheader} "; 25. } 26. if(defined( $args{cert})&&defined( $args{key})){ 27. $cmd .="--cert=$args{cert} --key=$args{key} "; 28. } 29. if( $ipaddr =~/:/){# handle IPv6 addresses 30. $cmd .="https://[${ipaddr}]"; 31. }else{ 32. $cmd .="https://${ipaddr}"; 33. } 34. if(defined( $args{port})){ 35. $cmd .=":$args{port}/"; 36. }else{ 37. # just slap on a slash 38. $cmd .='/'; 39. } 40. Log("Running $cmd"); 41. # Now run the httpclient program 42. open( PROG,"$cmd 2>&1 |"); 43. my $response =''; 44. while(){ 45. $response .= $_; 46. } 47. if(! close PROG ){ 48. MonitorFailed("httpclient failed: $response")if $?; 49. MonitorFailed("$!") if $!; 50. MonitorFailed("Unknown error"); 51. } 52. Log("Output: $response"); 53. if( $response !~/^HTTP\/\d\.\d\s+(\d+)/){ 54. my $idx = index( $response,"\n"); 55. my $firstline = substr( $response,0,($idx >0)?$idx:15); 56. $firstline =~ s/\r$//; 57. MonitorFailed("HTTP request failed: first line was '$firstline'"); 58. } 59. if(defined( $args{responsecode})){ 60. if( $1 !~/$args{responsecode}/){ 61. MonitorFailed("HTTP request failed, expected '$args{responsecode}', got '$1'"); 62. } 63. } 64. MonitorWorked();