2017-08-25 18:13:32 +02:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
2017-10-13 00:47:02 +02:00
|
|
|
# make-csr is a shell script designed to automatically generate a
|
2017-08-25 18:13:32 +02:00
|
|
|
# certificate signing request (CSR) from an Apache or a Nginx vhost
|
|
|
|
#
|
|
|
|
# Author: Victor Laborie <vlaborie@evolix.fr>
|
|
|
|
# Licence: AGPLv3
|
|
|
|
#
|
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
real_ip_for_domain() {
|
|
|
|
dig +short "$1" | grep -oE "([0-9]+\.){3}[0-9]+"
|
|
|
|
}
|
2017-10-13 11:16:21 +02:00
|
|
|
local_ip() {
|
|
|
|
ip a | grep brd | cut -d'/' -f1 | grep -oE "([0-9]+\.){3}[0-9]+"
|
|
|
|
}
|
2017-10-13 00:47:02 +02:00
|
|
|
|
2017-08-25 18:13:32 +02:00
|
|
|
get_domains() {
|
2017-10-13 00:47:02 +02:00
|
|
|
echo "$vhostfile" | grep -q nginx
|
2017-09-21 00:39:06 +02:00
|
|
|
if [ "$?" -eq 0 ]; then
|
2017-10-13 00:47:02 +02:00
|
|
|
domains=$(
|
|
|
|
grep -oE "^( )*[^#]+" "$vhostfile" \
|
|
|
|
| grep -oE "[^\$]server_name.*;$" \
|
|
|
|
| sed 's/server_name//' \
|
|
|
|
| tr -d ';' \
|
|
|
|
| sed 's/\s\{1,\}//' \
|
|
|
|
| sed 's/\s\{1,\}/\n/g' \
|
|
|
|
| sort \
|
|
|
|
| uniq
|
|
|
|
)
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
echo "$vhostfile" | grep -q apache2
|
2017-09-21 00:39:06 +02:00
|
|
|
if [ "$?" -eq 0 ]; then
|
2017-10-13 00:47:02 +02:00
|
|
|
domains=$(
|
|
|
|
grep -oE "^( )*[^#]+" "$vhostfile" \
|
|
|
|
| grep -oE "(ServerName|ServerAlias).*" \
|
|
|
|
| sed 's/ServerName//' \
|
|
|
|
| sed 's/ServerAlias//' \
|
|
|
|
| sed 's/\s\{1,\}//' \
|
|
|
|
| sort \
|
|
|
|
| uniq
|
|
|
|
)
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
|
|
|
valid_domains=""
|
|
|
|
nb=0
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
echo "Valid(s) domain(s) in ${VHOST} :"
|
2017-09-21 00:39:06 +02:00
|
|
|
for domain in $domains; do
|
2017-10-13 00:47:02 +02:00
|
|
|
real_ip=$(real_ip_for_domain "${domain}")
|
|
|
|
for ip in $(echo "${SRV_IP}" | xargs -n1); do
|
2017-09-21 00:39:06 +02:00
|
|
|
if [ "${ip}" = "${real_ip}" ]; then
|
2017-10-13 00:47:02 +02:00
|
|
|
valid_domains="${valid_domains} ${domain}"
|
|
|
|
nb=$(( nb + 1 ))
|
|
|
|
echo "* ${domain} -> ${real_ip}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
done
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
if [ "${nb}" -eq 0 ]; then
|
|
|
|
nb=$(echo "${domains}" | wc -l)
|
2017-09-21 00:39:06 +02:00
|
|
|
echo "* No valid domain found"
|
|
|
|
echo "All following(s) domain(s) will be used for CSR creation :"
|
|
|
|
for domain in $domains; do
|
2017-10-13 00:47:02 +02:00
|
|
|
echo "* ${domain}"
|
2017-09-21 00:39:06 +02:00
|
|
|
done
|
|
|
|
else
|
2017-10-13 00:47:02 +02:00
|
|
|
domains="${valid_domains}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
domains=$(echo "$domains" | xargs -n1)
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
make_key() {
|
2017-10-13 00:47:02 +02:00
|
|
|
openssl genrsa -out "${SSL_KEY_FILE}" "${SSL_KEY_SIZE}" 2>/dev/null
|
|
|
|
chown root: "${SSL_KEY_FILE}"
|
|
|
|
chmod 600 "${SSL_KEY_FILE}"
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
make_csr() {
|
2017-09-21 00:39:06 +02:00
|
|
|
domains="$1"
|
2017-10-13 00:47:02 +02:00
|
|
|
nb=$(echo "${domains}" | wc -l)
|
|
|
|
config_file="/tmp/make-csr-${VHOST}.conf"
|
|
|
|
|
|
|
|
mkdir -p -m 0755 "${CSR_DIR}"
|
2017-08-25 18:13:32 +02:00
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
if [ "${nb}" -eq 1 ]; then
|
|
|
|
cat ${SSL_CONFIG_FILE} - > "${config_file}" <<EOF
|
2017-08-25 18:13:32 +02:00
|
|
|
CN=$domains
|
|
|
|
EOF
|
2017-10-13 00:47:02 +02:00
|
|
|
openssl req -new -sha256 -key "${SSL_KEY_FILE}" -config "${config_file}" -out "${CSR_FILE}"
|
|
|
|
elif [ "${nb}" -gt 1 ]; then
|
|
|
|
san=""
|
|
|
|
for domain in $domains; do
|
|
|
|
san="${san},DNS:${domain}"
|
2017-09-21 00:39:06 +02:00
|
|
|
done
|
2017-10-13 00:47:02 +02:00
|
|
|
san=$(echo "${san}" | sed 's/,//')
|
|
|
|
cat ${SSL_CONFIG_FILE} - > "${config_file}" <<EOF
|
2017-08-25 18:13:32 +02:00
|
|
|
[SAN]
|
2017-10-13 00:47:02 +02:00
|
|
|
subjectAltName=${san}
|
2017-08-25 18:13:32 +02:00
|
|
|
EOF
|
2017-10-13 00:47:02 +02:00
|
|
|
openssl req -new -sha256 -key "${SSL_KEY_FILE}" -reqexts SAN -config "${config_file}" > "${CSR_FILE}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
if [ -f "${CSR_FILE}" ]; then
|
|
|
|
chmod 644 "${CSR_FILE}"
|
|
|
|
mkdir -p -m 0755 "${SELF_SIGNED_DIR}"
|
|
|
|
openssl x509 -req -sha256 -days 365 -in "${CSR_FILE}" -signkey "${SSL_KEY_FILE}" -out "${SELF_SIGNED_FILE}"
|
|
|
|
[ -f "${SELF_SIGNED_FILE}" ] && chmod 644 "${SELF_SIGNED_FILE}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
2017-02-03 15:52:48 +01:00
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
sed_selfsigned_cert_path_for_apache() {
|
|
|
|
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
|
2017-02-03 15:52:48 +01:00
|
|
|
SSLEngine On
|
2017-10-13 00:47:02 +02:00
|
|
|
SSLCertificateFile ${SELF_SIGNED_FILE}
|
|
|
|
SSLCertificateKeyFile ${SSL_KEY_FILE}
|
2017-02-03 15:52:48 +01:00
|
|
|
EOF
|
2017-09-21 00:39:06 +02:00
|
|
|
else
|
2017-10-13 00:47:02 +02:00
|
|
|
sed -i "s~^SSLCertificateFile.*$~SSLCertificateFile ${SELF_SIGNED_FILE}~" "${apache_ssl_vhost_path}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
2017-02-03 15:52:48 +01:00
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
sed_selfsigned_cert_path_for_nginx() {
|
|
|
|
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};
|
2017-02-03 15:52:48 +01:00
|
|
|
EOF
|
2017-09-21 00:39:06 +02:00
|
|
|
else
|
2017-10-13 00:47:02 +02:00
|
|
|
sed -i "s~^ssl_certificate[^_].*$~ssl_certificate ${SELF_SIGNED_FILE};~" "${nginx_ssl_vhost_path}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
first_vhost_file_found() {
|
|
|
|
vhost=$1
|
|
|
|
|
|
|
|
ls "/etc/nginx/sites-enabled/${vhost}" \
|
|
|
|
"/etc/nginx/sites-enabled/${vhost}.conf" \
|
|
|
|
"/etc/apache2/sites-enabled/${vhost}.conf" 2>/dev/null \
|
|
|
|
| head -n 1
|
|
|
|
}
|
|
|
|
|
|
|
|
default_key_size() {
|
|
|
|
grep default_bits ${SSL_CONFIG_FILE} \
|
|
|
|
| cut -d'=' -f2 \
|
|
|
|
| xargs
|
|
|
|
}
|
|
|
|
|
2017-08-25 18:13:32 +02:00
|
|
|
main() {
|
2017-09-21 00:39:06 +02:00
|
|
|
if [ "$#" -ne 1 ]; then
|
|
|
|
echo "You need to provide one argument !" >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
# Read configuration file, if it exists
|
2017-09-21 00:39:06 +02:00
|
|
|
[ -f /etc/default/evoacme ] && . /etc/default/evoacme
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
# Default value for main variables
|
|
|
|
CSR_DIR=${CSR_DIR:-'/etc/ssl/requests'}
|
|
|
|
CRT_DIR=${CRT_DIR:-'/etc/letsencrypt'}
|
|
|
|
SSL_CONFIG_FILE=${SSL_CONFIG_FILE:-"${CRT_DIR}/openssl.cnf"}
|
|
|
|
SELF_SIGNED_DIR=${SELF_SIGNED_DIR:-'/etc/ssl/self-signed'}
|
|
|
|
SSL_KEY_DIR=${SSL_KEY_DIR:-'/etc/ssl/private'}
|
|
|
|
SSL_KEY_SIZE=${SSL_KEY_SIZE:-$(default_key_size)}
|
|
|
|
SRV_IP=${SRV_IP:-""}
|
|
|
|
|
|
|
|
VHOST=$(basename "$1" .conf)
|
|
|
|
SELF_SIGNED_FILE="${SELF_SIGNED_DIR}/${VHOST}.pem"
|
|
|
|
SSL_KEY_FILE="${SSL_KEY_DIR}/${VHOST}.key"
|
|
|
|
LIVE_DIR="${CRT_DIR}/${VHOST}/live"
|
|
|
|
CSR_FILE="${CSR_DIR}/${VHOST}.csr"
|
|
|
|
|
2017-10-13 11:16:21 +02:00
|
|
|
LOCAL_IP=$(local_ip)
|
2017-10-13 00:47:02 +02:00
|
|
|
if [ -n "${SRV_IP}" ]; then
|
2017-10-13 11:16:21 +02:00
|
|
|
SRV_IP="${SRV_IP} ${LOCAL_IP}"
|
2017-10-13 00:47:02 +02:00
|
|
|
else
|
2017-10-13 11:16:21 +02:00
|
|
|
SRV_IP="${LOCAL_IP}"
|
2017-10-13 00:47:02 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
vhostfile=$(first_vhost_file_found "${VHOST}")
|
|
|
|
|
|
|
|
if [ ! -h "${vhostfile}" ]; then
|
|
|
|
echo "${VHOST} is not a valid virtualhost !" >&2
|
2017-09-21 00:39:06 +02:00
|
|
|
exit 1
|
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
|
2017-10-13 00:47:02 +02:00
|
|
|
if [ -f "${SSL_KEY_FILE}" ]; then
|
|
|
|
echo "${VHOST} key already exist, overwrite it? [yN]"
|
2017-09-21 00:39:06 +02:00
|
|
|
read REPLY
|
2017-10-13 00:47:02 +02:00
|
|
|
|
|
|
|
[ "${REPLY}" = "Y" ] || [ "${REPLY}" = "y" ] || exit 0
|
|
|
|
rm -f "/etc/apache2/ssl/${VHOST}.conf /etc/nginx/ssl/${VHOST}.conf"
|
|
|
|
[ -h "${LIVE_DIR}" ] && rm "${LIVE_DIR}"
|
2017-09-21 00:39:06 +02:00
|
|
|
fi
|
2017-08-25 18:13:32 +02:00
|
|
|
|
2017-09-21 00:39:06 +02:00
|
|
|
get_domains
|
|
|
|
make_key
|
2017-10-13 00:47:02 +02:00
|
|
|
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"
|
2017-08-25 18:13:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
main "$@"
|