Import scripts

This commit is contained in:
Jérémy Lecour 2019-11-04 15:16:05 +01:00 committed by Jérémy Lecour
parent 80ab9e094c
commit d850495d80
3 changed files with 709 additions and 0 deletions

303
evoacme.sh Executable file
View file

@ -0,0 +1,303 @@
#!/bin/bash
#
# evoacme is a shell script to manage Let's Encrypt certificate with
# certbot tool but with a dedicated user (no-root) and from a csr
#
# Author: Victor Laborie <vlaborie@evolix.fr>
# Licence: AGPLv3
#
set -e
set -u
usage() {
cat <<EOT
Usage: ${PROGNAME} NAME
NAME must be correspond to :
- a CSR in ${CSR_DIR}/NAME.csr
- a KEY in ${SSL_KEY_DIR}/NAME.key
If env variable TEST=1, certbot is run in staging mode
If env variable DRY_RUN=1, certbot is run in dry-run mode
If env variable QUIET=1, no message is output
If env variable VERBOSE=1, debug messages are output
EOT
}
log() {
if [ "${QUIET}" != "1" ]; then
echo "${PROGNAME}: $1"
fi
}
debug() {
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
>&2 echo "${PROGNAME}: $1"
fi
}
error() {
>&2 echo "${PROGNAME}: $1"
[ "$1" = "invalid argument(s)" ] && >&2 usage
exit 1
}
sed_cert_path_for_apache() {
local vhost=$1
local vhost_full_path="/etc/apache2/ssl/${vhost}.conf"
local cert_path=$2
[ ! -r "${vhost_full_path}" ] && return 0
local search="^SSLCertificateFile.*$"
local replace="SSLCertificateFile ${cert_path}"
if grep -qE "${search}" "${vhost_full_path}"; then
[ -w "${vhost_full_path}" ] || error "File ${vhost_full_path} is not writable"
sed -i "s~${search}~${replace}~" "${vhost_full_path}"
debug "Config in ${vhost_full_path} has been updated"
$(command -v apache2ctl) -t 2>/dev/null
[ "${?}" -eq 0 ] || $(command -v apache2ctl) -t
fi
}
sed_cert_path_for_nginx() {
local vhost=$1
local vhost_full_path="/etc/nginx/ssl/${vhost}.conf"
local cert_path=$2
[ ! -r "${vhost_full_path}" ] && return 0
local search="^ssl_certificate[^_].*$"
local replace="ssl_certificate ${cert_path};"
if grep -qE "${search}" "${vhost_full_path}"; then
[ -w "${vhost_full_path}" ] || error "File ${vhost_full_path} is not writable"
sed -i "s~${search}~${replace}~" "${vhost_full_path}"
debug "Config in ${vhost_full_path} has been updated"
$(command -v nginx) -t 2>/dev/null
[ "${?}" -eq 0 ] || $(command -v nginx) -t
fi
}
x509_verify() {
local file="$1"
[ -r "$file" ] || error "File ${file} not found"
"${OPENSSL_BIN}" x509 -noout -modulus -in "$file" >/dev/null
}
x509_enddate() {
local file="$1"
[ -r "$file" ] || error "File ${file} not found"
"${OPENSSL_BIN}" x509 -noout -enddate -in "$file"
}
csr_verify() {
local file="$1"
[ -r "$file" ] || error "File ${file} not found"
"${OPENSSL_BIN}" req -noout -modulus -in "$file" >/dev/null
}
main() {
# check arguments
[ "$#" -eq 1 ] || error "invalid argument(s)"
[ "$1" = "-h" ] || [ "$1" = "--help" ] && usage && exit 0
mkdir -p "${ACME_DIR}"
chown acme: "${ACME_DIR}"
[ -w "${ACME_DIR}" ] || error "Directory ${ACME_DIR} is not writable"
[ -d "${CSR_DIR}" ] || error "Directory ${CSR_DIR} is not found"
mkdir -p "${CRT_DIR}"
chown acme: "${CRT_DIR}"
[ -w "${CRT_DIR}" ] || error "Directory ${CRT_DIR} is not writable"
mkdir -p "${LOG_DIR}"
chown acme: "${LOG_DIR}"
[ -w "${LOG_DIR}" ] || error "Directory ${LOG_DIR} is not writable"
mkdir -p "${HOOKS_DIR}"
chown acme: "${HOOKS_DIR}"
[ -d "${HOOKS_DIR}" ] || error "Directory ${HOOKS_DIR} is not found"
readonly VHOST=$(basename "$1" .conf)
# check for important programs
readonly OPENSSL_BIN=$(command -v openssl) || error "openssl command not installed"
readonly CERTBOT_BIN=$(command -v certbot) || error "certbot command not installed"
# double check for directories
[ -d "${ACME_DIR}" ] || error "${ACME_DIR} is not a directory"
[ -d "${CSR_DIR}" ] || error "${CSR_DIR} is not a directory"
[ -d "${LOG_DIR}" ] || error "${LOG_DIR} is not a directory"
#### CSR VALIDATION
# verify .csr file
readonly CSR_FILE="${CSR_DIR}/${VHOST}.csr"
debug "Using CSR file: ${CSR_FILE}"
[ -f "${CSR_FILE}" ] || error "${CSR_FILE} absent"
[ -r "${CSR_FILE}" ] || error "${CSR_FILE} is not readable"
csr_verify "${CSR_FILE}" || error "${CSR_FILE} is invalid"
# Hook for evoadmin-web in cluster mode : check master status
local evoadmin_state_file="/home/${VHOST}/state"
[ -r "${evoadmin_state_file}" ] \
&& grep -q "STATE=slave" "${evoadmin_state_file}" \
&& debug "We are slave of this evoadmin cluster. Quit!" \
&& exit 0
#### INIT OR RENEW?
readonly LIVE_DIR="${CRT_DIR}/${VHOST}/live"
readonly LIVE_CERT="${LIVE_DIR}/cert.crt"
readonly LIVE_FULLCHAIN="${LIVE_DIR}/fullchain.pem"
readonly LIVE_CHAIN="${LIVE_DIR}/chain.pem"
# If live symlink already exists, it's not our first time...
if [ -h "${LIVE_DIR}" ]; then
# we have a live symlink
# let's see if there is a cert to renew
x509_verify "${LIVE_CERT}" || error "${LIVE_CERT} is invalid"
# Verify if our certificate will expire
crt_end_date=$(x509_enddate "${LIVE_CERT}" | cut -d= -f2)
date_renew=$(date -ud "${crt_end_date} - ${SSL_MINDAY} days" +"%s")
date_today=$(date +'%s')
if [ "${date_today}" -lt "${date_renew}" ]; then
debug "Cert ${LIVE_CERT} expires at ${crt_end_date} => more than ${SSL_MINDAY} days: kthxbye."
exit 0
fi
fi
#### CERTIFICATE CREATION WITH CERTBOT
local iteration=$(date "+%Y%m%d%H%M%S")
[ -n "${iteration}" ] || error "invalid iteration (${iteration})"
readonly NEW_DIR="${CRT_DIR}/${VHOST}/${iteration}"
[ -d "${NEW_DIR}" ] && error "${NEW_DIR} directory already exists, remove it manually."
mkdir -p "${NEW_DIR}"
chown -R acme: "${CRT_DIR}"
chmod -R 0700 "${CRT_DIR}"
chmod -R g+rX "${CRT_DIR}"
debug "New cert will be created in ${NEW_DIR}"
readonly NEW_CERT="${NEW_DIR}/cert.crt"
readonly NEW_FULLCHAIN="${NEW_DIR}/fullchain.pem"
readonly NEW_CHAIN="${NEW_DIR}/chain.pem"
local CERTBOT_MODE=""
[ "${TEST}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --test-cert"
[ "${QUIET}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --quiet"
[ "${DRY_RUN}" = "1" ] && CERTBOT_MODE="${CERTBOT_MODE} --dry-run"
local CERTBOT_REGISTRATION="--agree-tos"
if [ -n "${SSL_EMAIL}" ]; then
debug "Registering at certbot with ${SSL_EMAIL} as email"
CERTBOT_REGISTRATION="${CERTBOT_REGISTRATION} -m ${SSL_EMAIL}"
else
debug "Registering at certbot without email"
CERTBOT_REGISTRATION="${CERTBOT_REGISTRATION} --register-unsafely-without-email"
fi
# Permissions checks for acme user
sudo -u acme test -r "${CSR_FILE}" || error "File ${CSR_FILE} is not readable by user 'acme'"
sudo -u acme test -w "${NEW_DIR}" || error "Directory ${NEW_DIR} is not writable by user 'acme'"
# create a certificate with certbot
# we disable the set -e during the certbot call
set +e
sudo -u acme \
"${CERTBOT_BIN}" \
certonly \
${CERTBOT_MODE} \
${CERTBOT_REGISTRATION} \
--non-interactive \
--webroot \
--csr "${CSR_FILE}" \
--webroot-path "${ACME_DIR}" \
--cert-path "${NEW_CERT}" \
--fullchain-path "${NEW_FULLCHAIN}" \
--chain-path "${NEW_CHAIN}" \
--logs-dir "$LOG_DIR" \
2>&1 \
| grep -v "certbot.crypto_util"
if [ "${PIPESTATUS[0]}" != "0" ]; then
error "Certbot has exited with a non-zero exit code when generating ${NEW_CERT}"
fi
set -e
if [ "${DRY_RUN}" = "1" ]; then
debug "In dry-run mode, we stop here. Bye"
exit 0
fi
# verify if all is right
x509_verify "${NEW_CERT}" || error "${NEW_CERT} is invalid"
x509_verify "${NEW_FULLCHAIN}" || error "${NEW_FULLCHAIN} is invalid"
x509_verify "${NEW_CHAIN}" || error "${NEW_CHAIN} is invalid"
log "New certificate available at ${NEW_CERT}"
#### CERTIFICATE ACTIVATION
# link dance
if [ -h "${LIVE_DIR}" ]; then
rm "${LIVE_DIR}"
debug "Remove ${LIVE_DIR} link"
fi
ln -s "${NEW_DIR}" "${LIVE_DIR}"
debug "Link ${NEW_DIR} to ${LIVE_DIR}"
# verify final path
x509_verify "${LIVE_CERT}" || error "${LIVE_CERT} is invalid"
# update Apache
sed_cert_path_for_apache "${VHOST}" "${LIVE_FULLCHAIN}"
# update Nginx
sed_cert_path_for_nginx "${VHOST}" "${LIVE_FULLCHAIN}"
#### EXECUTE HOOKS
#
# executable scripts placed in ${HOOKS_DIR}
# are executed, unless their name ends with ".disabled"
export EVOACME_VHOST_NAME="${VHOST}"
export EVOACME_CERT="${LIVE_CERT}"
export EVOACME_CHAIN="${LIVE_CHAIN}"
export EVOACME_FULLCHAIN="${LIVE_FULLCHAIN}"
# search for files in hooks directory
for hook in $(find ${HOOKS_DIR} -type f); do
# keep only executables files, not containing a "."
if [ -x "${hook}" ] && (basename "${hook}" | grep -vqF "."); then
debug "Executing ${hook}"
${hook}
fi
done
}
readonly PROGNAME=$(basename "$0")
readonly PROGDIR=$(realpath -m $(dirname "$0"))
readonly ARGS=$@
readonly VERBOSE=${VERBOSE:-"0"}
readonly QUIET=${QUIET:-"0"}
readonly TEST=${TEST:-"0"}
readonly DRY_RUN=${DRY_RUN:-"0"}
# Read configuration file, if it exists
[ -r /etc/default/evoacme ] && . /etc/default/evoacme
# Default value for main variables
readonly SSL_KEY_DIR=${SSL_KEY_DIR:-"/etc/ssl/private"}
readonly ACME_DIR=${ACME_DIR:-"/var/lib/letsencrypt"}
readonly CSR_DIR=${CSR_DIR:-"/etc/ssl/requests"}
readonly CRT_DIR=${CRT_DIR:-"/etc/letsencrypt"}
readonly LOG_DIR=${LOG_DIR:-"/var/log/evoacme"}
readonly HOOKS_DIR=${HOOKS_DIR:-"${CRT_DIR}/hooks"}
readonly SSL_MINDAY=${SSL_MINDAY:-"30"}
readonly SSL_EMAIL=${SSL_EMAIL:-""}
main ${ARGS}

253
make-csr.sh Executable file
View file

@ -0,0 +1,253 @@
#!/bin/bash
#
# make-csr is a shell script designed to automatically generate a
# certificate signing request (CSR) from an Apache or a Nginx vhost
#
# Author: Victor Laborie <vlaborie@evolix.fr>
# Licence: AGPLv3
#
set -u
usage() {
cat <<EOT
Usage: ${PROGNAME} VHOST DOMAIN...
VHOST must correspond to an Apache or Nginx enabled VHost
If VHOST ends with ".conf" it is stripped,
then files are seached at those paths:
- /etc/apache2/sites-enables/VHOST.conf
- /etc/nginx/sites-enabled/VHOST.conf
- /etc/nginx/sites-enabled/VHOST
DOMAIN... is a list of domains for the CSR (passed as arguments or input)
If env variable VERBOSE=1, debug messages are sent to stderr
EOT
}
debug() {
if [ "${VERBOSE}" = 1 ]; then
>&2 echo "${PROGNAME}: $1"
fi
}
error() {
>&2 echo "${PROGNAME}: $1"
exit 1
}
default_key_size() {
grep default_bits "${SSL_CONFIG_FILE}" | cut -d'=' -f2 | xargs
}
sed_selfsigned_cert_path_for_apache() {
local apache_ssl_vhost_path="$1"
mkdir -p $(dirname "${apache_ssl_vhost_path}")
if [ ! -f "${apache_ssl_vhost_path}" ]; then
cat > "${apache_ssl_vhost_path}" <<EOF
SSLEngine On
SSLCertificateFile ${SELF_SIGNED_FILE}
SSLCertificateKeyFile ${SSL_KEY_FILE}
EOF
debug "SSL config added in ${apache_ssl_vhost_path}"
else
local search="^SSLCertificateFile.*$"
local replace="SSLCertificateFile ${SELF_SIGNED_FILE}"
sed -i "s~${search}~${replace}~" "${apache_ssl_vhost_path}"
debug "SSL config updated in ${apache_ssl_vhost_path}"
fi
}
sed_selfsigned_cert_path_for_nginx() {
local nginx_ssl_vhost_path="$1"
mkdir -p $(dirname "${nginx_ssl_vhost_path}")
if [ ! -f "${nginx_ssl_vhost_path}" ]; then
cat > "${nginx_ssl_vhost_path}" <<EOF
ssl_certificate ${SELF_SIGNED_FILE};
ssl_certificate_key ${SSL_KEY_FILE};
EOF
debug "SSL config added in ${nginx_ssl_vhost_path}"
else
local search="^ssl_certificate[^_].*$"
local replace="ssl_certificate ${SELF_SIGNED_FILE};"
sed -i "s~${search}~${replace}~" "${nginx_ssl_vhost_path}"
debug "SSL config updated in ${nginx_ssl_vhost_path}"
fi
}
openssl_selfsigned() {
local csr="$1"
local key="$2"
local crt="$3"
local cfg="$4"
local crt_dir=$(dirname ${crt})
[ -r "${csr}" ] || error "File ${csr} is not readable"
[ -r "${key}" ] || error "File ${key} is not readable"
[ -w "${crt_dir}" ] || error "Directory ${crt_dir} is not writable"
if grep -q SAN "${cfg}"; then
"${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -extensions SAN -extfile "${cfg}" -signkey "${key}" -out "${crt}" 2> /dev/null
else
"${OPENSSL_BIN}" x509 -req -sha256 -days 365 -in "${csr}" -signkey "${key}" -out "${crt}" 2> /dev/null
fi
[ -r "${crt}" ] || error "Something went wrong, ${crt} has not been generated"
}
openssl_key(){
local key="$1"
local key_dir=$(dirname "${key}")
local size="$2"
[ -w "${key_dir}" ] || error "Directory ${key_dir} is not writable"
"${OPENSSL_BIN}" genrsa -out "${key}" "${size}" 2> /dev/null
[ -r "${key}" ] || error "Something went wrong, ${key} has not been generated"
}
openssl_csr() {
local csr="$1"
local csr_dir=$(dirname "${csr}")
local key="$2"
local cfg="$3"
[ -w "${csr_dir}" ] || error "Directory ${csr_dir} is not writable"
if $(grep -q "DNS:" "${cfg}"); then
# CSR with SAN
"${OPENSSL_BIN}" req -new -sha256 -key "${key}" -reqexts SAN -config "${cfg}" -out "${csr}"
else
# Single domain CSR
"${OPENSSL_BIN}" req -new -sha256 -key "${key}" -config "${cfg}" -out "${csr}"
fi
[ -r "${csr}" ] || error "Something went wrong, ${csr} has not been generated"
}
make_key() {
local key="$1"
local size="$2"
openssl_key "${key}" "${size}"
debug "Private key stored at ${key}"
chown root: "${key}"
chmod 600 "${key}"
}
make_csr() {
local domains=$@
local nb=$#
local config_file="/tmp/make-csr-${VHOST}.conf"
local san=""
mkdir -p -m 0755 "${CSR_DIR}" || error "Unable to mkdir ${CSR_DIR}"
if [ "${nb}" -eq 1 ]; then
cat "${SSL_CONFIG_FILE}" - > "${config_file}" <<EOF
CN=$domains
EOF
elif [ "${nb}" -gt 1 ]; then
for domain in ${domains}; do
san="${san},DNS:${domain}"
done
san=$(echo "${san}" | sed 's/^,//')
cat "${SSL_CONFIG_FILE}" - > "${config_file}" <<EOF
CN=${domains%% *}
[SAN]
subjectAltName=${san}
EOF
fi
openssl_csr "${CSR_FILE}" "${SSL_KEY_FILE}" "${config_file}"
debug "CSR stored at ${CSR_FILE}"
if [ -r "${CSR_FILE}" ]; then
chmod 644 "${CSR_FILE}"
mkdir -p -m 0755 "${SELF_SIGNED_DIR}"
openssl_selfsigned "${CSR_FILE}" "${SSL_KEY_FILE}" "${SELF_SIGNED_FILE}" "${config_file}"
[ -r "${SELF_SIGNED_FILE}" ] && chmod 644 "${SELF_SIGNED_FILE}"
debug "Self-signed certificate stored at ${SELF_SIGNED_FILE}"
fi
}
main() {
if [ -t 0 ]; then
# We have STDIN, so we should have at least 2 arguments
if [ "$#" -lt 2 ]; then
>&2 echo "invalid arguments"
>&2 usage
exit 1
fi
# read VHOST from first argument
VHOST="$1"
# remove the first argument
shift
# read domains from remaining arguments
DOMAINS=$@
else
# We don't have STDIN, so we should have only 1 argument
if [ "$#" != 1 ]; then
>&2 echo "invalid arguments"
>&2 usage
exit 1
fi
# read VHOST from first argument
VHOST="$1"
# read domains from input
DOMAINS=
while read -r line ; do
DOMAINS="${DOMAINS} ${line}"
done
# trim the string to remove leading/trailing spaces
DOMAINS=$(echo "${DOMAINS}" | xargs)
fi
readonly VHOST
readonly DOMAINS
mkdir -p "${CSR_DIR}"
chown root: "${CSR_DIR}"
[ -w "${CSR_DIR}" ] || error "Directory ${CSR_DIR} is not writable"
mkdir -p "${SELF_SIGNED_DIR}"
chown root: "${SELF_SIGNED_DIR}"
[ -w "${SELF_SIGNED_DIR}" ] || error "Directory ${SELF_SIGNED_DIR} is not writable"
mkdir -p "${SSL_KEY_DIR}"
[ -w "${SSL_KEY_DIR}" ] || error "Directory ${SSL_KEY_DIR} is not writable"
[ -r "${SSL_CONFIG_FILE}" ] || error "File ${SSL_CONFIG_FILE} is not readable"
# check for important programs
readonly OPENSSL_BIN=$(command -v openssl) || error "openssl command not installed"
readonly SELF_SIGNED_FILE="${SELF_SIGNED_DIR}/${VHOST}.pem"
readonly SSL_KEY_FILE="${SSL_KEY_DIR}/${VHOST}.key"
readonly CSR_FILE="${CSR_DIR}/${VHOST}.csr"
make_key "${SSL_KEY_FILE}" "${SSL_KEY_SIZE}"
make_csr ${DOMAINS}
command -v apache2ctl >/dev/null && sed_selfsigned_cert_path_for_apache "/etc/apache2/ssl/${VHOST}.conf"
command -v nginx >/dev/null && sed_selfsigned_cert_path_for_nginx "/etc/nginx/ssl/${VHOST}.conf"
exit 0
}
readonly PROGNAME=$(basename "$0")
readonly PROGDIR=$(realpath -m $(dirname "$0"))
readonly ARGS=$@
readonly VERBOSE=${VERBOSE:-"0"}
# Read configuration file, if it exists
[ -r /etc/default/evoacme ] && . /etc/default/evoacme
# Default value for main variables
readonly CSR_DIR=${CSR_DIR:-'/etc/ssl/requests'}
readonly SSL_CONFIG_FILE=${SSL_CONFIG_FILE:-"/etc/letsencrypt/openssl.cnf"}
readonly SELF_SIGNED_DIR=${SELF_SIGNED_DIR:-'/etc/ssl/self-signed'}
readonly SSL_KEY_DIR=${SSL_KEY_DIR:-'/etc/ssl/private'}
readonly SSL_KEY_SIZE=${SSL_KEY_SIZE:-$(default_key_size)}
main ${ARGS}

153
vhost-domains.sh Executable file
View file

@ -0,0 +1,153 @@
#!/bin/bash
#
# make-csr is a shell script designed to automatically generate a
# certificate signing request (CSR) from an Apache or a Nginx vhost
#
# Author: Victor Laborie <vlaborie@evolix.fr>
# Licence: AGPLv3
#
set -u
usage() {
cat <<EOT
Usage: ${PROGNAME} VHOST
VHOST must correspond to an Apache or Nginx enabled VHost
If VHOST ends with ".conf" it is stripped,
then files are seached at those paths:
- /etc/apache2/sites-enables/VHOST.conf
- /etc/nginx/sites-enabled/VHOST.conf
- /etc/nginx/sites-enabled/VHOST
If env variable VERBOSE=1, debug messages are sent to stderr
EOT
}
debug() {
if [ "${VERBOSE}" = 1 ]; then
>&2 echo "${PROGNAME}: $1"
fi
}
error() {
>&2 echo "${PROGNAME}: $1"
exit 1
}
real_ip_for_domain() {
dig +short "$1" | grep -oE "([0-9]+\.){3}[0-9]+"
}
local_ip() {
ip a | grep brd | cut -d'/' -f1 | grep -oE "([0-9]+\.){3}[0-9]+"
}
nginx_domains() {
local vhost_file="$1"
grep -oE "^( )*[^#]+" "${vhost_file}" \
| grep -oE "[^\$]server_name.*;$" \
| sed 's/server_name//' \
| tr -d ';' \
| sed 's/\s\{1,\}//' \
| sed 's/\s\{1,\}/\n/g' \
| sort \
| uniq
}
apache_domains() {
local vhost_file="$1"
grep -oE "^( )*[^#]+" "${vhost_file}" \
| grep -oE "(ServerName|ServerAlias).*" \
| sed 's/ServerName//' \
| sed 's/ServerAlias//' \
| sed 's/\s\{1,\}//' \
| sort \
| uniq
}
get_domains() {
local vhost_file="$1"
local ips="$2"
local domains=""
local valid_domains=""
local nb=0
if $(echo "${vhost_file}" | grep -q nginx); then
debug "Nginx vhost file used"
domains=$(nginx_domains "${vhost_file}")
fi
if $(echo "${vhost_file}" | grep -q apache2); then
debug "Apache vhost file used"
domains=$(apache_domains "${vhost_file}")
fi
debug "Valid(s) domain(s) in ${vhost_file} :"
for domain in ${domains}; do
real_ip=$(real_ip_for_domain "${domain}")
for ip in $(echo "${ips}" | xargs -n1); do
if [ "${ip}" = "${real_ip}" ]; then
valid_domains="${valid_domains} ${domain}"
nb=$(( nb + 1 ))
debug "* ${domain} -> ${real_ip}"
fi
done
done
if [ "${nb}" -eq 0 ]; then
nb=$(echo "${domains}" | wc -l)
debug "* No valid domain found"
debug "All following(s) domain(s) will be used for CSR creation :"
for domain in ${domains}; do
debug "* ${domain}"
done
else
domains="${valid_domains}"
fi
echo "${domains}" | xargs -n 1
}
first_vhost_file_found() {
local vhost_name="$1"
ls "/etc/nginx/sites-enabled/${vhost_name}" \
"/etc/nginx/sites-enabled/${vhost_name}.conf" \
"/etc/apache2/sites-enabled/${vhost_name}.conf" \
2>/dev/null \
| head -n 1
}
main() {
if [ "$#" != 1 ]; then
>&2 usage
exit 1
fi
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
exit 0
fi
local vhost_name=$(basename "$1" .conf)
local vhost_file=$(first_vhost_file_found "${vhost_name}")
if [ ! -h "${vhost_file}" ]; then
>&2 echo "No virtualhost has been found for '${vhost_name}'."
exit 1
fi
local ips=$(local_ip)
if [ -n "${SRV_IP}" ]; then
ips="${ips} ${SRV_IP}"
fi
get_domains "${vhost_file}" "${ips}"
}
readonly PROGNAME=$(basename "$0")
readonly PROGDIR=$(realpath -m $(dirname "$0"))
readonly ARGS=$@
readonly VERBOSE=${VERBOSE:-"0"}
readonly SRV_IP=${SRV_IP:-""}
main $ARGS