Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- ##### Sanity checks
- ## Strictly IPv4 notation.
- # The openssl binary doesn't allow the use of IPv6 notation in the -connect parameter of the s_client subcommand.
- # F5 exports the NODE_IP variable, which always contains the IPv6-form, even when the IP address is IPv4.
- # Stripping the unwanted part solves this.
- monitor_targetip=$(echo "$1" | sed 's/::ffff://')
- ##
- ## Binary validation
- # 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.
- # You can modify the PATH variable under which the monitor executes by explicityly defining it in the Variables section off the monitor definition.
- required_programs="openssl logger cat grep egrep awk tr seq sleep"
- missing_programs=0
- missing_programs_output=""
- missing_programs_counter=0
- for current_program in $required_programs ; do
- program_path=$(which $current_program)
- if [ $? -eq 0 ] ; then
- eval "$current_program=$program_path"
- else
- output="$missing_programs_output$current_program,"
- let missing_programs_counter=$missing_programs_counter+1
- fi
- done
- if [ $missing_programs_counter -gt 0 ] ; then
- 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
- echo -e "The program(s) that could not be found are: $missing_programs_output" >> /var/log/ltm
- echo -e "The location of these programs needs to be under one the following directories: '$PATH'" >> /var/log/ltm
- exit 1
- fi
- ##
- #####
- ##### Preparations before running the checks
- ## Setting the default settings
- # These are needed in case the creator of the monitor failed to specify all the required variables
- monitor_debug=0
- monitor_method="GET"
- monitor_uri="/"
- monitor_httpstatus="200"
- monitor_hostname="$monitor_targetip"
- monitor_targetport="$NODE_PORT"
- monitor_receivestring=""
- monitor_header=""
- monitor_stdin_sleeptime="3" # this is required to make openssl s_client accept the input from stdin before it closes.
- monitor_exitstatus=1
- log_monitor_debug_specified=0
- log_monitor_method_specified=0
- log_monitor_uri_specified=0
- log_monitor_httpstatus_specified=0
- log_monitor_hostname_specified=0
- log_monitor_targetport_specified=0
- log_monitor_receivestring_specified=0
- log_monitor_header_specified=0
- log_monitor_receivestring_match=0
- log_monitor_httpstatus_match=0
- ##
- ## Overriding the default settings if needed
- # This part loops through the possible variables and checks if they have been defined.
- # If one has been defined, it checks if it's not empty and adds it to the actual action-variable ($monitor_something).
- monitor_variable_items="method uri httpstatus hostname targetip targetport debug receivestring header stdin_sleeptime exitstatus"
- for current_monitor_variable_item in $monitor_variable_items ; do
- current_monitor_variable_name_for_usage="monitor_${current_monitor_variable_item}"
- current_monitor_variable_name_for_logging="log_${current_monitor_variable_name_for_usage}_specified"
- if [ "$current_monitor_variable_item" == "header" ] ; then
- tmp=""
- for i in `$seq 1 50` ; do
- current_monitor_variable_name_for_input="$(echo "$current_monitor_variable_item" | $tr 'a-z' 'A-Z')$i"
- eval "current_monitor_variable_value_for_input=\$$current_monitor_variable_name_for_input"
- if ! [ "$current_monitor_variable_value_for_input" == "" ] ; then
- if [ $i -eq 1 ] ; then
- tmp="${current_monitor_variable_value_for_input}"
- else
- tmp="${tmp}\r\n${current_monitor_variable_value_for_input}"
- fi
- fi
- unset current_monitor_variable_name_for_input
- done
- eval "$current_monitor_variable_name_for_usage=\"$tmp\""
- eval "$current_monitor_variable_name_for_logging=1"
- else
- current_monitor_variable_name_for_input=$(echo "$current_monitor_variable_item" | tr 'a-z' 'A-Z')
- eval "current_monitor_variable_value_for_input=\$$current_monitor_variable_name_for_input"
- eval "current_monitor_variable_value_for_usage=\$$current_monitor_variable_name_for_usage"
- if ! [ "$current_monitor_variable_value_for_input" == "" ] ; then
- eval "$current_monitor_variable_name_for_usage=$current_monitor_variable_value_for_input"
- eval "$current_monitor_variable_name_for_logging=1"
- fi
- fi
- unset tmp current_monitor_variable_name_for_usage current_monitor_variable_name_for_logging current_monitor_variable_name_for_input
- done
- ###
- #####
- ##### Running the checks
- ## Obtaining the HTTP content through openssl
- 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`
- ##
- ## Obtaining the HTTP Status code from the returned contents
- http_error_code=$(echo "$http_content" | $egrep "HTTP/1\.[0-1] " | $awk '{print $2}')
- ##
- ## Determining the 'up' or 'down' status
- if [ "$http_error_code" == "$monitor_httpstatus" ] ; then
- log_monitor_httpstatus_match=1
- if ! [ "$monitor_receivestring" == "" ] ; then
- receive_string_check=$(echo "$http_content" | $grep "$monitor_receivestring")
- if ! [ "$receive_string_check" == "" ] ; then
- log_monitor_receivestring_match=1
- monitor_exitstatus=0
- fi
- else
- monitor_exitstatus=0
- fi
- fi
- ##
- #####
- ##### Supplying the debug logs if requested
- ## Dump each variable
- if [ "$monitor_debug" == "1" ] ; then
- this_run=$(date +%s)
- log_prefix="HTTPS_SNI [$this_run]:"
- echo "" | $logger -p local0.debug
- echo "$log_prefix Monitor Description:" | $logger -p local0.debug
- for current_monitor_variable_item in $monitor_variable_items ; do
- current_monitor_variable_name_for_usage="monitor_${current_monitor_variable_item}"
- current_monitor_variable_name_for_logging="log_${current_monitor_variable_name_for_usage}_specified"
- eval "current_monitor_variable_value_for_usage=\"\$$current_monitor_variable_name_for_usage\""
- eval "current_monitor_variable_value_for_logging=\$$current_monitor_variable_name_for_logging"
- if [ "$current_monitor_variable_value_for_logging" == "1" ] ; then
- echo "$log_prefix - $current_monitor_variable_name_for_usage => $current_monitor_variable_value_for_usage" | $logger -p local0.debug
- else
- echo "$log_prefix - $current_monitor_variable_name_for_usage => default ($current_monitor_variable_value_for_usage)" | $logger -p local0.debug
- fi
- unset current_monitor_variable_name_for_usage current_monitor_variable_name_for_logging
- done
- echo "$log_prefix Monitor Status:" | $logger -p local0.debug
- if [ "$log_monitor_receivestring_match" == "0" ] ; then
- echo "$log_prefix - Receive String: no match" | $logger -p local0.debug
- else
- echo "$log_prefix - Receive String: match" | $logger -p local0.debug
- fi
- if [ "$log_monitor_httpstatus_match" == "0" ] ; then
- echo "$log_prefix - HTTP Status: no match" | $logger -p local0.debug
- else
- echo "$log_prefix - Receive String: match" | $logger -p local0.debug
- fi
- if [ "$monitor_exitstatus" == "0" ] ; then
- echo "$log_prefix - Final Result: UP" | $logger -p local0.debug
- else
- echo "$log_prefix - Final Result: DOWN" | $logger -p local0.debug
- fi
- echo "" | logger -p local0.debug
- echo "" | logger -p local0.debug
- fi
- ##
- #####
- ##### Telling F5 the monitor status should be up
- ## Echoing 'up' to stdout
- if [ "$monitor_exitstatus" == "0" ] ; then
- echo "up"
- fi
- ##
- ## Exiting accordingly (0 or 1)
- exit $monitor_exitstatus
- ##
- #####
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement