feat: granular subsystem commands with parallel scanner execution
Split monolithic scan_updates into individual subsystems (updates/storage/system/docker). Scanners now run in parallel via goroutines - cuts scan time roughly in half, maybe more. Agent changes: - Orchestrator pattern for scanner management - New scanners: storage (disk metrics), system (cpu/mem/processes) - New commands: scan_storage, scan_system, scan_docker - Wrapped existing scanners (APT/DNF/Docker/Windows/Winget) with common interface - Version bump to 0.1.20 Server changes: - Migration 015: agent_subsystems table with trigger for auto-init - Subsystem CRUD: enable/disable, interval (5min-24hr), auto-run toggle - API routes: /api/v1/agents/:id/subsystems/* (9 endpoints) - Stats tracking per subsystem Web UI changes: - ChatTimeline shows subsystem-specific labels and icons - AgentScanners got interactive toggles, interval dropdowns, manual trigger buttons - TypeScript types added for subsystems Backward compatible with legacy scan_updates - for now. Bugs probably exist somewhere.
This commit is contained in:
@@ -128,6 +128,7 @@ func main() {
|
||||
refreshTokenQueries := queries.NewRefreshTokenQueries(db.DB)
|
||||
registrationTokenQueries := queries.NewRegistrationTokenQueries(db.DB)
|
||||
userQueries := queries.NewUserQueries(db.DB)
|
||||
subsystemQueries := queries.NewSubsystemQueries(db.DB)
|
||||
|
||||
// Ensure admin user exists
|
||||
if err := userQueries.EnsureAdminUser(cfg.Admin.Username, cfg.Admin.Username+"@redflag.local", cfg.Admin.Password); err != nil {
|
||||
@@ -153,6 +154,7 @@ func main() {
|
||||
registrationTokenHandler := handlers.NewRegistrationTokenHandler(registrationTokenQueries, agentQueries, cfg)
|
||||
rateLimitHandler := handlers.NewRateLimitHandler(rateLimiter)
|
||||
downloadHandler := handlers.NewDownloadHandler(filepath.Join("/app"), cfg)
|
||||
subsystemHandler := handlers.NewSubsystemHandler(subsystemQueries, commandQueries)
|
||||
|
||||
// Setup router
|
||||
router := gin.Default()
|
||||
@@ -195,6 +197,17 @@ func main() {
|
||||
agents.POST("/:id/system-info", rateLimiter.RateLimit("agent_reports", middleware.KeyByAgentID), agentHandler.ReportSystemInfo)
|
||||
agents.POST("/:id/rapid-mode", rateLimiter.RateLimit("agent_reports", middleware.KeyByAgentID), agentHandler.SetRapidPollingMode)
|
||||
agents.DELETE("/:id", agentHandler.UnregisterAgent)
|
||||
|
||||
// Subsystem routes
|
||||
agents.GET("/:id/subsystems", subsystemHandler.GetSubsystems)
|
||||
agents.GET("/:id/subsystems/:subsystem", subsystemHandler.GetSubsystem)
|
||||
agents.PATCH("/:id/subsystems/:subsystem", subsystemHandler.UpdateSubsystem)
|
||||
agents.POST("/:id/subsystems/:subsystem/enable", subsystemHandler.EnableSubsystem)
|
||||
agents.POST("/:id/subsystems/:subsystem/disable", subsystemHandler.DisableSubsystem)
|
||||
agents.POST("/:id/subsystems/:subsystem/trigger", subsystemHandler.TriggerSubsystem)
|
||||
agents.GET("/:id/subsystems/:subsystem/stats", subsystemHandler.GetSubsystemStats)
|
||||
agents.POST("/:id/subsystems/:subsystem/auto-run", subsystemHandler.SetAutoRun)
|
||||
agents.POST("/:id/subsystems/:subsystem/interval", subsystemHandler.SetInterval)
|
||||
}
|
||||
|
||||
// Dashboard/Web routes (protected by web auth)
|
||||
|
||||
Reference in New Issue
Block a user