Files
certigo/backend/providers/dummy.go
2025-11-20 13:29:13 +01:00

206 lines
5.4 KiB
Go

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
}