123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- package controller
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "github.com/google/uuid"
- "github.com/gorilla/mux"
- "github.com/gravitl/netmaker/logger"
- "github.com/gravitl/netmaker/logic"
- "github.com/gravitl/netmaker/models"
- "github.com/gravitl/netmaker/mq"
- "github.com/gravitl/netmaker/servercfg"
- "golang.org/x/exp/slog"
- )
- func gwHandlers(r *mux.Router) {
- r.HandleFunc("/api/nodes/{network}/{nodeid}/gateway", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceIngress, http.HandlerFunc(createGateway)))).Methods(http.MethodPost)
- r.HandleFunc("/api/nodes/{network}/{nodeid}/gateway", logic.SecurityCheck(true, http.HandlerFunc(deleteGateway))).Methods(http.MethodDelete)
- // old relay handlers
- r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", logic.SecurityCheck(true, http.HandlerFunc(createGateway))).Methods(http.MethodPost)
- r.HandleFunc("/api/nodes/{network}/{nodeid}/deleterelay", logic.SecurityCheck(true, http.HandlerFunc(deleteGateway))).Methods(http.MethodDelete)
- }
- // @Summary Create a gateway
- // @Router /api/nodes/{network}/{nodeid}/gateway [post]
- // @Tags Nodes
- // @Security oauth2
- // @Success 200 {object} models.ApiNode
- // @Failure 500 {object} models.ErrorResponse
- func createGateway(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- nodeid := params["nodeid"]
- netid := params["network"]
- node, err := logic.ValidateParams(nodeid, netid)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- host, err := logic.GetHost(node.HostID.String())
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- var req models.CreateGwReq
- err = json.NewDecoder(r.Body).Decode(&req)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- if req.IsInternetGateway && len(req.InetNodeClientIDs) > 0 {
- err = logic.ValidateInetGwReq(node, req.InetNodeReq, false)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- }
- node, err = logic.CreateIngressGateway(netid, nodeid, req.IngressRequest)
- if err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to create gateway on node [%s] on network [%s]: %v",
- nodeid, netid, err))
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- req.RelayRequest.NetID = netid
- req.RelayRequest.NodeID = nodeid
- _, relayNode, err := logic.CreateRelay(req.RelayRequest)
- if err != nil {
- logger.Log(
- 0,
- r.Header.Get("user"),
- fmt.Sprintf(
- "failed to create relay on node [%s] on network [%s]: %v",
- req.RelayRequest.NodeID,
- req.RelayRequest.NetID,
- err,
- ),
- )
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- for _, relayedNodeID := range relayNode.RelayedNodes {
- relayedNode, err := logic.GetNodeByID(relayedNodeID)
- if err == nil {
- if relayedNode.FailedOverBy != uuid.Nil {
- go logic.ResetFailedOverPeer(&relayedNode)
- }
- }
- }
- if len(req.InetNodeClientIDs) > 0 {
- logic.SetInternetGw(&node, req.InetNodeReq)
- if servercfg.IsPro {
- if _, exists := logic.FailOverExists(node.Network); exists {
- go func() {
- logic.ResetFailedOverPeer(&node)
- mq.PublishPeerUpdate(false)
- }()
- }
- }
- if node.IsGw && node.IngressDNS == "" {
- node.IngressDNS = "1.1.1.1"
- }
- logic.UpsertNode(&node)
- }
- logger.Log(
- 1,
- r.Header.Get("user"),
- "created gw node",
- req.RelayRequest.NodeID,
- "on network",
- req.RelayRequest.NetID,
- )
- logic.GetNodeStatus(&relayNode, false)
- apiNode := relayNode.ConvertToAPINode()
- logic.LogEvent(&models.Event{
- Action: models.Create,
- Source: models.Subject{
- ID: r.Header.Get("user"),
- Name: r.Header.Get("user"),
- Type: models.UserSub,
- },
- TriggeredBy: r.Header.Get("user"),
- Target: models.Subject{
- ID: node.ID.String(),
- Name: host.Name,
- Type: models.GatewaySub,
- },
- Origin: models.Dashboard,
- })
- host.IsStaticPort = true
- logic.UpsertHost(host)
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(apiNode)
- go func() {
- if err := mq.NodeUpdate(&node); err != nil {
- slog.Error("error publishing node update to node", "node", node.ID, "error", err)
- }
- mq.PublishPeerUpdate(false)
- }()
- }
- // @Summary Delete a gateway
- // @Router /api/nodes/{network}/{nodeid}/gateway [delete]
- // @Tags Nodes
- // @Security oauth2
- // @Success 200 {object} models.ApiNode
- // @Failure 500 {object} models.ErrorResponse
- func deleteGateway(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- var params = mux.Vars(r)
- nodeid := params["nodeid"]
- netid := params["network"]
- node, err := logic.ValidateParams(nodeid, netid)
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- node, removedClients, err := logic.DeleteIngressGateway(nodeid)
- if err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to delete ingress gateway on node [%s] on network [%s]: %v",
- nodeid, netid, err))
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- updateNodes, node, err := logic.DeleteRelay(netid, nodeid)
- if err != nil {
- logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- node, err = logic.GetNodeByID(node.ID.String())
- if err != nil {
- logger.Log(0, r.Header.Get("user"), "failed to get node", err.Error())
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- host, err := logic.GetHost(node.HostID.String())
- if err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- logic.UnsetInternetGw(&node)
- node.IsGw = false
- logic.UpsertNode(&node)
- logger.Log(1, r.Header.Get("user"), "deleted gw", nodeid, "on network", netid)
- go func() {
- host, err := logic.GetHost(node.HostID.String())
- if err == nil {
- allNodes, err := logic.GetAllNodes()
- if err != nil {
- return
- }
- for _, relayedNode := range updateNodes {
- err = mq.NodeUpdate(&relayedNode)
- if err != nil {
- logger.Log(
- 1,
- "relayed node update ",
- relayedNode.ID.String(),
- "on network",
- relayedNode.Network,
- ": ",
- err.Error(),
- )
- }
- h, err := logic.GetHost(relayedNode.HostID.String())
- if err == nil {
- if h.OS == models.OS_Types.IoT {
- nodes, err := logic.GetAllNodes()
- if err != nil {
- return
- }
- node.IsRelay = true // for iot update to recognise that it has to delete relay peer
- if err = mq.PublishSingleHostPeerUpdate(h, nodes, &node, nil, false, nil); err != nil {
- logger.Log(1, "failed to publish peer update to host", h.ID.String(), ": ", err.Error())
- }
- }
- }
- }
- if len(removedClients) > 0 {
- if err := mq.PublishSingleHostPeerUpdate(host, allNodes, nil, removedClients[:], false, nil); err != nil {
- slog.Error("publishSingleHostUpdate", "host", host.Name, "error", err)
- }
- }
- mq.PublishPeerUpdate(false)
- if err := mq.NodeUpdate(&node); err != nil {
- slog.Error(
- "error publishing node update to node",
- "node",
- node.ID,
- "error",
- err,
- )
- }
- if servercfg.IsDNSMode() {
- logic.SetDNS()
- }
- }
- }()
- logic.LogEvent(&models.Event{
- Action: models.Delete,
- Source: models.Subject{
- ID: r.Header.Get("user"),
- Name: r.Header.Get("user"),
- Type: models.UserSub,
- },
- TriggeredBy: r.Header.Get("user"),
- Target: models.Subject{
- ID: node.ID.String(),
- Name: host.Name,
- Type: models.GatewaySub,
- },
- Origin: models.Dashboard,
- })
- logic.GetNodeStatus(&node, false)
- apiNode := node.ConvertToAPINode()
- logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeid)
- w.WriteHeader(http.StatusOK)
- json.NewEncoder(w).Encode(apiNode)
- }
|