#!/usr/bin/env bash # =============================================================== # - Don't make definitions here! Do this at the configuration file # ================================================================ script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" # ---------- # - # - Script checks, whether the certificate/key for dovecot services are up to date. If # - newer versions than the installed one found, script changes the installed # - key/cert to the latest version. # - # ---------- LOCK_DIR="/tmp/${script_name%%.*}.LOCK" log_file="${LOCK_DIR}/${script_name%%.*}.log" restart_service=false # ------------- # --- Some functions # ------------- clean_up() { # Perform program exit housekeeping rm -rf "$LOCK_DIR" 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 ]: $*" echo "" echo -e " \033[31m\033[1mScript was interupted\033[m!" else echo " [ Fatal ]: $*" echo "" echo " Script was terminated...." fi echo "" clean_up 1 } error() { echo "" if $terminal ; then echo -e " [ \033[31m\033[1mError\033[m ]: $*" else echo " [ Error ]: $*" fi echo "" } warn() { echo "" if $terminal ; then echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" else echo " [ Warning ]: $*" fi echo "" } info() { if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" echo "" fi } echo_failed(){ if $terminal ; then echo -e "\033[75G[ \033[1;31mfailed\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[75G[ \033[90mskipped\033[m ]" fi } echo_done() { if $terminal ; then echo -e "\033[75G[ \033[32mdone\033[m ]" fi } echo_ok() { if $terminal ; then echo -e "\033[75G[ \033[32mok\033[m ]" fi } blank_line() { if $terminal ; then echo "" fi } detect_os_1 () { if $(which lsb_release > /dev/null 2>&1) ; then os_dist="$(lsb_release -i | awk '{print tolower($3)}')" os_version="$(lsb_release -r | awk '{print tolower($2)}')" os_codename="$(lsb_release -c | awk '{print tolower($2)}')" if [[ "$os_dist" = "debian" ]]; then if $(echo "$os_version" | grep -q '\.') ; then os_version=$(echo "$os_version" | cut --delimiter='.' -f1) fi fi elif [[ -e "/etc/os-release" ]]; then . /etc/os-release os_dist=$ID os_version=${VERSION_ID} fi # remove whitespace from os_dist and os_version os_dist="${os_dist// /}" os_version="${os_version// /}" } # ------------- # - Job is already running? # ------------- # - If job already runs, stop execution.. # - if mkdir "$LOCK_DIR" 2> /dev/null ; then # - Remove lockdir when the script finishes, or when it receives a signal # - trap clean_up SIGHUP SIGINT SIGTERM else msg="A previos instance of script \"`basename $0`\" seems already be running." echo "" if $terminal ; then echo -e "[ \033[31m\033[1mFatal\033[m ]: $msg" echo "" echo -e " \033[31m\033[1mScript was interupted\033[m!" else echo " [ Fatal ]: $msg" echo "" echo " Script was interupted!" fi echo exit 1 fi # ------------- # --- Some checks # ------------- # - Running in a terminal? # - if [[ -t 1 ]] ; then terminal=true else terminal=false fi # - Detect OS - Set variable # - os_dist # - os_version # - os_codename # - detect_os_1 # - Read Configurations from $conf_file # - if [[ ! -f "$conf_file" ]]; then fatal " Configuration file '$(basename ${conf_file})' not found!" else source $conf_file fi [[ -z "$service_domain" ]] && fatal " Parameter 'service_domain' not set but is reqired!" [[ -z "$cert_installed" ]] && cert_installed="/etc/dovecot/ssl/mailserver.crt" [[ -z "$cert_newest" ]] && cert_newest="/var/lib/dehydrated/certs/${service_domain}/fullchain.pem" [[ -z "$key_installed" ]] && key_installed="/etc/dovecot/ssl/mailserver.key" [[ -z "$key_newest" ]] && key_newest="/var/lib/dehydrated/certs/${service_domain}/privkey.pem" [[ -z "$service_name" ]] && service_name="Dovecot" [[ -z "$check_string_ps" ]] && check_string_ps="[[:digit:]]\ /usr/local/dovecot-[[:digit:]]{1,2}\.[[:digit:]]{1,2}\.[[:digit:]]{1,2}(\.[[:digit:]]{1,2})?/sbin/dovecot" # - Systemd supported ? # - systemd_supported=false systemd=$(which systemd) systemctl=$(which systemctl) if [[ -n "$systemd" ]] && [[ -n "$systemctl" ]] ; then systemd_supported=true fi SYSTEMD_SERVICE= SYSV_INIT_SCRIPT= if $systemd_supported ; then if systemctl -t service list-unit-files \ | grep -e "^${service_name,,}d" \ | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}d" | awk '{print$1}' | head -1)" elif systemctl -t service list-unit-files \ | grep -e "^${service_name,,}-server" \ | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}-server" | awk '{print$1}' | head -1)" elif systemctl -t service list-unit-files \ | grep -e "^${service_name,,}" \ | grep -q -E "(enabled|disabled|generated)" 2> /devnull ; then SYSTEMD_SERVICE="$(systemctl -t service list-unit-files | grep -e "^${service_name,,}" | awk '{print$1}' | head -1)" fi fi if [[ -z "$SYSTEMD_SERVICE" ]]; then if [[ -x "/etc/init.d/${service_name,,}" ]]; then SYSV_INIT_SCRIPT="/etc/init.d/${service_name,,}" elif [[ -x "/etc/init.d/${service_name,,}d" ]]; then SYSV_INIT_SCRIPT="/etc/init.d/${service_name,,}d" elif [[ -x "/etc/init.d/${service_name,,}-server" ]]; then SYSV_INIT_SCRIPT="/etc/init.d/${service_name,,}-server" fi fi if [[ -z "$SYSTEMD_SERVICE" ]] && [[ -z "$SYSV_INIT_SCRIPT" ]] ; then fatal "Neither an init-script nor a service file for $service_name found!" fi # ------------- # - Don't run script, if any give path for cert/key does not exists # ------------- if [[ ! -f "$cert_newest" ]] ; then fatal "Newest Certificate '$cert_newest' for service '${service_name}' not found!" elif [[ ! -f "$key_newest" ]] ; then fatal "Newest Key '$key_newest' for service '${service_name}' not found!" fi blank_line echononl " Create Cert/Key Directory '$(dirname "$cert_installed")'.." if [[ ! -d "$(dirname "$cert_installed")" ]] ; then mkdir -p "$(dirname "$cert_installed")" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done echononl " Change Permissions for Cert/Key Directory '$(dirname "$cert_installed")'.." chmod 755 "$(dirname "$cert_installed")" > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat "$log_file")" fi else echo_failed error "$(cat "$log_file")" fi else echo_skipped fi dh_pem_file="$(dirname "$cert_installed")/dh_4096.pem" echononl " Create SSL DH parameters '$dh_pem_file'.." if [[ -s "$dh_pem_file" ]]; then echo_skipped else if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then openssl dhparam -out "$dh_pem_file" 4096 > $log_file 2>&1 else openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > $log_file 2>&1 fi if [[ $? -eq 0 ]] ; then echo_done else echo_failed error "$(cat "$log_file")" fi fi # ------------- # - Check if key/cert are up to date, change them if needed. # ------------- if ! diff "$(realpath "$cert_installed")" "$(realpath "$cert_newest")" > /dev/null 2>&1 ; then _failed=false warn "Certificate for service '${service_name}' is outdated! Try to update certificate and key.." echononl " Update certificat for for service '${service_name}' .." > $log_file if [[ -h "$cert_installed" ]] ; then rm "$(realpath "$cert_installed")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi rm "$cert_installed" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi fi if [[ -f "$cert_installed" ]] ; then rm "$cert_installed" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi fi cp -a "$(realpath "$cert_newest")" "$(dirname "$cert_installed")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi chmod 644 "$(dirname "$cert_installed")/$(basename "$(realpath "$cert_newest")")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi ln -s "$(basename "$(realpath "$cert_newest")")" "$cert_installed" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed error "$(cat "$log_file")" else echo_done fi if ! $_failed ; then _failed=false echononl " Update key for service '${service_name}' .." if [[ -h "$key_installed" ]] ; then rm "$(realpath "$key_installed")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi rm "$key_installed" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi fi if [[ -f "key_installed" ]] ; then rm "$key_installed" > $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi fi cp -a "$(realpath "$key_newest")" "$(dirname "$key_installed")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi chmod 644 "$(dirname "$key_installed")/$(basename "$(realpath "$key_newest")")" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi ln -s "$(basename "$(realpath "$key_newest")")" "$key_installed" >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed error "$(cat "$log_file")" else echo_done restart_service=true fi fi if ! $_failed ; then if $terminal ; then info "Certificate/Key for service '${service_name}' is now up to date" else echo "" echo " [ Info ]: Certificate/Key for service '${service_name}' is now up to date" echo "" fi else error "Updating Certificate/Key for service '${service_name}' failed!" fi else up_to_date=true info "Certificate for service '${service_name}' is up to date!" fi if $restart_service ; then _failed=false echononl "Going to restart Service '${service_name}' .." if [[ -n "$SYSTEMD_SERVICE" ]] ; then $systemctl daemon-reload > $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi sleep 2 $systemctl stop $SYSTEMD_SERVICE >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi sleep 10 $systemctl start $SYSTEMD_SERVICE >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed error "$(cat "$log_file")" else echo_done fi else $SYSV_INIT_SCRIPT stop > $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi sleep 10 $SYSV_INIT_SCRIPT start >> $log_file 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ; then echo_failed error "$(cat "$log_file")" else echo_done fi fi if ! $_failed ; then declare -i counter=0 PID=$(ps -e f | grep -E "${check_string_ps}"| grep -v grep | awk '{print$1}') while [[ "X${PID}" = "X" ]]; do if [[ $counter -gt 10 ]]; then _failed=true break else ((counter++)) fi sleep 1 PID=$(ps -e f | grep -E "${check_string_ps}"| grep -v grep | awk '{print$1}') done fi if $_failed ; then error "Restarting service '${service_name}' failed!" else if $terminal ; then info "'${service_name}' Service was restarted. the new pid is '$PID'." else echo "" echo " '${service_name}' Service was restarted. the new pid is '$PID'." echo "" fi fi fi clean_up 0