Advertisement
Guest User

F5 HTTPS SNI Monitor Script

a guest
Mar 23rd, 2014
4,194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 7.47 KB | None | 0 0
  1. #!/bin/bash
  2. ##### Sanity checks
  3. ## Strictly IPv4 notation.
  4. # The openssl binary doesn't allow the use of IPv6 notation in the -connect parameter of the s_client subcommand.
  5. # F5 exports the NODE_IP variable, which always contains the IPv6-form, even when the IP address is IPv4.
  6. # Stripping the unwanted part solves this.
  7. monitor_targetip=$(echo "$1" | sed 's/::ffff://')
  8. ##
  9.  
  10. ## Binary validation
  11. # Finding all the binaries is paramount for this script to run successfully. These binaries must be found under one or more directories in the PATH variable.
  12. # You can modify the PATH variable under which the monitor executes by explicityly defining it in the Variables section off the monitor definition.
  13. required_programs="openssl logger cat grep egrep awk tr seq sleep"
  14. missing_programs=0
  15. missing_programs_output=""
  16. missing_programs_counter=0
  17. for current_program in $required_programs ; do
  18.     program_path=$(which $current_program)
  19.     if [ $? -eq 0 ] ; then
  20.         eval "$current_program=$program_path"
  21.     else
  22.         output="$missing_programs_output$current_program,"
  23.         let missing_programs_counter=$missing_programs_counter+1
  24.     fi
  25. done
  26.  
  27. if [ $missing_programs_counter -gt 0 ] ; then
  28.     echo -e "ERROR: An external monitor script failed to locate one or more of its required programs. The script cannot continue unless you fix this." >> /var/log/ltm
  29.     echo -e "The program(s) that could not be found are: $missing_programs_output" >> /var/log/ltm
  30.     echo -e "The location of these programs needs to be under one the following directories: '$PATH'" >> /var/log/ltm
  31.     exit 1
  32. fi
  33. ##
  34. #####
  35.  
  36.  
  37.  
  38.  
  39. ##### Preparations before running the checks
  40. ## Setting the default settings
  41. # These are needed in case the creator of the monitor failed to specify all the required variables
  42. monitor_debug=0
  43. monitor_method="GET"
  44. monitor_uri="/"
  45. monitor_httpstatus="200"
  46. monitor_hostname="$monitor_targetip"
  47. monitor_targetport="$NODE_PORT"
  48. monitor_receivestring=""
  49. monitor_header=""
  50. monitor_stdin_sleeptime="3" # this is required to make openssl s_client accept the input from stdin before it closes.
  51. monitor_exitstatus=1
  52. log_monitor_debug_specified=0
  53. log_monitor_method_specified=0
  54. log_monitor_uri_specified=0
  55. log_monitor_httpstatus_specified=0
  56. log_monitor_hostname_specified=0
  57. log_monitor_targetport_specified=0
  58. log_monitor_receivestring_specified=0
  59. log_monitor_header_specified=0
  60. log_monitor_receivestring_match=0
  61. log_monitor_httpstatus_match=0
  62. ##
  63.  
  64. ## Overriding the default settings if needed
  65. # This part loops through the possible variables and checks if they have been defined.
  66. # If one has been defined, it checks if it's not empty and adds it to the actual action-variable ($monitor_something).
  67. monitor_variable_items="method uri httpstatus hostname targetip targetport debug receivestring header stdin_sleeptime exitstatus"
  68. for current_monitor_variable_item in $monitor_variable_items ; do
  69.     current_monitor_variable_name_for_usage="monitor_${current_monitor_variable_item}"
  70.     current_monitor_variable_name_for_logging="log_${current_monitor_variable_name_for_usage}_specified"
  71.     if [ "$current_monitor_variable_item" == "header" ] ; then
  72.         tmp=""
  73.         for i in `$seq 1 50` ; do
  74.             current_monitor_variable_name_for_input="$(echo "$current_monitor_variable_item" | $tr 'a-z' 'A-Z')$i"
  75.             eval "current_monitor_variable_value_for_input=\$$current_monitor_variable_name_for_input"
  76.             if ! [ "$current_monitor_variable_value_for_input" == "" ] ; then
  77.                 if [ $i -eq 1 ] ; then
  78.                     tmp="${current_monitor_variable_value_for_input}"
  79.                 else
  80.                     tmp="${tmp}\r\n${current_monitor_variable_value_for_input}"
  81.                 fi
  82.             fi
  83.             unset current_monitor_variable_name_for_input
  84.         done
  85.         eval "$current_monitor_variable_name_for_usage=\"$tmp\""
  86.         eval "$current_monitor_variable_name_for_logging=1"
  87.     else
  88.         current_monitor_variable_name_for_input=$(echo "$current_monitor_variable_item" | tr 'a-z' 'A-Z')
  89.         eval "current_monitor_variable_value_for_input=\$$current_monitor_variable_name_for_input"
  90.         eval "current_monitor_variable_value_for_usage=\$$current_monitor_variable_name_for_usage"
  91.         if ! [ "$current_monitor_variable_value_for_input" == "" ] ; then
  92.             eval "$current_monitor_variable_name_for_usage=$current_monitor_variable_value_for_input"
  93.             eval "$current_monitor_variable_name_for_logging=1"
  94.         fi
  95.     fi
  96.     unset tmp current_monitor_variable_name_for_usage current_monitor_variable_name_for_logging current_monitor_variable_name_for_input
  97. done
  98. ###
  99. #####
  100.  
  101.  
  102.  
  103. ##### Running the checks
  104. ## Obtaining the HTTP content through openssl
  105. http_content=`(echo -e "$monitor_method $monitor_uri HTTP/1.1\r\nHost: $monitor_hostname\r\n${monitor_header}\r"; $sleep $monitor_stdin_sleeptime) | $openssl s_client -connect $monitor_targetip:$monitor_targetport -servername $monitor_hostname`
  106. ##
  107.  
  108. ## Obtaining the HTTP Status code from the returned contents
  109. http_error_code=$(echo "$http_content" | $egrep "HTTP/1\.[0-1] " | $awk '{print $2}')
  110. ##
  111.  
  112. ## Determining the 'up' or 'down' status
  113. if [ "$http_error_code" == "$monitor_httpstatus" ] ; then
  114.     log_monitor_httpstatus_match=1
  115.     if ! [ "$monitor_receivestring" == "" ] ; then
  116.         receive_string_check=$(echo "$http_content" | $grep "$monitor_receivestring")
  117.         if ! [ "$receive_string_check" == "" ] ; then
  118.             log_monitor_receivestring_match=1
  119.             monitor_exitstatus=0
  120.         fi
  121.     else
  122.         monitor_exitstatus=0
  123.     fi
  124. fi
  125. ##
  126. #####
  127.  
  128.  
  129.  
  130.  
  131. ##### Supplying the debug logs if requested
  132. ## Dump each variable
  133. if [ "$monitor_debug" == "1" ] ; then
  134.     this_run=$(date +%s)
  135.     log_prefix="HTTPS_SNI [$this_run]:"
  136.     echo "" | $logger -p local0.debug
  137.     echo "$log_prefix Monitor Description:" | $logger -p local0.debug
  138.     for current_monitor_variable_item in $monitor_variable_items ; do
  139.         current_monitor_variable_name_for_usage="monitor_${current_monitor_variable_item}"
  140.         current_monitor_variable_name_for_logging="log_${current_monitor_variable_name_for_usage}_specified"
  141.         eval "current_monitor_variable_value_for_usage=\"\$$current_monitor_variable_name_for_usage\""
  142.         eval "current_monitor_variable_value_for_logging=\$$current_monitor_variable_name_for_logging"
  143.         if [ "$current_monitor_variable_value_for_logging" == "1" ] ; then
  144.             echo "$log_prefix - $current_monitor_variable_name_for_usage => $current_monitor_variable_value_for_usage" | $logger -p local0.debug
  145.         else
  146.             echo "$log_prefix - $current_monitor_variable_name_for_usage => default ($current_monitor_variable_value_for_usage)" | $logger -p local0.debug
  147.         fi
  148.         unset current_monitor_variable_name_for_usage current_monitor_variable_name_for_logging
  149.     done
  150.  
  151.     echo "$log_prefix Monitor Status:" | $logger -p local0.debug
  152.     if [ "$log_monitor_receivestring_match" == "0" ] ; then
  153.         echo "$log_prefix - Receive String: no match" | $logger -p local0.debug
  154.     else
  155.         echo "$log_prefix - Receive String: match" | $logger -p local0.debug
  156.     fi
  157.  
  158.     if [ "$log_monitor_httpstatus_match" == "0" ] ; then
  159.         echo "$log_prefix - HTTP Status: no match" | $logger -p local0.debug
  160.     else
  161.         echo "$log_prefix - Receive String: match" | $logger -p local0.debug
  162.     fi
  163.  
  164.     if [ "$monitor_exitstatus" == "0" ] ; then
  165.         echo "$log_prefix - Final Result: UP" | $logger -p local0.debug
  166.     else
  167.         echo "$log_prefix - Final Result: DOWN" | $logger -p local0.debug
  168.     fi
  169.     echo "" | logger -p local0.debug
  170.     echo "" | logger -p local0.debug
  171. fi
  172. ##
  173. #####
  174.  
  175.  
  176.  
  177.  
  178. ##### Telling F5 the monitor status should be up
  179. ## Echoing 'up' to stdout
  180. if [ "$monitor_exitstatus" == "0" ] ; then
  181.     echo "up"
  182. fi
  183. ##
  184.  
  185. ## Exiting accordingly (0 or 1)
  186. exit $monitor_exitstatus
  187. ##
  188. #####
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement