feat: route every console session through the agent relay

This commit is contained in:
2026-07-29 13:07:30 +01:00
parent 59d147fe4d
commit c0bec3737b
2 changed files with 63 additions and 13 deletions
+35 -2
View File
@@ -1,6 +1,7 @@
package api
import (
"errors"
"net"
"net/http"
"os"
@@ -33,6 +34,15 @@ func consoleConnect(c *gin.Context) {
return
}
if srv.Status != "active" {
c.JSON(http.StatusConflict, gin.H{
"error": "agent_offline",
"message": "The agent on this server is not connected. " +
"Console sessions are relayed by the agent, so it must be online.",
})
return
}
sess, err := services.CreateConsoleSession(auth.InstanceID(c), body.ServerID, body.Protocol, body.KeyID, actorFromCtx(c), c.ClientIP())
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
@@ -59,7 +69,7 @@ func consoleConnect(c *gin.Context) {
}
services.LogEvent(auth.InstanceID(c), "console.opened", actorFromCtx(c), srv.ServerID, "",
"console session opened ("+body.Protocol+")")
"console session opened ("+body.Protocol+", agent-relayed)")
c.JSON(http.StatusOK, gin.H{
"session_id": sess.SessionID,
@@ -124,7 +134,25 @@ func consoleTunnel(c *gin.Context) {
return
}
}
gp, err := services.BuildGuacParams(srv, sess.Protocol, sess.SSHUsername, privKey, passphrase, rdpUser, rdpPass)
targetPort, err := services.TargetPort(srv, sess.Protocol)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
relay, err := services.OpenConsoleProxy(instanceID, srv.ServerID, targetPort)
if err != nil {
if errors.Is(err, services.ErrAgentOffline) {
c.JSON(http.StatusConflict, gin.H{"error": "agent_offline"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": "could not open relay"})
return
}
defer relay.Close()
gp, err := services.BuildGuacParams(sess.Protocol, sess.SSHUsername, privKey, passphrase,
rdpUser, rdpPass, relay.Host, relay.Port)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
@@ -162,6 +190,11 @@ func consoleTunnel(c *gin.Context) {
wsServer := guac.NewWebsocketServer(connect)
wsServer.OnDisconnect = func(id string, r *http.Request, t guac.Tunnel) {
if reason := relay.Reason(); reason != "" {
services.LogEvent(instanceID, "console.proxy_failed", actorFromCtx(c), srv.ServerID, "",
"console relay failed: "+reason)
}
relay.Close()
_ = services.EndConsoleSession(instanceID, sessionID)
}
wsServer.ServeHTTP(c.Writer, c.Request)