Files
certigo/backend/providers/provider.go

219 lines
5.8 KiB
Go

package providers
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
)
// ProviderConfig enthält die Konfiguration eines Providers
type ProviderConfig struct {
Enabled bool `json:"enabled"`
AcmeReady bool `json:"acme_ready"`
Settings map[string]interface{} `json:"settings"`
}
// SignCSRResult enthält das Ergebnis einer CSR-Signierung
type SignCSRResult struct {
CertificatePEM string `json:"certificatePEM"`
OrderID string `json:"orderId,omitempty"`
Status string `json:"status"`
Message string `json:"message,omitempty"`
}
// Provider Interface für alle SSL Certificate Provider
type Provider interface {
// GetName gibt den Namen des Providers zurück
GetName() string
// GetDisplayName gibt den Anzeigenamen zurück
GetDisplayName() string
// GetDescription gibt eine Beschreibung zurück
GetDescription() string
// ValidateConfig validiert die Konfiguration
ValidateConfig(settings map[string]interface{}) error
// TestConnection testet die Verbindung zum Provider
TestConnection(settings map[string]interface{}) error
// GetRequiredSettings gibt die erforderlichen Einstellungen zurück
GetRequiredSettings() []SettingField
// SignCSR signiert einen CSR und gibt das Zertifikat zurück
SignCSR(csrPEM string, settings map[string]interface{}) (*SignCSRResult, error)
// GetCertificate ruft ein Zertifikat anhand der Zertifikat-ID ab
GetCertificate(certificateID string, settings map[string]interface{}) (string, error)
}
// ProviderManager verwaltet alle Provider
type ProviderManager struct {
providers map[string]Provider
configs map[string]*ProviderConfig
configDir string
mu sync.RWMutex
}
var manager *ProviderManager
var once sync.Once
// GetManager gibt die Singleton-Instanz des ProviderManagers zurück
func GetManager() *ProviderManager {
once.Do(func() {
manager = &ProviderManager{
providers: make(map[string]Provider),
configs: make(map[string]*ProviderConfig),
configDir: "./config/providers",
}
manager.loadAllConfigs()
})
return manager
}
// RegisterProvider registriert einen neuen Provider
func (pm *ProviderManager) RegisterProvider(provider Provider) {
pm.mu.Lock()
defer pm.mu.Unlock()
providerID := pm.getProviderID(provider.GetName())
pm.providers[providerID] = provider
// Lade Konfiguration falls vorhanden
if pm.configs[providerID] == nil {
pm.configs[providerID] = &ProviderConfig{
Enabled: false,
AcmeReady: false,
Settings: make(map[string]interface{}),
}
}
}
// GetProvider gibt einen Provider zurück
func (pm *ProviderManager) GetProvider(id string) (Provider, bool) {
pm.mu.RLock()
defer pm.mu.RUnlock()
provider, exists := pm.providers[id]
return provider, exists
}
// GetAllProviders gibt alle registrierten Provider zurück
func (pm *ProviderManager) GetAllProviders() map[string]Provider {
pm.mu.RLock()
defer pm.mu.RUnlock()
result := make(map[string]Provider)
for id, provider := range pm.providers {
result[id] = provider
}
return result
}
// GetProviderConfig gibt die Konfiguration eines Providers zurück
func (pm *ProviderManager) GetProviderConfig(id string) (*ProviderConfig, error) {
pm.mu.RLock()
defer pm.mu.RUnlock()
config, exists := pm.configs[id]
if !exists {
return &ProviderConfig{
Enabled: false,
AcmeReady: false,
Settings: make(map[string]interface{}),
}, nil
}
return config, nil
}
// UpdateProviderConfig aktualisiert die Konfiguration eines Providers
func (pm *ProviderManager) UpdateProviderConfig(id string, config *ProviderConfig) error {
pm.mu.Lock()
defer pm.mu.Unlock()
provider, exists := pm.providers[id]
if !exists {
return fmt.Errorf("provider %s nicht gefunden", id)
}
// Validiere Konfiguration
if err := provider.ValidateConfig(config.Settings); err != nil {
return fmt.Errorf("ungültige Konfiguration: %v", err)
}
pm.configs[id] = config
// Speichere Konfiguration in Datei
return pm.saveConfig(id, config)
}
// SetProviderEnabled aktiviert/deaktiviert einen Provider
func (pm *ProviderManager) SetProviderEnabled(id string, enabled bool) error {
pm.mu.Lock()
defer pm.mu.Unlock()
if pm.configs[id] == nil {
pm.configs[id] = &ProviderConfig{
Enabled: enabled,
AcmeReady: false,
Settings: make(map[string]interface{}),
}
} else {
pm.configs[id].Enabled = enabled
}
return pm.saveConfig(id, pm.configs[id])
}
// getProviderID erstellt eine ID aus dem Provider-Namen
func (pm *ProviderManager) getProviderID(name string) string {
return name
}
// loadAllConfigs lädt alle Konfigurationsdateien
func (pm *ProviderManager) loadAllConfigs() {
// Stelle sicher, dass das Verzeichnis existiert
os.MkdirAll(pm.configDir, 0755)
// Lade alle JSON-Dateien im Konfigurationsverzeichnis
files, err := filepath.Glob(filepath.Join(pm.configDir, "*.json"))
if err != nil {
return
}
for _, file := range files {
id := filepath.Base(file[:len(file)-5]) // Entferne .json
config, err := pm.loadConfig(id)
if err == nil {
pm.configs[id] = config
}
}
}
// loadConfig lädt eine Konfigurationsdatei
func (pm *ProviderManager) loadConfig(id string) (*ProviderConfig, error) {
filePath := filepath.Join(pm.configDir, id+".json")
data, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
var config ProviderConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, err
}
return &config, nil
}
// saveConfig speichert eine Konfiguration in eine Datei
func (pm *ProviderManager) saveConfig(id string, config *ProviderConfig) error {
// Stelle sicher, dass das Verzeichnis existiert
os.MkdirAll(pm.configDir, 0755)
filePath := filepath.Join(pm.configDir, id+".json")
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
return os.WriteFile(filePath, data, 0644)
}