diff --git a/cmd/pulse/main.go b/cmd/pulse/main.go index f8e160e..082d975 100644 --- a/cmd/pulse/main.go +++ b/cmd/pulse/main.go @@ -148,6 +148,9 @@ func runServer() { } if router != nil { router.SetMonitor(reloadableMonitor.GetMonitor()) + if cfg := reloadableMonitor.GetConfig(); cfg != nil { + router.SetConfig(cfg) + } } return nil } @@ -175,6 +178,9 @@ func runServer() { log.Error().Err(err).Msg("Failed to reload monitor after mock.env change") } else if router != nil { router.SetMonitor(reloadableMonitor.GetMonitor()) + if cfg := reloadableMonitor.GetConfig(); cfg != nil { + router.SetConfig(cfg) + } } }) diff --git a/internal/api/config_handlers.go b/internal/api/config_handlers.go index 11d342c..0f4ea5d 100644 --- a/internal/api/config_handlers.go +++ b/internal/api/config_handlers.go @@ -23,12 +23,12 @@ import ( internalauth "github.com/rcourtman/pulse-go-rewrite/internal/auth" "github.com/rcourtman/pulse-go-rewrite/internal/config" + discoveryinternal "github.com/rcourtman/pulse-go-rewrite/internal/discovery" "github.com/rcourtman/pulse-go-rewrite/internal/mock" "github.com/rcourtman/pulse-go-rewrite/internal/models" "github.com/rcourtman/pulse-go-rewrite/internal/monitoring" "github.com/rcourtman/pulse-go-rewrite/internal/tempproxy" "github.com/rcourtman/pulse-go-rewrite/internal/websocket" - discoveryinternal "github.com/rcourtman/pulse-go-rewrite/internal/discovery" pkgdiscovery "github.com/rcourtman/pulse-go-rewrite/pkg/discovery" "github.com/rcourtman/pulse-go-rewrite/pkg/pbs" "github.com/rcourtman/pulse-go-rewrite/pkg/pmg" @@ -91,6 +91,14 @@ func (h *ConfigHandlers) SetMonitor(m *monitoring.Monitor) { h.monitor = m } +// SetConfig updates the configuration reference used by the handlers. +func (h *ConfigHandlers) SetConfig(cfg *config.Config) { + if cfg == nil { + return + } + h.config = cfg +} + // cleanupExpiredCodes removes expired or used setup codes periodically func (h *ConfigHandlers) cleanupExpiredCodes() { ticker := time.NewTicker(5 * time.Minute) @@ -2862,12 +2870,12 @@ func (h *ConfigHandlers) HandleDiscoverServers(w http.ResponseWriter, r *http.Re } response := map[string]interface{}{ - "servers": result.Servers, - "errors": result.Errors, - "environment": result.Environment, - "cached": true, - "updated": updatedUnix, - "age": ageSeconds, + "servers": result.Servers, + "errors": result.Errors, + "environment": result.Environment, + "cached": true, + "updated": updatedUnix, + "age": ageSeconds, } w.Header().Set("Content-Type", "application/json") diff --git a/internal/api/router.go b/internal/api/router.go index f6884ab..506e93b 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -1052,6 +1052,26 @@ func (r *Router) SetMonitor(m *monitoring.Monitor) { } } +// SetConfig refreshes the configuration reference used by the router and dependent handlers. +func (r *Router) SetConfig(cfg *config.Config) { + if cfg == nil { + return + } + + if r.config == nil { + r.config = cfg + } else { + *r.config = *cfg + } + + if r.configHandlers != nil { + r.configHandlers.SetConfig(r.config) + } + if r.systemSettingsHandler != nil { + r.systemSettingsHandler.SetConfig(r.config) + } +} + // reloadSystemSettings loads system settings from disk and caches them func (r *Router) reloadSystemSettings() { r.settingsMu.Lock() diff --git a/internal/api/system_settings.go b/internal/api/system_settings.go index 5594cb3..d09b4b2 100644 --- a/internal/api/system_settings.go +++ b/internal/api/system_settings.go @@ -58,6 +58,14 @@ func (h *SystemSettingsHandler) SetMonitor(m interface { h.monitor = m } +// SetConfig updates the configuration reference used by the handler. +func (h *SystemSettingsHandler) SetConfig(cfg *config.Config) { + if cfg == nil { + return + } + h.config = cfg +} + func firstValueForKeys(m map[string]interface{}, keys ...string) (interface{}, bool) { for _, key := range keys { if val, ok := m[key]; ok { @@ -682,12 +690,12 @@ func (h *SystemSettingsHandler) HandleSSHConfig(w http.ResponseWriter, r *http.R // Security: Use allowlist-based validation (safer than blocklist) // Only permit the specific directives Pulse needs for ProxyJump allowedDirectives := map[string]bool{ - "host": true, - "hostname": true, - "proxyjump": true, - "user": true, - "identityfile": true, - "stricthostkeychecking": true, + "host": true, + "hostname": true, + "proxyjump": true, + "user": true, + "identityfile": true, + "stricthostkeychecking": true, } // Parse and validate each line diff --git a/internal/monitoring/reload.go b/internal/monitoring/reload.go index cc5d299..097db3f 100644 --- a/internal/monitoring/reload.go +++ b/internal/monitoring/reload.go @@ -132,6 +132,16 @@ func (rm *ReloadableMonitor) GetMonitor() *Monitor { return rm.monitor } +// GetConfig returns the current configuration used by the monitor. +func (rm *ReloadableMonitor) GetConfig() *config.Config { + rm.mu.RLock() + defer rm.mu.RUnlock() + if rm.config == nil { + return nil + } + return rm.config +} + // GetState returns the current state func (rm *ReloadableMonitor) GetState() interface{} { return rm.GetMonitor().GetState()