package providers import ( "bytes" "encoding/base64" "encoding/json" "fmt" "io" "net/http" "strings" ) // DummyCAProvider ist ein Dummy-Provider für Tests type DummyCAProvider struct { baseURL string } func NewDummyCAProvider() *DummyCAProvider { return &DummyCAProvider{ baseURL: "http://localhost:8088", } } func (p *DummyCAProvider) GetName() string { return "dummy-ca" } func (p *DummyCAProvider) GetDisplayName() string { return "Dummy CA" } func (p *DummyCAProvider) GetDescription() string { return "Externe Dummy CA für Tests und Entwicklung (http://localhost:8088)" } func (p *DummyCAProvider) ValidateConfig(settings map[string]interface{}) error { // Dummy-Provider benötigt keine Konfiguration return nil } func (p *DummyCAProvider) TestConnection(settings map[string]interface{}) error { // Teste Verbindung zur externen CA über Health Check url := fmt.Sprintf("%s/health", p.baseURL) resp, err := http.Get(url) if err != nil { return fmt.Errorf("CA-Server nicht erreichbar: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("CA-Server antwortet mit Status %d", resp.StatusCode) } // Prüfe Response Body body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("fehler beim Lesen der Health-Check-Response: %v", err) } var healthResponse struct { Status string `json:"status"` } if err := json.Unmarshal(body, &healthResponse); err != nil { return fmt.Errorf("ungültige Health-Check-Response: %v", err) } if healthResponse.Status != "ok" { return fmt.Errorf("CA-Server meldet Status: %s", healthResponse.Status) } return nil } // GetRequiredSettings gibt die erforderlichen Einstellungen zurück func (p *DummyCAProvider) GetRequiredSettings() []SettingField { return []SettingField{} } // SignCSR signiert einen CSR über die externe Dummy CA API func (p *DummyCAProvider) SignCSR(csrPEM string, settings map[string]interface{}) (*SignCSRResult, error) { // Entferne mögliche Whitespace am Anfang/Ende csrPEM = strings.TrimSpace(csrPEM) // Base64-kodiere den CSR csrB64 := base64.StdEncoding.EncodeToString([]byte(csrPEM)) // Erstelle Request Body requestBody := map[string]interface{}{ "csr": csrB64, "action": "sign", "validity_days": 365, } // Konvertiere zu JSON jsonData, err := json.Marshal(requestBody) if err != nil { return nil, fmt.Errorf("fehler beim Erstellen des Request-Body: %v", err) } // Erstelle HTTP Request url := fmt.Sprintf("%s/csr", p.baseURL) req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("fehler beim Erstellen des HTTP-Requests: %v", err) } req.Header.Set("Content-Type", "application/json") // Führe Request aus client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("fehler beim Senden des Requests an die CA: %v", err) } defer resp.Body.Close() // Lese Response Body body, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("fehler beim Lesen der Response: %v", err) } // Prüfe Status Code if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("CA-API Fehler (Status %d): %s", resp.StatusCode, string(body)) } // Parse Response var apiResponse struct { ID string `json:"id"` Status string `json:"status"` Message string `json:"message"` Certificate string `json:"certificate"` Error string `json:"error"` } if err := json.Unmarshal(body, &apiResponse); err != nil { return nil, fmt.Errorf("fehler beim Parsen der Response: %v", err) } // Prüfe auf Fehler in der Response if apiResponse.Error != "" { return nil, fmt.Errorf("CA-API Fehler: %s", apiResponse.Error) } // Prüfe Status if apiResponse.Status != "success" { return nil, fmt.Errorf("CSR-Signierung fehlgeschlagen: %s", apiResponse.Message) } // Rückgabe des Ergebnisses return &SignCSRResult{ CertificatePEM: apiResponse.Certificate, OrderID: apiResponse.ID, Status: "issued", Message: apiResponse.Message, }, nil } // GetCertificate ruft ein Zertifikat über die externe Dummy CA API ab func (p *DummyCAProvider) GetCertificate(certificateID string, settings map[string]interface{}) (string, error) { if certificateID == "" { return "", fmt.Errorf("zertifikat-ID ist erforderlich") } // Erstelle HTTP Request url := fmt.Sprintf("%s/certificate/%s", p.baseURL, certificateID) resp, err := http.Get(url) if err != nil { return "", fmt.Errorf("fehler beim Abrufen des Zertifikats: %v", err) } defer resp.Body.Close() // Lese Response Body body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("fehler beim Lesen der Response: %v", err) } // Prüfe Status Code if resp.StatusCode == http.StatusNotFound { return "", fmt.Errorf("Zertifikat mit ID %s nicht gefunden", certificateID) } if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("CA-API Fehler (Status %d): %s", resp.StatusCode, string(body)) } // Parse Response var apiResponse struct { ID string `json:"id"` Certificate string `json:"certificate"` CreatedAt string `json:"created_at"` } if err := json.Unmarshal(body, &apiResponse); err != nil { return "", fmt.Errorf("fehler beim Parsen der Response: %v", err) } if apiResponse.Certificate == "" { return "", fmt.Errorf("zertifikat in Response nicht gefunden") } return apiResponse.Certificate, nil }