serverClient.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package controller
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. // "fmt"
  7. "net/http"
  8. "time"
  9. "strconv"
  10. "github.com/gorilla/mux"
  11. "github.com/gravitl/netmaker/functions"
  12. "github.com/gravitl/netmaker/serverctl"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "github.com/gravitl/netmaker/models"
  15. "github.com/gravitl/netmaker/mongoconn"
  16. "go.mongodb.org/mongo-driver/bson"
  17. "go.mongodb.org/mongo-driver/mongo/options"
  18. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  19. "github.com/skip2/go-qrcode"
  20. )
  21. func serverClientHandlers(r *mux.Router) {
  22. r.HandleFunc("/api/wgconf/{macaddress}", securityCheck(http.HandlerFunc(getWGClientConf))).Methods("GET")
  23. r.HandleFunc("/api/register", securityCheck(http.HandlerFunc(registerClient))).Methods("POST")
  24. }
  25. //Get an individual extclient. Nothin fancy here folks.
  26. func getWGClientConf(w http.ResponseWriter, r *http.Request) {
  27. // set header.
  28. w.Header().Set("Content-Type", "application/json")
  29. var params = mux.Vars(r)
  30. var extclient models.ExtClient
  31. collection := mongoconn.Client.Database("netmaker").Collection("extclients")
  32. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  33. filter := bson.M{"network": "grpc", "clientid": params["clientid"]}
  34. err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&extclient)
  35. if err != nil {
  36. returnErrorResponse(w, r, formatError(err, "internal"))
  37. return
  38. }
  39. gwnode, err := functions.GetNodeByMacAddress(extclient.Network, extclient.IngressGatewayID)
  40. if err != nil {
  41. fmt.Println("Could not retrieve Ingress Gateway Node " + extclient.IngressGatewayID)
  42. returnErrorResponse(w, r, formatError(err, "internal"))
  43. return
  44. }
  45. network, err := functions.GetParentNetwork(extclient.Network)
  46. if err != nil {
  47. fmt.Println("Could not retrieve Ingress Gateway Network " + extclient.Network)
  48. returnErrorResponse(w, r, formatError(err, "internal"))
  49. return
  50. }
  51. keepalive := ""
  52. if network.DefaultKeepalive != 0 {
  53. keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive))
  54. }
  55. gwendpoint := gwnode.Endpoint + ":" + strconv.Itoa(int(gwnode.ListenPort))
  56. config := fmt.Sprintf(`[Interface]
  57. Address = %s
  58. PrivateKey = %s
  59. [Peer]
  60. PublicKey = %s
  61. AllowedIPs = %s
  62. Endpoint = %s
  63. %s
  64. `, extclient.Address + "/32",
  65. extclient.PrivateKey,
  66. gwnode.PublicKey,
  67. network.AddressRange,
  68. gwendpoint,
  69. keepalive)
  70. if params["type"] == "qr" {
  71. bytes, err := qrcode.Encode(config, qrcode.Medium, 220)
  72. if err != nil {
  73. returnErrorResponse(w, r, formatError(err, "internal"))
  74. return
  75. }
  76. w.Header().Set("Content-Type", "image/png")
  77. w.WriteHeader(http.StatusOK)
  78. _, err = w.Write(bytes)
  79. if err != nil {
  80. returnErrorResponse(w, r, formatError(err, "internal"))
  81. return
  82. }
  83. return
  84. }
  85. if params["type"] == "file" {
  86. name := extclient.ClientID + ".conf"
  87. w.Header().Set("Content-Type", "application/config")
  88. w.Header().Set("Content-Disposition", "attachment; filename=\"" + name + "\"")
  89. w.WriteHeader(http.StatusOK)
  90. _, err := fmt.Fprint(w, config)
  91. if err != nil {
  92. returnErrorResponse(w, r, formatError(err, "internal"))
  93. }
  94. return
  95. }
  96. defer cancel()
  97. w.WriteHeader(http.StatusOK)
  98. json.NewEncoder(w).Encode(extclient)
  99. }
  100. func RegisterClient(client models.ServerClient) (models.ServerClient, error) {
  101. if client.PrivateKey == "" {
  102. privateKey, err := wgtypes.GeneratePrivateKey()
  103. if err != nil {
  104. return client, err
  105. }
  106. client.PrivateKey = privateKey.String()
  107. client.PublicKey = privateKey.PublicKey().String()
  108. }
  109. if client.Address == "" {
  110. newAddress, err := functions.UniqueAddress6(client.Network)
  111. if err != nil {
  112. return client, err
  113. }
  114. client.Address6 = newAddress
  115. }
  116. if client.Network == "" { client.Network = "comms" }
  117. server, err := serverctl.GetServerWGConf()
  118. if err != nil {
  119. return client, err
  120. }
  121. client.ServerEndpoint = server.ServerEndpoint
  122. client.ServerPort = server.ServerPort
  123. client.ServerKey = server.ServerKey
  124. collection := mongoconn.Client.Database("netmaker").Collection("serverclients")
  125. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  126. // insert our network into the network table
  127. _, err = collection.InsertOne(ctx, client)
  128. defer cancel()
  129. if err != nil {
  130. return client, err
  131. }
  132. err = serverctl.ReconfigureServerWireGuard()
  133. return client, err
  134. }
  135. func registerClient(w http.ResponseWriter, r *http.Request) {
  136. w.Header().Set("Content-Type", "application/json")
  137. var errorResponse = models.ErrorResponse{
  138. Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
  139. }
  140. var clientreq models.ServerClient
  141. //get node from body of request
  142. err := json.NewDecoder(r.Body).Decode(&clientreq)
  143. if err != nil {
  144. returnErrorResponse(w, r, formatError(err, "internal"))
  145. return
  146. }
  147. if servercfg.IsRegisterKeyRequired() {
  148. validKey := functions.IsKeyValidGlobal(clientreq.AccessKey)
  149. if !validKey {
  150. errorResponse = models.ErrorResponse{
  151. Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.",
  152. }
  153. returnErrorResponse(w, r, errorResponse)
  154. return
  155. }
  156. }
  157. client, err := RegisterClient(clientreq)
  158. if err != nil {
  159. returnErrorResponse(w, r, formatError(err, "internal"))
  160. return
  161. }
  162. w.WriteHeader(http.StatusOK)
  163. json.NewEncoder(w).Encode(client)
  164. }