package api import ( "encoding/json" "log" "net/http" "time" "github.com/cynfo/rmm-backend/ws" ) func (h *Handler) setupTunnelRoutes(mux *http.ServeMux, hub *ws.Hub) { // Command-Endpoints mux.HandleFunc("POST /api/v1/agents/{id}/exec", h.executeCommand(hub)) mux.HandleFunc("POST /api/v1/agents/{id}/tunnel", h.openTunnel(hub)) mux.HandleFunc("DELETE /api/v1/agents/{id}/tunnel/{tunnel_id}", h.closeTunnel(hub)) mux.HandleFunc("GET /api/v1/agents/{id}/tunnels", h.listTunnels(hub)) // HTTP-Proxy durch Tunnel mux.HandleFunc("GET /api/v1/agents/{id}/proxy/{tunnel_id}/", h.httpProxy(hub)) mux.HandleFunc("POST /api/v1/agents/{id}/proxy/{tunnel_id}/", h.httpProxy(hub)) mux.HandleFunc("PUT /api/v1/agents/{id}/proxy/{tunnel_id}/", h.httpProxy(hub)) mux.HandleFunc("DELETE /api/v1/agents/{id}/proxy/{tunnel_id}/", h.httpProxy(hub)) // WebSocket-Endpoint mux.HandleFunc("GET /api/v1/agent/ws", ws.NewWebSocketHandler(hub)) // Hub-Status mux.HandleFunc("GET /api/v1/hub/status", h.hubStatus(hub)) } func (h *Handler) executeCommand(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { agentID := r.PathValue("id") // Request parsen var req struct { Command string `json:"command"` Timeout int `json:"timeout,omitempty"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "Ungültige Anfrage") return } if req.Command == "" { writeError(w, http.StatusBadRequest, "Parameter 'command' erforderlich") return } if req.Timeout == 0 { req.Timeout = 30 } // Prüfen ob Agent verbunden ist if !hub.IsAgentConnected(agentID) { writeError(w, http.StatusServiceUnavailable, "Agent nicht verbunden") return } // Command-Message erstellen cmd := map[string]interface{}{ "type": "command", "id": generateID(), "command": "exec", "params": map[string]interface{}{ "command": req.Command, "timeout": req.Timeout, }, } cmdJSON, _ := json.Marshal(cmd) // Command an Agent senden if err := hub.SendToAgent(agentID, cmdJSON); err != nil { log.Printf("Command senden fehlgeschlagen: %v", err) writeError(w, http.StatusInternalServerError, "Command senden fehlgeschlagen") return } // Response zurückgeben writeJSON(w, http.StatusOK, map[string]interface{}{ "message": "Command gesendet", "command_id": cmd["id"], }) } } func (h *Handler) openTunnel(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { agentID := r.PathValue("id") // Request parsen var req struct { TargetHost string `json:"target_host"` TargetPort int `json:"target_port"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "Ungültige Anfrage") return } if req.TargetHost == "" || req.TargetPort <= 0 { writeError(w, http.StatusBadRequest, "target_host und target_port erforderlich") return } // Tunnel öffnen tunnel, err := hub.GetTunnelManager().OpenTunnel(agentID, req.TargetHost, req.TargetPort) if err != nil { log.Printf("Tunnel öffnen fehlgeschlagen: %v", err) writeError(w, http.StatusInternalServerError, err.Error()) return } // Response writeJSON(w, http.StatusCreated, map[string]interface{}{ "tunnel_id": tunnel.ID, "proxy_port": tunnel.ProxyPort, "target_host": tunnel.TargetHost, "target_port": tunnel.TargetPort, "created_at": tunnel.CreatedAt, }) } } func (h *Handler) closeTunnel(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { tunnelID := r.PathValue("tunnel_id") // Tunnel schließen if err := hub.GetTunnelManager().CloseTunnel(tunnelID); err != nil { writeError(w, http.StatusNotFound, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{ "message": "Tunnel geschlossen", }) } } func (h *Handler) listTunnels(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { agentID := r.PathValue("id") // Tunnel für Agent abrufen tunnels := hub.GetTunnelManager().GetAgentTunnels(agentID) // Response formatieren result := make([]map[string]interface{}, len(tunnels)) for i, tunnel := range tunnels { result[i] = map[string]interface{}{ "tunnel_id": tunnel.ID, "proxy_port": tunnel.ProxyPort, "target_host": tunnel.TargetHost, "target_port": tunnel.TargetPort, "active": tunnel.Active, "created_at": tunnel.CreatedAt, } } writeJSON(w, http.StatusOK, result) } } func (h *Handler) httpProxy(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { tunnelID := r.PathValue("tunnel_id") // HTTP-Proxy durch Tunnel if err := hub.GetTunnelManager().CreateHTTPProxy(tunnelID, w, r); err != nil { writeError(w, http.StatusNotFound, err.Error()) return } } } func (h *Handler) hubStatus(hub *ws.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { stats := hub.GetAgentStats() connectedAgents := hub.GetConnectedAgents() response := map[string]interface{}{ "status": "running", "connected_agents": connectedAgents, "stats": stats, "timestamp": time.Now(), } writeJSON(w, http.StatusOK, response) } }