enrollmentkeys.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package controller
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "time"
  7. "github.com/gorilla/mux"
  8. "github.com/gravitl/netmaker/logger"
  9. "github.com/gravitl/netmaker/logic"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/mq"
  12. "github.com/gravitl/netmaker/servercfg"
  13. )
  14. func enrollmentKeyHandlers(r *mux.Router) {
  15. r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(createEnrollmentKey))).Methods(http.MethodPost)
  16. r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(getEnrollmentKeys))).Methods(http.MethodGet)
  17. r.HandleFunc("/api/v1/enrollment-keys/{keyID}", logic.SecurityCheck(true, http.HandlerFunc(deleteEnrollmentKey))).Methods(http.MethodDelete)
  18. r.HandleFunc("/api/v1/host/register/{token}", http.HandlerFunc(handleHostRegister)).Methods(http.MethodPost)
  19. }
  20. // swagger:route GET /api/v1/enrollment-keys enrollmentKeys getEnrollmentKeys
  21. //
  22. // Lists all hosts.
  23. //
  24. // Schemes: https
  25. //
  26. // Security:
  27. // oauth
  28. //
  29. // Responses:
  30. // 200: getEnrollmentKeysSlice
  31. func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
  32. currentKeys, err := logic.GetAllEnrollmentKeys()
  33. if err != nil {
  34. logger.Log(0, r.Header.Get("user"), "failed to fetch enrollment keys: ", err.Error())
  35. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  36. return
  37. }
  38. for i := range currentKeys {
  39. currentKey := currentKeys[i]
  40. if err = logic.Tokenize(currentKey, servercfg.GetAPIHost()); err != nil {
  41. logger.Log(0, r.Header.Get("user"), "failed to get token values for keys:", err.Error())
  42. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  43. return
  44. }
  45. }
  46. // return JSON/API formatted keys
  47. logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
  48. w.WriteHeader(http.StatusOK)
  49. json.NewEncoder(w).Encode(currentKeys)
  50. }
  51. // swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey
  52. //
  53. // Deletes a Netclient host from Netmaker server.
  54. //
  55. // Schemes: https
  56. //
  57. // Security:
  58. // oauth
  59. //
  60. // Responses:
  61. // 200: deleteEnrollmentKeyResponse
  62. func deleteEnrollmentKey(w http.ResponseWriter, r *http.Request) {
  63. var params = mux.Vars(r)
  64. keyID := params["keyID"]
  65. err := logic.DeleteEnrollmentKey(keyID)
  66. if err != nil {
  67. logger.Log(0, r.Header.Get("user"), "failed to remove enrollment key: ", err.Error())
  68. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  69. return
  70. }
  71. logger.Log(2, r.Header.Get("user"), "deleted enrollment key", keyID)
  72. w.WriteHeader(http.StatusOK)
  73. }
  74. // swagger:route POST /api/v1/enrollment-keys enrollmentKeys createEnrollmentKey
  75. //
  76. // Creates an EnrollmentKey for hosts to use on Netmaker server.
  77. //
  78. // Schemes: https
  79. //
  80. // Security:
  81. // oauth
  82. //
  83. // Responses:
  84. // 200: createEnrollmentKeyResponse
  85. func createEnrollmentKey(w http.ResponseWriter, r *http.Request) {
  86. var enrollmentKeyBody models.APIEnrollmentKey
  87. err := json.NewDecoder(r.Body).Decode(&enrollmentKeyBody)
  88. if err != nil {
  89. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  90. err.Error())
  91. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  92. return
  93. }
  94. var newTime time.Time
  95. if enrollmentKeyBody.Expiration > 0 {
  96. newTime = time.Unix(enrollmentKeyBody.Expiration, 0)
  97. }
  98. newEnrollmentKey, err := logic.CreateEnrollmentKey(enrollmentKeyBody.UsesRemaining, newTime, enrollmentKeyBody.Networks, enrollmentKeyBody.Tags, enrollmentKeyBody.Unlimited)
  99. if err != nil {
  100. logger.Log(0, r.Header.Get("user"), "failed to create enrollment key:", err.Error())
  101. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  102. return
  103. }
  104. if err = logic.Tokenize(newEnrollmentKey, servercfg.GetAPIHost()); err != nil {
  105. logger.Log(0, r.Header.Get("user"), "failed to create enrollment key:", err.Error())
  106. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  107. return
  108. }
  109. logger.Log(2, r.Header.Get("user"), "created enrollment key")
  110. w.WriteHeader(http.StatusOK)
  111. json.NewEncoder(w).Encode(newEnrollmentKey)
  112. }
  113. // swagger:route POST /api/v1/enrollment-keys/{token} enrollmentKeys deleteEnrollmentKey
  114. //
  115. // Deletes a Netclient host from Netmaker server.
  116. //
  117. // Schemes: https
  118. //
  119. // Security:
  120. // oauth
  121. //
  122. // Responses:
  123. // 200: hostRegisterResponse
  124. func handleHostRegister(w http.ResponseWriter, r *http.Request) {
  125. var params = mux.Vars(r)
  126. token := params["token"]
  127. logger.Log(0, "received registration attempt with token", token)
  128. // check if token exists
  129. enrollmentKey, err := logic.DeTokenize(token)
  130. if err != nil {
  131. logger.Log(0, "invalid enrollment key used", token, err.Error())
  132. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  133. return
  134. }
  135. // get the host
  136. var newHost models.Host
  137. if err = json.NewDecoder(r.Body).Decode(&newHost); err != nil {
  138. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  139. err.Error())
  140. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  141. return
  142. }
  143. // check if host already exists
  144. if ok := logic.HostExists(&newHost); ok {
  145. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "attempted to re-register")
  146. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("host already exists"), "badrequest"))
  147. return
  148. }
  149. // version check
  150. if !logic.IsVersionComptatible(newHost.Version) || newHost.TrafficKeyPublic == nil {
  151. err := fmt.Errorf("incompatible netclient")
  152. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  153. return
  154. }
  155. key, keyErr := logic.RetrievePublicTrafficKey()
  156. if keyErr != nil {
  157. logger.Log(0, "error retrieving key:", keyErr.Error())
  158. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  159. return
  160. }
  161. // use the token
  162. if ok := logic.TryToUseEnrollmentKey(enrollmentKey); !ok {
  163. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration")
  164. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("invalid enrollment key"), "badrequest"))
  165. return
  166. }
  167. // register host
  168. logic.CheckHostPorts(&newHost)
  169. if err = logic.CreateHost(&newHost); err != nil {
  170. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration -", err.Error())
  171. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  172. return
  173. }
  174. // ready the response
  175. server := servercfg.GetServerInfo()
  176. server.TrafficKey = key
  177. logger.Log(0, newHost.Name, newHost.ID.String(), "registered with Netmaker")
  178. w.WriteHeader(http.StatusOK)
  179. json.NewEncoder(w).Encode(&server)
  180. // notify host of changes, peer and node updates
  181. go checkNetRegAndHostUpdate(enrollmentKey.Networks, &newHost)
  182. }
  183. // run through networks and send a host update
  184. func checkNetRegAndHostUpdate(networks []string, h *models.Host) {
  185. // publish host update through MQ
  186. if servercfg.IsMessageQueueBackend() {
  187. if err := mq.HostUpdate(&models.HostUpdate{
  188. Action: models.UpdateHost,
  189. Host: *h,
  190. }); err != nil {
  191. logger.Log(0, "failed to send host update after registration:", h.ID.String(), err.Error())
  192. }
  193. }
  194. for i := range networks {
  195. if ok, _ := logic.NetworkExists(networks[i]); ok {
  196. newNode, err := logic.UpdateHostNetwork(h, networks[i], true)
  197. if err != nil {
  198. logger.Log(0, "failed to add host to network:", h.ID.String(), h.Name, networks[i], err.Error())
  199. continue
  200. }
  201. logger.Log(1, "added new node", newNode.ID.String(), "to host", h.Name)
  202. if servercfg.IsMessageQueueBackend() {
  203. if err = mq.HostUpdate(&models.HostUpdate{
  204. Action: models.JoinHostToNetwork,
  205. Host: *h,
  206. Node: *newNode,
  207. }); err != nil {
  208. logger.Log(0, "failed to send host update to", h.ID.String(), networks[i], err.Error())
  209. }
  210. }
  211. }
  212. }
  213. if servercfg.IsMessageQueueBackend() {
  214. if err := mq.PublishPeerUpdate(); err != nil {
  215. logger.Log(0, "failed to publish peer update after host registration -", err.Error())
  216. }
  217. }
  218. }