Files
ROMFASTSQL/proxmox/vm201-windows/scripts/monitor-ssl-certificates.sh
Claude Agent 525919926c fix(vm201): roa-qr cert auto-renew + add to SSL monitor
Cauza ERR_CERT_DATE_INVALID pe roa-qr.romfast.ro: renewal-ul win-acme
avea Installation plugin "None" in loc de IIS -> certul se reinnoia in
store dar binding-ul SNI ramanea pe certul vechi (expirat 31 mai).

- monitor-ssl-certificates.sh: adaugat roa-qr.romfast.ro (Site ID 5);
  normalizat CRLF->LF (CRLF dadea exit 127 la exec pe Linux)
- docs: box incident 2026-06-25 cu cauza-radacina + diagnostic per renewal

Fix aplicat pe VM 201: plugin install None->IIS in renewal.json + force
renew (cert nou valid pana 23 sep 2026, binding auto-actualizat).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:01:00 +00:00

174 lines
5.1 KiB
Bash

#!/bin/bash
# Script: monitor-ssl-certificates.sh
# Locatie: /opt/scripts/monitor-ssl-certificates.sh (pe pvemini)
# Scop: Verifica certificatele SSL extern si alerteaza/forteaza reinstalare
# Rulare: Cron zilnic sau la cerere
set -e
# Configurare
DAYS_WARNING=14
DAYS_CRITICAL=7
LOG_FILE="/var/log/ssl-monitor.log"
EMAIL_TO="root" # Proxmox trimite la adresa configurata
# Domenii de verificat
# NOTA: efactura.roa.romfast.ro este un SENTINEL pentru certificatul wildcard
# *.roa.romfast.ro. Wildcardul nu poate fi testat direct, asa ca verificam
# un subdomeniu real acoperit de el. Site ID "WILDCARD" => doar ALERTA,
# fara auto-renew (wildcardul e DNS-01, reinnoit de cpanel-acme-dns.ps1 pe
# VM 201; auto-renew prin guest-exec nu mai functioneaza - exec dezactivat).
# Context: incident expirare wildcard 2026-05-31 (vezi README VM 201).
DOMAINS=(
"roa.romfast.ro"
"dokploy.romfast.ro"
"gitea.romfast.ro"
"roa2web.romfast.ro"
"roa-qr.romfast.ro"
"efactura.roa.romfast.ro"
)
# Site IDs pentru fiecare domeniu (in aceeasi ordine)
SITE_IDS=(1 2 3 4 5 "WILDCARD")
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
check_certificate() {
local domain=$1
local expiry_date expiry_epoch now_epoch days_left
# Obtine data expirare
expiry_date=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [[ -z "$expiry_date" ]]; then
echo "-1"
return
fi
# Calculeaza zilele ramase
expiry_epoch=$(date -d "$expiry_date" +%s 2>/dev/null)
now_epoch=$(date +%s)
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
echo "$days_left"
}
force_renew_certificate() {
local site_id=$1
local domain=$2
# Wildcard (*.roa) = DNS-01, reinnoit automat de cpanel-acme-dns.ps1 pe VM 201.
# Nu incercam auto-renew aici (nu e HTTP-01/siteid si guest-exec e dezactivat) -
# doar semnalam ca a expirat ca sa intervina cineva pe VM 201.
if ! [[ "$site_id" =~ ^[0-9]+$ ]]; then
log "ALERTA: $domain (wildcard *.roa) necesita interventie manuala pe VM 201 - verifica renewal-ul win-acme cu validare cPanel (cpanel-acme-dns.ps1)"
return 1
fi
log "Fortez reinstalare certificat pentru $domain (Site ID: $site_id)..."
# Executa pe VM 201 prin Proxmox guest agent
result=$(qm guest exec 201 -- powershell -Command \
"cd C:\\Tools\\win-acme; .\\wacs.exe --target iis --siteid $site_id --installation iis --force" 2>&1)
if echo "$result" | grep -q '"exitcode" : 0'; then
log "SUCCES: Certificat reinstalat pentru $domain"
return 0
else
log "EROARE: Reinstalare esuata pentru $domain"
log "$result"
return 1
fi
}
restart_iis() {
log "Restart IIS..."
qm guest exec 201 -- cmd /c "iisreset" >/dev/null 2>&1
log "IIS restartat"
}
send_alert() {
local subject=$1
local body=$2
# Foloseste sistemul de notificari Proxmox
if command -v pvesh &>/dev/null; then
echo "$body" | mail -s "$subject" "$EMAIL_TO" 2>/dev/null || true
fi
log "ALERT: $subject"
}
# Main
log "========== Verificare certificate SSL =========="
warnings=()
criticals=()
renewed=0
for i in "${!DOMAINS[@]}"; do
domain="${DOMAINS[$i]}"
site_id="${SITE_IDS[$i]}"
days_left=$(check_certificate "$domain")
if [[ "$days_left" == "-1" ]]; then
log "EROARE: Nu pot verifica $domain"
criticals+=("$domain: Nu pot obtine certificatul")
continue
fi
log "$domain: $days_left zile ramase"
if [[ $days_left -lt 0 ]]; then
criticals+=("$domain: EXPIRAT!")
# Forteaza reinstalare
if force_renew_certificate "$site_id" "$domain"; then
((renewed++))
fi
elif [[ $days_left -lt $DAYS_CRITICAL ]]; then
criticals+=("$domain: expira in $days_left zile")
# Forteaza reinstalare
if force_renew_certificate "$site_id" "$domain"; then
((renewed++))
fi
elif [[ $days_left -lt $DAYS_WARNING ]]; then
warnings+=("$domain: expira in $days_left zile")
# Forteaza reinstalare preventiv
if force_renew_certificate "$site_id" "$domain"; then
((renewed++))
fi
fi
done
# Restart IIS daca am reinoit
if [[ $renewed -gt 0 ]]; then
restart_iis
fi
# Trimite alerte
if [[ ${#criticals[@]} -gt 0 ]]; then
body="Certificate SSL CRITICE:\n\n"
for msg in "${criticals[@]}"; do
body+="- $msg\n"
done
body+="\nActiuni intreprinse: $renewed certificate reinstalate"
send_alert "[CRITICAL] Certificate SSL expirate/aproape de expirare" "$body"
fi
if [[ ${#warnings[@]} -gt 0 && ${#criticals[@]} -eq 0 ]]; then
body="Certificate SSL WARNING:\n\n"
for msg in "${warnings[@]}"; do
body+="- $msg\n"
done
body+="\nActiuni intreprinse: $renewed certificate reinstalate"
send_alert "[WARNING] Certificate SSL aproape de expirare" "$body"
fi
log "========== Sumar: $renewed reinstalate, ${#warnings[@]} warnings, ${#criticals[@]} critice =========="
exit 0