enrollmentkeys.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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}", logic.SecurityCheck(true, 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.GetServer()); 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.GetServer()); 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. // check if token exists
  128. enrollmentKey, err := logic.DeTokenize(token)
  129. if err != nil {
  130. logger.Log(0, "invalid enrollment key used", token, err.Error())
  131. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  132. return
  133. }
  134. // get the host
  135. var newHost models.Host
  136. if err = json.NewDecoder(r.Body).Decode(&newHost); err != nil {
  137. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  138. err.Error())
  139. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  140. return
  141. }
  142. // check if host already exists
  143. if ok := logic.HostExists(&newHost); ok {
  144. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "attempted to re-register")
  145. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("host already exists"), "badrequest"))
  146. return
  147. }
  148. // version check
  149. if !logic.IsVersionComptatible(newHost.Version) || newHost.TrafficKeyPublic == nil {
  150. err := fmt.Errorf("incompatible netclient")
  151. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  152. return
  153. }
  154. key, keyErr := logic.RetrievePublicTrafficKey()
  155. if keyErr != nil {
  156. logger.Log(0, "error retrieving key:", keyErr.Error())
  157. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  158. return
  159. }
  160. // use the token
  161. if ok := logic.TryToUseEnrollmentKey(enrollmentKey); !ok {
  162. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration")
  163. logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("invalid enrollment key"), "badrequest"))
  164. return
  165. }
  166. // register host
  167. logic.CheckHostPorts(&newHost)
  168. if err = logic.CreateHost(&newHost); err != nil {
  169. logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration -", err.Error())
  170. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  171. return
  172. }
  173. // ready the response
  174. server := servercfg.GetServerInfo()
  175. server.TrafficKey = key
  176. logger.Log(2, r.Header.Get("user"), "deleted enrollment key", token)
  177. w.WriteHeader(http.StatusOK)
  178. json.NewEncoder(w).Encode(&server)
  179. // notify host of changes, peer and node updates
  180. go checkNetRegAndHostUpdate(enrollmentKey.Networks, &newHost)
  181. }
  182. // run through networks and send a host update
  183. func checkNetRegAndHostUpdate(networks []string, h *models.Host) {
  184. // publish host update through MQ
  185. if servercfg.IsMessageQueueBackend() {
  186. if err := mq.HostUpdate(&models.HostUpdate{
  187. Action: models.UpdateHost,
  188. Host: *h,
  189. }); err != nil {
  190. logger.Log(0, "failed to send host update after registration:", h.ID.String(), err.Error())
  191. }
  192. }
  193. for i := range networks {
  194. if ok, _ := logic.NetworkExists(networks[i]); ok {
  195. newNode, err := logic.UpdateHostNetwork(h, networks[i], true)
  196. if err != nil {
  197. logger.Log(0, "failed to add host to network:", h.ID.String(), h.Name, networks[i], err.Error())
  198. continue
  199. }
  200. logger.Log(1, "added new node", newNode.ID.String(), "to host", h.Name)
  201. if servercfg.IsMessageQueueBackend() {
  202. if err = mq.HostUpdate(&models.HostUpdate{
  203. Action: models.JoinHostToNetwork,
  204. Host: *h,
  205. Node: *newNode,
  206. }); err != nil {
  207. logger.Log(0, "failed to send host update to", h.ID.String(), networks[i], err.Error())
  208. }
  209. }
  210. }
  211. }
  212. if servercfg.IsMessageQueueBackend() {
  213. if err := mq.PublishPeerUpdate(); err != nil {
  214. logger.Log(0, "failed to publish peer update after host registration -", err.Error())
  215. }
  216. }
  217. }