Fix: SettingsController in install.sh aktualisiert (rmmagent[general] Parsing)

This commit is contained in:
cynfo3000
2026-03-01 01:37:35 +01:00
parent 77ec200b42
commit c114df215a
11 changed files with 534 additions and 60 deletions
+73 -5
View File
@@ -28,6 +28,7 @@ func (h *Handler) SetupRoutes(mux *http.ServeMux, hub *ws.Hub) {
// Bestehende Agent-Routes
mux.HandleFunc("POST /api/v1/agent/register", h.registerAgent)
mux.HandleFunc("POST /api/v1/agent/heartbeat", h.heartbeat)
mux.HandleFunc("POST /api/v1/agents", h.preRegisterAgent)
mux.HandleFunc("GET /api/v1/agents", h.listAgents)
mux.HandleFunc("GET /api/v1/agents/events", h.getAllAgentEvents)
mux.HandleFunc("GET /api/v1/agents/{id}", h.getAgent)
@@ -114,6 +115,17 @@ func (h *Handler) registerAgent(w http.ResponseWriter, r *http.Request) {
}
}
if agentID == "" {
// Nach pre-registriertem Agent mit gleichem Namen suchen (hostname="(ausstehend)")
if existing, err := h.db.GetAgentByName(req.Name); err == nil && existing != nil {
if existing.Hostname == "(ausstehend)" {
agentID = existing.ID
isExisting = true
log.Printf("Pre-registrierten Agent gefunden: %s (%s)", existing.Name, existing.ID)
}
}
}
if agentID == "" {
agentID = generateID()
}
@@ -145,6 +157,50 @@ func (h *Handler) registerAgent(w http.ResponseWriter, r *http.Request) {
})
}
// POST /api/v1/agents - Pre-Registration einer Firewall
func (h *Handler) preRegisterAgent(w http.ResponseWriter, r *http.Request) {
var req struct {
Name string `json:"name"`
CustomerID *int `json:"customer_id,omitempty"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "Ungueltige Anfrage")
return
}
if req.Name == "" {
writeError(w, http.StatusBadRequest, "Name ist erforderlich")
return
}
agentID := generateID()
agent := &models.Agent{
ID: agentID,
Name: req.Name,
Hostname: "(ausstehend)",
IP: "",
RegisteredAt: time.Now().UTC(),
}
if err := h.db.RegisterAgent(agent); err != nil {
log.Printf("Fehler bei Pre-Registration: %v", err)
writeError(w, http.StatusInternalServerError, "Pre-Registration fehlgeschlagen")
return
}
// Optionale Kundenzuordnung
if req.CustomerID != nil {
h.db.AssignAgentCustomer(agentID, *req.CustomerID)
}
log.Printf("Agent pre-registriert: %s (%s)", req.Name, agentID)
writeJSON(w, http.StatusCreated, map[string]interface{}{
"id": agentID,
"name": req.Name,
"message": "Firewall erfolgreich pre-registriert",
})
}
// POST /api/v1/agent/heartbeat
func (h *Handler) heartbeat(w http.ResponseWriter, r *http.Request) {
var req models.HeartbeatRequest
@@ -158,6 +214,9 @@ func (h *Handler) heartbeat(w http.ResponseWriter, r *http.Request) {
return
}
// Agent-Version VOR Update lesen (fuer Update-Flag Logik)
prevAgentVersion := h.db.GetAgentVersionFromDB(req.AgentID)
// Agent-Version aktualisieren
if req.AgentVersion != "" {
h.db.UpdateAgentVersion(req.AgentID, req.AgentVersion)
@@ -177,14 +236,23 @@ func (h *Handler) heartbeat(w http.ResponseWriter, r *http.Request) {
// Pruefen ob Update ansteht (default freebsd fuer OPNsense)
if h.db.IsUpdateRequested(req.AgentID) {
if version, hash, _, err := h.db.GetFirmwareInfo("freebsd"); err == nil {
if version != req.AgentVersion {
version, hash, _, err := h.db.GetFirmwareInfo("freebsd")
if err != nil {
// Keine Firmware vorhanden — Flag sinnlos, loeschen
h.db.ClearUpdateRequest(req.AgentID)
} else if version == req.AgentVersion {
// Agent hat genau die Firmware-Version — fertig
h.db.ClearUpdateRequest(req.AgentID)
} else {
// Pruefen ob Agent-Version sich seit Flag-Setzung geaendert hat
// (z.B. manuelles Update auf andere Version)
if prevAgentVersion != "" && prevAgentVersion != req.AgentVersion {
// Version hat sich geaendert — Update war erfolgreich (manuell oder anderweitig)
h.db.ClearUpdateRequest(req.AgentID)
} else {
resp.UpdateAvailable = true
resp.UpdateVersion = version
resp.UpdateHash = hash
} else {
// Gleiche Version — Flag zuruecksetzen
h.db.ClearUpdateRequest(req.AgentID)
}
}
}
+28
View File
@@ -416,6 +416,27 @@ func (d *Database) GetAgentByHostname(hostname string) (*models.Agent, error) {
return &a, nil
}
func (d *Database) GetAgentByName(name string) (*models.Agent, error) {
var a models.Agent
var lastHB sql.NullTime
err := d.db.QueryRow(
"SELECT id, name, hostname, ip, opnsense_version, registered_at, last_heartbeat FROM agents WHERE name = $1 LIMIT 1",
name,
).Scan(&a.ID, &a.Name, &a.Hostname, &a.IP, &a.OPNsenseVersion, &a.RegisteredAt, &lastHB)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
if lastHB.Valid {
a.LastHeartbeat = &lastHB.Time
}
return &a, nil
}
func (d *Database) GetAgent(id string) (*models.Agent, *models.SystemData, error) {
var a models.Agent
var lastHB sql.NullTime
@@ -505,6 +526,13 @@ func (d *Database) SetUpdateRequestAll(requested bool) (int64, error) {
return res.RowsAffected()
}
// Agent-Version direkt aus DB lesen (vor dem Update durch Heartbeat)
func (d *Database) GetAgentVersionFromDB(id string) string {
var version string
d.db.QueryRow("SELECT agent_version FROM agents WHERE id = $1", id).Scan(&version)
return version
}
// Agent-Firmware speichern (pro Plattform)
func (d *Database) SaveAgentFirmware(version, platform, hash string, binary []byte) error {
_, err := d.db.Exec(`
+9
View File
@@ -21,6 +21,15 @@ type SystemData struct {
Plugins []PluginInfo `json:"plugins,omitempty"`
Updates *UpdateInfo `json:"updates,omitempty"`
CronJobs []CronJob `json:"cron_jobs,omitempty"`
License *LicenseInfo `json:"license,omitempty"`
}
type LicenseInfo struct {
IsBusinessEdition bool `json:"is_business_edition"`
ProductName string `json:"product_name,omitempty"`
Subscription string `json:"subscription,omitempty"`
ValidTo string `json:"valid_to,omitempty"`
DaysRemaining int `json:"days_remaining,omitempty"`
}
type WireGuardTunnel struct {