gateway.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. package logic
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "slices"
  7. "sort"
  8. "time"
  9. "github.com/gravitl/netmaker/database"
  10. "github.com/gravitl/netmaker/db"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/schema"
  14. "github.com/gravitl/netmaker/servercfg"
  15. )
  16. // IsInternetGw - checks if node is acting as internet gw
  17. func IsInternetGw(node models.Node) bool {
  18. e := schema.Egress{
  19. Network: node.Network,
  20. }
  21. egList, _ := e.ListByNetwork(db.WithContext(context.TODO()))
  22. for _, egI := range egList {
  23. if egI.IsInetGw {
  24. if _, ok := egI.Nodes[node.ID.String()]; ok {
  25. return true
  26. }
  27. }
  28. }
  29. return false
  30. }
  31. // GetInternetGateways - gets all the nodes that are internet gateways
  32. func GetInternetGateways() ([]models.Node, error) {
  33. nodes, err := GetAllNodes()
  34. if err != nil {
  35. return nil, err
  36. }
  37. igs := make([]models.Node, 0)
  38. for _, node := range nodes {
  39. if node.EgressDetails.IsInternetGateway {
  40. igs = append(igs, node)
  41. }
  42. }
  43. return igs, nil
  44. }
  45. // GetAllIngresses - gets all the nodes that are ingresses
  46. func GetAllIngresses() ([]models.Node, error) {
  47. nodes, err := GetAllNodes()
  48. if err != nil {
  49. return nil, err
  50. }
  51. ingresses := make([]models.Node, 0)
  52. for _, node := range nodes {
  53. if node.IsIngressGateway {
  54. ingresses = append(ingresses, node)
  55. }
  56. }
  57. return ingresses, nil
  58. }
  59. // GetAllEgresses - gets all the nodes that are egresses
  60. func GetAllEgresses() ([]models.Node, error) {
  61. nodes, err := GetAllNodes()
  62. if err != nil {
  63. return nil, err
  64. }
  65. egresses := make([]models.Node, 0)
  66. for _, node := range nodes {
  67. if node.EgressDetails.IsEgressGateway {
  68. egresses = append(egresses, node)
  69. }
  70. }
  71. return egresses, nil
  72. }
  73. // CreateEgressGateway - creates an egress gateway
  74. func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
  75. node, err := GetNodeByID(gateway.NodeID)
  76. if err != nil {
  77. return models.Node{}, err
  78. }
  79. host, err := GetHost(node.HostID.String())
  80. if err != nil {
  81. return models.Node{}, err
  82. }
  83. if host.OS != "linux" { // support for other OS to be added
  84. return models.Node{}, errors.New(host.OS + " is unsupported for egress gateways")
  85. }
  86. if host.FirewallInUse == models.FIREWALL_NONE {
  87. return models.Node{}, errors.New("please install iptables or nftables on the device")
  88. }
  89. if len(gateway.RangesWithMetric) == 0 && len(gateway.Ranges) > 0 {
  90. for _, rangeI := range gateway.Ranges {
  91. gateway.RangesWithMetric = append(gateway.RangesWithMetric, models.EgressRangeMetric{
  92. Network: rangeI,
  93. RouteMetric: 256,
  94. })
  95. }
  96. }
  97. for i := len(gateway.Ranges) - 1; i >= 0; i-- {
  98. // check if internet gateway IPv4
  99. if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
  100. // remove inet range
  101. gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
  102. continue
  103. }
  104. normalized, err := NormalizeCIDR(gateway.Ranges[i])
  105. if err != nil {
  106. return models.Node{}, err
  107. }
  108. gateway.Ranges[i] = normalized
  109. }
  110. rangesWithMetric := []string{}
  111. for i := len(gateway.RangesWithMetric) - 1; i >= 0; i-- {
  112. if gateway.RangesWithMetric[i].Network == "0.0.0.0/0" || gateway.RangesWithMetric[i].Network == "::/0" {
  113. // remove inet range
  114. gateway.RangesWithMetric = append(gateway.RangesWithMetric[:i], gateway.RangesWithMetric[i+1:]...)
  115. continue
  116. }
  117. normalized, err := NormalizeCIDR(gateway.RangesWithMetric[i].Network)
  118. if err != nil {
  119. return models.Node{}, err
  120. }
  121. gateway.RangesWithMetric[i].Network = normalized
  122. rangesWithMetric = append(rangesWithMetric, gateway.RangesWithMetric[i].Network)
  123. if gateway.RangesWithMetric[i].RouteMetric <= 0 || gateway.RangesWithMetric[i].RouteMetric > 999 {
  124. gateway.RangesWithMetric[i].RouteMetric = 256
  125. }
  126. }
  127. sort.Strings(gateway.Ranges)
  128. sort.Strings(rangesWithMetric)
  129. if !slices.Equal(gateway.Ranges, rangesWithMetric) {
  130. return models.Node{}, errors.New("invalid ranges")
  131. }
  132. if gateway.NatEnabled == "" {
  133. gateway.NatEnabled = "yes"
  134. }
  135. err = ValidateEgressGateway(gateway)
  136. if err != nil {
  137. return models.Node{}, err
  138. }
  139. if gateway.Ranges == nil {
  140. gateway.Ranges = make([]string, 0)
  141. }
  142. node.EgressDetails.IsEgressGateway = true
  143. node.EgressDetails.EgressGatewayRanges = gateway.Ranges
  144. node.EgressDetails.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
  145. node.EgressDetails.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
  146. node.SetLastModified()
  147. if err = UpsertNode(&node); err != nil {
  148. return models.Node{}, err
  149. }
  150. return node, nil
  151. }
  152. // ValidateEgressGateway - validates the egress gateway model
  153. func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
  154. return nil
  155. }
  156. // DeleteEgressGateway - deletes egress from node
  157. func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
  158. node, err := GetNodeByID(nodeid)
  159. if err != nil {
  160. return models.Node{}, err
  161. }
  162. node.EgressDetails.IsEgressGateway = false
  163. node.EgressDetails.EgressGatewayRanges = []string{}
  164. node.EgressDetails.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone
  165. node.SetLastModified()
  166. if err = UpsertNode(&node); err != nil {
  167. return models.Node{}, err
  168. }
  169. return node, nil
  170. }
  171. // CreateIngressGateway - creates an ingress gateway
  172. func CreateIngressGateway(netid string, nodeid string, ingress models.IngressRequest) (models.Node, error) {
  173. node, err := GetNodeByID(nodeid)
  174. if err != nil {
  175. return models.Node{}, err
  176. }
  177. if node.IsRelayed {
  178. return models.Node{}, errors.New("gateway cannot be created on a relayed node")
  179. }
  180. host, err := GetHost(node.HostID.String())
  181. if err != nil {
  182. return models.Node{}, err
  183. }
  184. if host.OS != "linux" {
  185. return models.Node{}, errors.New("gateway can only be created on linux based node")
  186. }
  187. network, err := GetParentNetwork(netid)
  188. if err != nil {
  189. return models.Node{}, err
  190. }
  191. node.IsIngressGateway = true
  192. node.IsGw = true
  193. if !servercfg.IsPro {
  194. node.EgressDetails.IsInternetGateway = ingress.IsInternetGateway
  195. }
  196. node.IngressGatewayRange = network.AddressRange
  197. node.IngressGatewayRange6 = network.AddressRange6
  198. node.IngressDNS = ingress.ExtclientDNS
  199. if node.EgressDetails.IsInternetGateway && node.IngressDNS == "" {
  200. node.IngressDNS = "1.1.1.1"
  201. }
  202. node.IngressPersistentKeepalive = 20
  203. if ingress.PersistentKeepalive != 0 {
  204. node.IngressPersistentKeepalive = ingress.PersistentKeepalive
  205. }
  206. node.IngressMTU = 1420
  207. if ingress.MTU != 0 {
  208. node.IngressMTU = ingress.MTU
  209. }
  210. if servercfg.IsPro {
  211. if _, exists := FailOverExists(node.Network); exists {
  212. ResetFailedOverPeer(&node)
  213. }
  214. }
  215. node.SetLastModified()
  216. node.Metadata = ingress.Metadata
  217. if node.Metadata == "" {
  218. node.Metadata = "This host can be used for remote access"
  219. }
  220. if node.Tags == nil {
  221. node.Tags = make(map[models.TagID]struct{})
  222. }
  223. node.Tags[models.TagID(fmt.Sprintf("%s.%s", netid, models.GwTagName))] = struct{}{}
  224. err = UpsertNode(&node)
  225. if err != nil {
  226. return models.Node{}, err
  227. }
  228. err = SetNetworkNodesLastModified(netid)
  229. return node, err
  230. }
  231. // GetIngressGwUsers - lists the users having to access to ingressGW
  232. func GetIngressGwUsers(node models.Node) (models.IngressGwUsers, error) {
  233. gwUsers := models.IngressGwUsers{
  234. NodeID: node.ID.String(),
  235. Network: node.Network,
  236. }
  237. users, err := GetUsers()
  238. if err != nil {
  239. return gwUsers, err
  240. }
  241. for _, user := range users {
  242. if !user.IsAdmin && !user.IsSuperAdmin {
  243. gwUsers.Users = append(gwUsers.Users, user)
  244. }
  245. }
  246. return gwUsers, nil
  247. }
  248. // DeleteIngressGateway - deletes an ingress gateway
  249. func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error) {
  250. removedClients := []models.ExtClient{}
  251. node, err := GetNodeByID(nodeid)
  252. if err != nil {
  253. return models.Node{}, removedClients, err
  254. }
  255. clients, err := GetExtClientsByID(nodeid, node.Network)
  256. if err != nil && !database.IsEmptyRecord(err) {
  257. return models.Node{}, removedClients, err
  258. }
  259. removedClients = clients
  260. // delete ext clients belonging to ingress gateway
  261. if err = DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
  262. return models.Node{}, removedClients, err
  263. }
  264. logger.Log(3, "deleting ingress gateway")
  265. node.LastModified = time.Now().UTC()
  266. node.IsIngressGateway = false
  267. if !servercfg.IsPro {
  268. node.EgressDetails.IsInternetGateway = false
  269. }
  270. delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName)))
  271. node.IngressGatewayRange = ""
  272. node.Metadata = ""
  273. err = UpsertNode(&node)
  274. if err != nil {
  275. return models.Node{}, removedClients, err
  276. }
  277. err = SetNetworkNodesLastModified(node.Network)
  278. return node, removedClients, err
  279. }
  280. // DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
  281. func DeleteGatewayExtClients(gatewayID string, networkName string) error {
  282. currentExtClients, err := GetNetworkExtClients(networkName)
  283. if database.IsEmptyRecord(err) {
  284. return nil
  285. }
  286. if err != nil {
  287. return err
  288. }
  289. for _, extClient := range currentExtClients {
  290. if extClient.IngressGatewayID == gatewayID {
  291. if err = DeleteExtClient(networkName, extClient.ClientID); err != nil {
  292. logger.Log(1, "failed to remove ext client", extClient.ClientID)
  293. continue
  294. }
  295. }
  296. }
  297. return nil
  298. }
  299. // IsUserAllowedAccessToExtClient - checks if user has permission to access extclient
  300. func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bool {
  301. if username == MasterUser {
  302. return true
  303. }
  304. user, err := GetUser(username)
  305. if err != nil {
  306. return false
  307. }
  308. if user.UserName != client.OwnerID {
  309. return false
  310. }
  311. return true
  312. }