From 096e9833137e1400d89152e7a404c0c861a77f19 Mon Sep 17 00:00:00 2001 From: boban Date: Sun, 26 Apr 2026 08:27:49 +0200 Subject: [PATCH] Fix: SSL-Cert-Status zeigt 'Fehlt' obwohl Cert vorhanden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: /etc/letsencrypt/archive/ ist chmod 700 (root only). file_exists() auf Symlinks in live/ schlägt fehl weil Symlink-Ziel in archive/ nicht lesbar ist. is_dir() auf live/domain/ funktioniert da das Verzeichnis selbst 755 ist. - SettingsForm: file_exists() → is_dir() für Existenzcheck - SettingsForm: openssl-Aufruf via sudo -n (archive/ ist root-only) - installer.sh + update.sh: sudoers-Regel für openssl auf LE-Cert-Pfade (www-data darf nur exakt diesen openssl-Aufruf, keine anderen Pfade) Co-Authored-By: Claude Sonnet 4.6 --- app/Livewire/Ui/System/SettingsForm.php | 10 +++++++--- installer.sh | 1 + scripts/update.sh | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/Livewire/Ui/System/SettingsForm.php b/app/Livewire/Ui/System/SettingsForm.php index 8107ec2..9825267 100644 --- a/app/Livewire/Ui/System/SettingsForm.php +++ b/app/Livewire/Ui/System/SettingsForm.php @@ -296,12 +296,16 @@ class SettingsForm extends Component $certs[$key] = ['domain' => '', 'has_cert' => false, 'expiry' => null, 'status' => 'nodomain']; continue; } - $certFile = "/etc/letsencrypt/live/{$domain}/fullchain.pem"; - if (! file_exists($certFile)) { + $certDir = "/etc/letsencrypt/live/{$domain}"; + $certFile = "{$certDir}/fullchain.pem"; + // live/ ist 755 (traversierbar), archive/ ist 700 — file_exists() schlägt fehl + // weil der Symlink auf archive/ zeigt. is_dir() auf live/domain/ funktioniert. + if (! is_dir($certDir)) { $certs[$key] = ['domain' => $domain, 'has_cert' => false, 'expiry' => null, 'status' => 'missing']; continue; } - $expiry = trim((string) @shell_exec("openssl x509 -enddate -noout -in " . escapeshellarg($certFile) . " 2>/dev/null | sed 's/notAfter=//'")); + // sudo nötig weil archive/ (Symlink-Ziel) nur root lesbar ist + $expiry = trim((string) @shell_exec("sudo -n openssl x509 -enddate -noout -in " . escapeshellarg($certFile) . " 2>/dev/null | sed 's/notAfter=//'")); $expiryTs = $expiry ? strtotime($expiry) : null; $daysLeft = $expiryTs ? (int) round(($expiryTs - time()) / 86400) : null; $certStatus = match (true) { diff --git a/installer.sh b/installer.sh index 7374555..b9359fb 100644 --- a/installer.sh +++ b/installer.sh @@ -591,6 +591,7 @@ www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-apply-domains www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-fetch-tags www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-update www-data ALL=(root) NOPASSWD: /usr/bin/certbot +www-data ALL=(root) NOPASSWD: /usr/bin/openssl x509 -enddate -noout -in /etc/letsencrypt/live/*/fullchain.pem SUDOERS chmod 440 /etc/sudoers.d/mailwolt-certbot diff --git a/scripts/update.sh b/scripts/update.sh index 256e4f3..39303e7 100644 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -324,7 +324,15 @@ echo "[✓] Update abgeschlossen: ${OLD_VER} → ${NEW_VER} (${OLD_REV:0:7} → install -m 755 "${APP_DIR}/scripts/mailwolt-fetch-tags" /usr/local/sbin/mailwolt-fetch-tags install -m 755 "${APP_DIR}/scripts/update.sh" /usr/local/sbin/mailwolt-update -# Sudoers: sicherstellen dass mailwolt-fetch-tags eingetragen ist (Upgrade-Pfad für bestehende Instanzen) -if [[ -f /etc/sudoers.d/mailwolt-certbot ]] && ! grep -q 'mailwolt-fetch-tags' /etc/sudoers.d/mailwolt-certbot; then - echo 'www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-fetch-tags' >> /etc/sudoers.d/mailwolt-certbot -fi \ No newline at end of file +# Sudoers: fehlende Einträge nachrüsten (Upgrade-Pfad für bestehende Instanzen) +_sudoers_add() { + local file="$1" rule="$2" + if [[ -f "$file" ]] && ! grep -qF "$rule" "$file"; then + chmod 640 "$file" + echo "$rule" >> "$file" + chmod 440 "$file" + fi +} +_sudoers_add /etc/sudoers.d/mailwolt-certbot 'www-data ALL=(root) NOPASSWD: /usr/local/sbin/mailwolt-fetch-tags' +_sudoers_add /etc/sudoers.d/mailwolt-certbot 'www-data ALL=(root) NOPASSWD: /usr/bin/openssl x509 -enddate -noout -in /etc/letsencrypt/live/*/fullchain.pem' +_sudoers_add /etc/sudoers.d/mailwolt-dkim 'www-data ALL=(root) NOPASSWD: /usr/bin/openssl x509 -enddate -noout -in /etc/letsencrypt/live/*/fullchain.pem' \ No newline at end of file