package providers import ( "fmt" "io" "net/http" "strings" "time" ) // LetsEncryptProvider ist der Provider für Let's Encrypt type LetsEncryptProvider struct { environment string // "production" oder "staging" } // NewLetsEncryptProvider erstellt einen neuen Let's Encrypt Provider func NewLetsEncryptProvider(environment string) *LetsEncryptProvider { if environment != "staging" && environment != "production" { environment = "production" } return &LetsEncryptProvider{ environment: environment, } } func (p *LetsEncryptProvider) GetName() string { if p.environment == "staging" { return "letsencrypt-staging" } return "letsencrypt-production" } func (p *LetsEncryptProvider) GetDisplayName() string { if p.environment == "staging" { return "Let's Encrypt (Staging)" } return "Let's Encrypt (Production)" } func (p *LetsEncryptProvider) GetDescription() string { if p.environment == "staging" { return "Let's Encrypt Staging Environment für Tests" } return "Let's Encrypt Production Certificate Authority" } func (p *LetsEncryptProvider) GetDirectoryURL() string { if p.environment == "staging" { return "https://acme-staging-v02.api.letsencrypt.org/directory" } return "https://acme-v02.api.letsencrypt.org/directory" } func (p *LetsEncryptProvider) GetRenewalInfoURL() string { if p.environment == "staging" { return "https://acme-staging-v02.api.letsencrypt.org/acme/renewal-info" } return "https://acme-v02.api.letsencrypt.org/acme/renewal-info" } func (p *LetsEncryptProvider) ValidateConfig(settings map[string]interface{}) error { // Let's Encrypt benötigt keine zusätzliche Konfiguration // Die Directory URL wird automatisch basierend auf der Environment gesetzt return nil } func (p *LetsEncryptProvider) TestConnection(settings map[string]interface{}) error { // Teste Verbindung zum ACME Directory directoryURL := p.GetDirectoryURL() client := &http.Client{ Timeout: 10 * time.Second, } resp, err := client.Get(directoryURL) if err != nil { return fmt.Errorf("ACME Directory nicht erreichbar: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("ACME Directory antwortet mit Status %d: %s", resp.StatusCode, string(body)) } // Prüfe ob es ein gültiges ACME Directory ist body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("fehler beim Lesen der Directory-Response: %v", err) } // Einfache Validierung: Prüfe ob "newAccount" oder "newNonce" im Body enthalten ist bodyStr := string(body) if !strings.Contains(bodyStr, "newAccount") && !strings.Contains(bodyStr, "newNonce") { return fmt.Errorf("ungültige ACME Directory Response") } return nil } func (p *LetsEncryptProvider) GetRequiredSettings() []SettingField { // Let's Encrypt benötigt keine zusätzlichen Einstellungen // Die Directory URL wird automatisch basierend auf der Environment gesetzt return []SettingField{} }