Browse Source

Allow Netmaker IPs for Nameservers (#3695)

* feat(go): allow netmaker nameserver ip;

* feat(go): filter out node's ips from nameservers;

* feat(go): update nameservers on node deletion;

* address nil checks

* address nil checks

---------

Co-authored-by: abhishek9686 <[email protected]>
Vishal Dalwadi 1 month ago
parent
commit
5448de6036
3 changed files with 110 additions and 18 deletions
  1. 49 14
      logic/dns.go
  2. 25 0
      logic/nodes.go
  3. 36 4
      pro/logic/dns.go

+ 49 - 14
logic/dns.go

@@ -432,24 +432,15 @@ func validateNameserverReq(ns schema.Nameserver) error {
 	if len(ns.Servers) == 0 {
 		return errors.New("atleast one nameserver should be specified")
 	}
-	network, err := GetNetwork(ns.NetworkID)
+	_, err := GetNetwork(ns.NetworkID)
 	if err != nil {
 		return errors.New("invalid network id")
 	}
-	_, cidr, err4 := net.ParseCIDR(network.AddressRange)
-	_, cidr6, err6 := net.ParseCIDR(network.AddressRange6)
 	for _, nsIPStr := range ns.Servers {
 		nsIP := net.ParseIP(nsIPStr)
 		if nsIP == nil {
 			return errors.New("invalid nameserver " + nsIPStr)
 		}
-		if err4 == nil && nsIP.To4() != nil {
-			if cidr.Contains(nsIP) {
-				return errors.New("cannot use netmaker IP as nameserver")
-			}
-		} else if err6 == nil && cidr6.Contains(nsIP) {
-			return errors.New("cannot use netmaker IP as nameserver")
-		}
 	}
 	if !ns.MatchAll && len(ns.MatchDomains) == 0 {
 		return errors.New("atleast one match domain is required")
@@ -478,6 +469,15 @@ func validateNameserverReq(ns schema.Nameserver) error {
 }
 
 func getNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
+	filters := make(map[string]bool)
+	if node.Address.IP != nil {
+		filters[node.Address.IP.String()] = true
+	}
+
+	if node.Address6.IP != nil {
+		filters[node.Address6.IP.String()] = true
+	}
+
 	ns := &schema.Nameserver{
 		NetworkID: node.Network,
 	}
@@ -486,11 +486,17 @@ func getNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
 		if !nsI.Status {
 			continue
 		}
+
+		filteredIps := FilterOutIPs(nsI.Servers, filters)
+		if len(filteredIps) == 0 {
+			continue
+		}
+
 		_, all := nsI.Tags["*"]
 		if all {
 			for _, matchDomain := range nsI.MatchDomains {
 				returnNsLi = append(returnNsLi, models.Nameserver{
-					IPs:         nsI.Servers,
+					IPs:         filteredIps,
 					MatchDomain: matchDomain,
 				})
 			}
@@ -500,7 +506,7 @@ func getNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
 		if _, ok := nsI.Nodes[node.ID.String()]; ok {
 			for _, matchDomain := range nsI.MatchDomains {
 				returnNsLi = append(returnNsLi, models.Nameserver{
-					IPs:         nsI.Servers,
+					IPs:         filteredIps,
 					MatchDomain: matchDomain,
 				})
 			}
@@ -528,6 +534,16 @@ func getNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 		if err != nil {
 			continue
 		}
+
+		filters := make(map[string]bool)
+		if node.Address.IP != nil {
+			filters[node.Address.IP.String()] = true
+		}
+
+		if node.Address6.IP != nil {
+			filters[node.Address6.IP.String()] = true
+		}
+
 		ns := &schema.Nameserver{
 			NetworkID: node.Network,
 		}
@@ -536,11 +552,17 @@ func getNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 			if !nsI.Status {
 				continue
 			}
+
+			filteredIps := FilterOutIPs(nsI.Servers, filters)
+			if len(filteredIps) == 0 {
+				continue
+			}
+
 			_, all := nsI.Tags["*"]
 			if all {
 				for _, matchDomain := range nsI.MatchDomains {
 					returnNsLi = append(returnNsLi, models.Nameserver{
-						IPs:         nsI.Servers,
+						IPs:         filteredIps,
 						MatchDomain: matchDomain,
 					})
 				}
@@ -550,7 +572,7 @@ func getNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 			if _, ok := nsI.Nodes[node.ID.String()]; ok {
 				for _, matchDomain := range nsI.MatchDomains {
 					returnNsLi = append(returnNsLi, models.Nameserver{
-						IPs:         nsI.Servers,
+						IPs:         filteredIps,
 						MatchDomain: matchDomain,
 					})
 				}
@@ -631,3 +653,16 @@ func IsValidMatchDomain(s string) bool {
 	}
 	return true
 }
+
+// FilterOutIPs removes ips in the filters map from the ips slice.
+func FilterOutIPs(ips []string, filters map[string]bool) []string {
+	var filteredIps []string
+	for _, ip := range ips {
+		_, ok := filters[ip]
+		if !ok {
+			filteredIps = append(filteredIps, ip)
+		}
+	}
+
+	return filteredIps
+}

+ 25 - 0
logic/nodes.go

@@ -15,10 +15,12 @@ import (
 	validator "github.com/go-playground/validator/v10"
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/db"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/logic/acls/nodeacls"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/schema"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/validation"
 	"github.com/seancfoley/ipaddress-go/ipaddr"
@@ -322,6 +324,29 @@ func DeleteNode(node *models.Node, purge bool) error {
 		return err
 	}
 
+	filters := make(map[string]bool)
+	if node.Address.IP != nil {
+		filters[node.Address.IP.String()] = true
+	}
+
+	if node.Address6.IP != nil {
+		filters[node.Address6.IP.String()] = true
+	}
+
+	nameservers, _ := (&schema.Nameserver{
+		NetworkID: node.Network,
+	}).ListByNetwork(db.WithContext(context.TODO()))
+	for _, ns := range nameservers {
+		ns.Servers = FilterOutIPs(ns.Servers, filters)
+		if len(ns.Servers) > 0 {
+			_ = ns.Update(db.WithContext(context.TODO()))
+		} else {
+			// TODO: deleting a nameserver dns server could cause trouble for other nodes.
+			// TODO: try to figure out a sequence that works the best.
+			_ = ns.Delete(db.WithContext(context.TODO()))
+		}
+	}
+
 	go RemoveNodeFromAclPolicy(*node)
 	go RemoveNodeFromEgress(*node)
 	return nil

+ 36 - 4
pro/logic/dns.go

@@ -65,6 +65,15 @@ func ValidateNameserverReq(ns schema.Nameserver) error {
 }
 
 func GetNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
+	filters := make(map[string]bool)
+	if node.Address.IP != nil {
+		filters[node.Address.IP.String()] = true
+	}
+
+	if node.Address6.IP != nil {
+		filters[node.Address6.IP.String()] = true
+	}
+
 	ns := &schema.Nameserver{
 		NetworkID: node.Network,
 	}
@@ -73,11 +82,17 @@ func GetNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
 		if !nsI.Status {
 			continue
 		}
+
+		filteredIps := logic.FilterOutIPs(nsI.Servers, filters)
+		if len(filteredIps) == 0 {
+			continue
+		}
+
 		_, all := nsI.Tags["*"]
 		if all {
 			for _, matchDomain := range nsI.MatchDomains {
 				returnNsLi = append(returnNsLi, models.Nameserver{
-					IPs:         nsI.Servers,
+					IPs:         filteredIps,
 					MatchDomain: matchDomain,
 				})
 			}
@@ -88,7 +103,7 @@ func GetNameserversForNode(node *models.Node) (returnNsLi []models.Nameserver) {
 			if _, ok := nsI.Tags[tagI.String()]; ok {
 				for _, matchDomain := range nsI.MatchDomains {
 					returnNsLi = append(returnNsLi, models.Nameserver{
-						IPs:         nsI.Servers,
+						IPs:         filteredIps,
 						MatchDomain: matchDomain,
 					})
 				}
@@ -126,11 +141,22 @@ func GetNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 	if h.DNS != "yes" {
 		return
 	}
+
 	for _, nodeID := range h.Nodes {
 		node, err := logic.GetNodeByID(nodeID)
 		if err != nil {
 			continue
 		}
+
+		filters := make(map[string]bool)
+		if node.Address.IP != nil {
+			filters[node.Address.IP.String()] = true
+		}
+
+		if node.Address6.IP != nil {
+			filters[node.Address6.IP.String()] = true
+		}
+
 		ns := &schema.Nameserver{
 			NetworkID: node.Network,
 		}
@@ -139,11 +165,17 @@ func GetNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 			if !nsI.Status {
 				continue
 			}
+
+			filteredIps := logic.FilterOutIPs(nsI.Servers, filters)
+			if len(filteredIps) == 0 {
+				continue
+			}
+
 			_, all := nsI.Tags["*"]
 			if all {
 				for _, matchDomain := range nsI.MatchDomains {
 					returnNsLi = append(returnNsLi, models.Nameserver{
-						IPs:         nsI.Servers,
+						IPs:         filteredIps,
 						MatchDomain: matchDomain,
 					})
 				}
@@ -154,7 +186,7 @@ func GetNameserversForHost(h *models.Host) (returnNsLi []models.Nameserver) {
 				if _, ok := nsI.Tags[tagI.String()]; ok {
 					for _, matchDomain := range nsI.MatchDomains {
 						returnNsLi = append(returnNsLi, models.Nameserver{
-							IPs:         nsI.Servers,
+							IPs:         filteredIps,
 							MatchDomain: matchDomain,
 						})
 					}