fix: Fixes API routes.
This commit is contained in:
parent
fe8980b265
commit
bcf97fde6d
15 changed files with 284 additions and 132 deletions
|
@ -6,6 +6,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"git.terah.dev/imterah/hermes/api/backendruntime"
|
||||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||||
"git.terah.dev/imterah/hermes/api/jwtcore"
|
"git.terah.dev/imterah/hermes/api/jwtcore"
|
||||||
"git.terah.dev/imterah/hermes/api/permissions"
|
"git.terah.dev/imterah/hermes/api/permissions"
|
||||||
|
@ -23,12 +24,13 @@ type BackendLookupRequest struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SanitizedBackend struct {
|
type SanitizedBackend struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
BackendID uint `json:"id"`
|
BackendID uint `json:"id"`
|
||||||
OwnerID uint `json:"ownerID"`
|
OwnerID uint `json:"ownerID"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Backend string `json:"backend"`
|
Backend string `json:"backend"`
|
||||||
BackendParameters *string `json:"connectionDetails"`
|
BackendParameters *string `json:"connectionDetails"`
|
||||||
|
Logs []string `json:"logs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LookupResponse struct {
|
type LookupResponse struct {
|
||||||
|
@ -121,12 +123,25 @@ func LookupBackend(c *gin.Context) {
|
||||||
hasSecretVisibility := permissions.UserHasPermission(user, "backends.secretVis")
|
hasSecretVisibility := permissions.UserHasPermission(user, "backends.secretVis")
|
||||||
|
|
||||||
for backendIndex, backend := range backends {
|
for backendIndex, backend := range backends {
|
||||||
|
foundBackend, ok := backendruntime.RunningBackends[backend.ID]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("Failed to get backend #%d controller", backend.ID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Failed to get backends",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sanitizedBackends[backendIndex] = &SanitizedBackend{
|
sanitizedBackends[backendIndex] = &SanitizedBackend{
|
||||||
BackendID: backend.ID,
|
BackendID: backend.ID,
|
||||||
OwnerID: backend.UserID,
|
OwnerID: backend.UserID,
|
||||||
Name: backend.Name,
|
Name: backend.Name,
|
||||||
Description: backend.Description,
|
Description: backend.Description,
|
||||||
Backend: backend.Backend,
|
Backend: backend.Backend,
|
||||||
|
Logs: foundBackend.Logs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if backend.UserID == user.ID || hasSecretVisibility {
|
if backend.UserID == user.ID || hasSecretVisibility {
|
||||||
|
|
|
@ -106,33 +106,10 @@ func GetConnections(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var backend dbcore.Backend
|
backendRuntime, ok := backendruntime.RunningBackends[proxy.BackendID]
|
||||||
backendRequest := dbcore.DB.Where("id = ?", proxy.BackendID).First(&backend)
|
|
||||||
|
|
||||||
if backendRequest.Error != nil {
|
|
||||||
log.Warnf("failed to find backend: %s", backendRequest.Error)
|
|
||||||
|
|
||||||
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 {
|
if !ok {
|
||||||
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", backend.ID)
|
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", proxy.BackendID)
|
||||||
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"error": "Couldn't fetch backend runtime",
|
"error": "Couldn't fetch backend runtime",
|
||||||
|
|
|
@ -4,9 +4,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.terah.dev/imterah/hermes/api/backendruntime"
|
||||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||||
"git.terah.dev/imterah/hermes/api/jwtcore"
|
"git.terah.dev/imterah/hermes/api/jwtcore"
|
||||||
"git.terah.dev/imterah/hermes/api/permissions"
|
"git.terah.dev/imterah/hermes/api/permissions"
|
||||||
|
"git.terah.dev/imterah/hermes/commonbackend"
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
|
@ -16,17 +18,12 @@ type ProxyCreationRequest struct {
|
||||||
Token string `validate:"required" json:"token"`
|
Token string `validate:"required" json:"token"`
|
||||||
Name string `validate:"required" json:"name"`
|
Name string `validate:"required" json:"name"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Protcol string `validate:"required" json:"protcol"`
|
Protocol string `validate:"required" json:"protocol"`
|
||||||
SourceIP string `validate:"required" json:"source_ip"`
|
SourceIP string `validate:"required" json:"sourceIP"`
|
||||||
SourcePort uint16 `validate:"required" json:"source_port"`
|
SourcePort uint16 `validate:"required" json:"sourcePort"`
|
||||||
DestinationPort uint16 `validate:"required" json:"destination_port"`
|
DestinationPort uint16 `validate:"required" json:"destinationPort"`
|
||||||
ProviderID uint `validate:"required" json:"provider_id"`
|
ProviderID uint `validate:"required" json:"providerID"`
|
||||||
AutoStart bool `json:"auto_start"`
|
AutoStart *bool `json:"autoStart"`
|
||||||
}
|
|
||||||
|
|
||||||
type ProxyCreationResponse struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
Id uint `json:"id"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateProxy(c *gin.Context) {
|
func CreateProxy(c *gin.Context) {
|
||||||
|
@ -75,9 +72,9 @@ func CreateProxy(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Protcol != "tcp" && req.Protcol != "udp" {
|
if req.Protocol != "tcp" && req.Protocol != "udp" {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "Body protocol must be either 'tcp' or 'udp'",
|
"error": "Protocol must be either 'tcp' or 'udp'",
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -85,31 +82,39 @@ func CreateProxy(c *gin.Context) {
|
||||||
|
|
||||||
var backend dbcore.Backend
|
var backend dbcore.Backend
|
||||||
backendRequest := dbcore.DB.Where("id = ?", req.ProviderID).First(&backend)
|
backendRequest := dbcore.DB.Where("id = ?", req.ProviderID).First(&backend)
|
||||||
|
|
||||||
if backendRequest.Error != nil {
|
if backendRequest.Error != nil {
|
||||||
log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error)
|
log.Warnf("failed to find if backend exists or not: %s", backendRequest.Error)
|
||||||
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"error": "Failed to find if provider exists",
|
"error": "Failed to find if backend exists",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
backendExists := backendRequest.RowsAffected > 0
|
backendExists := backendRequest.RowsAffected > 0
|
||||||
|
|
||||||
if !backendExists {
|
if !backendExists {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "Could not find provider",
|
"error": "Could not find backend",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autoStart := false
|
||||||
|
|
||||||
|
if req.AutoStart != nil {
|
||||||
|
autoStart = *req.AutoStart
|
||||||
|
}
|
||||||
|
|
||||||
proxy := &dbcore.Proxy{
|
proxy := &dbcore.Proxy{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
BackendID: req.ProviderID,
|
BackendID: req.ProviderID,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Description: req.Description,
|
Description: req.Description,
|
||||||
Protocol: req.Protcol,
|
Protocol: req.Protocol,
|
||||||
SourceIP: req.SourceIP,
|
SourceIP: req.SourceIP,
|
||||||
SourcePort: req.SourcePort,
|
SourcePort: req.SourcePort,
|
||||||
DestinationPort: req.DestinationPort,
|
DestinationPort: req.DestinationPort,
|
||||||
AutoStart: req.AutoStart,
|
AutoStart: autoStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
if result := dbcore.DB.Create(proxy); result.Error != nil {
|
if result := dbcore.DB.Create(proxy); result.Error != nil {
|
||||||
|
@ -120,8 +125,50 @@ func CreateProxy(c *gin.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &ProxyCreationResponse{
|
if autoStart {
|
||||||
Success: true,
|
backend, ok := backendruntime.RunningBackends[proxy.BackendID]
|
||||||
Id: proxy.ID,
|
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", proxy.BackendID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
|
"id": proxy.ID,
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.RuntimeCommands <- &commonbackend.AddProxy{
|
||||||
|
Type: "addProxy",
|
||||||
|
SourceIP: proxy.SourceIP,
|
||||||
|
SourcePort: proxy.SourcePort,
|
||||||
|
DestPort: proxy.DestinationPort,
|
||||||
|
Protocol: proxy.Protocol,
|
||||||
|
}
|
||||||
|
|
||||||
|
backendResponse := <-backend.RuntimeCommands
|
||||||
|
|
||||||
|
switch responseMessage := backendResponse.(type) {
|
||||||
|
case error:
|
||||||
|
log.Warnf("Failed to get response for backend #%d: %s", proxy.BackendID, responseMessage.Error())
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "failed to get response from backend",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
case *commonbackend.ProxyStatusResponse:
|
||||||
|
if !responseMessage.IsActive {
|
||||||
|
log.Warnf("Failed to start proxy for backend #%d", proxy.BackendID)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Errorf("Got illegal response type for backend #%d: %T", proxy.BackendID, responseMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
|
"id": proxy.ID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,23 +19,23 @@ type ProxyLookupRequest struct {
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Protocol *string `json:"protocol"`
|
Protocol *string `json:"protocol"`
|
||||||
SourceIP *string `json:"source_ip"`
|
SourceIP *string `json:"sourceIP"`
|
||||||
SourcePort *uint16 `json:"source_port"`
|
SourcePort *uint16 `json:"sourcePort"`
|
||||||
DestinationPort *uint16 `json:"destination_port"`
|
DestinationPort *uint16 `json:"destPort"`
|
||||||
ProviderID *uint `json:"provider_id"`
|
ProviderID *uint `json:"providerID"`
|
||||||
AutoStart *bool `json:"auto_start"`
|
AutoStart *bool `json:"autoStart"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SanitizedProxy struct {
|
type SanitizedProxy struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Protcol string `json:"protcol"`
|
Protcol string `json:"protocol"`
|
||||||
SourceIP string `json:"source_ip"`
|
SourceIP string `json:"sourceIP"`
|
||||||
SourcePort uint16 `json:"source_port"`
|
SourcePort uint16 `json:"sourcePort"`
|
||||||
DestinationPort uint16 `json:"destination_port"`
|
DestinationPort uint16 `json:"destPort"`
|
||||||
ProviderID uint `json:"provider_id"`
|
ProviderID uint `json:"providerID"`
|
||||||
AutoStart bool `json:"auto_start"`
|
AutoStart bool `json:"autoStart"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyLookupResponse struct {
|
type ProxyLookupResponse struct {
|
||||||
|
@ -63,6 +63,7 @@ func LookupProxy(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := jwtcore.GetUserFromJWT(req.Token)
|
user, err := jwtcore.GetUserFromJWT(req.Token)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "token is expired" || err.Error() == "user does not exist" {
|
if err.Error() == "token is expired" || err.Error() == "user does not exist" {
|
||||||
c.JSON(http.StatusForbidden, gin.H{
|
c.JSON(http.StatusForbidden, gin.H{
|
||||||
|
@ -89,13 +90,16 @@ func LookupProxy(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if *req.Protcol != "tcp" && *req.Protcol != "udp" {
|
if req.Protocol != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{
|
if *req.Protocol != "tcp" && *req.Protocol != "udp" {
|
||||||
"error": "Protocol specified in body must either be 'tcp' or 'udp'",
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
})
|
"error": "Protocol specified in body must either be 'tcp' or 'udp'",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxies := []dbcore.Proxy{}
|
proxies := []dbcore.Proxy{}
|
||||||
|
|
||||||
queryString := []string{}
|
queryString := []string{}
|
||||||
queryParameters := []interface{}{}
|
queryParameters := []interface{}{}
|
||||||
|
|
||||||
|
@ -103,34 +107,42 @@ func LookupProxy(c *gin.Context) {
|
||||||
queryString = append(queryString, "id = ?")
|
queryString = append(queryString, "id = ?")
|
||||||
queryParameters = append(queryParameters, req.Id)
|
queryParameters = append(queryParameters, req.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Name != nil {
|
if req.Name != nil {
|
||||||
queryString = append(queryString, "name = ?")
|
queryString = append(queryString, "name = ?")
|
||||||
queryParameters = append(queryParameters, req.Name)
|
queryParameters = append(queryParameters, req.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Description != nil {
|
if req.Description != nil {
|
||||||
queryString = append(queryString, "description = ?")
|
queryString = append(queryString, "description = ?")
|
||||||
queryParameters = append(queryParameters, req.Description)
|
queryParameters = append(queryParameters, req.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.SourceIP != nil {
|
if req.SourceIP != nil {
|
||||||
queryString = append(queryString, "name = ?")
|
queryString = append(queryString, "name = ?")
|
||||||
queryParameters = append(queryParameters, req.Name)
|
queryParameters = append(queryParameters, req.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.SourcePort != nil {
|
if req.SourcePort != nil {
|
||||||
queryString = append(queryString, "sourceport = ?")
|
queryString = append(queryString, "sourceport = ?")
|
||||||
queryParameters = append(queryParameters, req.SourcePort)
|
queryParameters = append(queryParameters, req.SourcePort)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.DestinationPort != nil {
|
if req.DestinationPort != nil {
|
||||||
queryString = append(queryString, "destinationport = ?")
|
queryString = append(queryString, "destinationport = ?")
|
||||||
queryParameters = append(queryParameters, req.DestinationPort)
|
queryParameters = append(queryParameters, req.DestinationPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.ProviderID != nil {
|
if req.ProviderID != nil {
|
||||||
queryString = append(queryString, "backendid = ?")
|
queryString = append(queryString, "backendid = ?")
|
||||||
queryParameters = append(queryParameters, req.ProviderID)
|
queryParameters = append(queryParameters, req.ProviderID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.AutoStart != nil {
|
if req.AutoStart != nil {
|
||||||
queryString = append(queryString, "autostart = ?")
|
queryString = append(queryString, "autostart = ?")
|
||||||
queryParameters = append(queryParameters, req.AutoStart)
|
queryParameters = append(queryParameters, req.AutoStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Protocol != nil {
|
if req.Protocol != nil {
|
||||||
queryString = append(queryString, "protocol = ?")
|
queryString = append(queryString, "protocol = ?")
|
||||||
queryParameters = append(queryParameters, req.Protocol)
|
queryParameters = append(queryParameters, req.Protocol)
|
||||||
|
@ -140,7 +152,7 @@ func LookupProxy(c *gin.Context) {
|
||||||
log.Warnf("failed to get proxies: %s", err.Error())
|
log.Warnf("failed to get proxies: %s", err.Error())
|
||||||
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
"error": "failed to get forward rules",
|
"error": "Failed to get proxies",
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -149,15 +161,10 @@ func LookupProxy(c *gin.Context) {
|
||||||
sanitizedProxies := make([]*SanitizedProxy, len(proxies))
|
sanitizedProxies := make([]*SanitizedProxy, len(proxies))
|
||||||
|
|
||||||
for proxyIndex, proxy := range proxies {
|
for proxyIndex, proxy := range proxies {
|
||||||
description := ""
|
|
||||||
if proxy.Description != nil {
|
|
||||||
description = *proxy.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
sanitizedProxies[proxyIndex] = &SanitizedProxy{
|
sanitizedProxies[proxyIndex] = &SanitizedProxy{
|
||||||
Id: proxy.ID,
|
Id: proxy.ID,
|
||||||
Name: proxy.Name,
|
Name: proxy.Name,
|
||||||
Description: &description,
|
Description: proxy.Description,
|
||||||
Protcol: proxy.Protocol,
|
Protcol: proxy.Protocol,
|
||||||
SourceIP: proxy.SourceIP,
|
SourceIP: proxy.SourceIP,
|
||||||
SourcePort: proxy.SourcePort,
|
SourcePort: proxy.SourcePort,
|
||||||
|
|
|
@ -4,9 +4,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.terah.dev/imterah/hermes/api/backendruntime"
|
||||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||||
"git.terah.dev/imterah/hermes/api/jwtcore"
|
"git.terah.dev/imterah/hermes/api/jwtcore"
|
||||||
"git.terah.dev/imterah/hermes/api/permissions"
|
"git.terah.dev/imterah/hermes/api/permissions"
|
||||||
|
"git.terah.dev/imterah/hermes/commonbackend"
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
|
@ -17,10 +19,6 @@ type ProxyRemovalRequest struct {
|
||||||
ID uint `validate:"required" json:"id"`
|
ID uint `validate:"required" json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyRemovalResponse struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveProxy(c *gin.Context) {
|
func RemoveProxy(c *gin.Context) {
|
||||||
var req ProxyRemovalRequest
|
var req ProxyRemovalRequest
|
||||||
|
|
||||||
|
@ -100,7 +98,56 @@ func RemoveProxy(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &ProxyRemovalResponse{
|
backend, ok := backendruntime.RunningBackends[proxy.BackendID]
|
||||||
Success: true,
|
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", proxy.BackendID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Couldn't fetch backend runtime",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.RuntimeCommands <- &commonbackend.RemoveProxy{
|
||||||
|
Type: "removeProxy",
|
||||||
|
SourceIP: proxy.SourceIP,
|
||||||
|
SourcePort: proxy.SourcePort,
|
||||||
|
DestPort: proxy.DestinationPort,
|
||||||
|
Protocol: proxy.Protocol,
|
||||||
|
}
|
||||||
|
|
||||||
|
backendResponse := <-backend.RuntimeCommands
|
||||||
|
|
||||||
|
switch responseMessage := backendResponse.(type) {
|
||||||
|
case error:
|
||||||
|
log.Warnf("Failed to get response for backend #%d: %s", proxy.BackendID, responseMessage.Error())
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Failed to get response from backend. Proxy was still successfully deleted",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
case *commonbackend.ProxyStatusResponse:
|
||||||
|
if responseMessage.IsActive {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Failed to stop proxy. Proxy was still successfully deleted",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Errorf("Got illegal response type for backend #%d: %T", proxy.BackendID, responseMessage)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Got invalid response from backend. Proxy was still successfully deleted",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,6 @@ type ProxyStartRequest struct {
|
||||||
ID uint `validate:"required" json:"id"`
|
ID uint `validate:"required" json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyStartResponse struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartProxy(c *gin.Context) {
|
func StartProxy(c *gin.Context) {
|
||||||
var req ProxyStartRequest
|
var req ProxyStartRequest
|
||||||
|
|
||||||
|
@ -92,9 +88,19 @@ func StartProxy(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
backend := backendruntime.RunningBackends[proxy.BackendID]
|
backend, ok := backendruntime.RunningBackends[proxy.BackendID]
|
||||||
|
|
||||||
backend.RuntimeCommands <- commonbackend.AddProxy{
|
if !ok {
|
||||||
|
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", proxy.BackendID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Couldn't fetch backend runtime",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.RuntimeCommands <- &commonbackend.AddProxy{
|
||||||
Type: "addProxy",
|
Type: "addProxy",
|
||||||
SourceIP: proxy.SourceIP,
|
SourceIP: proxy.SourceIP,
|
||||||
SourcePort: proxy.SourcePort,
|
SourcePort: proxy.SourcePort,
|
||||||
|
@ -121,13 +127,19 @@ func StartProxy(c *gin.Context) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
log.Errorf("Got illegal response type for backend #%d: %T", proxy.BackendID, responseMessage)
|
log.Errorf("Got illegal response type for backend #%d: %T", proxy.BackendID, responseMessage)
|
||||||
break
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Got invalid response from backend. Proxy was still successfully deleted",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &ProxyStartResponse{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
Success: true,
|
"success": true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,6 @@ type ProxyStopRequest struct {
|
||||||
ID uint `validate:"required" json:"id"`
|
ID uint `validate:"required" json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyStopResponse struct {
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func StopProxy(c *gin.Context) {
|
func StopProxy(c *gin.Context) {
|
||||||
var req ProxyStopRequest
|
var req ProxyStopRequest
|
||||||
|
|
||||||
|
@ -92,9 +88,19 @@ func StopProxy(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
backend := backendruntime.RunningBackends[proxy.BackendID]
|
backend, ok := backendruntime.RunningBackends[proxy.BackendID]
|
||||||
|
|
||||||
backend.RuntimeCommands <- commonbackend.RemoveProxy{
|
if !ok {
|
||||||
|
log.Warnf("Couldn't fetch backend runtime from backend ID #%d", proxy.BackendID)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Couldn't fetch backend runtime",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.RuntimeCommands <- &commonbackend.RemoveProxy{
|
||||||
Type: "removeProxy",
|
Type: "removeProxy",
|
||||||
SourceIP: proxy.SourceIP,
|
SourceIP: proxy.SourceIP,
|
||||||
SourcePort: proxy.SourcePort,
|
SourcePort: proxy.SourcePort,
|
||||||
|
@ -102,7 +108,36 @@ func StopProxy(c *gin.Context) {
|
||||||
Protocol: proxy.Protocol,
|
Protocol: proxy.Protocol,
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &ProxyStopResponse{
|
backendResponse := <-backend.RuntimeCommands
|
||||||
Success: true,
|
|
||||||
|
switch responseMessage := backendResponse.(type) {
|
||||||
|
case error:
|
||||||
|
log.Warnf("Failed to get response for backend #%d: %s", proxy.BackendID, responseMessage.Error())
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "failed to get response from backend",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
case *commonbackend.ProxyStatusResponse:
|
||||||
|
if responseMessage.IsActive {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "failed to stop proxy",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Errorf("Got illegal response type for backend #%d: %T", proxy.BackendID, responseMessage)
|
||||||
|
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": "Got invalid response from backend. Proxy was still successfully deleted",
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
|
|
||||||
"git.terah.dev/imterah/hermes/api/backendruntime"
|
"git.terah.dev/imterah/hermes/api/backendruntime"
|
||||||
"git.terah.dev/imterah/hermes/api/controllers/v1/backends"
|
"git.terah.dev/imterah/hermes/api/controllers/v1/backends"
|
||||||
"git.terah.dev/imterah/hermes/api/controllers/v1/forward"
|
|
||||||
"git.terah.dev/imterah/hermes/api/controllers/v1/proxies"
|
"git.terah.dev/imterah/hermes/api/controllers/v1/proxies"
|
||||||
"git.terah.dev/imterah/hermes/api/controllers/v1/users"
|
"git.terah.dev/imterah/hermes/api/controllers/v1/users"
|
||||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||||
|
@ -202,7 +201,7 @@ func entrypoint(cCtx *cli.Context) error {
|
||||||
engine.POST("/api/v1/forward/remove", proxies.RemoveProxy)
|
engine.POST("/api/v1/forward/remove", proxies.RemoveProxy)
|
||||||
engine.POST("/api/v1/forward/start", proxies.StartProxy)
|
engine.POST("/api/v1/forward/start", proxies.StartProxy)
|
||||||
engine.POST("/api/v1/forward/stop", proxies.StopProxy)
|
engine.POST("/api/v1/forward/stop", proxies.StopProxy)
|
||||||
engine.POST("/api/v1/forward/connections", forward.GetConnections)
|
engine.POST("/api/v1/forward/connections", proxies.GetConnections)
|
||||||
|
|
||||||
log.Infof("Listening on '%s'", listeningAddress)
|
log.Infof("Listening on '%s'", listeningAddress)
|
||||||
err = engine.Run(listeningAddress)
|
err = engine.Run(listeningAddress)
|
||||||
|
|
|
@ -38,7 +38,6 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
|
|
||||||
switch commandType {
|
switch commandType {
|
||||||
case "start":
|
case "start":
|
||||||
// TODO: implement response logic
|
|
||||||
command, ok := commandRaw.(*commonbackend.Start)
|
command, ok := commandRaw.(*commonbackend.Start)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -75,7 +74,6 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
|
|
||||||
helper.socket.Write(responseMarshalled)
|
helper.socket.Write(responseMarshalled)
|
||||||
case "stop":
|
case "stop":
|
||||||
// TODO: implement response logic
|
|
||||||
_, ok := commandRaw.(*commonbackend.Stop)
|
_, ok := commandRaw.(*commonbackend.Stop)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -112,7 +110,6 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
|
|
||||||
helper.socket.Write(responseMarshalled)
|
helper.socket.Write(responseMarshalled)
|
||||||
case "addProxy":
|
case "addProxy":
|
||||||
// TODO: implement response logic
|
|
||||||
command, ok := commandRaw.(*commonbackend.AddProxy)
|
command, ok := commandRaw.(*commonbackend.AddProxy)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -148,14 +145,40 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
|
|
||||||
helper.socket.Write(responseMarshalled)
|
helper.socket.Write(responseMarshalled)
|
||||||
case "removeProxy":
|
case "removeProxy":
|
||||||
// TODO: implement response logic
|
|
||||||
command, ok := commandRaw.(*commonbackend.RemoveProxy)
|
command, ok := commandRaw.(*commonbackend.RemoveProxy)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("failed to typecast")
|
return fmt.Errorf("failed to typecast")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = helper.Backend.StopProxy(command)
|
ok, err = helper.Backend.StopProxy(command)
|
||||||
|
var hasAnyFailed bool
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Warnf("failed to remove proxy (%s:%d -> remote:%d): RemoveProxy returned into failure state", command.SourceIP, command.SourcePort, command.DestPort)
|
||||||
|
hasAnyFailed = true
|
||||||
|
} else if err != nil {
|
||||||
|
log.Warnf("failed to remove proxy (%s:%d -> remote:%d): %s", command.SourceIP, command.SourcePort, command.DestPort, err.Error())
|
||||||
|
hasAnyFailed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &commonbackend.ProxyStatusResponse{
|
||||||
|
Type: "proxyStatusResponse",
|
||||||
|
SourceIP: command.SourceIP,
|
||||||
|
SourcePort: command.SourcePort,
|
||||||
|
DestPort: command.DestPort,
|
||||||
|
Protocol: command.Protocol,
|
||||||
|
IsActive: hasAnyFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
responseMarshalled, err := commonbackend.Marshal(response.Type, response)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to marshal response: %s", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.socket.Write(responseMarshalled)
|
||||||
case "proxyConnectionsRequest":
|
case "proxyConnectionsRequest":
|
||||||
_, ok := commandRaw.(*commonbackend.ProxyConnectionsRequest)
|
_, ok := commandRaw.(*commonbackend.ProxyConnectionsRequest)
|
||||||
|
|
||||||
|
@ -180,7 +203,6 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "checkClientParameters":
|
case "checkClientParameters":
|
||||||
// TODO: implement response logic
|
|
||||||
command, ok := commandRaw.(*commonbackend.CheckClientParameters)
|
command, ok := commandRaw.(*commonbackend.CheckClientParameters)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -201,7 +223,6 @@ func (helper *BackendApplicationHelper) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "checkServerParameters":
|
case "checkServerParameters":
|
||||||
// TODO: implement response logic
|
|
||||||
command, ok := commandRaw.(*commonbackend.CheckServerParameters)
|
command, ok := commandRaw.(*commonbackend.CheckServerParameters)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -5,24 +5,24 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/create
|
url: http://127.0.0.1:8000/api/v1/forward/create
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "914abf2223f84375eed884671bfaefd7755d378af496b345f322214e75b51ed4465f11e26c944914c9b4fcc35c53250325fbc6530853ddfed8f72976d6fc5",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"name": "Test Route",
|
"name": "Test Route",
|
||||||
"description": "This is a test route for SSH",
|
"description": "This is a test route for SSH",
|
||||||
|
|
||||||
"protocol": "tcp",
|
"protocol": "tcp",
|
||||||
|
|
||||||
"sourceIP": "127.0.0.1",
|
"sourceIP": "127.0.0.1",
|
||||||
"sourcePort": "8000",
|
"sourcePort": 8000,
|
||||||
|
|
||||||
"destinationPort": "9000",
|
"destinationPort": 9000,
|
||||||
|
|
||||||
"providerID": "1"
|
"providerID": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/connections
|
url: http://127.0.0.1:8000/api/v1/forward/connections
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "914abf2223f84375eed884671bfaefd7755d378af496b345f322214e75b51ed4465f11e26c944914c9b4fcc35c53250325fbc6530853ddfed8f72976d6fc5",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"id": "1"
|
"id": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/lookup
|
url: http://127.0.0.1:8000/api/v1/forward/lookup
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "535c80825631c04b9add7a8682e06799d62ba57b5089b557f5bab2183fc9926b187b3b8d96da8ef16c67ec80f2917cf81bc21337f47728534f58ac9c4ed5f3fe",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"protocol": "tcp"
|
"protocol": "tcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,14 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/remove
|
url: http://127.0.0.1:8000/api/v1/forward/remove
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "f1b89cc337073476289ade17ffbe7a6419b4bd52aa7ede26114bffd76fa263b5cb1bcaf389462e1d9e7acb7f4b6a7c28152a9cc9af83e3ec862f1892b1",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"name": "Test Route",
|
"id": 1
|
||||||
"description": "This is a test route for portcopier.",
|
|
||||||
|
|
||||||
"sourceIP": "127.0.0.1",
|
|
||||||
"sourcePort": "8000",
|
|
||||||
|
|
||||||
"destinationPort": "9000",
|
|
||||||
|
|
||||||
"providerID": "1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/start
|
url: http://127.0.0.1:8000/api/v1/forward/start
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "914abf2223f84375eed884671bfaefd7755d378af496b345f322214e75b51ed4465f11e26c944914c9b4fcc35c53250325fbc6530853ddfed8f72976d6fc5",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"id": "1"
|
"id": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
url: http://127.0.0.1:3000/api/v1/forward/stop
|
url: http://127.0.0.1:8000/api/v1/forward/stop
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"token": "914abf2223f84375eed884671bfaefd7755d378af496b345f322214e75b51ed4465f11e26c944914c9b4fcc35c53250325fbc6530853ddfed8f72976d6fc5",
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiMSJdLCJleHAiOjE3MzUwNzY0MTEsIm5iZiI6MTczNDk5MDAxMSwiaWF0IjoxNzM0OTkwMDExfQ.N9TLraX4peHt7FKv8tPcHuEzL0K7T2IBEw3piQS_4OY",
|
||||||
"id": "1"
|
"id": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue