rmm2/backend/models/agent.go
cynfo3000 e74cdce0ba Agent-Updater, Multi-Plattform Firmware, Frontend Firmware-Seite, Agent-Tab, Zertifikate-Redesign
Updater:
- Separater Go-Daemon (rmm-updater) als eigener rc.d Service
- Pollt alle 60s: Firmware vorhanden + Hash unterschiedlich + Flag gesetzt
- Download -> SHA256 Verify -> Agent Stop -> Replace -> Agent Start
- Automatisches Rollback bei Fehler
- Deployed und getestet auf allen 3 Firewalls (.1, .19, .33)

Backend:
- Firmware-DB multi-plattform (freebsd/linux/windows)
- update_requested Flag pro Agent in agents Tabelle
- Heartbeat-Response liefert update_available wenn Flag gesetzt
- Neue Endpoints: request-update, request-update-all, firmware/download
- Auth: JWT + CombinedAuth Middleware (API-Key OR JWT)
- Customers CRUD + Agent-Zuordnung
- Users CRUD + Passwort-Aenderung

Frontend:
- Firmware-Seite: Multi-Plattform Upload, Agent-Liste mit Update-Trigger
- Agent-Tab im AgentPanel: Update-Button, nuetzliche Befehle, Agent-Info
- Zertifikate-Tab redesigned: Karten-Layout mit Restlaufzeit und Farbbalken
- Sidebar: Firmware-Eintrag hinzugefuegt

Plugin:
- install.sh erweitert: Installiert Agent + Updater + rc.d Services
- rmm_updater rc.d Service

README:
- Architektur-Diagramm erweitert (Frontend + Updater)
- Auth, Customers, Users, Firmware API dokumentiert
- Updater-Flow dokumentiert
- Frontend-Seiten und Deploy beschrieben
- DB-Schema aktualisiert (neue Tabellen)
- Dateistruktur erweitert (updater/, frontend/, firmware.go, auth.go)
2026-02-28 22:43:03 +01:00

65 lines
1.8 KiB
Go

package models
import "time"
// Agent repraesentiert einen registrierten OPNsense-Agent
type Agent struct {
ID string `json:"id"`
Name string `json:"name"`
Hostname string `json:"hostname"`
IP string `json:"ip"`
OPNsenseVersion string `json:"opnsense_version"`
AgentVersion string `json:"agent_version,omitempty"`
RegisteredAt time.Time `json:"registered_at"`
LastHeartbeat *time.Time `json:"last_heartbeat,omitempty"`
CustomerID *int `json:"customer_id,omitempty"`
UpdateRequested bool `json:"update_requested"`
}
// AgentResponse erweitert Agent um den berechneten Status
type AgentResponse struct {
Agent
Status string `json:"status"`
}
// AgentEvent repraesentiert ein Event in der agent_events Tabelle
type AgentEvent struct {
ID int `json:"id"`
AgentID string `json:"agent_id"`
EventType string `json:"event_type"`
Message string `json:"message,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// CalculateAgentStatus berechnet den Status aus dem letzten Heartbeat
func CalculateAgentStatus(lastHeartbeat *time.Time) string {
if lastHeartbeat == nil {
return "unknown"
}
age := time.Since(*lastHeartbeat)
switch {
case age < 2*time.Minute:
return "online"
case age < 5*time.Minute:
return "stale"
default:
return "offline"
}
}
// RegisterRequest - Agent-Registrierung
type RegisterRequest struct {
AgentID string `json:"agent_id,omitempty"`
Name string `json:"name"`
Hostname string `json:"hostname"`
IP string `json:"ip"`
OPNsenseVersion string `json:"opnsense_version"`
AgentVersion string `json:"agent_version,omitempty"`
}
// RegisterResponse
type RegisterResponse struct {
ID string `json:"id"`
Message string `json:"message"`
}