183 lines
4.9 KiB
Go
183 lines
4.9 KiB
Go
package providers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
// ACMEProvider Interface für ACME-basierte Certificate Authorities
|
|
type ACMEProvider interface {
|
|
// GetName gibt den Namen des ACME-Providers zurück
|
|
GetName() string
|
|
// GetDisplayName gibt den Anzeigenamen zurück
|
|
GetDisplayName() string
|
|
// GetDescription gibt eine Beschreibung zurück
|
|
GetDescription() string
|
|
// GetDirectoryURL gibt die ACME Directory URL zurück
|
|
GetDirectoryURL() string
|
|
// GetRenewalInfoURL gibt die RenewalInfo API URL zurück (optional)
|
|
GetRenewalInfoURL() string
|
|
// ValidateConfig validiert die Konfiguration
|
|
ValidateConfig(settings map[string]interface{}) error
|
|
// TestConnection testet die Verbindung zum ACME-Server
|
|
TestConnection(settings map[string]interface{}) error
|
|
// GetRequiredSettings gibt die erforderlichen Einstellungen zurück
|
|
GetRequiredSettings() []SettingField
|
|
}
|
|
|
|
// ACMEProviderConfig enthält die Konfiguration eines ACME-Providers
|
|
type ACMEProviderConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
Settings map[string]interface{} `json:"settings"`
|
|
}
|
|
|
|
// ACMEProviderManager verwaltet alle ACME-Provider
|
|
type ACMEProviderManager struct {
|
|
providers map[string]ACMEProvider
|
|
configs map[string]*ACMEProviderConfig
|
|
configDir string
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
var acmeManager *ACMEProviderManager
|
|
var acmeOnce sync.Once
|
|
|
|
// GetACMEManager gibt die Singleton-Instanz des ACMEProviderManagers zurück
|
|
func GetACMEManager() *ACMEProviderManager {
|
|
acmeOnce.Do(func() {
|
|
acmeManager = &ACMEProviderManager{
|
|
providers: make(map[string]ACMEProvider),
|
|
configs: make(map[string]*ACMEProviderConfig),
|
|
configDir: "./config/providers",
|
|
}
|
|
acmeManager.loadAllConfigs()
|
|
})
|
|
return acmeManager
|
|
}
|
|
|
|
// RegisterACMEProvider registriert einen neuen ACME-Provider
|
|
func (pm *ACMEProviderManager) RegisterACMEProvider(provider ACMEProvider) {
|
|
pm.mu.Lock()
|
|
defer pm.mu.Unlock()
|
|
|
|
providerID := provider.GetName()
|
|
pm.providers[providerID] = provider
|
|
|
|
// Lade Konfiguration falls vorhanden
|
|
if pm.configs[providerID] == nil {
|
|
pm.configs[providerID] = &ACMEProviderConfig{
|
|
Enabled: false,
|
|
Settings: make(map[string]interface{}),
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetACMEProvider gibt einen ACME-Provider zurück
|
|
func (pm *ACMEProviderManager) GetACMEProvider(id string) (ACMEProvider, bool) {
|
|
pm.mu.RLock()
|
|
defer pm.mu.RUnlock()
|
|
provider, exists := pm.providers[id]
|
|
return provider, exists
|
|
}
|
|
|
|
// GetAllACMEProviders gibt alle registrierten ACME-Provider zurück
|
|
func (pm *ACMEProviderManager) GetAllACMEProviders() map[string]ACMEProvider {
|
|
pm.mu.RLock()
|
|
defer pm.mu.RUnlock()
|
|
result := make(map[string]ACMEProvider)
|
|
for id, provider := range pm.providers {
|
|
result[id] = provider
|
|
}
|
|
return result
|
|
}
|
|
|
|
// GetACMEProviderConfig gibt die Konfiguration eines ACME-Providers zurück
|
|
func (pm *ACMEProviderManager) GetACMEProviderConfig(id string) (*ACMEProviderConfig, error) {
|
|
pm.mu.RLock()
|
|
defer pm.mu.RUnlock()
|
|
|
|
config, exists := pm.configs[id]
|
|
if !exists {
|
|
return &ACMEProviderConfig{
|
|
Enabled: false,
|
|
Settings: make(map[string]interface{}),
|
|
}, nil
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
// SetACMEProviderEnabled aktiviert/deaktiviert einen ACME-Provider
|
|
func (pm *ACMEProviderManager) SetACMEProviderEnabled(id string, enabled bool) error {
|
|
pm.mu.Lock()
|
|
defer pm.mu.Unlock()
|
|
|
|
if pm.configs[id] == nil {
|
|
pm.configs[id] = &ACMEProviderConfig{
|
|
Enabled: enabled,
|
|
Settings: make(map[string]interface{}),
|
|
}
|
|
} else {
|
|
pm.configs[id].Enabled = enabled
|
|
}
|
|
|
|
return pm.saveConfig(id, pm.configs[id])
|
|
}
|
|
|
|
// loadAllConfigs lädt alle Konfigurationsdateien
|
|
func (pm *ACMEProviderManager) 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
|
|
// Nur ACME-Provider-Konfigurationen laden (beginnen mit "letsencrypt")
|
|
if id == "letsencrypt-production" || id == "letsencrypt-staging" {
|
|
config, err := pm.loadConfig(id)
|
|
if err == nil {
|
|
pm.configs[id] = config
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// loadConfig lädt eine Konfigurationsdatei
|
|
func (pm *ACMEProviderManager) loadConfig(id string) (*ACMEProviderConfig, error) {
|
|
filePath := filepath.Join(pm.configDir, id+".json")
|
|
|
|
data, err := os.ReadFile(filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var config ACMEProviderConfig
|
|
if err := json.Unmarshal(data, &config); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// saveConfig speichert eine Konfiguration in eine Datei
|
|
func (pm *ACMEProviderManager) saveConfig(id string, config *ACMEProviderConfig) 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)
|
|
}
|
|
|