acls.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "net/http"
  6. "net/url"
  7. "time"
  8. "github.com/google/uuid"
  9. "github.com/gorilla/mux"
  10. "github.com/gravitl/netmaker/logger"
  11. "github.com/gravitl/netmaker/logic"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/mq"
  14. )
  15. func aclHandlers(r *mux.Router) {
  16. r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(getAcls))).
  17. Methods(http.MethodGet)
  18. r.HandleFunc("/api/v1/acls/policy_types", logic.SecurityCheck(true, http.HandlerFunc(aclPolicyTypes))).
  19. Methods(http.MethodGet)
  20. r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(createAcl))).
  21. Methods(http.MethodPost)
  22. r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(updateAcl))).
  23. Methods(http.MethodPut)
  24. r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(deleteAcl))).
  25. Methods(http.MethodDelete)
  26. r.HandleFunc("/api/v1/acls/debug", logic.SecurityCheck(true, http.HandlerFunc(aclDebug))).
  27. Methods(http.MethodGet)
  28. }
  29. // @Summary List Acl Policy types
  30. // @Router /api/v1/acls/policy_types [get]
  31. // @Tags ACL
  32. // @Accept json
  33. // @Success 200 {array} models.SuccessResponse
  34. // @Failure 500 {object} models.ErrorResponse
  35. func aclPolicyTypes(w http.ResponseWriter, r *http.Request) {
  36. resp := models.AclPolicyTypes{
  37. RuleTypes: []models.AclPolicyType{
  38. models.DevicePolicy,
  39. models.UserPolicy,
  40. },
  41. SrcGroupTypes: []models.AclGroupType{
  42. models.UserAclID,
  43. models.UserGroupAclID,
  44. models.DeviceAclID,
  45. },
  46. DstGroupTypes: []models.AclGroupType{
  47. models.DeviceAclID,
  48. // models.NetmakerIPAclID,
  49. // models.NetmakerSubNetRangeAClID,
  50. },
  51. ProtocolTypes: []models.ProtocolType{
  52. {
  53. Name: models.Http,
  54. AllowedProtocols: []models.Protocol{
  55. models.TCP,
  56. },
  57. PortRange: "80",
  58. },
  59. {
  60. Name: models.Https,
  61. AllowedProtocols: []models.Protocol{
  62. models.TCP,
  63. },
  64. PortRange: "443",
  65. },
  66. // {
  67. // Name: "MySQL",
  68. // AllowedProtocols: []models.Protocol{
  69. // models.TCP,
  70. // },
  71. // PortRange: "3306",
  72. // },
  73. // {
  74. // Name: "DNS TCP",
  75. // AllowedProtocols: []models.Protocol{
  76. // models.TCP,
  77. // },
  78. // PortRange: "53",
  79. // },
  80. // {
  81. // Name: "DNS UDP",
  82. // AllowedProtocols: []models.Protocol{
  83. // models.UDP,
  84. // },
  85. // PortRange: "53",
  86. // },
  87. {
  88. Name: models.AllTCP,
  89. AllowedProtocols: []models.Protocol{
  90. models.TCP,
  91. },
  92. PortRange: "All ports",
  93. },
  94. {
  95. Name: models.AllUDP,
  96. AllowedProtocols: []models.Protocol{
  97. models.UDP,
  98. },
  99. PortRange: "All ports",
  100. },
  101. {
  102. Name: models.ICMPService,
  103. AllowedProtocols: []models.Protocol{
  104. models.ICMP,
  105. },
  106. PortRange: "",
  107. },
  108. {
  109. Name: models.Custom,
  110. AllowedProtocols: []models.Protocol{
  111. models.UDP,
  112. models.TCP,
  113. },
  114. PortRange: "All ports",
  115. AllowPortSetting: true,
  116. },
  117. },
  118. }
  119. logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched acls types")
  120. }
  121. func aclDebug(w http.ResponseWriter, r *http.Request) {
  122. nodeID, _ := url.QueryUnescape(r.URL.Query().Get("node"))
  123. peerID, _ := url.QueryUnescape(r.URL.Query().Get("peer"))
  124. node, err := logic.GetNodeByID(nodeID)
  125. if err != nil {
  126. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  127. return
  128. }
  129. peer, err := logic.GetNodeByID(peerID)
  130. if err != nil {
  131. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  132. return
  133. }
  134. allowed, _ := logic.IsNodeAllowedToCommunicate(node, peer)
  135. logic.ReturnSuccessResponseWithJson(w, r, allowed, "fetched all acls in the network ")
  136. }
  137. // @Summary List Acls in a network
  138. // @Router /api/v1/acls [get]
  139. // @Tags ACL
  140. // @Accept json
  141. // @Success 200 {array} models.SuccessResponse
  142. // @Failure 500 {object} models.ErrorResponse
  143. func getAcls(w http.ResponseWriter, r *http.Request) {
  144. netID := r.URL.Query().Get("network")
  145. if netID == "" {
  146. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("network id param is missing"), "badrequest"))
  147. return
  148. }
  149. // check if network exists
  150. _, err := logic.GetNetwork(netID)
  151. if err != nil {
  152. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  153. return
  154. }
  155. acls, err := logic.ListAcls(models.NetworkID(netID))
  156. if err != nil {
  157. logger.Log(0, r.Header.Get("user"), "failed to get all network acl entries: ", err.Error())
  158. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  159. return
  160. }
  161. logic.SortAclEntrys(acls[:])
  162. logic.ReturnSuccessResponseWithJson(w, r, acls, "fetched all acls in the network "+netID)
  163. }
  164. // @Summary Create Acl
  165. // @Router /api/v1/acls [post]
  166. // @Tags ACL
  167. // @Accept json
  168. // @Success 200 {array} models.SuccessResponse
  169. // @Failure 500 {object} models.ErrorResponse
  170. func createAcl(w http.ResponseWriter, r *http.Request) {
  171. var req models.Acl
  172. err := json.NewDecoder(r.Body).Decode(&req)
  173. if err != nil {
  174. logger.Log(0, "error decoding request body: ",
  175. err.Error())
  176. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  177. return
  178. }
  179. user, err := logic.GetUser(r.Header.Get("user"))
  180. if err != nil {
  181. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  182. return
  183. }
  184. err = logic.ValidateCreateAclReq(req)
  185. if err != nil {
  186. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  187. return
  188. }
  189. acl := req
  190. acl.ID = uuid.New().String()
  191. acl.CreatedBy = user.UserName
  192. acl.CreatedAt = time.Now().UTC()
  193. acl.Default = false
  194. // validate create acl policy
  195. if !logic.IsAclPolicyValid(acl) {
  196. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid policy"), "badrequest"))
  197. return
  198. }
  199. err = logic.InsertAcl(acl)
  200. if err != nil {
  201. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  202. return
  203. }
  204. acl, err = logic.GetAcl(acl.ID)
  205. if err != nil {
  206. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  207. return
  208. }
  209. go mq.PublishPeerUpdate(false)
  210. logic.ReturnSuccessResponseWithJson(w, r, acl, "created acl successfully")
  211. }
  212. // @Summary Update Acl
  213. // @Router /api/v1/acls [put]
  214. // @Tags ACL
  215. // @Accept json
  216. // @Success 200 {array} models.SuccessResponse
  217. // @Failure 500 {object} models.ErrorResponse
  218. func updateAcl(w http.ResponseWriter, r *http.Request) {
  219. var updateAcl models.UpdateAclRequest
  220. err := json.NewDecoder(r.Body).Decode(&updateAcl)
  221. if err != nil {
  222. logger.Log(0, "error decoding request body: ",
  223. err.Error())
  224. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  225. return
  226. }
  227. acl, err := logic.GetAcl(updateAcl.ID)
  228. if err != nil {
  229. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  230. return
  231. }
  232. if !logic.IsAclPolicyValid(updateAcl.Acl) {
  233. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid policy"), "badrequest"))
  234. return
  235. }
  236. if updateAcl.Acl.NetworkID != acl.NetworkID {
  237. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid policy, network id mismatch"), "badrequest"))
  238. return
  239. }
  240. if !acl.Default && updateAcl.NewName != "" {
  241. //check if policy exists with same name
  242. updateAcl.Acl.Name = updateAcl.NewName
  243. }
  244. err = logic.UpdateAcl(updateAcl.Acl, acl)
  245. if err != nil {
  246. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  247. return
  248. }
  249. go mq.PublishPeerUpdate(false)
  250. logic.ReturnSuccessResponse(w, r, "updated acl "+acl.Name)
  251. }
  252. // @Summary Delete Acl
  253. // @Router /api/v1/acls [delete]
  254. // @Tags ACL
  255. // @Accept json
  256. // @Success 200 {array} models.SuccessResponse
  257. // @Failure 500 {object} models.ErrorResponse
  258. func deleteAcl(w http.ResponseWriter, r *http.Request) {
  259. aclID, _ := url.QueryUnescape(r.URL.Query().Get("acl_id"))
  260. if aclID == "" {
  261. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("acl id is required"), "badrequest"))
  262. return
  263. }
  264. acl, err := logic.GetAcl(aclID)
  265. if err != nil {
  266. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  267. return
  268. }
  269. if acl.Default {
  270. logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("cannot delete default policy"), "badrequest"))
  271. return
  272. }
  273. err = logic.DeleteAcl(acl)
  274. if err != nil {
  275. logic.ReturnErrorResponse(w, r,
  276. logic.FormatError(errors.New("cannot delete default policy"), "internal"))
  277. return
  278. }
  279. go mq.PublishPeerUpdate(false)
  280. logic.ReturnSuccessResponse(w, r, "deleted acl "+acl.Name)
  281. }