diff --git a/backend/api/controllers/v1/proxies/connections.go b/backend/api/controllers/v1/proxies/connections.go index 781b1f5..8e7ea8b 100644 --- a/backend/api/controllers/v1/proxies/connections.go +++ b/backend/api/controllers/v1/proxies/connections.go @@ -8,6 +8,7 @@ import ( "git.terah.dev/imterah/hermes/api/dbcore" "git.terah.dev/imterah/hermes/api/jwtcore" "git.terah.dev/imterah/hermes/api/permissions" + "git.terah.dev/imterah/hermes/commonbackend" "github.com/charmbracelet/log" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" @@ -18,17 +19,22 @@ type ConnectionsRequest struct { Id uint `validate:"required" json:"id"` } -type SanitizedBackends struct { - UserID uint `json:"user_id"` - Name string `json:"name"` - Description string `json:"description"` - Backend string `json:"backend"` - BackendParameters string `json:"backend_parameters"` +type ConnectionDetailsForConnection struct { + SourceIP string `json:"sourceIP"` + SourcePort uint16 `json:"sourcePort"` + DestPort uint16 `json:"destPort"` +} + +type SanitizedConnection struct { + ClientIP string `json:"ip"` + Port uint16 `json:"port"` + + ConnectionDetails *ConnectionDetailsForConnection `json:"connectionDetails"` } type ConnectionsResponse struct { - Success bool `json:"success"` - Data []*SanitizedBackends `json:"data"` + Success bool `json:"success"` + Data []*SanitizedConnection `json:"data"` } func Connections(c *gin.Context) { @@ -62,7 +68,7 @@ func Connections(c *gin.Context) { log.Warnf("Failed to get user from the provided JWT token: %s", err.Error()) c.JSON(http.StatusInternalServerError, gin.H{ - "error": "failed to parse token", + "error": "Failed to parse token", }) return @@ -77,11 +83,11 @@ func Connections(c *gin.Context) { return } - var routes []dbcore.Proxy - routesRequest := dbcore.DB.Where("id = ?", req.Id).First(&routes) + var proxy dbcore.Proxy + proxyRequest := dbcore.DB.Where("id = ?", req.Id).First(&proxy) - if routesRequest.Error != nil { - log.Warnf("failed to find proxy: %s", routesRequest.Error) + if proxyRequest.Error != nil { + log.Warnf("failed to find proxy: %s", proxyRequest.Error) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to find forward entry", @@ -90,9 +96,9 @@ func Connections(c *gin.Context) { return } - routesExist := routesRequest.RowsAffected > 0 + proxyExists := proxyRequest.RowsAffected > 0 - if !routesExist { + if !proxyExists { c.JSON(http.StatusBadRequest, gin.H{ "error": "No forward entry found", }) @@ -100,13 +106,81 @@ func Connections(c *gin.Context) { return } - // FIXME(greysoh): not finished - var backends []dbcore.Backend + var backend dbcore.Backend + backendRequest := dbcore.DB.Where("id = ?", proxy.BackendID).First(&backend) - sanitizedBackends := make([]*SanitizedBackends, len(backends)) + if backendRequest.Error != nil { + log.Warnf("failed to find backend: %s", backendRequest.Error) - c.JSON(http.StatusOK, gin.H{ - "success": true, - "data": sanitizedBackends, - }) + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to find backend entry", + }) + + return + } + + backendExists := backendRequest.RowsAffected > 0 + + if !backendExists { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "No forward entry found", + }) + + return + } + + backendRuntime, ok := backendruntime.RunningBackends[backend.ID] + + if !ok { + log.Warnf("Couldn't fetch backend runtime from backend ID #%d", backend.ID) + + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Couldn't fetch backend runtime", + }) + + return + } + + backendRuntime.RuntimeCommands <- &commonbackend.ProxyConnectionsRequest{ + Type: "proxyConnectionsRequest", + } + + backendResponse := <-backendRuntime.RuntimeCommands + + switch responseMessage := backendResponse.(type) { + case error: + log.Warnf("Failed to get response for backend: %s", responseMessage.Error()) + + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to get status response from backend", + }) + case *commonbackend.ProxyConnectionsResponse: + sanitizedConnections := []*SanitizedConnection{} + + for _, connection := range responseMessage.Connections { + if connection.SourceIP == proxy.SourceIP && connection.SourcePort == proxy.SourcePort && proxy.DestinationPort == proxy.DestinationPort { + sanitizedConnections = append(sanitizedConnections, &SanitizedConnection{ + ClientIP: connection.ClientIP, + Port: connection.ClientPort, + + ConnectionDetails: &ConnectionDetailsForConnection{ + SourceIP: proxy.SourceIP, + SourcePort: proxy.SourcePort, + DestPort: proxy.DestinationPort, + }, + }) + } + } + + c.JSON(http.StatusOK, &ConnectionsResponse{ + Success: true, + Data: sanitizedConnections, + }) + default: + log.Warnf("Got illegal response type for backend: %T", responseMessage) + + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Got illegal response type", + }) + } }