From 9211cb8970a042aecd6c499738b2240a97b617f7 Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 4 Aug 2017 12:00:34 +0200 Subject: [PATCH] - Add script 'bind_get_zonefile_by_hostname.sh'. - bind_get_domain_by_hostname.sh: some minor changes and bug fixes. --- bind_get_domain_by_hostname.sh | 104 ++++++++-- bind_get_zonefile_by_hostname.sh | 331 +++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+), 22 deletions(-) create mode 100755 bind_get_zonefile_by_hostname.sh diff --git a/bind_get_domain_by_hostname.sh b/bind_get_domain_by_hostname.sh index 8d20696..0a95813 100755 --- a/bind_get_domain_by_hostname.sh +++ b/bind_get_domain_by_hostname.sh @@ -28,12 +28,28 @@ usage() { Usage: $(basename $0) [Options] - Script checks if a given hostname is supported by this nameserver. Hostname can - alos be a TLD name. + Script checks if a given hostname is supported by this nameserver. The concerning + zone will be printed out. - As result the Script returns the zone (domain) of the given hostname." In silent - mode (-q), script returns an empty String, if the given hostname is not - supported by this nameserver. + If running in a terminal and not in silent mode (-q), the output is clearly + arranged in a human readable way. + + If not running in a terminal or silent mode (-q) is set, only the name of the + zonefile will be printed out or an empty string, if the given hostname is + not supported by this nameservice. + + Parameter "check" can be used, to test whether this script is accessable (e.g. from a + further script on a remote host). Nothing will be done, scripts returns '0'. + + Return (Exit) Codes: + success: + 0: hostname is supported + error: + 10: Invalid hostname/domain given + 11: the given hostname is not supported by this nameserver + 12: given hostname is supported, but this nameserver is not the master of + the concerning zone + 99: Fatal error Options: @@ -106,6 +122,10 @@ echo_skipped() { fi } + +trap clean_up SIGHUP SIGINT SIGTERM + + # - Test whether stdout (file descriptor 1) is a terminal or not (e.g. cron # - or if you pipe the output to some other program) # @@ -132,10 +152,18 @@ if [[ $# -ne 1 ]] ; then if $verbose ; then usage "wrong number of arguments" else - clean_up 10 + clean_up 99 fi fi +# - Parameter "check" can be used, to test whether this script +# - is accessable (e.g. from a script on a remote host) +# - +if [[ "$1" = "check" ]]; then + info "Script \033[1m$(basename $0)\033[m was successfully invoked, but its only a test." + clean_up 0 +fi + hostname=$1 @@ -143,7 +171,7 @@ $verbose && echo "" if [[ -z "$hostname" ]] ; then error "No hostname/domain given!" - clean_up 10 + clean_up 99 fi @@ -187,7 +215,6 @@ fi $verbose && echo "" - # - Validate Syntax of given domain # - valid_domain_regex="^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$" @@ -206,28 +233,61 @@ else clean_up 10 fi + +# - Is hostname supported by this nameserver? +# - _failed=false -_hostname=$(echo ${hostname//\./\\.}) -while ! grep -E "^\s*zone\s+\"?$_hostname" $ZONES_DECLARATION_FILE > /dev/null 2>&1 ; do - hostname=${hostname#*.} - _hostname=$(echo ${hostname//\./\\.}) - if [[ ! $_hostname =~ \. ]]; then +zone=$hostname +_zone=$(echo ${zone//\./\\.}) +while ! grep -E "^\s*zone\s+\"?$_zone" $ZONES_DECLARATION_FILE > /dev/null 2>&1 ; do + zone=${zone#*.} + _zone=$(echo ${zone//\./\\.}) + if [[ ! $_zone =~ \. ]]; then _failed=true break fi done if $_failed ; then - $verbose && error "hostname \"$1\" not supported by this nameserver!" -else - domain=$hostname - if $verbose ; then - info "Hosted Zone: \033[1m${domain}\033[m" - else - echo "$domain" - fi + $verbose && error "hostname \"$hostname\" not supported by this nameserver!" + clean_up 11 fi -$verbose && echo +# - Is this nameserver also the master? +# - +_found=false +_found_zonefile=false +_is_master=false +zone_file="" +regex_zone="^[[:space:]]*zone[[:space:]]+\"?$(echo ${zone//\./\\.})\"" +regex_file="^[[:space:]]*file" +regex_master="type[[:space:]]+master" +while IFS='' read -r line || [[ -n "$line" ]] ; do + if [[ $line =~ $regex_zone ]]; then + _found=true + fi + if $_found ; then + if [[ $line =~ $regex_master ]]; then + _is_master=true + fi + if [[ "$line" =~ ^[[:space:]]*\}[[:space:]]*\; ]]; then + break + fi + fi +done < $ZONES_DECLARATION_FILE + + +if $_is_master ; then + if $verbose ; then + info "Hosted Zone: \033[1m${zone}\033[m" + else + echo "$zone" + fi +else + $verbose && error "hostname \"$hostname\" is supported but this nameserver is not the master!" + clean_up 12 +fi + +$verbose && echo "" clean_up 0 diff --git a/bind_get_zonefile_by_hostname.sh b/bind_get_zonefile_by_hostname.sh new file mode 100755 index 0000000..447e576 --- /dev/null +++ b/bind_get_zonefile_by_hostname.sh @@ -0,0 +1,331 @@ +#!/usr/bin/env bash + + +working_dir="$(dirname $(realpath $0))" +conf_file="${working_dir}/conf/bind.conf" + +log_file="$(mktemp)" + + +#--------------------------------------- +#----------------------------- +# Setting Defaults +#----------------------------- +#--------------------------------------- + +DEFAULT_CONF_FILE_DIR="/etc/bind" + +#--------------------------------------- +#----------------------------- +# Base Function(s) +#----------------------------- +#--------------------------------------- + +usage() { + echo + [ -n "$1" ] && echo -e "Error: $1\n" + + cat< | check + + Script checks if a given hostname is supported by this nameserver. The concerning + zonefile will be printed out. + + If running in a terminal and not in silent mode (-q), the output is clearly + arranged in a human readable way. + + If not running in a terminal or silent mode (-q) is set, only the name of the + zonefile will be printed out or an empty string, if the given hostname is + not supported by this nameservice. + + Parameter "check" can be used, to test whether this script is accessable (e.g. from a + further script on a remote host). Nothing will be done, scripts returns '0'. + + Return (Exit) Codes: + success: + 0: hostname is supported + error: + 10: Invalid hostname/domain given + 11: the given hostname is not supported by this nameserver + 12: given hostname is supported, but this nameserver is not the master of + the concerning zone + 99: Fatal error + + Options: + + -h + Prints this help. + + -q + Runs in silent mode. + +EOF +clean_up 1 +} + +clean_up() { + + # Perform program exit housekeeping + rm $log_file + exit $1 +} + +echononl(){ + if $verbose ; then + echo X\\c > /tmp/shprompt$$ + if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then + echo -e -n "$*\\c" 1>&2 + else + echo -e -n "$*" 1>&2 + fi + rm /tmp/shprompt$$ + fi +} + +fatal(){ + echo "" + echo -e "[ \033[31m\033[1mError\033[m ]: $*" + echo "" + echo -e "\t\033[31m\033[1mScript is canceled\033[m\033[m" + echo "" + clean_up 99 +} + +warn (){ + if $verbose ; then + echo "" + echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" + echo "" + fi +} + +info (){ + if $verbose ; then + echo "" + echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" + echo "" + fi +} + +ok (){ + if $verbose ; then + echo "" + echo -e "\t[ \033[36m\033[1mOk\033[m ]: $*" + echo "" + fi +} + +error(){ + if $verbose ; then + echo "" + echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" + echo "" + fi +} + +echo_ok() { + if $verbose ; then + echo -e "\033[75G[ \033[32mok\033[m ]" + fi +} +echo_failed(){ + if $verbose ; then + echo -e "\033[75G[ \033[1;31mfailed\033[m ]" + fi +} +echo_skipped() { + if $verbose ; then + echo -e "\033[75G[ \033[33m\033[1mskipped\033[m ]" + fi +} + +containsElement () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} + + +trap clean_up SIGHUP SIGINT SIGTERM + +# - Test whether stdout (file descriptor 1) is a terminal or not (e.g. cron +# - or if you pipe the output to some other program) +# +if [[ -t 1 ]] ; then + verbose=true +else + verbose=false +fi + + +while getopts hq opt ; do + case $opt in + q) verbose=false + ;; + h) usage + ;; + *) + ;; + esac +done + +shift $(expr $OPTIND - 1) +if [[ $# -ne 1 ]] ; then + if $verbose ; then + usage "wrong number of arguments" + else + clean_up 99 + fi +fi + +# - Parameter "check" can be used, to test whether this script +# - is accessable (e.g. from a script on a remote host) +# - +if [[ "$1" = "check" ]]; then + info "Script \033[1m$(basename $0)\033[m was successfully invoked, but its only a test." + clean_up 0 +fi + +hostname=$1 + + +$verbose && echo "" + +if [[ -z "$hostname" ]] ; then + error "No hostname/domain given!" + clean_up 99 +fi + + + +#--------------------------------------- +#----------------------------- +# Load default values from bind.conf +# +# Overwrites the settings above +# +#----------------------------- +#--------------------------------------- + +if $verbose ; then + clear + echo "" + echo -e "\033[32mRunning script \033[1m"$(basename $0)"\033[m .." + echo "" +fi + + +info "Given hostname: \033[1m${hostname}\033[m" + + +echononl "\t Loading default Configuration values from $(basename ${conf_file}).." +if [[ ! -f "$conf_file" ]]; then + echo_skipped +else + source "${conf_file}" > $log_file 2>&1 + if [[ $? -eq 0 ]]; then + echo_ok + else + echo_failed + fatal "$(cat $log_file)" + fi +fi + +[[ -n "$CONF_FILE_DIR" ]] || CONF_FILE_DIR="$DEFAULT_CONF_FILE_DIR" +[[ -n "$ZONES_DECLARATION_FILE" ]] || ZONES_DECLARATION_FILE="${CONF_FILE_DIR}/named.conf.local" + +$verbose && echo "" + + +# - Validate Syntax of given domain +# - +valid_domain_regex="^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$" +echononl "\t Validate syntax of given domain.." +if [[ $hostname =~ $valid_domain_regex ]]; then + if [[ ! $hostname =~ \. ]]; then + echo_failed + error "Invalid hostname/domain given!" + clean_up 10 + else + echo_ok + fi +else + echo_failed + error "Invalid hostname/domain given!" + clean_up 10 +fi + + +# - Is hostname supported by this nameserver? +# - +_failed=false +zone="$hostname" +_zone=$(echo ${zone//\./\\.}) +while ! grep -E "^\s*zone\s+\"?$_zone" $ZONES_DECLARATION_FILE > /dev/null 2>&1 ; do + zone=${zone#*.} + _zone=$(echo ${zone//\./\\.}) + if [[ ! $_zone =~ \. ]]; then + _failed=true + break + fi +done + +if $_failed ; then + $verbose && error "hostname \"$hostname\" not supported by this nameserver!" + clean_up 11 +fi + + +# - Determine zonefile (by reading bind configuration) +# - +_found=false +_found_zonefile=false +_is_master=false +zone_file="" +regex_zone="^[[:space:]]*zone[[:space:]]+\"?$(echo ${zone//\./\\.})\"" +regex_file="^[[:space:]]*file" +regex_master="type[[:space:]]+master" +while IFS='' read -r line || [[ -n "$line" ]] ; do + if [[ $line =~ $regex_zone ]]; then + _found=true + fi + if $_found ; then + if [[ $line =~ $regex_file ]]; then + zone_file=`echo $line | awk '{print$2}'` + shopt -s extglob + if [[ $zone_file =~ \; ]]; then + zone_file=${zone_file%%*(\;)} + fi + if [[ $zone_file =~ ^\" ]]; then + zone_file=${zone_file##*(\")} + zone_file=${zone_file%%*(\")} + fi + shopt -u extglob + fi + if [[ $line =~ $regex_master ]]; then + _is_master=true + fi + if [[ "$line" =~ ^[[:space:]]*\}[[:space:]]*\; ]]; then + if $_is_master && [[ -n "$zone_file" ]]; then + _found_zonefile=true + fi + break + fi + fi +done < $ZONES_DECLARATION_FILE + +if $_found_zonefile ; then + if $verbose ; then + info "Zonefile for '$hostname': \033[1m${zone_file}\033[m" + else + echo "$zone_file" + fi +else + $verbose && error "hostname \"$hostname\" is supported but this nameserver is not the master!" + clean_up 12 +fi + +$verbose && echo +clean_up 0 +