egress.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package logic
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "maps"
  8. "net"
  9. "github.com/gravitl/netmaker/db"
  10. "github.com/gravitl/netmaker/models"
  11. "github.com/gravitl/netmaker/schema"
  12. )
  13. func ValidateEgressReq(e *schema.Egress) error {
  14. if e.Network == "" {
  15. return errors.New("network id is empty")
  16. }
  17. _, err := GetNetwork(e.Network)
  18. if err != nil {
  19. return errors.New("failed to get network " + err.Error())
  20. }
  21. if !e.IsInetGw {
  22. if e.Range == "" {
  23. return errors.New("egress range is empty")
  24. }
  25. _, _, err = net.ParseCIDR(e.Range)
  26. if err != nil {
  27. return errors.New("invalid egress range " + err.Error())
  28. }
  29. err = ValidateEgressRange(e.Network, []string{e.Range})
  30. if err != nil {
  31. return errors.New("invalid egress range " + err.Error())
  32. }
  33. } else {
  34. if len(e.Nodes) > 1 {
  35. return errors.New("can only set one internet routing node")
  36. }
  37. req := models.InetNodeReq{}
  38. for k := range e.Nodes {
  39. inetNode, err := GetNodeByID(k)
  40. if err != nil {
  41. return errors.New("invalid routing node " + err.Error())
  42. }
  43. // check if node is acting as egress gw already
  44. GetNodeEgressInfo(&inetNode)
  45. if err := ValidateInetGwReq(inetNode, req, false); err != nil {
  46. return errors.New("invalid routing node " + err.Error())
  47. }
  48. }
  49. }
  50. if len(e.Nodes) != 0 {
  51. for k := range e.Nodes {
  52. _, err := GetNodeByID(k)
  53. if err != nil {
  54. return errors.New("invalid routing node " + err.Error())
  55. }
  56. }
  57. }
  58. return nil
  59. }
  60. func GetInetClientsFromAclPolicies(eID string) (inetClientIDs []string) {
  61. e := schema.Egress{ID: eID}
  62. err := e.Get(db.WithContext(context.TODO()))
  63. if err != nil || !e.Status {
  64. return
  65. }
  66. acls, _ := ListAclsByNetwork(models.NetworkID(e.Network))
  67. for _, acl := range acls {
  68. for _, dstI := range acl.Dst {
  69. if dstI.ID == models.EgressID {
  70. if dstI.Value != eID {
  71. continue
  72. }
  73. for _, srcI := range acl.Src {
  74. if srcI.Value == "*" {
  75. continue
  76. }
  77. if srcI.ID == models.NodeID {
  78. inetClientIDs = append(inetClientIDs, srcI.Value)
  79. }
  80. if srcI.ID == models.NodeTagID {
  81. inetClientIDs = append(inetClientIDs, GetNodeIDsWithTag(models.TagID(srcI.Value))...)
  82. }
  83. }
  84. }
  85. }
  86. }
  87. return
  88. }
  89. func isNodeUsingInternetGw(node *models.Node) {
  90. host, err := GetHost(node.HostID.String())
  91. if err != nil {
  92. return
  93. }
  94. if host.IsDefault {
  95. return
  96. }
  97. nodeTags := maps.Clone(node.Tags)
  98. nodeTags[models.TagID(node.ID.String())] = struct{}{}
  99. acls, _ := ListAclsByNetwork(models.NetworkID(node.Network))
  100. for _, acl := range acls {
  101. if !acl.Enabled {
  102. continue
  103. }
  104. srcVal := convAclTagToValueMap(acl.Src)
  105. for _, dstI := range acl.Dst {
  106. if dstI.ID == models.EgressID {
  107. e := schema.Egress{ID: dstI.Value}
  108. err := e.Get(db.WithContext(context.TODO()))
  109. if err != nil || !e.Status {
  110. continue
  111. }
  112. if e.IsInetGw {
  113. if _, ok := srcVal[node.ID.String()]; ok {
  114. for nodeID := range e.Nodes {
  115. if nodeID == node.ID.String() {
  116. continue
  117. }
  118. node.InternetGwID = nodeID
  119. return
  120. }
  121. }
  122. for tagID := range nodeTags {
  123. if _, ok := srcVal[tagID.String()]; ok {
  124. for nodeID := range e.Nodes {
  125. if nodeID == node.ID.String() {
  126. continue
  127. }
  128. node.InternetGwID = nodeID
  129. return
  130. }
  131. }
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. func AddEgressInfoToNode(targetNode *models.Node, e schema.Egress) {
  139. req := models.EgressGatewayRequest{
  140. NodeID: targetNode.ID.String(),
  141. NetID: targetNode.Network,
  142. }
  143. if metric, ok := e.Nodes[targetNode.ID.String()]; ok {
  144. if e.IsInetGw {
  145. targetNode.IsInternetGateway = true
  146. targetNode.InetNodeReq = models.InetNodeReq{
  147. InetNodeClientIDs: GetInetClientsFromAclPolicies(e.ID),
  148. }
  149. req.Ranges = append(req.Ranges, "0.0.0.0/0")
  150. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  151. Network: "0.0.0.0/0",
  152. Nat: true,
  153. RouteMetric: 256,
  154. })
  155. req.Ranges = append(req.Ranges, "::/0")
  156. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  157. Network: "::/0",
  158. Nat: true,
  159. RouteMetric: 256,
  160. })
  161. } else {
  162. m64, err := metric.(json.Number).Int64()
  163. if err != nil {
  164. m64 = 256
  165. }
  166. m := uint32(m64)
  167. req.Ranges = append(req.Ranges, e.Range)
  168. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  169. Network: e.Range,
  170. Nat: e.Nat,
  171. RouteMetric: m,
  172. })
  173. }
  174. }
  175. if e.Nat {
  176. req.NatEnabled = "yes"
  177. }
  178. targetNode.EgressDetails.IsEgressGateway = true
  179. targetNode.EgressDetails.EgressGatewayRanges = req.Ranges
  180. targetNode.EgressDetails.EgressGatewayRequest = req
  181. }
  182. func GetNodeEgressInfo(targetNode *models.Node) {
  183. if targetNode.Mutex != nil {
  184. targetNode.Mutex.Lock()
  185. defer targetNode.Mutex.Unlock()
  186. }
  187. eli, _ := (&schema.Egress{Network: targetNode.Network}).ListByNetwork(db.WithContext(context.TODO()))
  188. req := models.EgressGatewayRequest{
  189. NodeID: targetNode.ID.String(),
  190. NetID: targetNode.Network,
  191. }
  192. defer func() {
  193. isNodeUsingInternetGw(targetNode)
  194. }()
  195. for _, e := range eli {
  196. if !e.Status || e.Network != targetNode.Network {
  197. continue
  198. }
  199. if metric, ok := e.Nodes[targetNode.ID.String()]; ok {
  200. if e.IsInetGw {
  201. targetNode.IsInternetGateway = true
  202. targetNode.InetNodeReq = models.InetNodeReq{
  203. InetNodeClientIDs: GetInetClientsFromAclPolicies(e.ID),
  204. }
  205. req.Ranges = append(req.Ranges, "0.0.0.0/0")
  206. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  207. Network: "0.0.0.0/0",
  208. Nat: true,
  209. RouteMetric: 256,
  210. })
  211. req.Ranges = append(req.Ranges, "::/0")
  212. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  213. Network: "::/0",
  214. Nat: true,
  215. RouteMetric: 256,
  216. })
  217. } else {
  218. m64, err := metric.(json.Number).Int64()
  219. if err != nil {
  220. m64 = 256
  221. }
  222. m := uint32(m64)
  223. req.Ranges = append(req.Ranges, e.Range)
  224. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  225. Network: e.Range,
  226. Nat: e.Nat,
  227. RouteMetric: m,
  228. })
  229. }
  230. }
  231. }
  232. if len(req.Ranges) > 0 {
  233. targetNode.EgressDetails.IsEgressGateway = true
  234. targetNode.EgressDetails.EgressGatewayRanges = req.Ranges
  235. targetNode.EgressDetails.EgressGatewayRequest = req
  236. targetHost, _ := GetHost(targetNode.HostID.String())
  237. fmt.Println("TARGET NODE: ", targetHost.Name, targetNode.EgressDetails.EgressGatewayRanges, targetNode.EgressDetails.EgressGatewayRequest)
  238. }
  239. }
  240. func RemoveNodeFromEgress(node models.Node) {
  241. egs, _ := (&schema.Egress{}).ListByNetwork(db.WithContext(context.TODO()))
  242. for _, egI := range egs {
  243. if _, ok := egI.Nodes[node.ID.String()]; ok {
  244. delete(egI.Nodes, node.ID.String())
  245. egI.Update(db.WithContext(context.TODO()))
  246. }
  247. }
  248. }