#!/usr/bin/env bash # - Adds DKIM subdomain delegation for a given domain # - # - Return (Exit) Codes: # - success: # - 0: Slave zone added / Access check successfully # - 1: Slave zone already exists # - # - error: # - 15: Variable for DNS master Server not present # - 21: Adding Zone failed #- 99: Fatal error # - # - Example: # - bind_create_dkim_delegation.sh oopen.de script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" base_conf_file="${working_dir}/conf/bind.conf" script_conf_file="${working_dir}/conf/${script_name%%.*}.conf" log_file="$(mktemp)" backup_date="$(date +%Y-%m-%d-%H%M)" # ---------- # Setting Defaults # ---------- DEFAULT_CONF_FILE_DIR="/etc/bind" DEFAULT_BIND_USER="bind" DEFAULT_BIND_GROUP="bind" DEFAULT_ZONE_FILE_SLAVE_DIR="/var/cache/bind" DEFAULT_ZONE_FILE_SUFFIX="zone" # ********** # Don't make changes after this # ********** # ---------- # Base Function(s) # ---------- usage() { [[ -n "$1" ]] && error "$1" [[ $verbose ]] && echo -e " \033[1mUsage:\033[m $(basename $0) [Options] | check \033[1mDescription\033[m \033[1mReturn (Exit) Codes\033[m success: 0: Slave zone added / Access check successfully 1: Slave zone already exists error: 15: Variable for DNS master Server (DKIM_DNS_MASTER) not present 21: Adding Zone failed 23: Reload bind configuration failed 99: Fatal error \033[1mOptions\033[m -h Prints this help. -M Primary master for the new DKIM slave zone. -q Runs in silent mode. \033[1mFiles\033[m Basic Configuration file: $base_conf_file Script specific Configuration file: $script_conf_file \033[1mExample:\033[m Create Configuration for Slave DKIM zone _domainkey.oopen.de $(basename $0) oopen.de " clean_up 100 } clean_up() { # Perform program exit housekeeping rm $log_file blank_line if [[ -n "$1" ]] ; then ret_val=$1 else ret_val=99 fi exit $ret_val } 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 } warn (){ if $verbose ; then echo "" echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" echo "" fi } info (){ if $verbose ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" echo "" fi } error(){ if $verbose ; then echo "" echo -e " [ \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 } backup_dir () { dir_to_backup=$1 echononl "Backup existing directory \"$dir_to_backup\" .." if [[ -d "$dir_to_backup" ]] ; then cp -a "$dir_to_backup" "${dir_to_backup}.$backup_date" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "Backup directory \"$dir_to_backup\" failed!" clean_up 99 fi else echo_failed error "Directory \"$dir_to_backup\" not found. No Backup written!" clean_up 99 fi } blank_line() { if $verbose ; then echo "" fi } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap clean_up SIGHUP SIGINT SIGTERM # ---------- # - Some checks .. # ---------- # - Running in a terminal? # - if [[ -t 1 ]] ; then verbose=true else verbose=false fi # -Is systemd supported on this system? # - systemd_supported=false systemd=$(which systemd) systemctl=$(which systemctl) if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then systemd_supported=true fi # - Print help? # - if [[ "$(trim $*)" = " -h" ]] || [[ "$(trim $*)" = " --help" ]] ; then usage fi if [[ -z "$(which basename)" ]]; then fatal 'It seems "basename" is not installed, but needed!' fi if [[ -z "$(which realpath)" ]]; then fatal 'It seems "realpath" is not installed, but needed!' fi # ========== # - Begin Main Script # ========== # ---------- # - Headline # ---------- if $terminal ; then echo "" echo -e "\033[1m----------\033[m" echo -e "\033[32m\033[1mRunning script \033[m\033[1m$script_name\033[32m .. \033[m" echo -e "\033[1m----------\033[m" fi # ---------- # - Read commandline parameter # ---------- while getopts hM:q opt ; do case $opt in q) verbose=true ;; h) usage ;; M) DKIM_DNS_MASTER="$OPTARG" ;; \?) usage ;; *) ;; esac done if [[ "$1" = "check" ]]; then info "Script \033[1m$(basename $0)\033[m was successfully invoked, but its only a test." clean_up 0 fi dkim_domain=$1 # ---------- # Read Configurations from $base_conf_file # ---------- blank_line echononl "Loading default basic configurations from $(basename ${base_conf_file}).." if [[ ! -f "$base_conf_file" ]]; then echo_skipped else source "${base_conf_file}" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi fi echononl "Loading script specific configurations from $(basename ${script_conf_file}).." if [[ ! -f "$script_conf_file" ]]; then echo_skipped else source "${script_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" [[ -n "$BIND_USER" ]] || BIND_USER="$DEFAULT_BIND_USER" [[ -n "$BIND_GROUP" ]] || BIND_GROUP="$DEFAULT_BIND_GROUP" [[ -n "$ZONE_FILE_SLAVE_DIR" ]] || ZONE_FILE_SLAVE_DIR="$DEFAULT_ZONE_FILE_SLAVE_DIR" [[ -n "$ZONE_FILE_SUFFIX" ]] || ZONE_FILE_SUFFIX="$DEFAULT_ZONE_FILE_SUFFIX" if [[ -z "$DKIM_DNS_MASTER" ]] ; then error "DNS master Server not present!" clean_up 15 else IP_DNS_MASTER="$(dig +short $DKIM_DNS_MASTER)" # - Eliminate trailing '.' character(s) # - IP_DNS_MASTER="${IP_DNS_MASTER%"${IP_DNS_MASTER##*[!\.]}"}" fi if [[ -z "$ALLOW_TRANSFER_OPTION" ]] ; then ALLOW_TRANSFER_OPTION="$(dig +short $DKIM_DNS_MASTER)" # - Eliminate trailing '.' character(s) # - ALLOW_TRANSFER_OPTION="${ALLOW_TRANSFER_OPTION%"${ALLOW_TRANSFER_OPTION##*[!\.]}"}" fi zone=_domainkey.${dkim_domain} if $(grep -q -E "^\s*zone\s+\"$zone\"" $ZONES_DECLARATION_FILE 2>/dev/null) ; then info "Zone declaration for "$zone" already exists." clean_up 1 fi # - Backup ZONES_DECLARATION_FILE # - echononl "Backup file '$ZONES_DECLARATION_FILE'.." cp -a "$ZONES_DECLARATION_FILE" "${ZONES_DECLARATION_FILE}.$backup_date" > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed fatal "$(cat $log_file)" fi # - Add zone definition to ZONES_DECLARATION_FILE (/etc/bind/named.conf.local) # - echononl "Add zone definition to '$ZONES_DECLARATION_FILE' .." cat <> $ZONES_DECLARATION_FILE 2> $log_file zone "$zone" { type slave; file "${ZONE_FILE_SLAVE_DIR}/${zone}.${ZONE_FILE_SUFFIX}"; //allow-query { any; }; allow-transfer { $ALLOW_TRANSFER_OPTION; }; masters { $IP_DNS_MASTER; }; }; EOF if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" clean_up 20 fi # - (re)Load Bind base configuration # - echononl "Reload bind configuration.." rndc reconfig > $log_file 2>&1 if [[ $? -eq 0 ]]; then echo_ok else echo_failed error "$(cat $log_file)" clean_up 23 fi blank_line clean_up 0