From cb40bac624a9774da02320818b9855b3cbc92040 Mon Sep 17 00:00:00 2001 From: Iridias Date: Fri, 16 Jul 2021 14:43:58 +0200 Subject: [PATCH] support negative searches (ensure a string does not occur in the page-source) --- CHANGELOG.md | 1 + README.md | 3 ++- check_http_expect | 51 +++++++++++++++++++++++++++--------- checkcommand_httpexpect.conf | 7 ++++- example_icingaservice.conf | 1 + 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bac9e5..a4ab9af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Version 0.5 - [Enh] Support specifying multiple search-strings - [Enh] Support changing the user-agent - [Enh] Added simple config/example for an icinga CheckCommand and Service +- [Enh] Support to ensure one or more specific strings do not occur in the page-source - [Cha] Use bash instead of sh Version 0.3 (unreleased) diff --git a/README.md b/README.md index c7589b2..9dbbbb2 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,11 @@ Nagios plugin that will check a website (behind .htacess and/or behind POST logi ## 1. Usage ```shell -Usage: check_http_expect --url --find [--find ] [--huser ] [--hpass ] [--lurl ] [--cookie [--cookie ]] [--ldata [--ldata ]] +Usage: check_http_expect --url --find [--find ] [--avoid ] [--huser ] [--hpass ] [--lurl ] [--cookie [--cookie ]] [--ldata [--ldata ]] --url Target URL --find Find string in source of Target URL ('grep -E'-style regex allowed / can be specified multiple times) + --avoid (Required if find is not specified) ensure that the string does not appear in the source of Target URL ('grep -E'-style regex allowed / can be specified multiple times) --huser (Optional) htaccess username --hpass (Optional) htaccess password --lurl (Optional) Url for POST login diff --git a/check_http_expect b/check_http_expect index 5588098..c617fea 100755 --- a/check_http_expect +++ b/check_http_expect @@ -31,6 +31,7 @@ EXIT_UNKNOWN=3 # defaults useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" searchStrings=() +avoidStrings=() ################################################################################ # @@ -74,7 +75,7 @@ print_version() { # @output string The usage screen. # @return integer 0 print_usage() { - printf "Usage: check_http_expect --url --find [--insecure] [--huser ] [--hpass ] [--lurl ] [--cookie [--cookie ]][--ldata [--ldata ]]\n" + printf "Usage: check_http_expect --url --find [--avoid ] [--insecure] [--huser ] [--hpass ] [--lurl ] [--cookie [--cookie ]][--ldata [--ldata ]]\n" printf "OR %s --check\n" "${INFO_NAME}" printf "OR %s --help\n" "${INFO_NAME}" printf "OR %s --version\n\n" "${INFO_NAME}" @@ -97,12 +98,14 @@ print_help() { # Show defaults printf " --url Target URL\n" printf " --find Find string in source of Target URL ('grep -E'-style regex allowed)\n" + printf " --avoid [required if find is not specified] ensure that the string does not appear in the source of Target URL\n" printf " --insecure [optional] allow insecure SSL connections\n" printf " --huser [optional] htaccess username\n" printf " --hpass [optional] htaccess password\n" printf " --lurl [optional] Url for POST login\n" printf " --ldata [optional] POST data (can be specified multiple times)\n" - printf " --cookie [optional] set cookies for request\n\n" + printf " --cookie [optional] set cookies for request\n" + printf " --ua [optional] use this user-agent instead of the default one\n\n" printf " --check Check for program requirements.\n" printf " --help Show this help\n" @@ -110,7 +113,15 @@ print_help() { return 0 } - +print_search() { + local separator=$1 + if [ "${#searchStrings[@]}" -gt 0 ]; then + printf "%s\n${separator}" "${searchStrings[@]}" + fi + if [ "${#avoidStrings[@]}" -gt 0 ]; then + printf "[NOT] %s\n${separator}" "${avoidStrings[@]}" + fi +} ################################################################################ # @@ -191,6 +202,10 @@ while [ $# -gt 0 ]; do searchStrings+=("$1") shift ;; + --avoid) + avoidStrings+=("$1") + shift + ;; # Cookies --cookie) if [ -z "$cookies" ]; then @@ -227,7 +242,7 @@ if [ -z "$url" ]; then exit 1 fi -if [ "${#searchStrings[@]}" -eq 0 ]; then +if [[ "${#searchStrings[@]}" -eq 0 && "${#avoidStrings[@]}" -eq 0 ]]; then echo "Error, You must specify what you are looking for." print_usage exit 1 @@ -295,9 +310,10 @@ http_server="$(echo "${head}" | head -n20 | grep -E '^Server:\s' | sed 's/^Serve match="" numberOfResults=0 matchingStringAmount=0 -expectedMatches=${#searchStrings[@]} +expectedMatches=$((${#searchStrings[@]} + ${#avoidStrings[@]})) + i=0 -while [ $i -lt "$expectedMatches" ]; do +while [ $i -lt "${#searchStrings[@]}" ]; do el=${searchStrings[$i]} number=$(echo "${data}" | grep -cE "${el}") match+="$(echo "${data}" | grep -E "${el}")" @@ -308,19 +324,30 @@ while [ $i -lt "$expectedMatches" ]; do ((i++)) done +i=0 +while [ $i -lt "${#avoidStrings[@]}" ]; do + el=${avoidStrings[$i]} + number=$(echo "${data}" | grep -cE "${el}") + if [ "$number" -eq 0 ]; then + match+=" [NOT] ${el}" + matchingStringAmount=$((matchingStringAmount + 1)) + fi + ((i++)) +done + if [ "${expectedMatches}" -eq ${matchingStringAmount} ]; then - if [ "$number" = "1" ]; then - printf "[OK] 1 match found for: \"%s\" | 'Results'=%d\n" "$(printf "%s\n" "${searchStrings[@]}")" "${numberOfResults}" + if [ "$numberOfResults" = "1" ]; then + printf "[OK] 1 match found for: \"%s\" | 'Results'=%d\n" "$(print_search)" "${numberOfResults}" else - printf "[OK] %d matches found for: \"%s\" | 'Results'=%d\n" "${numberOfResults}" "$(printf "%s\n" "${searchStrings[@]}")" "${numberOfResults}" + printf "[OK] %d matches found for: \"%s\" | 'Results'=%d\n" "${numberOfResults}" "$(print_search)" "${numberOfResults}" fi EXIT="$EXIT_OK" elif [ ${matchingStringAmount} -gt 0 ]; then - printf "[WARN] Not all matches found for: \"%s\" | 'Results'=%d but expected: %d\n" "$(printf "%s\n" "${searchStrings[@]}")" "${matchingStringAmount}" "${expectedMatches}" + printf "[WARN] Not all matches found for: \"%s\" | 'Results'=%d but expected: %d\n" "$(print_search)" "${matchingStringAmount}" "${expectedMatches}" EXIT="$EXIT_WARN" else - printf "[CRITICAL] No matches found for: \"%s\" | 'Results'=0\n" "$(printf "%s\n" "${searchStrings[@]}")" + printf "[CRITICAL] No matches found for: \"%s\" | 'Results'=0\n" "$(print_search)" EXIT="$EXIT_ERR" fi @@ -331,7 +358,7 @@ echo "Http info: ${http_info}" echo "Server: ${http_server}" echo "Url: ${url}" #echo "Post Data: ${ldata}" -echo "Search: $(printf "%s\n\t\t" "${searchStrings[@]}")" +echo "Search: $(print_search '\t\t')" echo "Num matches: ${numberOfResults}" echo "Matches:" echo "----------------------------------------" diff --git a/checkcommand_httpexpect.conf b/checkcommand_httpexpect.conf index 32afd54..a3c76bf 100644 --- a/checkcommand_httpexpect.conf +++ b/checkcommand_httpexpect.conf @@ -11,7 +11,12 @@ object CheckCommand "http_expect" { "--find" = { value = "$http_expect_find$" description = "Text or RegEx to search for" - required = true + required = false + } + "--avoid" = { + value = "$http_expect_avoid$" + description = "Text or RegEx that shall not occur" + required = false } "--ua" = { value = "$http_expect_useragent$" diff --git a/example_icingaservice.conf b/example_icingaservice.conf index 7d526db..9f5a150 100644 --- a/example_icingaservice.conf +++ b/example_icingaservice.conf @@ -10,5 +10,6 @@ object Service "check_title" { vars.http_expect_url = "https://duckduckgo.com" vars.http_expect_find = [ "DuckDuckGo — Privacy, simplified.", "Duck it" ] + vars.http_expect_avoid = "content=\"(nofollow|Nofollow|NOFOLLOW)\"" vars.http_expect_ua = "curl/7.37.0" }