diff --git a/logic/hosts.go b/logic/hosts.go index 2ea04349..b655198f 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -1,11 +1,15 @@ package logic import ( + "crypto/md5" "encoding/json" "errors" "fmt" "log" + "net/http" + "strconv" + "github.com/devilcove/httpclient" "github.com/google/uuid" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" @@ -201,11 +205,13 @@ func RemoveHost(h *models.Host) error { if len(h.Nodes) > 0 { return fmt.Errorf("host still has associated nodes") } + DeRegisterHostWithTurn(h.ID.String()) return database.DeleteRecord(database.HOSTS_TABLE_NAME, h.ID.String()) } // RemoveHostByID - removes a given host by id from server func RemoveHostByID(hostID string) error { + DeRegisterHostWithTurn(hostID) return database.DeleteRecord(database.HOSTS_TABLE_NAME, hostID) } @@ -428,3 +434,53 @@ func GetHostByNodeID(id string) *models.Host { } return nil } + +// ConvHostPassToHash - converts password to md5 hash +func ConvHostPassToHash(hostPass string) string { + return fmt.Sprintf("%x", md5.Sum([]byte(hostPass))) +} + +// RegisterHostWithTurn - registers the host with the given turn server +func RegisterHostWithTurn(hostID, hostPass string) error { + + api := httpclient.JSONEndpoint[models.SuccessResponse, models.ErrorResponse]{ + URL: servercfg.GetTurnApiHost(), + Route: "/api/v1/host/register", + Method: http.MethodPost, + //Authorization: fmt.Sprintf("Bearer %s", op.AuthToken), + Data: models.HostTurnRegister{ + HostID: hostID, + HostPassHash: ConvHostPassToHash(hostPass), + }, + Response: models.SuccessResponse{}, + ErrorResponse: models.ErrorResponse{}, + } + _, errData, err := api.GetJSON(models.SuccessResponse{}, models.ErrorResponse{}) + if err != nil { + if errors.Is(err, httpclient.ErrStatus) { + logger.Log(1, "error server status", strconv.Itoa(errData.Code), errData.Message) + } + return err + } + return nil +} + +// DeRegisterHostWithTurn - to be called when host need to be deregistered from a turn server +func DeRegisterHostWithTurn(hostID string) error { + + api := httpclient.JSONEndpoint[models.SuccessResponse, models.ErrorResponse]{ + URL: servercfg.GetTurnApiHost(), + Route: fmt.Sprintf("/api/v1/host/deregister?host_id=%s", hostID), + Method: http.MethodPost, + Response: models.SuccessResponse{}, + ErrorResponse: models.ErrorResponse{}, + } + _, errData, err := api.GetJSON(models.SuccessResponse{}, models.ErrorResponse{}) + if err != nil { + if errors.Is(err, httpclient.ErrStatus) { + logger.Log(1, "error server status", strconv.Itoa(errData.Code), errData.Message) + } + return err + } + return nil +} diff --git a/models/host.go b/models/host.go index 0c5f7a6c..f1fe7bf8 100644 --- a/models/host.go +++ b/models/host.go @@ -116,6 +116,8 @@ const ( RequestAck = "REQ_ACK" // CheckIn - update last check in times and public address and interfaces CheckIn = "CHECK_IN" + // REGISTER_WITH_TURN - registers host with turn server if configured + RegisterWithTurn = "REGISTER_WITH_TURN" ) // HostUpdate - struct for host update diff --git a/mq/handlers.go b/mq/handlers.go index 22c5e62a..6394fd51 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -140,6 +140,8 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) { return } sendPeerUpdate = true + case models.RegisterWithTurn: + logic.RegisterHostWithTurn(hostUpdate.Host.ID.String(), hostUpdate.Host.HostPass) } if sendPeerUpdate { diff --git a/turnserver/config/config.go b/turnserver/config/config.go index 6db005c2..cb6648d6 100644 --- a/turnserver/config/config.go +++ b/turnserver/config/config.go @@ -87,3 +87,13 @@ func GetAPIPort() int { } return apiport } + +// GetUserName - gets the username for the apis +func GetUserName() string { + return os.Getenv("USERNAME") +} + +// GetPassword - gets the password for the server apis +func GetPassword() string { + return os.Getenv("PASSWORD") +} diff --git a/turnserver/internal/host/host.go b/turnserver/internal/host/host.go index 7a92ebc7..dcedc9a5 100644 --- a/turnserver/internal/host/host.go +++ b/turnserver/internal/host/host.go @@ -35,5 +35,5 @@ func Remove(c *gin.Context) { return } utils.ReturnSuccessResponse(c, - fmt.Sprintf("unregistred host (%s) successfully", hostID), nil) + fmt.Sprintf("unregistered host (%s) successfully", hostID), nil) } diff --git a/turnserver/main.go b/turnserver/main.go index 47bbe844..1945e047 100644 --- a/turnserver/main.go +++ b/turnserver/main.go @@ -15,16 +15,14 @@ import ( func main() { ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} - // Wait for interrupt signal to gracefully shutdown the server with - // a timeout of 5 seconds. quit := make(chan os.Signal, 2) - // kill (no param) default send syscanll.SIGTERM - // kill -2 is syscall.SIGINT - // kill -9 is syscall. SIGKILL but cant be caught, so don't need add it wg.Add(1) go controller.HandleRESTRequests(ctx, wg) wg.Add(1) go turn.Start(ctx, wg) + // kill (no param) default send syscanll.SIGTERM + // kill -2 is syscall.SIGINT + // kill -9 is syscall. SIGKILL but cant be caught, so don't need add it signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit logger.Log(0, "Recieved Shutdown Signal...") diff --git a/turnserver/src/routes/routes.go b/turnserver/src/routes/routes.go index 5559da0c..72b2b5ba 100644 --- a/turnserver/src/routes/routes.go +++ b/turnserver/src/routes/routes.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/gravitl/netmaker/turnserver/config" "github.com/gravitl/netmaker/turnserver/internal/host" ) @@ -15,9 +16,15 @@ func Init(r *gin.Engine) *gin.Engine { } func registerRoutes(r *gin.RouterGroup) { - r.POST("/host/register", host.Register) - r.DELETE("/host/deregister", host.Remove) - r.GET("/status", status) + r.POST("/host/register", gin.BasicAuth(gin.Accounts{ + config.GetUserName(): config.GetPassword(), + }), host.Register) + r.DELETE("/host/deregister", gin.BasicAuth(gin.Accounts{ + config.GetUserName(): config.GetPassword(), + }), host.Remove) + r.GET("/status", gin.BasicAuth(gin.Accounts{ + config.GetUserName(): config.GetPassword(), + }), status) } func status(c *gin.Context) {