# Automatische Zertifikats-Erneuerung Konzept für Let's Encrypt ## 1. Übersicht ### 1.1 Ziel Implementierung einer automatischen Erneuerungsfunktion für Let's Encrypt (LE) Zertifikate, die ablaufende Zertifikate rechtzeitig erneuert, bevor sie ablaufen. ### 1.2 Anforderungen - **Proaktive Erneuerung**: Zertifikate werden erneuert, bevor sie ablaufen (z.B. 30 Tage vor Ablauf) - **Automatische Ausführung**: Läuft im Hintergrund ohne Benutzerinteraktion - **Fehlerbehandlung**: Robustes Error-Handling und Retry-Mechanismus - **Logging & Monitoring**: Umfassendes Logging für Nachverfolgbarkeit - **Konfigurierbarkeit**: Erneuerungs-Schwellenwerte und Intervalle konfigurierbar - **Berechtigungen**: Respektiert bestehende Permission-Systeme - **DNS-Validierung**: Automatische DNS-Challenge-Validierung vor Erneuerung --- ## 2. Architektur ### 2.1 Komponenten-Übersicht ``` ┌─────────────────────────────────────────────────────────────┐ │ Auto-Renewal System │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Scheduler │───>│ Certificate │───>│ Renewal │ │ │ │ (Cron) │ │ Scanner │ │ Worker │ │ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ v v v │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Config │ │ Database │ │ ACME │ │ │ │ Manager │ │ Queries │ │ Client │ │ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Logger │ │ Notifier │ │ Retry │ │ │ │ Service │ │ Service │ │ Manager │ │ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.2 Workflow ``` 1. Scheduler startet (z.B. täglich um 02:00 Uhr) │ ├─> 2. Scanner identifiziert ablaufende Zertifikate │ (expires_at < now + renewal_threshold) │ ├─> 3. Für jedes Zertifikat: │ │ │ ├─> 3.1 Prüfe ob Auto-Renewal aktiviert │ │ │ ├─> 3.2 Prüfe ob bereits Erneuerung läuft │ │ │ ├─> 3.3 Prüfe Berechtigungen (Space-Zugriff) │ │ │ ├─> 3.4 Validiere DNS (CNAME Check) │ │ │ ├─> 3.5 Erstelle Renewal-Job │ │ │ └─> 3.6 Queue für Worker │ ├─> 4. Worker verarbeitet Jobs sequenziell │ │ │ ├─> 4.1 Hole FQDN-Informationen │ │ │ ├─> 4.2 Hole ACME-Provider-Konfiguration │ │ │ ├─> 4.3 Rufe RequestCertificate() auf │ │ │ ├─> 4.4 Speichere neues Zertifikat │ │ │ ├─> 4.5 Markiere altes Zertifikat als "replaced" │ │ │ └─> 4.6 Logge Erfolg/Fehler │ └─> 5. Cleanup & Reporting ``` --- ## 3. Datenbank-Schema ### 3.1 Erweiterte Certificates-Tabelle ```sql -- Migration: Erweitere certificates-Tabelle um Auto-Renewal-Felder ALTER TABLE certificates ADD COLUMN auto_renewal_enabled BOOLEAN DEFAULT 1; ALTER TABLE certificates ADD COLUMN renewal_attempts INTEGER DEFAULT 0; ALTER TABLE certificates ADD COLUMN last_renewal_attempt DATETIME; ALTER TABLE certificates ADD COLUMN next_renewal_check DATETIME; ALTER TABLE certificates ADD COLUMN renewal_status TEXT; -- 'pending', 'in_progress', 'success', 'failed', 'disabled' ALTER TABLE certificates ADD COLUMN replaced_by_cert_id TEXT; -- ID des neuen Zertifikats ALTER TABLE certificates ADD COLUMN replaces_cert_id TEXT; -- ID des ersetzten Zertifikats ``` ### 3.2 Neue Tabelle: certificate_renewal_logs ```sql CREATE TABLE IF NOT EXISTS certificate_renewal_logs ( id TEXT PRIMARY KEY, certificate_id TEXT NOT NULL, fqdn_id TEXT NOT NULL, space_id TEXT NOT NULL, renewal_status TEXT NOT NULL, -- 'started', 'success', 'failed', 'skipped' renewal_reason TEXT, -- 'expiring_soon', 'manual', 'retry' error_message TEXT, old_expires_at DATETIME, new_expires_at DATETIME, new_certificate_id TEXT, renewal_duration_seconds INTEGER, trace_id TEXT, created_at DATETIME NOT NULL, FOREIGN KEY (certificate_id) REFERENCES certificates(id) ON DELETE CASCADE, FOREIGN KEY (fqdn_id) REFERENCES fqdns(id) ON DELETE CASCADE, FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE ); CREATE INDEX idx_renewal_logs_certificate_id ON certificate_renewal_logs(certificate_id); CREATE INDEX idx_renewal_logs_created_at ON certificate_renewal_logs(created_at); CREATE INDEX idx_renewal_logs_status ON certificate_renewal_logs(renewal_status); ``` ### 3.3 Neue Tabelle: renewal_config ```sql CREATE TABLE IF NOT EXISTS renewal_config ( id TEXT PRIMARY KEY DEFAULT 'global', enabled BOOLEAN DEFAULT 1, renewal_threshold_days INTEGER DEFAULT 30, -- Erneuere X Tage vor Ablauf check_interval_hours INTEGER DEFAULT 24, -- Wie oft prüfen (in Stunden) max_renewal_attempts INTEGER DEFAULT 3, -- Max. Versuche pro Zertifikat retry_delay_hours INTEGER DEFAULT 24, -- Wartezeit zwischen Retries notification_enabled BOOLEAN DEFAULT 0, notification_email TEXT, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL ); -- Initiale Konfiguration einfügen INSERT INTO renewal_config (id, enabled, renewal_threshold_days, check_interval_hours, max_renewal_attempts, retry_delay_hours, created_at, updated_at) VALUES ('global', 1, 30, 24, 3, 24, datetime('now'), datetime('now')); ``` ### 3.4 FQDN-Tabelle Erweiterung ```sql -- Optional: Pro-FQDN Auto-Renewal-Einstellungen ALTER TABLE fqdns ADD COLUMN auto_renewal_enabled BOOLEAN DEFAULT 1; ``` --- ## 4. Konfiguration ### 4.1 Global Configuration (Environment Variables) ```bash # Auto-Renewal Einstellungen AUTO_RENEWAL_ENABLED=true AUTO_RENEWAL_THRESHOLD_DAYS=30 AUTO_RENEWAL_CHECK_INTERVAL_HOURS=24 AUTO_RENEWAL_SCHEDULE="0 2 * * *" # Cron-Format: Täglich um 02:00 Uhr AUTO_RENEWAL_MAX_ATTEMPTS=3 AUTO_RENEWAL_RETRY_DELAY_HOURS=24 # Notifications AUTO_RENEWAL_NOTIFICATIONS_ENABLED=false AUTO_RENEWAL_NOTIFICATION_EMAIL=admin@example.com # Concurrency AUTO_RENEWAL_MAX_CONCURRENT=1 # Anzahl paralleler Erneuerungen ``` ### 4.2 Per-FQDN Configuration - **Default**: Auto-Renewal aktiviert für alle FQDNs - **Opt-out**: Pro FQDN deaktivierbar über `fqdns.auto_renewal_enabled` - **Opt-out**: Pro Zertifikat deaktivierbar über `certificates.auto_renewal_enabled` --- ## 5. Scheduler-Implementierung ### 5.1 Optionen #### Option A: Go Cron Library (Empfohlen) ```go import "github.com/robfig/cron/v3" c := cron.New() c.AddFunc("0 2 * * *", func() { runCertificateRenewalScan() }) c.Start() ``` **Vorteile:** - Einfach zu implementieren - Gut getestet - Cron-Format unterstützt **Nachteile:** - Läuft nur im Backend-Prozess - Bei Neustart muss Scheduler neu gestartet werden #### Option B: Separate Background Service ```go // Separate Go-Routine die kontinuierlich läuft go func() { ticker := time.NewTicker(24 * time.Hour) for { select { case <-ticker.C: runCertificateRenewalScan() case <-ctx.Done(): return } } }() ``` **Vorteile:** - Einfacher zu debuggen - Keine externe Dependency **Nachteile:** - Weniger flexibel als Cron - Muss selbst implementiert werden #### Option C: System Cron Job ```bash # /etc/cron.d/certigo-renewal 0 2 * * * curl -X POST http://localhost:8080/api/internal/renewal/scan ``` **Vorteile:** - Unabhängig vom Backend-Prozess - Läuft auch wenn Backend neu gestartet wird **Nachteile:** - Externe Dependency (curl) - Schwieriger zu debuggen - Benötigt separaten API-Endpunkt **Empfehlung: Option A (Go Cron Library)** --- ## 6. Certificate Scanner ### 6.1 Query für ablaufende Zertifikate ```sql SELECT c.id, c.fqdn_id, c.space_id, c.certificate_id, c.provider_id, c.expires_at, c.auto_renewal_enabled, c.renewal_status, c.renewal_attempts, c.last_renewal_attempt, f.fqdn, f.acme_email, f.acme_key_id, f.provider_id as fqdn_provider_id FROM certificates c INNER JOIN fqdns f ON c.fqdn_id = f.id WHERE -- Nur Leaf-Zertifikate (nicht Intermediate) c.is_intermediate = 0 -- Nur Let's Encrypt Zertifikate (via certigo-acmeproxy) AND c.provider_id = 'certigo-acmeproxy' -- Nur gültige/ausgestellte Zertifikate AND c.status = 'issued' -- Auto-Renewal muss aktiviert sein AND (c.auto_renewal_enabled IS NULL OR c.auto_renewal_enabled = 1) AND (f.auto_renewal_enabled IS NULL OR f.auto_renewal_enabled = 1) -- Zertifikat läuft bald ab AND c.expires_at IS NOT NULL AND datetime(c.expires_at) <= datetime('now', '+' || ? || ' days') -- Keine laufende Erneuerung AND (c.renewal_status IS NULL OR c.renewal_status != 'in_progress') -- Nicht zu viele Versuche AND (c.renewal_attempts IS NULL OR c.renewal_attempts < ?) -- Retry-Delay eingehalten AND ( c.last_renewal_attempt IS NULL OR datetime(c.last_renewal_attempt) <= datetime('now', '-' || ? || ' hours') ) ORDER BY c.expires_at ASC; ``` ### 6.2 Filter-Logik **Ausschluss-Kriterien:** 1. ✅ Intermediate-Zertifikate (nur Leaf) 2. ✅ Nur `certigo-acmeproxy` Provider 3. ✅ Status = 'issued' 4. ✅ Auto-Renewal aktiviert (Certificate + FQDN) 5. ✅ `expires_at` innerhalb Threshold 6. ✅ Keine laufende Erneuerung (`renewal_status != 'in_progress'`) 7. ✅ Max. Versuche nicht überschritten 8. ✅ Retry-Delay eingehalten --- ## 7. Renewal Worker ### 7.1 Renewal-Prozess ```go func renewCertificate(certID string, fqdnID string, spaceID string) error { traceID := generateTraceID() // 1. Markiere als "in_progress" updateRenewalStatus(certID, "in_progress", traceID) // 2. Hole FQDN-Informationen fqdn, err := getFQDN(fqdnID) if err != nil { logRenewalError(certID, traceID, "FQDN nicht gefunden", err) return err } // 3. Prüfe DNS (CNAME) if !validateDNSCNAME(fqdn.FQDN) { logRenewalError(certID, traceID, "DNS-CNAME nicht gültig", nil) return fmt.Errorf("DNS validation failed") } // 4. Hole ACME-Provider-Konfiguration providerConfig, err := getACMEProviderConfig(fqdn.ProviderID) if err != nil { logRenewalError(certID, traceID, "Provider-Konfiguration nicht gefunden", err) return err } // 5. Rufe RequestCertificate() auf result, err := RequestCertificate( fqdn.FQDN, fqdn.AcmeEmail, fqdnID, fqdn.AcmeKeyID, traceID, updateTokenFunc, cleanupTokenFunc, statusCallback, ) if err != nil { // 6a. Fehler: Erhöhe Versuche, setze Retry-Zeitpunkt incrementRenewalAttempts(certID) setNextRenewalCheck(certID, time.Now().Add(retryDelay)) updateRenewalStatus(certID, "failed", traceID) logRenewalError(certID, traceID, "Erneuerung fehlgeschlagen", err) return err } // 6b. Erfolg: Speichere neues Zertifikat newCertID, err := saveNewCertificate(result, fqdnID, spaceID) if err != nil { logRenewalError(certID, traceID, "Fehler beim Speichern", err) return err } // 7. Verknüpfe alte und neue Zertifikate linkCertificates(certID, newCertID) // 8. Markiere als erfolgreich updateRenewalStatus(certID, "success", traceID) logRenewalSuccess(certID, newCertID, traceID) // 9. Optional: Benachrichtigung senden sendRenewalNotification(fqdn.FQDN, newCertID, traceID) return nil } ``` ### 7.2 Concurrency Control **Sequenzielle Verarbeitung:** - Pro FQDN nur eine Erneuerung gleichzeitig - Pro Space max. N Erneuerungen parallel (konfigurierbar) - Global max. M Erneuerungen parallel (konfigurierbar) **Implementierung:** ```go // Semaphore für Concurrency Control var renewalSemaphore = make(chan struct{}, maxConcurrentRenewals) func renewCertificateWithLock(certID string, fqdnID string, spaceID string) error { renewalSemaphore <- struct{}{} // Acquire defer func() { <-renewalSemaphore }() // Release return renewCertificate(certID, fqdnID, spaceID) } ``` --- ## 8. Fehlerbehandlung & Retry ### 8.1 Fehler-Kategorien | Fehler-Typ | Retry? | Max. Versuche | Beispiel | |-----------|--------|--------------|----------| | DNS-Validierung fehlgeschlagen | ✅ Ja | 3 | CNAME nicht gesetzt | | ACME-Provider-Fehler | ✅ Ja | 3 | Rate Limit erreicht | | Netzwerk-Fehler | ✅ Ja | 5 | Timeout, Connection Error | | Konfigurations-Fehler | ❌ Nein | 0 | Provider nicht konfiguriert | | Berechtigungs-Fehler | ❌ Nein | 0 | Kein Space-Zugriff | ### 8.2 Retry-Strategie **Exponential Backoff:** ``` Versuch 1: Sofort Versuch 2: Nach 24 Stunden Versuch 3: Nach 48 Stunden Versuch 4+: Nach 72 Stunden ``` **Oder: Fixed Delay** ``` Alle Retries: Nach X Stunden (konfigurierbar, Default: 24h) ``` ### 8.3 Fehler-Logging ```go type RenewalError struct { CertificateID string FQDN string ErrorType string // 'dns', 'acme', 'network', 'config' ErrorMessage string TraceID string Timestamp time.Time Attempt int } ``` --- ## 9. Logging & Monitoring ### 9.1 Structured Logging **Erfolgreiche Erneuerung:** ```json { "event": "certificate_renewal_success", "trace_id": "abc123", "certificate_id": "cert-uuid", "fqdn": "example.com", "old_expires_at": "2025-02-15T10:00:00Z", "new_expires_at": "2025-05-15T10:00:00Z", "new_certificate_id": "new-cert-uuid", "duration_seconds": 45, "timestamp": "2025-01-15T02:05:00Z" } ``` **Fehlgeschlagene Erneuerung:** ```json { "event": "certificate_renewal_failed", "trace_id": "abc123", "certificate_id": "cert-uuid", "fqdn": "example.com", "error_type": "dns_validation", "error_message": "CNAME record not found", "attempt": 1, "max_attempts": 3, "next_retry": "2025-01-16T02:00:00Z", "timestamp": "2025-01-15T02:05:00Z" } ``` ### 9.2 Audit Logs **Integration in bestehendes Audit-System:** ```go auditService.Track(ctx, "RENEW", "certificate", certID, "system", "auto-renewal", map[string]interface{}{ "fqdn": fqdn, "old_expires_at": oldExpiresAt, "new_expires_at": newExpiresAt, "trace_id": traceID, }, ipAddress, userAgent) ``` ### 9.3 Metrics **Zu tracken:** - Anzahl Erneuerungen pro Tag/Woche/Monat - Erfolgsrate (Erfolgreich / Gesamt) - Durchschnittliche Erneuerungsdauer - Anzahl fehlgeschlagener Erneuerungen - Anzahl Retries - Zertifikate die bald ablaufen (Warnung) --- ## 10. API-Endpunkte ### 10.1 Manuelle Erneuerung **POST** `/api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renew` Manuell eine Erneuerung auslösen. **Response:** ```json { "success": true, "message": "Erneuerung gestartet", "trace_id": "abc123", "estimated_completion": "2025-01-15T02:05:00Z" } ``` ### 10.2 Erneuerungs-Status abrufen **GET** `/api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renewal-status` **Response:** ```json { "auto_renewal_enabled": true, "renewal_status": "success", "renewal_attempts": 1, "last_renewal_attempt": "2025-01-15T02:00:00Z", "next_renewal_check": "2025-01-16T02:00:00Z", "replaced_by_cert_id": "new-cert-uuid" } ``` ### 10.3 Erneuerungs-Logs abrufen **GET** `/api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renewal-logs` **Query Parameters:** - `limit` (optional): Anzahl Einträge (Default: 50) - `offset` (optional): Pagination Offset **Response:** ```json { "logs": [ { "id": "log-uuid", "renewal_status": "success", "renewal_reason": "expiring_soon", "old_expires_at": "2025-02-15T10:00:00Z", "new_expires_at": "2025-05-15T10:00:00Z", "new_certificate_id": "new-cert-uuid", "renewal_duration_seconds": 45, "trace_id": "abc123", "created_at": "2025-01-15T02:00:00Z" } ], "total": 10, "limit": 50, "offset": 0 } ``` ### 10.4 Auto-Renewal konfigurieren **PUT** `/api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/auto-renewal` **Body:** ```json { "enabled": true } ``` ### 10.5 Global Configuration **GET** `/api/internal/renewal/config` **Response:** ```json { "enabled": true, "renewal_threshold_days": 30, "check_interval_hours": 24, "max_renewal_attempts": 3, "retry_delay_hours": 24 } ``` **PUT** `/api/internal/renewal/config` **Body:** ```json { "enabled": true, "renewal_threshold_days": 30, "check_interval_hours": 24, "max_renewal_attempts": 3, "retry_delay_hours": 24 } ``` ### 10.6 Manueller Scan (für Testing) **POST** `/api/internal/renewal/scan` Löst einen manuellen Scan aus (nur für Admins). **Response:** ```json { "success": true, "certificates_found": 5, "certificates_queued": 3, "certificates_skipped": 2 } ``` --- ## 11. Frontend-Integration ### 11.1 UI-Komponenten #### Auto-Renewal Toggle - **Ort**: Certificate Detail View - **Funktion**: Ein/Aus-Schalter für Auto-Renewal pro Zertifikat #### Renewal Status Badge - **Ort**: Certificate List & Detail View - **Anzeige**: - 🟢 "Auto-Renewal aktiv" (wenn enabled) - 🟡 "Erneuerung läuft" (wenn in_progress) - 🔴 "Erneuerung fehlgeschlagen" (wenn failed) - ⚪ "Auto-Renewal deaktiviert" (wenn disabled) #### Renewal History - **Ort**: Certificate Detail View - **Anzeige**: Tabelle mit Erneuerungs-Logs - **Spalten**: Datum, Status, Grund, Neue Ablaufzeit, Trace ID #### Manuelle Erneuerung Button - **Ort**: Certificate Detail View - **Funktion**: "Jetzt erneuern" Button (falls Auto-Renewal deaktiviert) #### Upcoming Renewals Dashboard - **Ort**: Dashboard/Overview - **Anzeige**: Liste von Zertifikaten die bald erneuert werden - **Filter**: Nach Space, FQDN, Ablaufdatum ### 11.2 Notifications (Optional) **Email-Benachrichtigungen:** - Erfolgreiche Erneuerung - Fehlgeschlagene Erneuerung (nach max. Versuchen) - Warnung: Zertifikat läuft in X Tagen ab (falls Erneuerung fehlschlägt) **In-App Notifications:** - Toast-Notification bei erfolgreicher Erneuerung - Alert bei fehlgeschlagener Erneuerung --- ## 12. Sicherheit & Berechtigungen ### 12.1 Berechtigungen **Auto-Renewal ausführen:** - System-User (für automatische Erneuerungen) - Admin-User (für manuelle Erneuerungen) - User mit `FULL_ACCESS` auf Space (für manuelle Erneuerungen) **Auto-Renewal konfigurieren:** - Admin-User - User mit `FULL_ACCESS` auf Space **Erneuerungs-Logs anzeigen:** - Alle User mit Space-Zugriff (READ-Berechtigung) ### 12.2 Rate Limiting **Let's Encrypt Rate Limits:** - 50 Certificates per Registered Domain per week - 300 New Orders per Account per 3 hours **Schutz:** - Tracke Anzahl Erneuerungen pro FQDN - Verzögere Erneuerung wenn Rate Limit erreicht - Logge Warnung bei Rate Limit --- ## 13. Testing & Rollout ### 13.1 Test-Plan **Phase 1: Unit Tests** - [ ] Certificate Scanner Query - [ ] Renewal Worker Logic - [ ] Retry-Mechanismus - [ ] Error-Handling **Phase 2: Integration Tests** - [ ] End-to-End Erneuerung (mit Staging ACME) - [ ] Fehler-Szenarien (DNS-Fehler, Rate Limit) - [ ] Concurrency Tests **Phase 3: Staging Tests** - [ ] Test mit echten Staging-Zertifikaten - [ ] Monitoring & Logging prüfen - [ ] Performance-Tests **Phase 4: Production Rollout** - [ ] Feature Flag aktivieren - [ ] Monitoring aktivieren - [ ] Schrittweise Aktivierung (zuerst einzelne FQDNs) ### 13.2 Rollback-Plan **Falls Probleme auftreten:** 1. Auto-Renewal global deaktivieren (Config) 2. Laufende Erneuerungen abbrechen (Status zurücksetzen) 3. Manuelle Erneuerung weiterhin möglich --- ## 14. Monitoring & Alerting ### 14.1 Health Checks **Endpoint:** `GET /api/health/renewal` **Response:** ```json { "status": "healthy", "last_scan": "2025-01-15T02:00:00Z", "next_scan": "2025-01-16T02:00:00Z", "certificates_pending": 2, "certificates_in_progress": 1, "certificates_failed": 0 } ``` ### 14.2 Alerts **Zu überwachen:** - ❌ Auto-Renewal Service läuft nicht - ⚠️ Viele fehlgeschlagene Erneuerungen (> 10% in 24h) - ⚠️ Zertifikate laufen in < 7 Tagen ab (ohne Erneuerung) - ⚠️ Rate Limit erreicht - ⚠️ Scheduler läuft nicht (letzter Scan > 48h her) --- ## 15. Zukünftige Erweiterungen ### 15.1 Multi-Provider Support - Erneuerung für andere Provider (nicht nur Let's Encrypt) ### 15.2 Smart Scheduling - Erneuerung basierend auf Traffic-Patterns - Erneuerung außerhalb der Geschäftszeiten ### 15.3 Batch Renewals - Erneuerung mehrerer Zertifikate gleichzeitig (wenn möglich) ### 15.4 Webhook-Integration - Webhooks für erfolgreiche/fehlgeschlagene Erneuerungen - Integration mit externen Monitoring-Tools ### 15.5 Certificate Rotation - Automatische Rotation von Private Keys - Unterstützung für Key-Rollover --- ## 16. Abhängigkeiten ### 16.1 Backend (Go) ```go // Cron Scheduler github.com/robfig/cron/v3 // (Bereits vorhanden) // - ACME Client (acme_client.go) // - Certificate Parser (cert_parser.go) // - Logger (cert_logger.go) ``` ### 16.2 Frontend Keine zusätzlichen Dependencies nötig. --- ## 17. Risiken & Mitigation ### 17.1 Risiken | Risiko | Wahrscheinlichkeit | Impact | Mitigation | |--------|-------------------|--------|------------| | Rate Limit erreicht | Mittel | Hoch | Rate Limit Tracking, Verzögerung | | DNS-Validierung fehlschlägt | Mittel | Hoch | DNS-Check vor Erneuerung, Retry | | ACME-Provider Downtime | Niedrig | Hoch | Retry-Mechanismus, Fallback | | Doppelte Erneuerung | Niedrig | Mittel | Status-Check, Locking | | Datenbank-Lock | Niedrig | Mittel | Transaktionen, Timeouts | ### 17.2 Best Practices - ✅ Idempotenz: Erneuerung kann mehrfach ausgeführt werden ohne Probleme - ✅ Atomic Operations: Datenbank-Transaktionen für Konsistenz - ✅ Graceful Degradation: Bei Fehlern weiterhin manuelle Erneuerung möglich - ✅ Comprehensive Logging: Alle Schritte loggen für Debugging - ✅ Rate Limit Awareness: Respektiere Let's Encrypt Limits --- ## 18. Zusammenfassung ### 18.1 Vorteile - **Automatisierung**: Keine manuelle Intervention nötig - **Zuverlässigkeit**: Zertifikate laufen nicht mehr ab - **Zeitersparnis**: Weniger manuelle Arbeit - **Sicherheit**: Immer gültige Zertifikate ### 18.2 Herausforderungen - **Komplexität**: Zusätzliche Infrastruktur und Code - **Fehlerbehandlung**: Robustes Error-Handling erforderlich - **Rate Limits**: Let's Encrypt Limits beachten - **Testing**: Umfangreiche Tests erforderlich ### 18.3 Empfohlene Implementierungs-Reihenfolge 1. **Phase 1**: Datenbank-Schema & Grundfunktionalität 2. **Phase 2**: Scanner & Worker 3. **Phase 3**: Scheduler & Automation 4. **Phase 4**: Frontend-Integration 5. **Phase 5**: Monitoring & Alerting 6. **Phase 6**: Notifications (Optional) --- **Erstellt am**: 2025-01-XX **Version**: 1.0 **Status**: Konzept - Noch nicht implementiert