#!/bin/bash # Centreon plugin to work with Pihole API ############ By @tips-of-mine ############ plugin_version="1.0" ########################################## red=$'\033[1;31m' yellow=$'\033[0;33m' nc=$'\033[0m' current_dira="$(pwd)" current_dir="/usr/lib/centreon/plugins" function info() { case "$1" in token) echo " " echo " ************************************************************************************************" echo " *" echo " * The file ${yellow}${api_token_file}${nc} does not exist or it's empty." echo " * You can get your token from the value ${yellow}WEBPASSWORD${nc} in the file ${yellow}/etc/pihole/setupVars.conf${nc}" echo " * Just put in the file ${yellow}${api_token_file}${nc} and that's it." echo " *" echo " * Example:" echo " * centreon-engine@centreon # ${yellow}touch ${api_token_file}${nc}" echo " * centreon-engine@centreon # ${yellow}echo 'PASTE_YOUR_TOKEN_HERE' >> ${api_token_file}${nc}" echo " *" echo " ************************************************************************************************" echo " " exit 1 ; ;; usage) echo " " echo " ************************************************************************************************" echo " *" echo " * Instructions for use" echo " *" echo " ************************************************************************************************" echo " *" echo " * Usage $0 -h pihole_ipaddress -e [ ads || being || clients || queries || unique] || -s || -i || -q || -t " echo " *" echo " * -h (host) " echo " * - ip address or fqdn name of the machine running Pi-Hole " echo " *" echo " * -c (cache) " echo " * - show cache " echo " *" echo " * -e (summary) " echo " * - ads : Number and percentage of ads blocked. " echo " * - being : Amount of blocked domain." echo " * - clients : Number of clients using Pihole as their DNS server " echo " * - domain : Number of domain queries " echo " * - queries : Number of DNS queries " echo " *" echo " * -f (forwarded) " echo " * - show forwarded " echo " *" echo " * -r (reply) " echo " * - show the status reply UNKNOWN, CNAME, IP, NODATA, NXDOMAIN " echo " *" echo " * -s (status) " echo " * - show the status service (enable/disable) " echo " *" echo " * -q (querie) " echo " * - queries by type AAAA, A, SOA, TXT, PTR, ANY, SRV, IPV4, IPV6 " echo " *" echo " * -t (top 10) " echo " * - Show a TOP number of queries by host " echo " *" echo " * -v (information) " echo " * - show the version of the plugin " echo " *" echo " ************************************************************************************************" echo " " exit 0 ; ;; version) echo " " echo " ************************************************************************************************" echo " *" echo " * Plugin by @tips-of-mine https://git.tips-of-mine.fr/ - Version: ${plugin_version} " echo " *" echo " ************************************************************************************************" echo " " exit 0 ; ;; esac } function ApiCall() { local obj=$1 local token=$2 pihole_api_tempfile="/tmp/pihole_api_${obj}.tmp" case $obj in "summary") pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed 's/{/\n/g ; s/","/\n/g ; s/"//g' > ${pihole_api_tempfile}) ;; "status") pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed 's/","/\n/g ; s/"//g' > ${pihole_api_tempfile}) ;; "getQueryTypes") pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed "s,),,g ; s,(,,g ; s/,\"/\n/g ; s/\"//g" > ${pihole_api_tempfile}) ;; "getQuerySources") pihole_api_output=$(curl "http://${pihole_ipadd}/admin/api.php?${obj}&auth=${token}" 2> /dev/null | sed 's,{"top_sources":{",,g ; s/,"/\n/g ; s/"//g ; s/}//g ; s/|/:/g' > ${pihole_api_tempfile}) esac } function GetApiToken() { # Default token file location api_token_file="${current_dir}/pihole-api.token" # If the file does not exist if [ ! -f ${api_token_file} ]; then echo " " echo " ************************************************************************************************" echo " *" echo " * ${red}The file ${api_token_file} does not exist ${nc}" echo " *" echo " ************************************************************************************************" echo " "; info token else export api_token=$(cat ${api_token_file}) # If the the api_token var is NULL because the file is empty (?) if [ -z ${api_token} ]; then echo " " echo " ************************************************************************************************" echo " *" echo " * ${red}The file ${api_token_file} exists, but it is empty ${nc}" echo " *" echo " ************************************************************************************************" echo " "; info token fi fi } function functSummary() { # This function requires a token GetApiToken # The summary option passed ApiCall "summary" "${api_token}" case "${summary_opt}" in ads) ads_percentage_today=$(cat ${pihole_api_tempfile} | grep ads_percentage_today | cut -f2 -d":") ads_blocked_today=$(cat ${pihole_api_tempfile} | grep ads_blocked_today | cut -f2 -d":") echo "ADS blocked today : ${ads_blocked_today}, Percentage = ${ads_percentage_today} % | 'TotalADS'=${ads_blocked_today} 'Percentage'=${ads_percentage_today}%" ;; being) domains_being_blocked=$(cat ${pihole_api_tempfile} | grep domains_being_blocked | cut -f2 -d":") echo "Domains blocked : ${domains_being_blocked} | 'Blocked'=${domains_being_blocked}" ;; clients) unique_clients=$(cat ${pihole_api_tempfile} | grep unique_clients | cut -f2 -d":") clients_ever_seen=$(cat ${pihole_api_tempfile} | grep clients_ever_seen | cut -f2 -d":") echo "${unique_clients} Hosts up, Total ${clients_ever_seen} | 'Hosts'=${unique_clients} 'TotalHosts'=${clients_ever_seen}" ;; domain) unique_domains=$(cat ${pihole_api_tempfile} | grep unique_domains | cut -f2 -d":") echo "Queries domain : ${unique_domains} | 'QueryDomain'=${unique_domains}" ;; queries) dns_queries_today=$(cat ${pihole_api_tempfile} | grep dns_queries_today | cut -f2 -d":") dns_queries_all_types=$(cat ${pihole_api_tempfile} | grep dns_queries_all_types | cut -f2 -d":") echo "DNS queries today : ${dns_queries_today}, queries all type : ${dns_queries_all_types} | 'DnsTotalToday'=${dns_queries_today} 'DnsAllType'=${dns_queries_all_types}" ;; *) echo " " echo " ************************************************************************************************" echo " *" echo " * ${red}Incorrect arugment > ${summary_opt} < for the option -s ${nc}" echo " *" echo " ************************************************************************************************" echo " "; info "usage" exit 1 ; ;; esac } function functCache() { # This function requires a token GetApiToken # Calling the api ApiCall "summary" "${api_token}" # queries_cached=$(cat ${pihole_api_tempfile} | grep -io "queries_cached:.*" | cut -f2 -d":" | sed 's/}//g') # echo "Use cache ${queries_cached} | 'cache'=${queries_cached} " } function functforwarded() { # This function requires a token GetApiToken # Calling the api ApiCall "summary" "${api_token}" # queries_forwarded=$(cat ${pihole_api_tempfile} | grep -io "queries_forwarded:.*" | cut -f2 -d":" | sed 's/}//g') # echo "Use forwarded ${queries_forwarded} | 'forwarded'=${queries_forwarded} " } function functStatus() { # This function requires a token GetApiToken # Calling the api ApiCall "status" "${api_token}" # status=$(cat ${pihole_api_tempfile} | grep -io "status:.*" | cut -f2 -d":" | sed 's/}//g') # if [[ ${status} == "enabled" ]]; then echo "OK - Status Pi-Hole is ${status} | 'enabled'=1, 'disabled'=0 " exit 0; elif [[ ${status} == "disabled" ]]; then echo "WARNING - Status Pi-Hole is ${status} | 'enabled'=0, 'disabled'=1 " exit 1; else echo "UNKNOWN - Status Pi-Hole is ${status} | 'enabled'=0, 'disabled'=0 " exit 3; fi } function functGetReply() { # This function requires a token GetApiToken # Calling the api ApiCall "summary" "${api_token}" # Local vars for query types local reply_UNKNOWN=$(cat ${pihole_api_tempfile} | grep reply_UNKNOWN | cut -f2 -d":") local reply_NODATA=$(cat ${pihole_api_tempfile} | grep reply_NODATA | cut -f2 -d":") local reply_NXDOMAIN=$(cat ${pihole_api_tempfile} | grep reply_NXDOMAIN | cut -f2 -d":") local reply_CNAME=$(cat ${pihole_api_tempfile} | grep reply_CNAME | cut -f2 -d":") local reply_IP=$(cat ${pihole_api_tempfile} | grep reply_IP | cut -f2 -d":") local reply_DOMAIN=$(cat ${pihole_api_tempfile} | grep reply_DOMAIN | cut -f2 -d":") texte="'UNKNOWN'=${reply_UNKNOWN}, 'NODATA'=${reply_NODATA}, 'NXDOMAIN'=${reply_NXDOMAIN}, 'CNAME'=${reply_CNAME}, 'IP'=${reply_IP}, 'DOMAIN'=${reply_DOMAIN}" datatexte="'UNKNOWN'=${reply_UNKNOWN}, 'NODATA'=${reply_NODATA}, 'NXDOMAIN'=${reply_NXDOMAIN}, 'CNAME'=${reply_CNAME}, 'IP'=${reply_IP}, 'DOMAIN'=${reply_DOMAIN}" echo "Reply type ${texte} | ${datatexte}" } function functGetQueryTypes() { # This function requires a token GetApiToken # Calling the api ApiCall "getQueryTypes" "${api_token}" # Local vars for query types local ipv4=$(cat ${pihole_api_tempfile} | grep -io "ipv4:.*" | cut -f2 -d":") local ipv6=$(cat ${pihole_api_tempfile} | grep -io "ipv6:.*" | cut -f2 -d":") local any=$(cat ${pihole_api_tempfile} | grep -io "any:.*" | cut -f2 -d":") local srv=$(cat ${pihole_api_tempfile} | grep -io "srv:.*" | cut -f2 -d":") local soa=$(cat ${pihole_api_tempfile} | grep -io "soa:.*" | cut -f2 -d":") local ptr=$(cat ${pihole_api_tempfile} | grep -xi "ptr:.*" | cut -f2 -d":") local naptr=$(cat ${pihole_api_tempfile} | grep -io "naptr:.*" | cut -f2 -d":") local txt=$(cat ${pihole_api_tempfile} | grep -io "txt:.*" | sed 's,},,g' | cut -f2 -d":") local mx=$(cat ${pihole_api_tempfile} | grep -io "mx:.*" | sed 's,},,g' | cut -f2 -d":") local ds=$(cat ${pihole_api_tempfile} | grep -io "ds:.*" | sed 's,},,g' | cut -f2 -d":") local rrsig=$(cat ${pihole_api_tempfile} | grep -io "rrsig:.*" | sed 's,},,g' | cut -f2 -d":") local dnskey=$(cat ${pihole_api_tempfile} | grep -io "ns:.*" | sed 's,},,g' | cut -f2 -d":") local ns=$(cat ${pihole_api_tempfile} | grep -io "ns:.*" | sed 's,},,g' | cut -f2 -d":") local other=$(cat ${pihole_api_tempfile} | grep -io "other:.*" | sed 's,},,g' | cut -f2 -d":") local svcb=$(cat ${pihole_api_tempfile} | grep -io "svcb:.*" | sed 's,},,g' | cut -f2 -d":") texte="'IPV4'=${ipv4}, 'IPV6'=${ipv6}, 'ANY'=${any}, 'SRV'=${srv}, 'SOA'=${soa}, 'PTR'=${ptr}, 'NAPTR'=${naptr}, 'TXT'=${txt}, 'MX'=${mx}, 'DS'=${ds}, 'RRSIG'=${rrsig}, 'DNSKEY'=${dnskey}, 'NS'=${ns}, 'OTHER'=${other}, 'SVCB'=${svcb}" datatexte="'IPV4'=${ipv4}, 'IPV6'=${ipv6}, 'ANY'=${any}, 'SRV'=${srv}, 'SOA'=${soa}, 'PTR'=${ptr}, 'NAPTR'=${naptr}, 'TXT'=${txt}, 'MX'=${mx}, 'DS'=${ds}, 'RRSIG'=${rrsig}, 'DNSKEY'=${dnskey}, 'NS'=${ns}, 'OTHER'=${other}, 'SVCB'=${svcb}" echo "Number of queries by type ${texte} | ${datatexte}" } function functGetQuerySources() { # This function requires a token GetApiToken # Calling the api ApiCall "getQuerySources" "${api_token}" while read line; do check_columns=$(echo $line | sed 's,:, ,g' | wc -w) host_name=$(echo $line | cut -f1 -d":") if [[ "${check_columns}" == "3" ]]; then columns="3" elif [[ "${check_columns}" == "2" ]]; then columns="2" else echo "Error formatting the list" echo " " exit 1; fi host_queries=$(echo ${line} | cut -f${columns} -d":") if [ -z "${host_queries}" ]; then host_queries="0"; fi texte="${texte} ${host_name}=${host_queries}\n" datatexte="${datatexte} ${host_name}=${host_queries}" done < ${pihole_api_tempfile} echo -e "Top hosts by queries :\n${texte}|${datatexte}" } # Display if there is no argument if [ $# -eq 0 ]; then info "usage" exit 1; fi # The options passed by the user while getopts "h:e:cfqrstv" opt; do case "$opt" in h ) pihole_ipadd=${OPTARG} ;; c ) e ) summary_selected="y" summary_opt=${OPTARG} ;; f ) query_forwarded="y" ;; q ) query_type_selected="y" ;; r ) query_type_reply="y" ;; s ) status="y" ;; t ) query_sources_selected="y" ;; v ) info "version" exit 0 ;; \?) echo " " echo " ************************************************************************************************" echo " *" echo " * ${red}Invalid option. -${OPTARG} ${nc}" echo " *" echo " * use -h to get help " echo " *" echo " ************************************************************************************************" echo " " exit 1 ;; esac done # The values passed by the user if [ -z ${pihole_ipadd} ]; then echo " " echo " ************************************************************************************************" echo " *" echo " * ${red}Please enter the Pihole IP address as follow: -h pihole_ipaddress ${nc}" echo " *" echo " ************************************************************************************************" echo " "; exit 1; else if [[ "${summary_selected}" == "y" ]]; then # Calling the summary function functSummary exit 0; elif [[ "${query_cached}" == "y" ]]; then # Calling the status Cache functCache exit 0; elif [[ "${status}" == "y" ]]; then # Calling the status service functStatus exit 0; elif [[ "${query_forwarded}" == "y" ]]; then # Calling the status forwarded functforwarded exit 0; elif [[ "${query_type_selected}" == "y" ]]; then # Calling the Query Types funct functGetQueryTypes exit 0; elif [[ "${query_sources_selected}" == "y" ]]; then # Calling the Query Source funct functGetQuerySources exit 0; elif [[ "${query_type_reply}" == "y" ]]; then # Calling the Query Reply funct functGetReply exit 0; else info "usage" fi # Just delete the temp file #rm -f ${pihole_api_tempfile} fi