#!/usr/bin/env bash script_name="$(basename $(realpath $0))" working_dir="$(dirname $(realpath $0))" conf_file="${working_dir}/conf/${script_name%%.*}.conf" log_file="$(mktemp)" random_prefix="$(head -c 300 /dev/urandom | tr -cd 'a-zA-Z0-9' | head -c 8)" backup_date=$(date +%Y-%m-%d-%H%M) # ============= # --- Some Variables # ============= NEED_APACHE_INFO=false NEED_INTERNAL_NAME_SERVER=false DEFAULT_HTTP_USER="www-data" DEFAULT_HTTP_GROUP="www-data" declare -a site_names_arr declare -a omitted_site_names_arr declare -a sites_external_ns_servers declare -a internal_ns_server_arr # ============= # --- Some Functions # ============= clean_up() { # Perform program exit housekeeping rm -f $log_file rm -rf /tmp/*.${random_prefix} 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 "\033[4G[ \033[5m\033[1m....\033[m ]\033[13G$*\\c" 1>&2 else echo -e -n "\033[4G[ \033[5m\033[1m....\033[m ]\033[13G$*" 1>&2 fi rm /tmp/shprompt$$ fi } echoprompt(){ if $terminal ; then echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo -e -n "\033[4G$*\\c" 1>&2 else echo -e -n "\033[4G$*" 1>&2 fi rm /tmp/shprompt$$ fi } echo_done() { if $terminal ; then echo -e "\033[4G[ \033[1;32mdone\033[m ]" fi } echo_ok() { if $terminal ; then echo -e "\033[4G[ \033[1;32mok\033[m ]" fi } echo_ignore() { if $terminal ; then echo -e "\033[4G[ \033[1;33mignore\033[m ]" fi } echo_warning() { if $terminal ; then echo -e "\033[4G[ \033[1;33m\033[1mwarn\033[m ]" fi } echo_failed(){ if $terminal ; then echo -e "\033[4G[ \033[1;31mfail\033[m ]" fi } echo_skipped() { if $terminal ; then echo -e "\033[4G[ \033[1;37mskip\033[m ]" fi } echo_wait(){ if $terminal ; then echo -en "\033[4G[ \033[5m\033[1m...\033[m ]" fi } fatal (){ blank_line if $terminal ; then echo "" echo -e "\033[1m---\033[m" echo "" echo -e "[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m" echo "" echo -e "\033[31m\033[1m Script will be interrupted..\033[m\033[m" else echo "" echo "---" echo "" echo "fatal: $*" echo "Script will be interrupted.." fi clean_up 1 } error(){ blank_line if $terminal ; then echo -e " [ \033[31m\033[1mFehler\033[m ]: $*" else echo "" echo "[ Error ]: $*" echo "" fi blank_line } warn (){ if $terminal ; then echo "" echo -e " [ \033[33m\033[1mWarning\033[m ]: $*" echo "" fi } info (){ if $terminal ; then echo "" echo -e " [ \033[32m\033[1mInfo\033[m ]: $*" echo "" fi } ## - Check if a given array (parameter 2) contains a given string (parameter 1) ## - containsElement () { local e for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done return 1 } trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } blank_line() { if $terminal ; then echo "" fi } ## - quicksorts positional arguments ## - return is in array qsort_ret qsort() { local pivot i smaller=() larger=() qsort_ret=() (($#==0)) && return 0 pivot=$1 shift for i; do if [[ $i < $pivot ]]; then smaller+=( "$i" ) else larger+=( "$i" ) fi done qsort "${smaller[@]}" smaller=( "${qsort_ret[@]}" ) qsort "${larger[@]}" larger=( "${qsort_ret[@]}" ) qsort_ret=( "${smaller[@]}" "$pivot" "${larger[@]}" ) } # ============= # --- 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 terminal=true else terminal=false 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" echo "" else echo "" echo "----------" echo "Running script '$script_name'.." echo "----------" echo "" fi # ---------- # Read Configurations from $conf_file # ---------- if [[ -f "$conf_file" ]]; then source "$conf_file" else warn "No configuration file '$conf_file' present.\n Loading default values.." fi [[ -z "$INTERNAL_NS_SERVER" ]] && NEED_INTERNAL_NAME_SERVER=true if [[ -n "$OMITTED_SITE_NAMES" ]] ; then for _site_name in $OMITTED_SITE_NAMES ; do omitted_site_names_arr+=("$_site_name") done fi echononl "Determin httpd binary .." _httpd_binary="$(which httpd)" if [[ -z "$_httpd_binary" ]] ; then _httpd_binary="$(which apache2)" if [[ -n "$_httpd_binary" ]] ; then [[ -f "/etc/apache2/envvars" ]] && source "/etc/apache2/envvars" fi fi if [[ -z "$_httpd_binary" ]]; then _httpd_binary="$(ps -axu | grep httpd | grep -e "^root" | grep -v grep | awk '{print$11}')" if [[ -z "$_httpd_binary" ]]; then if [[ -x "/usr/local/apache2/bin/httpd" ]]; then _httpd_binary="/usr/local/apache2/bin/httpd" echo_done else echo_failed fatal "Apache2 installation not found!" fi else echo_done fi else echo_done fi HTTPD_COMMAND="$_httpd_binary" echononl "Determin websevers user/group.." HTTP_USER="$($_httpd_binary -t -D DUMP_RUN_CFG | grep -i -e "^User" | awk '{print$2}' | cut -d"=" -f2 | tr -d '"')" if [[ $? -gt 0 ]]; then echo_failed NEED_APACHE_INFO=true else HTTP_GROUP="$($_httpd_binary -t -D DUMP_RUN_CFG | grep -i -e "^Group" | awk '{print$2}' | cut -d"=" -f2 | tr -d '"')" if [[ $? -gt 0 ]]; then echo_failed NEED_APACHE_INFO=true else if [ -z "$HTTP_USER" -o -z "$HTTP_GROUP" ]; then echo_failed NEED_APACHE_INFO=true else echo_done fi fi fi echononl "Determin Apache2 version number.." APACHE_VERSION="$(trim $($HTTPD_COMMAND -v | head -1 | cut -d ":" -f2))" if [[ $? -gt 0 ]]; then echo_failed else echo_done fi echononl "Determin ServerRoot Directory.." APACHE_SERVER_ROOT="$($_httpd_binary -t -D DUMP_RUN_CFG | grep ServerRoot | awk '{print$2}' | tr -d '"')" if [[ $? -gt 0 ]]; then echo_failed NEED_APACHE_INFO=true else if [[ -z "$APACHE_SERVER_ROOT" ]]; then if [[ -d "$(realpath "/usr/local/apache2/bin")" ]] \ && [[ "$(realpath "$(dirname "$_httpd_binary")")" = $(realpath /usr/local/apache2/bin) ]]; then echo_done APACHE_SERVER_ROOT="/usr/local/apache2" else echo_failed NEED_APACHE_INFO=true fi else echo_done if [[ "$(realpath "/usr/local/apache2")" = "${APACHE_SERVER_ROOT}" ]] ; then APACHE_SERVER_ROOT="/usr/local/apache2" fi fi fi echononl "Determin VHost directory.." if [[ -d "${APACHE_SERVER_ROOT}/sites-enabled" ]]; then APACHE_VHOST_DIR="${APACHE_SERVER_ROOT}/sites-enabled" elif [[ -d "${APACHE_SERVER_ROOT}/conf/vhosts" ]]; then APACHE_VHOST_DIR="${APACHE_SERVER_ROOT}/conf/vhosts" fi if [[ -n "${APACHE_VHOST_DIR}" ]] ; then echo_done else echo_failed NEED_APACHE_INFO=true fi if $NEED_INTERNAL_NAME_SERVER && $terminal ; then echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert (your) nameservers the sites will be checked against..." echo "" echo " Give a blank separated list of nameserver names." echo "" echo "" INTERNAL_NS_SERVER= if [ -z "$INTERNAL_NS_SERVER" ]; then echoprompt "Insert your nameservers: " read INTERNAL_NS_SERVER while [ "X$INTERNAL_NS_SERVER" = "X" ] ; do echo -e "\n\t\033[33m\033[1mEntering the Naserver (s) is required .\033[m\n" echoprompt "Insert your nameservers: " read INTERNAL_NS_SERVER done fi fi for _ns_server in $INTERNAL_NS_SERVER ; do internal_ns_server_arr+=("$_ns_server") done if $NEED_APACHE_INFO && $terminal ; then echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo "Give Apache ServerRoot directory." echo "" echo "" if [[ -n "$APACHE_SERVER_ROOT" ]]; then DEFAULT_APACHE_SERVER_ROOT="$APACHE_SERVER_ROOT" APACHE_SERVER_ROOT="" fi if [[ -n "$DEFAULT_APACHE_SERVER_ROOT" ]] ; then echoprompt "Apache2 ServerRoot directory: [${DEFAULT_APACHE_SERVER_ROOT}]: " read APACHE_SERVER_ROOT [[ -z $APACHE_SERVER_ROOT ]] && APACHE_SERVER_ROOT="$DEFAULT_APACHE_SERVER_ROOT" else while [[ -z "$APACHE_SERVER_ROOT" ]] ; do echoprompt "Apache2 ServerRoot directory: " read APACHE_SERVER_ROOT if [[ -z "$(trim "$APACHE_SERVER_ROOT")" ]] ; then echo -e "\n\033[4G\033[33m\033[1mApache2 ServerRoot directory is required!\033[m\n" echoprompt "Apache2 ServerRoot directory: " elif [[ ! -d "$(trim "$APACHE_SERVER_ROOT")" ]] ; then echo -e "\n\033[4G\033[33m\033[1mDirectory '$(trim "$APACHE_SERVER_ROOT")' not found!\033[m\n" APACHE_SERVER_ROOT="" echoprompt "Apache2 ServerRoot directory: " fi done fi echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo "Give Apache VHost directory." echo "" echo "" if [[ -n "$APACHE_VHOST_DIR" ]]; then DEFAULT_APACHE_VHOST_DIR="$APACHE_VHOST_DIR" APACHE_VHOST_DIR="" fi if [[ -n "$DEFAULT_APACHE_VHOST_DIR" ]] ; then echoprompt "Apache2 VHost directory: [${DEFAULT_APACHE_VHOST_DIR}]: " read APACHE_VHOST_DIR [[ -z $APACHE_VHOST_DIR ]] && APACHE_VHOST_DIR="$DEFAULT_APACHE_VHOST_DIR" else while [[ -z "$APACHE_VHOST_DIR" ]] ; do echoprompt "Apache2 VHost directory: " read APACHE_VHOST_DIR if [[ -z "$(trim "$APACHE_VHOST_DIR")" ]] ; then echo -e "\n\033[4G\033[33m\033[1mApache2 ServerRoot directory is required!\033[m\n" echoprompt "Apache2 VHost directory: " elif [[ ! -d "$(trim "$APACHE_VHOST_DIR")" ]] ; then echo -e "\n\033[4G\033[33m\033[1mDirectory '$(trim "$APACHE_VHOST_DIR")' not found!\033[m\n" APACHE_VHOST_DIR="" echoprompt "Apache2 VHost directory: " fi done fi if [[ -n "$HTTP_USER" ]]; then DEFAULT_HTTP_USER="$HTTP_USER" HTTP_USER="" fi if [[ -n "$HTTP_GROUP" ]]; then DEFAULT_HTTP_GROUP="$HTTP_GROUP" HTTP_GROUP="" fi echo "" echo "" echo -e "\033[32m--\033[m" echo "" echo "Insert User/Group of apache2 daemon (httpd)." echo "" echo "" echoprompt "Apache2 user [${DEFAULT_HTTP_USER}]: " read HTTP_USER [[ -z $HTTP_USER ]] && HTTP_USER="${DEFAULT_HTTP_USER}" echoprompt "Apache2 group [${DEFAULT_HTTP_USER}]: " read HTTP_GROUP [[ -z $HTTP_GROUP ]] && HTTP_GROUP="${DEFAULT_HTTP_GROUP}" fi if [[ -n "${APACHE_VHOST_DIR}" ]] ; then if [[ -d "${APACHE_VHOST_DIR}/DNS-outsourced" ]] ; then APACHE_DNS_OUTSOURCED_VHOST_DIR="${APACHE_VHOST_DIR}/DNS-outsourced" dns_outsource_dir=true else dns_outsource_dir=false fi fi if $terminal ; then echo "" echo "" echo -e "\033[4G\033[33mApache2 Info:\033[m" echo -e "\033[4G\033[33m=============\033[m" echo "" if [[ -n $APACHE_VERSION ]]; then echo -e "\033[4GApache2 version..................: $APACHE_VERSION" else echo -e "\033[4GApache2 version..................: \033[33m-- could not be determined --\033[m" fi echo "" if [[ -n "$APACHE_SERVER_ROOT" ]] ; then echo -e "\033[4GApache2 Root Directory...........: $APACHE_SERVER_ROOT" else echo -e "\033[4GServer Root Directory............: \033[33m-- could not be determined --\033[m" fi echo "" if [[ -x "$HTTPD_COMMAND" ]] ; then echo -e "\033[4GApache2 daemon ..................: $HTTPD_COMMAND" else echo -e "\033[4GApache2 daemon ..................: \033[33m-- could not be determined --\033[m" fi echo "" if [[ -n "${APACHE_VHOST_DIR}" ]] ; then echo -e "\033[4GApache2 VHost directory..........: $APACHE_VHOST_DIR" if $dns_outsource_dir ; then echo -e "\033[4G : $APACHE_DNS_OUTSOURCED_VHOST_DIR" fi else echo -e "\033[4GApache2 VHost directory..........: \033[33m-- could not be determined --\033[m" fi echo "" if [[ -n "$HTTP_USER" ]] ; then echo -e "\033[4GApache2 User.....................: $HTTP_USER" else echo -e "\033[4GApache2 User.....................: \033[33m-- could not be determined --\033[m" fi if [[ -n "$HTTP_GROUP" ]] ; then echo -e "\033[4GApache2 Group....................: $HTTP_GROUP" else echo -e "\033[4GApache2 Group....................: \033[33m-- could not be determined --\033[m" fi echo "" if [[ ${#internal_ns_server_arr[@]} -gt 0 ]] ; then _first=true for _ns_server in ${internal_ns_server_arr[@]} ; do if $_first ; then echo -e "\033[4GList of nameservers..............: $_ns_server" _first=false else echo -e "\033[39G$_ns_server" fi done else echo -e "\033[4GList of omitted site names.......: \033[33m-- Not given --\033[m" fi echo "" if [[ ${#omitted_site_names_arr[@]} -gt 0 ]] ; then _first=true for _site_name in ${omitted_site_names_arr[@]} ; do if $_first ; then echo -e "\033[4GList of omitted site names.......: $_site_name" _first=false else echo -e "\033[39G$_site_name" fi done else echo -e "\033[4GList of omitted site names.......: \033[33m-- Not given --\033[m" fi echo "" else echo "" echo " Apache2 Info:" echo " =============" echo "" if [[ -n $APACHE_VERSION ]]; then echo " Apache2 version..................: $APACHE_VERSION" else echo " Apache2 version..................: -- could not be determined --" fi echo "" if [[ -n "$APACHE_SERVER_ROOT" ]] ; then echo " Apache2 Root Directory...........: $APACHE_SERVER_ROOT" else echo " Server Root Directory............: -- could not be determined --" fi echo "" if [[ -x "$HTTPD_COMMAND" ]] ; then echo " Apache2 daemon ..................: $HTTPD_COMMAND" else echo " Apache2 daemon ..................: -- could not be determined --" fi echo "" if [[ -n "${APACHE_VHOST_DIR}" ]] ; then echo " Apache2 VHost directory..........: $APACHE_VHOST_DIR" if $dns_outsource_dir ; then echo " : $APACHE_DNS_OUTSOURCED_VHOST_DIR" fi else echo " Apache2 VHost directory..........: -- could not be determined --" fi echo "" if [[ -n "$HTTP_USER" ]] ; then echo " Apache2 User.....................: $HTTP_USER" else echo " Apache2 User.....................: -- could not be determined --" fi if [[ -n "$HTTP_GROUP" ]] ; then echo " Apache2 Group....................: $HTTP_GROUP" else echo " Apache2 Group....................: -- could not be determined --" fi echo "" if [[ ${#internal_ns_server_arr[@]} -gt 0 ]] ; then _first=true for _ns_server in ${internal_ns_server_arr[@]} ; do if $_first ; then echo " List of nameservers..............: $_ns_server" _first=false else echo " $_ns_server" fi done else echo " List of omitted site names.......: -- Not given --" fi echo "" if [[ ${#omitted_site_names_arr[@]} -gt 0 ]] ; then _first=true for _site_name in ${omitted_site_names_arr[@]} ; do if $_first ; then echo " List of omitted site names.......: $_site_name" _first=false else echo "\033[39G$_site_name" fi done else echo " List of omitted site names.......: \033[33m-- Not given --\033[m" fi echo "" fi if [[ -z "${APACHE_VHOST_DIR}" ]] ; then echo "" error "Apache2 VHost directory not known. Cannot determin sites with external authoritativ nameservers Exiting script now." clean_up 1 fi if [[ ${#internal_ns_server_arr[@]} -lt 1 ]] ; then echo "" error "List of internal nameservers not given. Cannot determin sites with external authoritativ nameservers Exiting script now." clean_up 1 fi if $terminal ; then echo "" echo -e "\033[4G\033[1m----------\033[m" echo -e "\033[4G\033[32mRunning main part of script\033[m - \033[5m\033[1mThis may take a while\033[m" echo -e "\033[4G\033[1m----------\033[m" echo "" else echo "" echo "----------" echo "Running main part of script '$script_name'.." echo "----------" echo "" fi # Get list of vhost configurations # declare -a _tmp_arr=() declare -a vhost_config_files_arr=() for _file in $(ls "${APACHE_VHOST_DIR}/"*.conf) ; do _tmp_arr+=("$(realpath $_file)") done if $dns_outsource_dir ; then for _file in $(ls "${APACHE_DNS_OUTSOURCED_VHOST_DIR}/"*.conf) ; do _tmp_arr+=("$(realpath $_file)") done fi # sort array '_tmp_arr' # IFS=$'\n' vhost_config_files_arr=($(sort <<<"${_tmp_arr[*]}")) sites_external_ns_servers=() if [[ ${#vhost_config_files_arr[@]} -gt 0 ]]; then for _config_file in "${vhost_config_files_arr[@]}" ; do [[ "$(basename "$_config_file")" =~ ^00 ]] && continue _server_name="" _server_aliases="" site_names_arr=() while read line ; do # Get ServerName # if echo $line | grep -e "^\s*ServerName" > /dev/null ; then _server_name="$(echo $line | awk '{print$2}')" if [[ ${#site_names_arr[@]} -eq 0 ]]; then site_names_arr+=("${_server_name}") elif [[ "${site_names_arr[0]}" != "$_server_name" ]]; then error "$_config_file: Misconfigured ServerName" fi continue fi # Get ServerAlias # if echo $line | grep -e "^\s*ServerAlias" > /dev/null ; then _server_aliases="$(echo $line | sed -e "s/ServerAlias//" | sed "s/^\s*//" | sed "s/\s*$//")" for _alias in $_server_aliases ; do if ! containsElement "$_alias" "${site_names_arr[@]}" ; then site_names_arr+=("${_alias}") else continue fi done continue fi done < "$_config_file" # Check if all site_names are hosted on your (the given) namesevers # for _site_name in "${site_names_arr[@]}" ; do [[ "$_site_name" =~ \.\* ]] && continue _found_omitted=false if [[ ${#omitted_site_names_arr[@]} -gt 0 ]]; then for _omitted_name in ${omitted_site_names_arr[@]} ; do [[ "$_site_name" =~ $_omitted_name ]] && _found_omitted=true break done $_found_omitted && continue fi _name="$_site_name" [[ $(dig +short $_name CNAME) ]] && continue authorited_ns_servers="$(dig +short $_name NS)" _error=false while [[ -z "$authorited_ns_servers" ]] ; do _name="${_name#*.}" authorited_ns_servers="$(dig +short $_name NS)" if [[ ! "$_name" =~ \. ]]; then error "Cannot detect authoritativ nameserver for \033[1m$_site_name\033[m" _error=true break fi done $_error && continue _found=false for _ns_name in $authorited_ns_servers ; do for _internal_ns_server in ${internal_ns_server_arr[@]} ; do if [[ "$_ns_name" =~ $_internal_ns_server ]] ; then _found=true break fi done if $_found ; then break; fi done if ! $_found ; then _first=true for _ns_name in $authorited_ns_servers ; do _ns_name="${_ns_name%.}" if $_first ; then ns_servers="${_ns_name}" _first=false else ns_servers="${ns_servers},$_ns_name" fi done sites_external_ns_servers+=("${_config_file}:${_site_name}:${ns_servers}") fi done done else warn "No VHost configuration found on this apache2 installation" fi if [[ ${#sites_external_ns_servers[@]} -gt 0 ]] ; then if $terminal ; then echo "" echo "" echo -e "\033[4G\033[1m----------\033[m" echo -e "\033[4G\033[1mSites with external authoritative nameservers\033[m" echo -e "\033[4G\033[1m----------\033[m" else echo "" echo "" echo " ----------" echo " Sites with external authoritative nameservers" echo " ----------" fi _first=true for _val in "${sites_external_ns_servers[@]}" ; do IFS=':' read -a _val_arr <<< "${_val}" config_file="${_val_arr[0]}" site_name="${_val_arr[1]}" names_server="${_val_arr[2]}" if [[ "${config_file}" != "${last_config_file}" ]] ; then _first=true if $terminal ; then echo "" echo "" echo -e "\033[4G\033[33m$(basename "${config_file}")\033[m" else echo "" echo "" echo " $(basename "${config_file}")" fi last_config_file="${config_file}" fi if $terminal ; then if $_first ; then _first=false else echo "" fi echo -en "\033[7G${site_name}:" IFS=',' read -ra _ns_name_arr <<< "$names_server" for _ns_name in "${_ns_name_arr[@]}" ; do echo -e "\033[45G${_ns_name}" done else echo -e " ${site_name}: ${names_server}" fi done fi clean_up 0