#!/usr/bin/env bash script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" LOCK_DIR="/tmp/$(basename $0).$$.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" # ------------- # - Default values # ------------- # - Give your default values here # - LOGGING=false BATCH_MODE=false DEFAULT_dns_dkim_zone_master_server="b.ns.oopen.de" DEFAULT_key_algo="hmac-sha256" DEFAULT_key_name="update-dkim" DEFAULT_key_secret="4woPu0jqf9Jp1IX+gduJ3BVW/1ZMeyCPTQMqEsMXLFw=" DEFAULT_ttl="43200" DEFAULT_dns_ssh_user="manage-bind" DEFAULT_dns_ssh_port=22 DEFAULT_dns_ssh_key="/root/.ssh/id_rsa-opendkim" DEFAULT_set_new_serial_script="/root/bin/bind/bind_set_new_serial.sh" DEFAULT_create_dkim_delegation_script="/root/bin/bind/bind_create_dkim_delegation.sh" DEFAULT_add_dkim_zone_master_script="/root/bin/bind/bind_add_dkim_zone_master.sh" DEFAULT_add_dkim_zone_slave_script="/root/bin/bind/bind_add_dkim_zone_slave.sh" # - We use actual timestamp as DEKIM Selector # - DEFAULT_dkim_selector=$(date +%s) DEFAULT_opendkim_dir="/etc/opendkim" # ------------- # --- Functions # ------------- usage() { [[ -n "$1" ]] && error "$1" [[ -z "${dkim_domain}" ]] && dkim_domain='' [[ -z "${update_zone}" ]] && update_zone='' [[ $terminal ]] && echo -e " \033[1mUsage:\033[m $(basename $0) [-a ] [-b] [-d ] [-h] [-n] [-s ] [-z \033[1mDescription\033[m This script generates DKIM key for a given DKIM domain. If the domain name is not given at command line by using \033[1m-d\033[m flag, the domain name will be requested interactively unless flag \033[1m-b\033[m (batch mode) is set. Unless flag \033[1m-n\033[m is set, also DNS entry for DKIM is set/updated at zone file for given update zone (flag \033[1m-z\033[m), So a CNAME record is needed at zone file for the given DKIM domain. This record looks like: \033[1m*._domainkey.${dkim_domain}. IN CNAME ${dkim_domain}.${update_zone}.\033[m \033[1mOptions\033[m -a Specifies the algorithm to use for the TSIG key. Available choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512. The default is hmac-sha256. Options are case-insensitive -b Script will run in batch mode, no user interaction is made. Flag \033[1m-n\033[m is ignored, or in other words: running in batch mode implies updating DNS DKIM record. Useful for cronjob. -d The domain for which DKIM support will be configured. If not give, the domain will be requested interactivly. -D Specifies the domain server where to send the dynamic updates. -h Prints this help. -n Do \033[1mNOT\033[m set/update DNS TXT record for DKIM domain. The default is to update DNS entry. This option is ignored if flag \033[1m-n\033[m is set. -s Give the secret for the key used by nsupdate to create/update the DNS TXT record. -t Specify the TTL value for the DKIM TXT record. -z The zone which is updated with the TXT entry for DKIM by using 'nsupdate'. \033[1mFiles\033[m $conf_file: Configuration file \033[1mExample:\033[m Cretate / Update DKIM key for domain \033[1moopen.de\033[m $(basename $0) -d oopen.de " clean_up 1 } clean_up() { # SIGHUP SIGINT SIGTERM if is_number ${1} && [[ ${1} -eq 127 ]] ; then blank_line if [[ -n "${key_dir}" ]] && [[ -d "${key_dir}" ]] ; then echononl "Clean up OpenDKIM key directory \033[1m${key_dir}\033[m .." if [[ -f "${key_dir}/${dkim_selector}.*" ]]; then rm -f "${key_dir}/${dkim_selector}.*" echo_ok else echo_skipped fi fi blank_line fi # Perform program exit housekeeping rm -rf "$LOCK_DIR" blank_line exit $1 } echononl(){ if $terminal ; 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 "" if $terminal ; then echo -e " [ \033[31m\033[1mFatal\033[m ] $*" else echo -e " [ Fatal ] $*" fi echo "" if $terminal ; then echo -e " \033[1mScript terminated\033[m.." else echo -e " Script terminated.." fi echo "" rm -rf $LOCK_DIR exit 1 } error (){ echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ] $*" else echo " [ Error ] $*" fi echo "" } warn (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarn\033[m ] $*" else echo " [ Warn ] $*" fi echo "" fi } todo (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[33m\033[1mToDo\033[m ] $*" else echo " [ ToDo ] $*" fi echo "" fi } info (){ if $LOGGING || $terminal ; then echo "" if $terminal ; then echo -e " [ \033[32m\033[1mInfo\033[m ] $*" else echo " [ Info ] $*" fi echo "" fi } echo_done() { if $terminal ; then echo -e "\033[80G[ \033[32mdone\033[m ]" fi } echo_ok() { if $terminal ; then echo -e "\033[80G[ \033[32mok\033[m ] " fi } echo_failed(){ if $terminal ; then echo -e "\033[80G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]" fi } echo_wait(){ if $terminal ; then echo -en "\033[80G[ \033[5m\033[1m...\033[m ]" fi } blank_line() { if $terminal ; then echo "" fi } containsElement () { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } # Check for positive number is_number() { return $(test ! -z "${1##*[!0-9]*}" > /dev/null 2>&1); # - also possible # - #[[ ! -z "${1##*[!0-9]*}" ]] && return 0 || return 1 #return $([[ ! -z "${1##*[!0-9]*}" ]]) } # - Remove leading/trailling whitespaces # - trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } delete_generated_files() { for _file in ${generated_files_arr[@]} ; do echononl " Delete file \033[1m$_file\033[m .." rm "$_file" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi done } # ---------- # - Jobhandling # ---------- # - Run 'clean_up' for signals SIGHUP SIGINT SIGTERM # - trap 'clean_up 127' SIGHUP SIGINT SIGTERM # - Create lock directory '$LOCK_DIR" # mkdir "$LOCK_DIR" # ------------- # - Some checks .. # ------------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false BATCH_MODE=true fi # - Is 'systemd' supported on this system # - # -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 # ========== # - 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 Configurations from $conf_file # ---------- domain="" update_zone="" if [[ -f "$conf_file" ]]; then source "$conf_file" else warn "No configuration file '$conf_file' present." fi # ------------- # - Read in Commandline arguments # ------------- while getopts bd:D:hns:t:z: opt ; do case $opt in b) BATCH_MODE=true ;; d) dkim_domain=$OPTARG ;; D) dns_dkim_zone_master_server=$OPTARG ;; h) usage ;; n) update_dns=false ;; s) key_secret=$OPTARG ;; t) ttl=$OPTARG ;; z) update_zone=$OPTARG ;; \?) usage esac done # - batch mode implies updating DKIM DNS record # - if $BATCH_MODE ; then update_dns=true fi if [[ -z "$dkim_domain" ]] && ! $BATCH_MODE ; then echo "" echo -e "\033[32m--\033[m" echo "" echo " Insert a domain name for which DKIM support should be configured." echo "" echo "" echononl " DKIM domain: " read dkim_domain while [ "X$dkim_domain" = "X" ] ; do echo -e "\n\t\033[33m\033[1mEingabe erforderlich.\033[m\n" echononl " DKIM domain: " read dkim_domain done elif $terminal ; then echo -e "\033[32m--\033[m" info "\033[32mCreate DKIM key/configuration for domain \033[37m\033[1m$dkim_domain\033[m" fi if [[ -z "$update_dns" ]] ; then echo "" echo -e "\033[32m--\033[m" echo "" echononl " Create/Update DKIM DNS record? (yes/no) [yes]: " read update_dns if [[ -z "$(trim $update_dns)" ]] ; then update_dns=true elif [[ "${update_dns,,}" = "yes" ]] || [[ "${update_dns,,}" = "true" ]] ; then update_dns=true else update_dns=false fi blank_line fi if $update_dns && [[ -z "$update_zone" ]] && ! $BATCH_MODE ; then echo "" echo -e "\033[32m--\033[m" echo "" echo " Which zone should contain the DKIM TXT record?" echo "" echo -e " Type \033[33m\033[m to use the default value \033[33m_domainkey.${dkim_domain}\033[m" echo "" echononl " update Zone [_domainkey.${dkim_domain}]: " read update_zone if [[ -z "$(trim $update_zone)" ]]; then update_zone="_domainkey.${dkim_domain}" fi elif $update_dns && $terminal ; then if [[ -n "$update_zone" ]]; then echo -e "\033[32m--\033[m" info "Zone \033[37m\033[1m${update_zone}\033[m is used for DKIM TXT record" fi else update_zone="_domainkey.${dkim_domain}" fi if $update_dns && [[ -z "$key_secret" ]] && ! $BATCH_MODE ; then echo "" echo -e "\033[32m--\033[m" echo "" echo " Give the secret of the TSIG update key used by nsupdate." echo "" echo "" echononl " Secret update key: " read key_secret while [ "X$key_secret" = "X" ] ; do echo -e "\n\t\033[33m\033[1mEingabe erforderlich.\033[m\n" echononl " Secret update key: " read key_secret done fi if $update_dns && [[ -z "$key_algo" ]] && ! $BATCH_MODE ; then echo "" echo -e "\033[32m--\033[m" echo "" echo " Specifies the algorithm to use for the TSIG key." echo "" echo " [1] hmac-md5" echo " [2] hmac-sha1" echo " [3] hmac-sha224" echo -e " [4] \033[37m\033[1mhmac-sha256\033[m" echo " [5] hmac-sha384" echo " [6] hmac-sha512" echo "" echo " Type a number or press to choose highlighted value" echo "" echononl " Key algorithm [hmac-sha256]: " while [[ "$key_algo" != "hmac-md5" ]] \ && [[ "$key_algo" != "hmac-sha1" ]] \ && [[ "$key_algo" != "hmac-sha224" ]] \ && [[ "$key_algo" != "hmac-sha256" ]] \ && [[ "$key_algo" != "hmac-sha384" ]] \ && [[ "$key_algo" != "hmac-sha512" ]] ; do read OPTION case $OPTION in 1) key_algo="hmac-md5" ;; 2) key_algo="hmac-sha1" ;; 3) key_algo="hmac-sha224" ;; 4) key_algo="hmac-sha256" ;; '') key_algo="hmac-sha256" ;; 5) key_algo="hmac-sha384" ;; 6) key_algo="hmac-sha512" ;; *) echo "" echo -e " \033[33m\033[1mFalsche Eingabe ! [ 1 = hmac-md5 | 2 = hmac-sha1 | .. ]\033[m" echo "" echononl " Key algorithm [hmac-sha256]:" ;; esac done fi if [[ -z "$dkim_domain" ]] ; then fatal "Running in batch mode, but no domain was given!" fi if $update_dns && [[ -z "$update_zone" ]] ; then update_zone="_domainkey.${dkim_domain}" fi if $update_dns && [[ -z "$key_secret" ]] ; then fatal "No secret for the update key used by nsupdate is given!" elif [[ -z "$key_secret" ]] ; then key_secret="${DEFAULT_key_secret}" fi if $update_dns && [[ -z "$key_algo" ]]; then key_algo="$DEFAULT_key_algo" else key_algo="${DEFAULT_key_algo}" fi if $update_dns && [[ -z "$key_name" ]]; then key_name="${DEFAULT_key_name}" else key_name="${DEFAULT_key_name}" fi if $update_dns && [[ -z "$ttl" ]]; then ttl="$DEFAULT_ttl" else ttl="$DEFAULT_ttl" fi if $update_dns && [[ -z "$dns_dkim_zone_master_server" ]]; then fatal "No DNS server for updating given!" fi #if [[ -z "$(dig +short ${dkim_domain} NS)" ]] ; then # fatal "No Nameserver for domain '${dkim_domain}' found!" #fi if $update_dns ; then cname_record="*._domainkey.${dkim_domain}. IN CNAME ${dkim_domain}.${update_zone}." fi # Access Credentials DNS Server [[ -z "$dns_ssh_user" ]] && dns_ssh_user="$DEFAULT_dns_ssh_user" [[ -z "$dns_ssh_port" ]] && dns_ssh_port="$DEFAULT_dns_ssh_port" [[ -z "$dns_ssh_key" ]] && dns_ssh_key="$DEFAULT_dns_ssh_key" #Scripts envoked at DNS Server [[ -z "$set_new_serial_script" ]] && set_new_serial_script="$DEFAULT_set_new_serial_script" [[ -z "$create_dkim_delegation_script" ]] && create_dkim_delegation_script="$DEFAULT_create_dkim_delegation_script" [[ -z "$add_dkim_zone_master_script" ]] && add_dkim_zone_master_script="$DEFAULT_add_dkim_zone_master_script" [[ -z "$add_dkim_zone_slave_script" ]] && add_dkim_zone_slave_script="$DEFAULT_add_dkim_zone_slave_script" blank_line echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo " Insert DKIM selector or type using actual timestamp ." echo "" echo "" while [[ -z "${dkim_selector}" ]]; do echononl " DKIM selector [ \033[1m${DEFAULT_dkim_selector}\033[m ]: " read dkim_selector if [[ -z "$(trim ${dkim_selector})" ]] ; then dkim_selector=${DEFAULT_dkim_selector} fi done echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo " Insert OpenDKIM directory or type using idefault ." echo "" echo "" while [[ -z "${opendkim_dir}" ]]; do echononl " DKIM (base) directory [ \033[1m${DEFAULT_opendkim_dir}\033[m ]: " read opendkim_dir if [[ -z "$(trim ${opendkim_dir})" ]] ; then opendkim_dir=${DEFAULT_opendkim_dir} fi done signing_table_file="${opendkim_dir}/signing.table" key_table_file="${opendkim_dir}/key.table" key_base_dir=${opendkim_dir}/keys if $terminal ; then echo "" echo -e " \033[1m----------\033[m" echo " DKIM Domain......................: $dkim_domain" echo " DKIM Selector....................: $dkim_selector" if $update_dns ; then echo -e " Create/Update DKIM TXT record....: \033[32mYes\033[m" echo " Domain used for DKIM TXT record..: $update_zone" echo " Secret for the update key........: $key_secret" echo " Algorithm used for the TSIG key..: $key_algo" echo " Name of the TSIG key.............: $key_name" else echo -e " Create/Update DKIM TXT record....: \033[33mNo\033[m" fi echo "" if [[ -z "${dns_dkim_zone_master_server}" ]] ; then echo -e " DNS Master Server................: \033[33m- Updating DNS was not requested -\033[m" else echo " DNS Master Server................: $dns_dkim_zone_master_server" fi if [[ -z "$ttl" ]] || [[ "${ttl,,}" = "none" ]] ; then echo -e " TTL for the DKIM TXT Record......: \033[33m- Not set -\033[m" else echo " TTL for the DKIM TXT Record......: $ttl" fi echo "" echo " OpenDKIM's etc-directory.........: $opendkim_dir" echo " Key directory....................: ${key_base_dir}/${dkim_domain}" echo " Signing table file...............: $signing_table_file" echo " Key table file...................: $key_table_file" echo -e " \033[1m----------\033[m" echo "" fi # ============= # - Start Configuration # ============= if $terminal && ! $BATCH_MODE ; then echo echo -n " Type upper case 'YES' to start: " read OK if [[ "$OK" != "YES" ]] ; then fatal "Abort by user request - Answer was not 'YES'" fi echo "" else declare -i _count=0 declare -i _stop=${#dkim_domain}+2 echo "" echo "*${dkim_domain}*" while [[ $_count -lt $_stop ]] ; do echo -n "=" ((_count++)) done echo "" fi key_dir=${key_base_dir}/${dkim_domain} dkim_domain_shortname="${dkim_domain%.*}" declare -a generated_files_arr=() declare -a dns_dkim_zone_slave_server_arr=() _create_delegation=false _create_dkim_zone=false # - Some basic checks # - if $terminal ; then echo "" echo "" echo -e " \033[32mSome basic checks\033[m" echo "" fi echononl "Determine responsible zone for '${dkim_domain}'.." found=true zone=${dkim_domain} while [[ -z "$(dig +short $zone ns 2>/dev/null)" ]] ; do zone=${zone#*.} if [[ ! $zone =~ \. ]]; then found=false break fi done if $found ; then echo_ok info "Found responsible zone for '${dkim_domain}': \033[37m\033[1m${zone}\033[m" else echo_failed fatal "No responsible zone for '${dkim_domain}' found!" fi for _server in $(dig +short ${zone} NS) ; do # - Eliminate trailing '.' character(s) # - _server="${_server%"${_server##*[!\.]}"}" [[ "$_server" = "$dns_dkim_zone_master_server" ]] && continue dns_dkim_zone_slave_server_arr+=("$_server") done _wait=false if $update_dns && [[ "$dkim_domain" != "$update_zone" ]] ; then if [[ -z "$(dig +short ${update_zone}. NS)" ]] ; then warn "No Subdomain delegation for zone '$update_zone' found!" if ! $BATCH_MODE ; then echo "" echo -e "\033[32m--\033[m" echo "" echononl "Create Subdomain delegation for zone '$update_zone'? (yes/no) [yes]: " read _create_delegation if [[ -z "$(trim $_create_delegation)" ]] ; then _create_delegation=true elif [[ "${_create_delegation,,}" = "yes" ]] || [[ "${_create_delegation,,}" = "true" ]] ; then _create_delegation=true else _create_delegation=false fi if ! $_create_delegation ; then _tmp_string="; ----- Delegation DKIM Keys ${dkim_domain}" for _server in $(dig +short ${dkim_domain} NS) ; do # - Eliminate trailing '.' character(s) # - _server="${_server%"${_server##*[!\.]}"}" _tmp_string="$_tmp_string\n${update_zone}. IN NS ${_server}." done blank_line todo "Create a delegation for zone \033[1m${update_zone}.\033[m\n\n$_tmp_string" _wait=true echo "" echo -e " After adjusting your nameserver continue with this script" echo "" echo -en " \033[33mType to continue or +C to abort:\033[m " read OK echo fi else _create_delegation=true fi else _create_delegation=false fi fi if $_create_delegation ; then # - Generate Subdomain delegation for zone update_zone # - if $terminal ; then echo "" echo "" echo -e " \033[32mGenerate Subdomain delegation for zone \033[37m\033[1m${update_zone}\033[m" echo "" fi echononl "Determin DNS master of '${zone}'.." _dns_master="$(dig +short ${zone} SOA 2>/dev/null | awk '{print$1}' | sed 's/\.$//')" if [[ -z "$_dns_master" ]]; then echo_failed if $terminal ; then fatal "Determin DNS master of '${zone}' failed!" else echo -e " [ Fatal ] Found responsible zone for '${dkim_domain}' (${zone}), but" echo -e " cannot determin master dns server for '${zone}'!" clean_up 1 fi else echo_ok fi # - Check if Nameserver is accessable via ssh # - echononl "Check if Nameserver '$_dns_master' is accessable via ssh .." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_dns_master "ls" > /dev/null 2>&1 if [[ $? -gt 0 ]] ;then echo_failed fatal "Nameserver \"$_dns_master\" is not reachable vis ssh!" else echo_ok fi # - Check if Script '$set_new_serial_script' is accessable via ssh .." # - echononl "Check Script '$set_new_serial_script' .." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_dns_master "sudo $set_new_serial_script check" > /dev/null 2>&1 if [[ $? -gt 0 ]] ;then echo_failed fatal "Script '$set_new_serial_script' is NOT accessable via ssh!" else echo_ok fi # - Check if Script '$create_dkim_delegation_script' is accessable via ssh .." # - echononl "Check Script '$create_dkim_delegation_script'.." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_dns_master "sudo $create_dkim_delegation_script check" > /dev/null 2>&1 if [[ $? -gt 0 ]] ;then echo_failed fatal "Script '$create_dkim_delegation_script' is NOT accessable via ssh!" else echo_ok fi blank_line _delegation_created=false echononl "Create NS Record (delegation) for '$update_zone'.." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_dns_master "sudo $create_dkim_delegation_script $dkim_domain" > /dev/null 2>&1 ret_val=$? case $ret_val in 0) $terminal && echo_skipped if $terminal ; then info "DKIM subdomain delegation for \033[1m${update_zone}\033[m already exists." else echo "" echo " [ Info ] DKIM subdomain delegation for ${update_zone} already exists." fi ;; 1) $terminal && echo_ok if $terminal ; then info "DKIM subdomain delegation for \033[1m${update_zone}\033[m added." else echo "" echo " [ Info ] DKIM subdomain delegation for ${update_zone} successfully added." fi _delegation_created=true ;; 11) $terminal && echo_failed fatal "No zonefile for domain '$dkim_domain' found!" ;; 15) $terminal && echo_failed fatal "Domain '$dkim_domain' not supported!" ;; 16) $terminal && echo_failed fatal "Determin nameservers for domain '$dkim_domain' failed!" ;; 21) $terminal && echo_failed fatal "Adding NS Record for subdomain delegation failed!" ;; 99) $terminal && echo_failed fatal "Fatal error!" ;; *) $terminal && echo_failed fatal "Unknown exit code from remote script \"$create_dkim_delegation_script\"!" ;; esac echononl "Increase serial an reload zone ($dkim_domain).." echo_wait if $_delegation_created ; then ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_dns_master "sudo $set_new_serial_script $dkim_domain" > /dev/null 2>&1 ret_val=$? case $ret_val in 0) $terminal && echo_ok if $terminal ; then info "Serial is replaced and Zone is reloaded (\033[1m${update_zone}\033[m)." else echo "" echo " [ Info ] Serial is replaced and Zone is reloaded (${update_zone})." fi ;; 10) $terminal && echo_failed fatal "Invalid Hostname/Domain given!" ;; 11) $terminal && echo_failed fatal "No zonefile found!" ;; 12) $terminal && echo_failed fatal "Determin new Serial failed!" ;; 13) $terminal && echo_failed fatal "Increasing Serial failed!" ;; 14) $terminal && echo_failed fatal "Reloading Zone failed!" ;; 15) $terminal && echo_failed fatal "Hostname/Domain not supported!" ;; 99) $terminal && echo_failed fatal "Fatal error!" ;; *) $terminal && echo_failed fatal "Unknown exit code from remote script \"$create_dkim_delegation_script\"!" ;; esac else echo_skipped fi fi # if $_create_delegation # - Check if zonefile creation is needed # - if $update_dns ; then for _server in ${dns_dkim_zone_slave_server_arr[@]} ; do if [[ -z "$(dig +short @$_server ${update_zone}. NS)" ]] ; then _create_dkim_zone=true break fi done fi if ! $_create_dkim_zone && $update_dns \ && [[ -z "$(dig +short @$dns_dkim_zone_master_server ${update_zone}. NS)" ]] ; then _create_dkim_zone=true fi if $_create_dkim_zone ; then blank_line # - Check if Script '$add_dkim_zone_master_script' is accessable via ssh .." # - echononl "Check Script '$add_dkim_zone_master_script'.." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$dns_dkim_zone_master_server "sudo $add_dkim_zone_master_script check" > /dev/null 2>&1 if [[ $? -gt 0 ]] ;then echo_failed echo -e "\n command was: ssh -q -p $dns_ssh_port \\ -o BatchMode=yes \\ -o StrictHostKeyChecking=no \\ -i $dns_ssh_key \\ $dns_ssh_user@$dns_dkim_zone_master_server \"sudo $add_dkim_zone_master_script check\"\n" fatal "Script '$add_dkim_zone_master_script' is NOT accessable via ssh at ${dns_dkim_zone_master_server}!" else echo_ok fi # - Check if Script '$add_dkim_zone_slave_script' is accessable on slave servers # - for _server in ${dns_dkim_zone_slave_server_arr[@]} ; do echononl "Check Script '$add_dkim_zone_slave_script' (${_server}).." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_server "sudo $add_dkim_zone_slave_script check" > /dev/null 2>&1 if [[ $? -gt 0 ]] ;then echo_failed fatal "Script '$add_dkim_zone_master_script' is NOT accessable via ssh!" else echo_ok fi done blank_line # - Create zone zone $update_zone at dns master # - if $terminal ; then echo "" echo "" echo -e " \033[32mCreate zone \033[37m\033[1m${update_zone}\033[m at dns master." echo "" fi echononl "Create zone '${update_zone}' at dns master '${dns_dkim_zone_master_server}'.." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$dns_dkim_zone_master_server "sudo $add_dkim_zone_master_script $dkim_domain" > /dev/null 2>&1 ret_val=$? case $ret_val in 0) $terminal && echo_ok if $terminal ; then info "Master zone \033[1m${update_zone}\033[m and zone file created." else echo "" echo " [ Info ] Master zone '${update_zone}'and zone file created." fi ;; 1) $terminal && echo_ok if $terminal ; then info "Master zone \033[1m${update_zone}\033[m already exists, zone file created." else echo "" echo " [ Info ] Master zone '${update_zone}' already exists, zone file created." fi ;; 2) $terminal && echo_skipped if $terminal ; then info "Master zone \033[1m${update_zone}\033[m and zone file already exists." else echo "" echo " [ Info ] Master zone '${update_zone}' and zone file already exists." fi ;; 10) $terminal && echo_failed fatal "Missing option for zone definition!" ;; 15) $terminal && echo_failed fatal "DKIM domain '$dkim_domain' not supported by this nameserver!" ;; 16) $terminal && echo_failed fatal "No responsible zone for '$dkim_domain' found!" ;; 17) $terminal && echo_failed fatal "No responsible nameservers found!" ;; 20) $terminal && echo_failed fatal "Adding Zone definition for '${update_zone}' failed!" ;; 21) $terminal && echo_failed fatal "Adding Zonefile for '${update_zone}' failed!" ;; 22) $terminal && echo_failed fatal "Change owner for newly created zonefile failed!" ;; 23) $terminal && echo_failed fatal "Reload bind configuration failed!" ;; 99) $terminal && echo_failed fatal "Fatal error!" ;; *) $terminal && echo_failed fatal "Unknown exit code from remote script \"$create_dkim_delegation_script\"!" ;; esac # - Create zone $update_zone ar dns slave(s) # - if $terminal ; then echo "" echo "" echo -e " \033[32mCreate zone \033[37m\033[1m${update_zone}\033[m at dns slave(s)." echo "" fi for _server in ${dns_dkim_zone_slave_server_arr[@]} ; do echononl "Create zone '${update_zone}' at dns slave '${_server}'.." echo_wait ssh -q -p $dns_ssh_port \ -o BatchMode=yes \ -o StrictHostKeyChecking=no \ -i $dns_ssh_key \ $dns_ssh_user@$_server "sudo $add_dkim_zone_slave_script $dkim_domain" > /dev/null 2>&1 ret_val=$? case $ret_val in 0) $terminal && echo_ok if $terminal ; then info "Slave zone \033[1m${update_zone}\033[m at '${_server}' configured." else echo "" echo " [ Info ] Slave zone '${update_zone}' at '${_server}' configured." fi echononl "Sleeping 5 seconds.." echo_wait echo_ok sleep 5 ;; 1) $terminal && echo_skipped if $terminal ; then info "Slave zone \033[1m${update_zone}\033[m already exists at '${_server}'." else echo "" echo " [ Info ] Slave zone '${update_zone}' already exists '${_server}'." fi ;; 15) $terminal && echo_failed fatal "Variable for DNS Master Server (DKIM_DNS_MASTER) not present!" ;; 21) $terminal && echo_failed fatal "Adding Slave Zone '${update_zone}' at '${_server}' failed!" ;; 23) $terminal && echo_failed fatal "Reload bind configuration failed!" ;; 99) $terminal && echo_failed fatal "Fatal error!" ;; *) $terminal && echo_failed fatal "Unknown exit code from remote script \"$create_dkim_delegation_script\"!" ;; esac done fi # - Generate private/public keys # - if $terminal ; then echo "" echo "" echo -e " \033[32mGenerate Generate private/public keys\033[m" echo "" fi # - Create Key directory for the given domain # - echononl " Create Key Directory '${key_dir}'" if [[ ! -d "$key_dir" ]]; then mkdir -p $key_dir 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi # - Generate private key # - # - This will give you two files, one containing the key # - and the other containing the TXT record you’ll need to # - set up DNS. # - # - Note: # - The generated TXT record cannot be used directly for # - 'bind' nameservers (TXT recors are restricted to 255 characters) # - echononl " Generate private key for domain '$dkim_domain'.." opendkim-genkey -D $key_dir -d $dkim_domain -b 2048 -r -s $dkim_selector > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok generated_files_arr+=("${key_dir}/${dkim_selector}.private") generated_files_arr+=("${key_dir}/${dkim_selector}.txt") else echo_failed error "$(cat $log_file)" fi # - Set up ownership an permissions # - echononl " Set ownership on '${key_dir}/${dkim_selector}.private'" if id -u "opendkim" >/dev/null 2>&1; then chown opendkim ${key_dir}/${dkim_selector}.private > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl " Set permissions on '${key_dir}/${dkim_selector}.private'" chmod 600 ${key_dir}/${dkim_selector}.private > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi echononl " Print out public key for domain '$dkim_domain'.." openssl rsa -in ${key_dir}/${dkim_selector}.private -pubout -out ${key_dir}/${dkim_selector}.public > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok generated_files_arr+=("${key_dir}/${dkim_selector}.public ") else echo_failed error "$(cat $log_file)" fi echononl " Print out public key as one line.." : > ${key_dir}/${dkim_selector}.public.one-line while IFS='' read -r _line || [[ -n $_line ]] ; do if echo "$_line" | grep -i -q -E "^---" 2> /dev/null ; then continue fi echo -n "${_line}" >> ${key_dir}/${dkim_selector}.public.one-line done < "${key_dir}/${dkim_selector}.public" echo_ok generated_files_arr+=("${key_dir}/${dkim_selector}.public.one-line") # - Generate TXT record for use in bind9 # - if $terminal ; then echo "" echo -e " \033[32mGenerate TXT record for use in bind9\033[m" echo "" fi # - Write file with bind9 dekim TXT record # - if $terminal ; then echo " Write bind9 dekim TXT record to file" fi echononl " '${key_dir}/${dkim_selector}.bind9'" echo "; ----- DKIM key $dkim_selector for ${dkim_domain}" > ${key_dir}/${dkim_selector}.bind9 echo -n "${dkim_selector}._domainkey.${dkim_domain}. $ttl IN TXT ( \"v=DKIM1; k=rsa; s=email; p=\"" >> ${key_dir}/${dkim_selector}.bind9 while IFS='' read -r _line || [[ -n $_line ]] ; do if echo "$_line" | grep -i -q -E "^---" 2> /dev/null ; then continue fi echo "" >> ${key_dir}/${dkim_selector}.bind9 echo -n " \"$_line\"" >> ${key_dir}/${dkim_selector}.bind9 done < "${key_dir}/${dkim_selector}.public" echo " )" >> ${key_dir}/${dkim_selector}.bind9 echo_ok generated_files_arr+=("${key_dir}/${dkim_selector}.bind9") # - Write TXT record as string for 'nsupdate' # - if $terminal ; then echo " Write TXT record as string for 'nsupdate' to file" fi echononl " '${key_dir}/${dkim_selector}.nsupdate'" echo -n "\"v=DKIM1; k=rsa; s=email; p=\"" >> ${key_dir}/${dkim_selector}.nsupdate while IFS='' read -r _line || [[ -n $_line ]] ; do if echo "$_line" | grep -i -q -E "^---" 2> /dev/null ; then continue fi echo -n " \"$_line\"" >> ${key_dir}/${dkim_selector}.nsupdate done < "${key_dir}/${dkim_selector}.public" echo_ok generated_files_arr+=("${key_dir}/${dkim_selector}.nsupdate") if ! $update_dns ; then [[ -z "${dns_dkim_zone_master_server}" ]] && dns_dkim_zone_master_server=${DEFAULT_dns_dkim_zone_master_server} blank_line todo "Now you have to add the TXT Record to your zone file.\n\n Copy/Paste the following data:\n\n$(cat ${key_dir}/${dkim_selector}.bind9)" echo "" echo -e "\n\n If you can use 'nsupdate', then issue the following command:\n\n" cat < $log_file 2>&1 server $dns_dkim_zone_master_server zone $update_zone key ${key_algo}:$key_name $key_secret update delete ${dkim_selector}.${update_zone}. update add ${dkim_selector}.${update_zone}. $ttl IN TXT $(cat ${key_dir}/${dkim_selector}.nsupdate) send EOF if [[ $? -eq 0 ]] ; then echo_ok cat < ${key_dir}/${dkim_selector}.nsupdate.command cat </dev/null ; then perl -i -n -p -e "s/^\*@$dkim_domain\s.*/*@$dkim_domain\t$dkim_domain_shortname/" $signing_table_file 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo -e "*@$dkim_domain\t$dkim_domain_shortname" >> $signing_table_file 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi # - Configure/Adjust the key table # - echononl " Configure/Adjust key table" if grep -q -E "^\s*$dkim_domain_shortname\s" $key_table_file 2>/dev/null ; then perl -i -n -p -e "s#^\s*$dkim_domain_shortname\s.*#${dkim_domain_shortname}\t\t${dkim_domain}:${dkim_selector}:${key_dir}/${dkim_selector}.private#" $key_table_file 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo -e "${dkim_domain_shortname}\t\t${dkim_domain}:${dkim_selector}:${key_dir}/${dkim_selector}.private" >> $key_table_file 2> $log_file if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi echononl " Adjust file ${key_dir}/generated_keys.selectors" echo "${dkim_selector}" >> ${key_dir}/generated_keys.selectors echo_done # - Restart OpenDKIM # - if $terminal ; then echo "" echo -e " \033[32m-----\033[m" echo "" fi echononl " Restart OpenDKIM.." echo_wait if $systemd_supported ; then systemctl reload opendkim > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else /etc/init.d/opendkim reload > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi fi if [[ -n "$log_file" ]]; then rm -f "$log_file" fi if $terminal ; then info "DKIM Key for domain \033[1m${dkim_domain}\033[m created/updated." if $update_dns ; then info "DKIM TXT Record with selector \033[1m$dkim_selector\033[m created." fi else echo "" echo " [ Info ] DKIM Key for domain ${dkim_domain} created/updated." echo "" echo " [ Info ] DKIM TXT Record with selector $dkim_selector created." echo "" fi blank_line clean_up 0 #txt_record="$(cat ${key_dir}/${dkim_selector}.txt | awk -F'"' '{print $2}' | tr -d '\n')" #txt_record_1=${txt_record:0:255} #txt_record_2=${txt_record:255} #new_txt_record="\"$txt_record_1\"\"$txt_record_2\""