evoacme: refactoring for make-csr

inspired from recent refactoring or evoacme itself
This commit is contained in:
Jérémy Lecour 2017-10-13 00:47:02 +02:00
parent 9fccd7e682
commit fb0c22dfd1

View file

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