LE_Wildcard/LE_Wildcard.sh

230 lines
12 KiB
Bash
Raw Normal View History

2020-05-19 20:19:26 +00:00
#!/bin/bash
# /volume1/homes/admin/script/LE_wildcard.sh create
# 1. Variablen für das Arbeitsverzeichnis, die Domainliste und ggf. die Mailadresse anpassen
2021-10-02 10:55:49 +00:00
# 2. das Skript mit dem Parameter 'create' als root aufrufen (die TXT-Records werden erstellt und ausgegeben) /pfad/zu/LE_wildcard.sh create
2020-05-19 20:19:26 +00:00
# 3. manuell die TXT-Records beim Anbieter anpassen
# 4. das Skript ohne Parameter aufrufen, um das Zertifikat zu erstellen / zu erneuern
# ➜ Das Default-Zertifikat des DSM wird erstetzt!
# ➜ Ebenso das Zertifikat aller Anwendungen, für die das Defaultzertifikat konfiguriert wurde!
# einige Quellen:
# http://www.stueben.de/lets-encrypt-wildcard/#comment-2208
# https://www.howtoforge.de/anleitung/erste-schritte-mit-acmesh-lets-encrypt-ssl-client/
# https://itnext.io/synology-lets-encrypt-dns-01-challenge-acme-sh-and-route53-af491786d262
# https://vdr.one/how-to-create-a-lets-encrypt-wildcard-certificate-on-a-synology-nas/
# https://letsencrypt.org/de/docs/rate-limits/
# ----- VARIABLEN ANPASSEN -----
WORKPATH="/volume1/homes/admin/_wildcardcert"
DOMAINLIST="-d *.domain1.de -d *.domain2.de -d domain1.de -d domain2.de" # jede Domain durch -d definieren!
ACCOUNTMAIL="mail@domain.de"
###################################################################################################################
# CERTPATH: in diesen Verzeichnissen speichert der DSM die Zertifikate
# bisher sind mir 2 Verzeichnisse bekannt:
CERTPATH=("/usr/local/etc/certificate/" "/usr/syno/etc/certificate/")
# Skript muss als root ausgeführt werden, da sonst kein Zugriff auf die Systemverzeichnisse möglich ist
if [ $(whoami) != "root" ]; then
echo "WARNUNG: das Skript muss von root ausgeführt werden!"
exit 1
fi
# Arbeitsordner ggf. erstellen
if [ ! -d "$WORKPATH/LE_CERT-home" ]; then
mkdir -p "$WORKPATH/LE_CERT-home"
fi
cd "$WORKPATH"
# ToDo: .acme.sh verwendet leider nicht die absoluten Pfadangaben …?
# --cert-file "$new_cert" --key-file "$new_privatkey" --ca-file "$new_intermediate_cert" --fullchain-file "$new_full_chain_certs"
# der Pfad zu den Dateien wird daher anhand des *.key-Files nach der "cert_create()"-Funktion ausgelesen
# new_cert="$WORKPATH/LE_CERT-home/cert-file.cer" # cert
# new_privatkey="$WORKPATH/LE_CERT-home/key-file.key" # private-key
# new_intermediate_cert="$WORKPATH/LE_CERT-home/ca.cer" # intermediate CA cert
# new_full_chain_certs="$WORKPATH/LE_CERT-home/fullchain.cer" # full_chain_certs
cert_create () {
# ----- ZERTIFIKAT VORBEREITEN -----
echo -n "Download acme.sh ➜ "
if [ -f ./acme.sh ]; then
echo "ok (bereits vorhanden / Version: $(get_key_value ./acme.sh VER))"
else
wget -q https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh
if [ -f ./acme.sh ]; then
echo "ok"
chmod a+x acme.sh
else
echo "fehlgeschlagen - das Skript wird beendet!"
exit
fi
fi
# create (Token für txt-Record):
echo "Zertifikatserstellung vorbereiten:"
echo "(folge den nachfolgenden Anweisungen im Output für den DNS txt-Record)"
# ./acme.sh --force --test --issue --home $WORKPATH --config-home "$WORKPATH" --cert-home "$WORKPATH/LE_CERT-home" --accountemail "${ACCOUNTMAIL}" ${DOMAINLIST} --cert-file "$new_cert" --key-file "$new_privatkey" --ca-file "$new_intermediate_cert" --fullchain-file "$new_full_chain_certs" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
./acme.sh --force --issue --home "$WORKPATH" --config-home "$WORKPATH" --cert-home "$WORKPATH/LE_CERT-home" --accountemail "${ACCOUNTMAIL}" ${DOMAINLIST} --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
exit 0
}
# initiale Zertifikatserstellung nur mit passendem Parameter (create) starten:
if [[ $1 = create ]]; then
cert_create
fi
# ----- PFADE FÜR DIE ZERTIFIKATE GENERIEREN -----
CERT_SUB_PATH=$(find "${WORKPATH}/LE_CERT-home" -name "*.key" -type f | head -n1 | sed -e "s%${WORKPATH}/LE_CERT-home%%g" )
# > den Fund könnte man noch mit der Domainliste abgleichen. So könnte man das Skript für mehrere Domains verwenden
CERT_SUB_PATH_AB="${CERT_SUB_PATH%.*}"
CERT_SUB_PATH_A="$(echo ${CERT_SUB_PATH_AB} | awk -F'/' '{print $2}' )"
new_cert="$WORKPATH/LE_CERT-home${CERT_SUB_PATH_AB}.cer" # cert
new_privatkey="$WORKPATH/LE_CERT-home${CERT_SUB_PATH_AB}.key" # private-key
new_intermediate_cert="$WORKPATH/LE_CERT-home/${CERT_SUB_PATH_A}/ca.cer" # intermediate CA cert
new_full_chain_certs="$WORKPATH/LE_CERT-home/${CERT_SUB_PATH_A}/fullchain.cer" # full_chain_certs
# ----- ZERTIFIKATE ERSTELLEN / ERNEUERN -----
echo -n "erstelle / erneuere das Zertifikat ➜ "
# acmeLOG=$(./acme.sh --force --home $WORKPATH --renew ${DOMAINLIST} --config-home "$WORKPATH" --accountemail "${ACCOUNTMAIL}" --cert-file "$new_cert" --key-file "$new_privatkey" --ca-file "$new_intermediate_cert" --fullchain-file "$new_full_chain_certs" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please )
acmeLOG=$(./acme.sh --force --home "$WORKPATH" --renew ${DOMAINLIST} --config-home "$WORKPATH" --cert-home "$WORKPATH/LE_CERT-home" --accountemail "${ACCOUNTMAIL}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please )
# Zertifikatserneuerung OK?:
if [ $? = 0 ]; then
if echo "$acmeLOG" | grep -q "Add the following TXT record" ; then
echo "! ! ! ACHTUNG ! ! ! TXT-Record muss erneuert werden"
echo "folge den nachstehenden Instruktionen und führe anschließend das Skript erneut aus:"
echo "$acmeLOG" | sed -e "s/^/ /g"
exit 0
fi
echo "ok"
echo -e
else
echo "FEHLER! Skript wird beendet"
echo "acme.sh - LOG:"
echo "$acmeLOG" | sed -e "s/^/ /g"
exit 1
fi
# ----- BACKUP & COPY CERTIFICATE -----
copy_cert () {
# diese Funktion
# ➜ identifiziert das Default-Zertifikat
# ➜ prüft die INFO-Datei, für welche Anwendung das Default-Zertifikat genutzt wird
# ➜ erstellt ein Backup der alten Zertifikatsdateien
# ➜ ersetzt die alten Zertifikatsdateien durch die erneuerten
# ➜ überträgt die Rechte und Besitzer von den alten Zertifikatsdateien auf die neuen
# ➜ startet im Abschluss den Webserver neu
copy_cert_sub () {
# Unterfunktion, da das Defaultzertifikat / Importpfad nicht durch die INFO abgedeckt wird
if [ -d "${TARGETPATH}" ]; then
BACKUPPATH="${BACKUPMAINPATH}/${SUBSCRIBER}"
echo " Speicherpfad: ➜ $TARGETPATH"
echo -n " Backup des alten Zertifikats ➜ "
if [ ! -d "${BACKUPPATH}" ]; then
mkdir -p "${BACKUPPATH}"
fi
# erstelle ein Backup für das aktuelle Verzeichnis
rsync -aHcxv "${TARGETPATH}" "${BACKUPPATH}" 2>&1 >/dev/null
if [ $? = 0 ]; then
echo "ok"
else
echo " Backup fehlgeschlagen! Nächster Ordner:"
return
fi
# identifiziere die Art der Dateiberechtigung:
if echo $( synoacltool -get "${BACKUPPATH}/${SERVICE}/cert.pem" ) | grep -q is_support_ACL ; then
permissions=acl
else
permissions=standard
fi
echo -n " Zertifikat ersetzen ➜ "
cp -f "$new_cert" "${TARGETPATH}/cert.pem"
cp -f "$new_privatkey" "${TARGETPATH}/privkey.pem"
cp -f "$new_intermediate_cert" "${TARGETPATH}/chain.pem"
cp -f "$new_full_chain_certs" "${TARGETPATH}/fullchain.pem"
# kopierte Dateien verifizieren:
copystate=0
if [[ $(/bin/md5sum "$new_cert" | awk '{print $1}') != $(/bin/md5sum "${TARGETPATH}/cert.pem" | awk '{print $1}') ]]; then
copystate=1
elif [[ $(/bin/md5sum "$new_privatkey" | awk '{print $1}') != $(/bin/md5sum "${TARGETPATH}/privkey.pem" | awk '{print $1}') ]]; then
copystate=1
elif [[ $(/bin/md5sum "$new_intermediate_cert" | awk '{print $1}') != $(/bin/md5sum "${TARGETPATH}/chain.pem" | awk '{print $1}') ]]; then
copystate=1
elif [[ $(/bin/md5sum "$new_full_chain_certs" | awk '{print $1}') != $(/bin/md5sum "${TARGETPATH}/fullchain.pem" | awk '{print $1}') ]]; then
copystate=1
fi
if [[ $copystate = 1 ]]; then
echo "fehlgeschlagen!"
continue
else
echo "fertig"
fi
# Übertrage Dateiattribute:
# ToDo: evtl. owner aus INFO übertragen
echo -n " Übertrage Dateiattribute ➜ "
if [ $permissions = acl ]; then
echo "(ACL)"
synoacltool -copy "${BACKUPPATH}/${SERVICE}/cert.pem" "${TARGETPATH}/cert.pem"
synoacltool -copy "${BACKUPPATH}/${SERVICE}/privkey.pem" "${TARGETPATH}/privkey.pem"
synoacltool -copy "${BACKUPPATH}/${SERVICE}/cert.pem" "${TARGETPATH}/cert.pem"
synoacltool -copy "${BACKUPPATH}/${SERVICE}/cert.pem" "${TARGETPATH}/cert.pem"
else
echo "(Standard Linuxrechte)"
cp --attributes-only -p "${BACKUPPATH}/${SERVICE}/cert.pem" "${TARGETPATH}/cert.pem"
cp --attributes-only -p "${BACKUPPATH}/${SERVICE}/privkey.pem" "${TARGETPATH}/privkey.pem"
cp --attributes-only -p "${BACKUPPATH}/${SERVICE}/chain.pem" "${TARGETPATH}/chain.pem"
cp --attributes-only -p "${BACKUPPATH}/${SERVICE}/fullchain.pem" "${TARGETPATH}/fullchain.pem"
fi
echo -e
fi
}
BACKUPMAINPATH="$WORKPATH/BackUP/$(date +%Y-%m-%d_%H-%M)"
for count in $(cat /usr/syno/etc/certificate/_archive/INFO | jq -r ".$(cat /usr/syno/etc/certificate/_archive/DEFAULT).services | to_entries | .[] | .key" 2>/dev/null) ; do
# Parameter aus INFO-File separieren (für DEFAULT-Zertifikat):
string=$(cat /usr/syno/etc/certificate/_archive/INFO | jq -r ".$(cat /usr/syno/etc/certificate/_archive/DEFAULT).services | to_entries" | jq -r ".[${count}].value")
SUBSCRIBER=$(echo "$string" | grep subscriber | awk '{print $2}' | sed -e "s/\"//g ; s/,$//g") # Hauptordner
SERVICE=$(echo "$string" | grep service | awk '{print $2}' | sed -e "s/\"//g ; s/,$//g") # Subordner
DISPLAY_NAME=$(echo "$string" | grep "\"display_name\"\:" | awk -F': ' '{print $2}' | sed -e "s/\"//g ; s/,$//g" )
echo "aktualisiere Zertifikat für >>> ${DISPLAY_NAME} <<<"
# suche das passende Verzeichnis für den Dienst und kopiere Zertifikat
# (das passende Elternverzeichnis der einzelnen Dienstezertifikate ist nicht in der INFO hinterlegt, daher muss gesucht werden):
for i in ${CERTPATH[@]}; do
TARGETPATH="${i}${SUBSCRIBER}/${SERVICE}"
copy_cert_sub
done
done
# aktualisiere das Default-Zertifikat im Importverzeichnis:
echo "aktualisiere noch das Zertifikat im Importverzeichnis: "
SUBSCRIBER="DSM_ImportDirectory"
SERVICE="$(cat /usr/syno/etc/certificate/_archive/DEFAULT)"
TARGETPATH="/usr/syno/etc/certificate/_archive/$(cat /usr/syno/etc/certificate/_archive/DEFAULT)"
copy_cert_sub
2021-09-23 11:55:34 +00:00
2020-05-19 20:19:26 +00:00
echo "abschließend Webserver neustarten"
2021-09-23 11:55:34 +00:00
if [ $(synogetkeyvalue /etc.defaults/VERSION majorversion) -ge 7 ]; then
# Neuer Befehl (DSM7)
/usr/bin/systemct restart nginx
else
# Alter Befehl (DSM6)
/usr/syno/sbin/synoservicectl --reload nginx
fi
2020-05-19 20:19:26 +00:00
}
copy_cert
exit 0