Aller au contenu

philou65

Membres
  • Inscription

  • Dernière visite

  1. Bonjour à Tous, Désolé de pas être très actif sur le forum par manque de temps en particulier. Mais je m'en remet à vos connaissances en la matières car je ne suis pas très compétent en commande Linux. Mon objectif est d'utiliser le planificateur de tâches du Synology pour la tâche suivante : Copy certificat let's encrypt existant d'un Nas source vers un autre Nas cible. J'ai 3 Nas Synology dont le 1er a un certificat "Let's Encrypt" qui se renouvelle régulièrement. Jusqu'à présent, je suis obligé de copier manuellement le dernier certificat à jour du 1er vers les 2 autres. Reprenez moi si je dis une bêtise, mais actuellement (sur les 2 autres NAS), il n'est pas possible de renouvellement (en mode auto tous les 3 mois) pour un même nom de domaine : Let's Encrypt ne le permet pas. J'ai donc demandé à une IA de me créer un script pour effectuer cette action mais je n'ai aucune certitude de son bon fonctionnement, pire créer des erreurs ou disfonctionnement du Nas cible. Ce script est ajouter sur le NAS source qui a le renouvellement automatique fonctionnel. Il vérifie si un changement de version de certificat a eu lieu sur le Nas source, et seulement si, effectuer les vérifications sur le Nas cible pour renouvellement, redémarre les services et contrôle si toutes les tâches se sont appliquées sans erreurs. Chose importante, ce script impose l'ouverture du service SSH sur les NAS. Je ne suis pas très chaud à faire cela pour les raisons évidentes de sécurité. S'il est possible de modifier ce besoin ou bien de le sécurisé, je suis à votre écoute. Je vous fourni le script ci-dessous, en espérant qu'une personne attentive et compétente prendra le temps de vérifier et me conseiller. Je suis preneur de tout autre script existant pour cette tâche si déjà existante. Vous remerciant par avance à ceux qui me lirons. PS : ce qui est en couleur est à personnaliser selon votre environnement En cas d'erreur, ne pas hésiter à me le faire savoir Cordialement **************************************************************************************************************** #!/bin/bash # ============================================================ # "VOTRE_NOM DE DOMAINE" certificate synchronisation - V3 # # Source: # NAS 1 # # Destination: # IP_NAS_CIBLE # # DSM 7.2.2-72806 Update 6 (version du DSM à préciser - Idéalement identique aux 2 Nas) # # Fonctions: # - auto-détection certificat via INFO # - détection renouvellement SHA256 # - transfert SSH/SCP # - import SYNO.Core.Certificate # - prise en compte restart_httpd # - vérification certificat installé # - vérification certificat HTTPS réellement présenté # - journalisation # - notification DSM en cas d'erreur # # ============================================================ set -u # ============================================================ # CONFIGURATION # ============================================================ CERT_NAME="VOTRE_NOM_DE_DOMAINE" NAS2="192.168.26.156" NAS2_USER="root" ARCHIVE_BASE="/usr/syno/etc/certificate/_archive" INFO_FILE="${ARCHIVE_BASE}/INFO" LOG_FILE="/var/log/VOTRE_NOM_DE_DOMAINE-cert-sync.log" LOG_MAX_SIZE=2097152 STATE_DIR="/usr/local/etc" STATE_FILE="${STATE_DIR}/VOTRE_NOM_DE_DOMAINE-cert-sync.sha256" REMOTE_TMP="/tmp/VOTRE_NOM_DE_DOMAINE-cert-sync" # HTTPS à vérifier sur NAS 2 HTTPS_HOST="IP_NAS_CIBLE" HTTPS_PORT="PORT_NAS_CIBLE" # Nombre de tentatives après import VERIFY_RETRIES=12 # secondes entre deux tentatives VERIFY_DELAY=5 # SSH SSH_OPTS=" -o BatchMode=yes -o ConnectTimeout=10 -o ServerAliveInterval=10 -o ServerAliveCountMax=3 " # ============================================================ # LOG # ============================================================ log() { echo "$(date '+%Y-%m-%d %H:%M:%S') | $*" >> "${LOG_FILE}" } # ============================================================ # NOTIFICATION # ============================================================ notify() { TITLE="$1" MESSAGE="$2" # -------------------------------------------------------- # Notification DSM. # # synodsmnotify est conservé comme notification locale. # Selon DSM/configuration, les chaînes libres peuvent être # ignorées car DSM 7 documente normalement des clés I18N. # -------------------------------------------------------- if [ -x /usr/syno/bin/synodsmnotify ]; then /usr/syno/bin/synodsmnotify \ @administrators \ "${TITLE}" \ "${MESSAGE}" \ >/dev/null 2>&1 || true fi } # ============================================================ # ERREUR # ============================================================ error_exit() { MSG="$1" log "============================================================" log "ERREUR | ${MSG}" log "============================================================" notify \ "Certificat ${CERT_NAME}" \ "Erreur synchronisation NAS 2 : ${MSG}" exit 1 } # ============================================================ # ROTATION LOG # ============================================================ mkdir -p "$(dirname "${LOG_FILE}")" if [ -f "${LOG_FILE}" ]; then LOG_SIZE=$(wc -c < "${LOG_FILE}" 2>/dev/null || echo 0) if [ "${LOG_SIZE}" -ge "${LOG_MAX_SIZE}" ]; then mv "${LOG_FILE}" "${LOG_FILE}.1" 2>/dev/null || true fi fi touch "${LOG_FILE}" || exit 1 chmod 600 "${LOG_FILE}" # ============================================================ # DEBUT # ============================================================ log "============================================================" log "Début synchronisation ${CERT_NAME}" log "============================================================" # ============================================================ # ROOT # ============================================================ if [ "$(id -u)" != "0" ]; then error_exit "Le script doit être exécuté en root." fi # ============================================================ # VERIFICATION COMMANDES # ============================================================ for CMD in jq openssl sha256sum ssh scp timeout; do if ! command -v "${CMD}" >/dev/null 2>&1; then error_exit "Commande absente : ${CMD}" fi done # ============================================================ # AUTO-DETECTION CERTIFICAT NAS 1 # ============================================================ if [ ! -f "${INFO_FILE}" ]; then error_exit "INFO introuvable : ${INFO_FILE}" fi SOURCE_CERT_ID=$( jq -r \ --arg CERT "${CERT_NAME}" \ ' to_entries[] | select( any( .value.services[]?; .display_name == $CERT ) ) | .key ' "${INFO_FILE}" | head -n 1 ) if [ -z "${SOURCE_CERT_ID}" ] || [ "${SOURCE_CERT_ID}" = "null" ]; then error_exit \ "Certificat ${CERT_NAME} introuvable sur NAS 1." fi SOURCE_DIR="${ARCHIVE_BASE}/${SOURCE_CERT_ID}" log "Certificat NAS 1 : ${SOURCE_CERT_ID}" log "Répertoire : ${SOURCE_DIR}" # ============================================================ # VERIFICATION FICHIERS SOURCE # ============================================================ for FILE in cert.pem chain.pem privkey.pem; do if [ ! -s "${SOURCE_DIR}/${FILE}" ]; then error_exit \ "Fichier source absent ou vide : ${FILE}" fi done # ============================================================ # VALIDATION CERTIFICAT # ============================================================ if ! openssl x509 \ -in "${SOURCE_DIR}/cert.pem" \ -noout >/dev/null 2>&1; then error_exit "Certificat source invalide." fi SOURCE_SUBJECT=$( openssl x509 \ -in "${SOURCE_DIR}/cert.pem" \ -noout -subject ) SOURCE_ISSUER=$( openssl x509 \ -in "${SOURCE_DIR}/cert.pem" \ -noout -issuer ) SOURCE_ENDDATE=$( openssl x509 \ -in "${SOURCE_DIR}/cert.pem" \ -noout -enddate ) SOURCE_SERIAL=$( openssl x509 \ -in "${SOURCE_DIR}/cert.pem" \ -noout -serial ) log "Sujet : ${SOURCE_SUBJECT}" log "Émetteur : ${SOURCE_ISSUER}" log "Expiration : ${SOURCE_ENDDATE}" log "Serial : ${SOURCE_SERIAL}" # ============================================================ # EMPREINTE # ============================================================ CURRENT_HASH=$( { sha256sum "${SOURCE_DIR}/cert.pem" sha256sum "${SOURCE_DIR}/chain.pem" sha256sum "${SOURCE_DIR}/privkey.pem" } | sha256sum | awk '{print $1}' ) log "Empreinte actuelle : ${CURRENT_HASH}" # ============================================================ # DETECTION RENOUVELLEMENT # ============================================================ if [ -f "${STATE_FILE}" ]; then OLD_HASH=$(cat "${STATE_FILE}" 2>/dev/null) log "Empreinte précédente : ${OLD_HASH}" if [ "${CURRENT_HASH}" = "${OLD_HASH}" ]; then log "Aucun changement détecté." log "Fin." log "============================================================" exit 0 fi log "Nouveau certificat détecté." else log "Première exécution : aucune empreinte précédente." fi # ============================================================ # SSH NAS 2 # ============================================================ log "Connexion SSH vers ${NAS2}..." if ! ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "echo SSH_OK" 2>/dev/null | grep -q "SSH_OK"; then error_exit \ "Connexion SSH impossible vers ${NAS2}." fi log "SSH OK." # ============================================================ # AUTO-DETECTION CERTIFICAT NAS 2 # ============================================================ REMOTE_CERT_ID=$( ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "jq -r --arg CERT '${CERT_NAME}' ' to_entries[] | select( any( .value.services[]?; .display_name == \$CERT ) ) | .key ' /usr/syno/etc/certificate/_archive/INFO" \ 2>/dev/null | head -n 1 ) if [ -z "${REMOTE_CERT_ID}" ] || [ "${REMOTE_CERT_ID}" = "null" ]; then error_exit \ "Certificat ${CERT_NAME} introuvable sur NAS 2." fi REMOTE_CERT_DIR="${ARCHIVE_BASE}/${REMOTE_CERT_ID}" log "Certificat NAS 2 : ${REMOTE_CERT_ID}" log "Répertoire : ${REMOTE_CERT_DIR}" # ============================================================ # PREPARATION TEMPORAIRE # ============================================================ log "Préparation transfert..." if ! ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "rm -rf '${REMOTE_TMP}' && mkdir -m 700 '${REMOTE_TMP}'"; then error_exit \ "Impossible de créer le répertoire temporaire NAS 2." fi # ============================================================ # NETTOYAGE DISTANT EN CAS D'ERREUR # ============================================================ cleanup_remote() { ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "rm -rf '${REMOTE_TMP}'" \ >/dev/null 2>&1 || true } # ============================================================ # COPIE # ============================================================ log "Copie cert.pem..." if ! scp ${SSH_OPTS} \ "${SOURCE_DIR}/cert.pem" \ "${NAS2_USER}@${NAS2}:${REMOTE_TMP}/cert.pem"; then cleanup_remote error_exit "Copie cert.pem échouée." fi log "Copie chain.pem..." if ! scp ${SSH_OPTS} \ "${SOURCE_DIR}/chain.pem" \ "${NAS2_USER}@${NAS2}:${REMOTE_TMP}/chain.pem"; then cleanup_remote error_exit "Copie chain.pem échouée." fi log "Copie privkey.pem..." if ! scp ${SSH_OPTS} \ "${SOURCE_DIR}/privkey.pem" \ "${NAS2_USER}@${NAS2}:${REMOTE_TMP}/privkey.pem"; then cleanup_remote error_exit "Copie privkey.pem échouée." fi ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "chmod 600 '${REMOTE_TMP}/privkey.pem'" log "Copie terminée." # ============================================================ # IMPORT DSM # ============================================================ log "Import certificat dans DSM..." REMOTE_RESULT=$( ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ bash <<REMOTE_SCRIPT set -u CERT_ID="${REMOTE_CERT_ID}" TMP="${REMOTE_TMP}" for FILE in cert.pem chain.pem privkey.pem; do if [ ! -s "\${TMP}/\${FILE}" ]; then echo '{"success":false,"error":"Fichier manquant"}' rm -rf "\${TMP}" exit 1 fi done # Validation certificat if ! openssl x509 \ -in "\${TMP}/cert.pem" \ -noout >/dev/null 2>&1; then echo '{"success":false,"error":"Certificat invalide"}' rm -rf "\${TMP}" exit 1 fi # ------------------------------------------------------------ # Import DSM # ------------------------------------------------------------ RESULT=\$( /usr/syno/bin/synowebapi \ --exec-fastwebapi \ api="SYNO.Core.Certificate" \ method="import" \ version="1" \ key_tmp="\"\${TMP}/privkey.pem\"" \ cert_tmp="\"\${TMP}/cert.pem\"" \ inter_cert_tmp="\"\${TMP}/chain.pem\"" \ id="\"\${CERT_ID}\"" \ desc="\"${CERT_NAME}\"" \ 2>&1 ) RET=\$? echo "\${RESULT}" rm -rf "\${TMP}" exit \${RET} REMOTE_SCRIPT ) REMOTE_RET=$? log "Réponse API : ${REMOTE_RESULT}" if [ "${REMOTE_RET}" -ne 0 ]; then error_exit \ "API DSM : code retour ${REMOTE_RET}." fi # ============================================================ # RESULTAT API # ============================================================ API_SUCCESS=$( echo "${REMOTE_RESULT}" | jq -r '.success // false' 2>/dev/null ) if [ "${API_SUCCESS}" != "true" ]; then error_exit \ "DSM n'a pas confirmé l'import." fi log "Import DSM réussi." # ============================================================ # DETECTION RESTART HTTPD # ============================================================ RESTART_HTTPD=$( echo "${REMOTE_RESULT}" | jq -r '.data.restart_httpd // .restart_httpd // false' \ 2>/dev/null ) log "restart_httpd : ${RESTART_HTTPD}" # ============================================================ # SI DSM DEMANDE RESTART HTTP # ============================================================ if [ "${RESTART_HTTPD}" = "true" ]; then log "DSM demande un redémarrage/rechargement HTTP." # -------------------------------------------------------- # On ne tue PAS nginx directement. # # On laisse DSM gérer ses services. # -------------------------------------------------------- ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "/usr/syno/bin/synowebapi \ --exec-fastwebapi \ api='SYNO.Core.Web.DSM' \ method='restart' \ version='1' \ >/dev/null 2>&1 || true" \ >/dev/null 2>&1 || true log "Commande de rechargement HTTP envoyée." else log "DSM n'indique pas de redémarrage HTTP nécessaire." fi # ============================================================ # ATTENTE DU SERVICE HTTPS # ============================================================ log "Attente disponibilité HTTPS NAS 2..." HTTPS_READY="false" for i in $(seq 1 "${VERIFY_RETRIES}"); do if timeout 5 bash -c \ "</dev/tcp/${HTTPS_HOST}/${HTTPS_PORT}" \ >/dev/null 2>&1; then HTTPS_READY="true" log "HTTPS disponible après ${i} tentative(s)." break fi log "HTTPS indisponible - tentative ${i}/${VERIFY_RETRIES}" sleep "${VERIFY_DELAY}" done if [ "${HTTPS_READY}" != "true" ]; then error_exit \ "HTTPS ${HTTPS_HOST}:${HTTPS_PORT} ne répond pas après import." fi # ============================================================ # VERIFICATION CERTIFICAT DANS ARCHIVE DSM # ============================================================ log "Vérification certificat dans _archive..." REMOTE_SERIAL=$( ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "openssl x509 \ -in '${REMOTE_CERT_DIR}/cert.pem' \ -noout -serial" \ 2>/dev/null ) if [ "${REMOTE_SERIAL}" != "${SOURCE_SERIAL}" ]; then error_exit \ "Serial du certificat installé différent." fi log "Serial _archive : OK." # ============================================================ # VERIFICATION SHA256 CERTIFICAT PUBLIC # ============================================================ SOURCE_CERT_HASH=$( sha256sum "${SOURCE_DIR}/cert.pem" | awk '{print $1}' ) REMOTE_CERT_HASH=$( ssh ${SSH_OPTS} \ "${NAS2_USER}@${NAS2}" \ "sha256sum '${REMOTE_CERT_DIR}/cert.pem'" | awk '{print $1}' ) if [ "${SOURCE_CERT_HASH}" != "${REMOTE_CERT_HASH}" ]; then error_exit \ "SHA256 du certificat _archive différent." fi log "SHA256 _archive : OK." # ============================================================ # VERIFICATION CERTIFICAT PRESENTE PAR HTTPS # # On interroge le NAS 2 directement. # # -servername = VOTRE_NOM_DE_DOMAINE.me # permet de tester le certificat du bon virtual host. # ============================================================ log "Vérification certificat réellement présenté par HTTPS..." REMOTE_HTTPS_SERIAL=$( echo | timeout 15 openssl s_client \ -connect "${HTTPS_HOST}:${HTTPS_PORT}" \ -servername "${CERT_NAME}" \ -showcerts \ 2>/dev/null | openssl x509 \ -noout \ -serial 2>/dev/null ) if [ -z "${REMOTE_HTTPS_SERIAL}" ]; then error_exit \ "Impossible de récupérer le certificat présenté par HTTPS." fi log "Serial HTTPS : ${REMOTE_HTTPS_SERIAL}" if [ "${REMOTE_HTTPS_SERIAL}" != "${SOURCE_SERIAL}" ]; then error_exit \ "Le certificat présenté par HTTPS ne correspond pas au certificat source." fi log "Certificat HTTPS : OK." # ============================================================ # VERIFICATION DATE D'EXPIRATION HTTPS # ============================================================ REMOTE_HTTPS_ENDDATE=$( echo | timeout 15 openssl s_client \ -connect "${HTTPS_HOST}:${HTTPS_PORT}" \ -servername "${CERT_NAME}" \ 2>/dev/null | openssl x509 \ -noout \ -enddate 2>/dev/null ) log "Expiration HTTPS : ${REMOTE_HTTPS_ENDDATE}" # ============================================================ # SAUVEGARDE ETAT # ============================================================ mkdir -p "${STATE_DIR}" echo "${CURRENT_HASH}" > "${STATE_FILE}" chmod 600 "${STATE_FILE}" log "Nouvelle empreinte enregistrée." # ============================================================ # SUCCES # ============================================================ log "============================================================" log "SUCCES" log "Certificat ${CERT_NAME} synchronisé vers NAS 2." log "Certificat DSM : ${REMOTE_CERT_ID}" log "Serial : ${SOURCE_SERIAL}" log "HTTPS : vérifié" log "============================================================" notify \ "Certificat ${CERT_NAME}" \ "Certificat renouvelé et vérifié sur le NAS 2." exit 0

Account

Navigation

Rechercher

Rechercher

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.