postfix/create_opendkim_key.sh

1380 lines
37 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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_key_algo="hmac-sha256"
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"
opendkim_dir="/etc/opendkim"
signing_table_file="${opendkim_dir}/signing.table"
key_table_file="${opendkim_dir}/key.table"
key_base_dir=${opendkim_dir}/keys
# -------------
# --- Functions
# -------------
usage() {
[[ -n "$1" ]] && error "$1"
[[ -z "${dkim_domain}" ]] && dkim_domain='<dkim-domain-name>'
[[ -z "${update_zone}" ]] && update_zone='<update-zone>'
[[ $terminal ]] && echo -e "
\033[1mUsage:\033[m
$(basename $0) [-a <key algorithm>] [-b] [-d <dkim-domain-name> ] [-h] [-n] [-s <secret>]
[-z <update-zone>
\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 <key algorithm>
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 <dkim-domain-name>
The domain for which DKIM support will be configured. If not give, the domain will be
requested interactivly.
-D <Domain Server>
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 <secret>
Give the secret for the key used by nsupdate to create/update the DNS TXT record.
-t <ttl>
Specify the TTL value for the DKIM TXT record.
-z <update-zone>
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() {
# 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
}
# - 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 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<return>\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
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 <RETURN> 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!"
fi
if $update_dns && [[ -z "$key_algo" ]]; then
key_algo="$DEFAULT_key_algo"
fi
if $update_dns && [[ -z "$key_name" ]]; then
key_name="$update_zone"
fi
if $update_dns && [[ -z "$ttl" ]]; then
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
# - We use actual timestamp as DEKIM Selector
# -
time_stamp=$(date +%s)
if $terminal ; then
echo ""
echo -e " \033[1m----------\033[m"
echo " DKIM Domain......................: $dkim_domain"
echo " DKIM Selector....................: $time_stamp"
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 ""
echo " DNS Master Server................: $dns_dkim_zone_master_server"
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 <return> to continue or <CTRL>+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
fatal "Script '$add_dkim_zone_master_script' is NOT accessable via ssh!"
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 $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 youll 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 $time_stamp > $log_file 2>&1
if [[ $? -eq 0 ]] ; then
echo_ok
generated_files_arr+=("${key_dir}/${time_stamp}.private")
generated_files_arr+=("${key_dir}/${time_stamp}.txt")
else
echo_failed
error "$(cat $log_file)"
fi
# - Set up ownership an permissions
# -
echononl " Set ownership on '${key_dir}/${time_stamp}.private'"
chown opendkim ${key_dir}/${time_stamp}.private > $log_file 2>&1
if [[ $? -eq 0 ]] ; then
echo_ok
else
echo_failed
error "$(cat $log_file)"
fi
echononl " Set permissions on '${key_dir}/${time_stamp}.private'"
chmod 600 ${key_dir}/${time_stamp}.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}/${time_stamp}.private -pubout -out ${key_dir}/${time_stamp}.public > $log_file 2>&1
if [[ $? -eq 0 ]] ; then
echo_ok
generated_files_arr+=("${key_dir}/${time_stamp}.public ")
else
echo_failed
error "$(cat $log_file)"
fi
# - 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}/${time_stamp}.bind9'"
echo "; ----- DKIM key $time_stamp for ${dkim_domain}" > ${key_dir}/${time_stamp}.bind9
echo -n "${time_stamp}._domainkey.${dkim_domain}. $ttl IN TXT ( \"v=DKIM1; k=rsa; s=email; p=\"" >> ${key_dir}/${time_stamp}.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}/${time_stamp}.bind9
echo -n " \"$_line\"" >> ${key_dir}/${time_stamp}.bind9
done < "${key_dir}/${time_stamp}.public"
echo " )" >> ${key_dir}/${time_stamp}.bind9
echo_ok
generated_files_arr+=("${key_dir}/${time_stamp}.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}/${time_stamp}.nsupdate'"
echo -n "\"v=DKIM1; k=rsa; s=email; p=\"" >> ${key_dir}/${time_stamp}.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}/${time_stamp}.nsupdate
done < "${key_dir}/${time_stamp}.public"
echo_ok
generated_files_arr+=("${key_dir}/${time_stamp}.nsupdate")
if ! $update_dns ; then
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}/${time_stamp}.bind9)"
echo ""
echo -e "After adjusting your nameserver continue with this script"
echo ""
echo -n "Type <return> to continue: "
read OK
echo
fi
if $update_dns ; then
# - Update DNS Server
# -
if $terminal ; then
echo ""
echo -e " \033[32mUpdate DNS Server \033[37m\033[1m${dns_dkim_zone_master_server}\033[m"
echo ""
fi
echononl " Update zone '$update_zone' .."
cat <<EOF | nsupdate -v -L3 > $log_file 2>&1
server $dns_dkim_zone_master_server
zone $update_zone
key ${key_algo}:$key_name $key_secret
update delete ${time_stamp}.${update_zone}.
update add ${time_stamp}.${update_zone}. $ttl IN TXT $(cat ${key_dir}/${time_stamp}.nsupdate)
send
EOF
if [[ $? -eq 0 ]] ; then
echo_ok
cat <<END
cat <<EOF | nsupdate -v -L3
server $dns_dkim_zone_master_server
zone $update_zone
key ${key_algo}:$key_name $key_secret
update delete ${time_stamp}.${update_zone}.
update add ${time_stamp}.${update_zone}. $ttl IN TXT $(cat ${key_dir}/${time_stamp}.nsupdate)
send
EOF
END
else
echo_failed
cat <<END
cat <<EOF | nsupdate -v -L3
server $dns_dkim_zone_master_server
zone $update_zone
key ${key_algo}:$key_name $key_secret
update delete ${time_stamp}.${update_zone}.
update add ${time_stamp}.${update_zone}. $ttl IN TXT $(cat ${key_dir}/${time_stamp}.nsupdate)
send
EOF
END
error "$(cat $log_file)"
echononl "continue anyway [yes/no]: "
read OK
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
echononl "Wrong entry! - repeat [yes/no]: "
read OK
done
if [[ $OK = "no" ]] ; then
error "Interrupted by user."
delete_generated_files
clean_up 1
fi
fi
fi
# - Configure OpenDKIM
# -
if $terminal ; then
echo ""
echo -e " \033[32mConfigure OpenDKIM for domain \033[37m\033[1m$dkim_domain\033[m"
echo ""
fi
# - Configure/Adjust the signing table
# -
echononl " Configure/Adjust signing table.."
if grep -q -E "^\s*\*@$dkim_domain\s" $signing_table_file 2>/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}:${time_stamp}:${key_dir}/${time_stamp}.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}:${time_stamp}:${key_dir}/${time_stamp}.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 "${time_stamp}" >> ${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$time_stamp\033[m created."
fi
else
echo ""
echo " [ Info ] DKIM Key for domain ${dkim_domain} created/updated."
echo ""
echo " [ Info ] DKIM TXT Record with selector $time_stamp created."
echo ""
fi
blank_line
clean_up 0
#txt_record="$(cat ${key_dir}/${time_stamp}.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\""