Просмотр исходного кода

pkg/k8s: enable peers to use DNS names

This commit enables peers defined using the Peer CRD to declare their
endpoints using DNS names.

Signed-off-by: Lucas Servén Marín <lserven@gmail.com>
Lucas Servén Marín 6 лет назад
Родитель
Сommit
116fb7337a

+ 9 - 2
cmd/kgctl/showconf.go

@@ -289,9 +289,16 @@ func translatePeer(peer *wireguard.Peer) *v1alpha1.Peer {
 		aips = append(aips, aip.String())
 	}
 	var endpoint *v1alpha1.PeerEndpoint
-	if peer.Endpoint != nil && peer.Endpoint.Port > 0 && peer.Endpoint.IP != nil {
+	if peer.Endpoint != nil && peer.Endpoint.Port > 0 && (peer.Endpoint.IP != nil || peer.Endpoint.DNS != "") {
+		var ip string
+		if peer.Endpoint.IP != nil {
+			ip = peer.Endpoint.IP.String()
+		}
 		endpoint = &v1alpha1.PeerEndpoint{
-			IP:   peer.Endpoint.IP.String(),
+			DNSOrIP: v1alpha1.DNSOrIP{
+				DNS: peer.Endpoint.DNS,
+				IP:  ip,
+			},
 			Port: peer.Endpoint.Port,
 		}
 	}

+ 24 - 4
pkg/k8s/apis/kilo/v1alpha1/types.go

@@ -19,9 +19,11 @@ import (
 	"errors"
 	"fmt"
 	"net"
+	"strings"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/util/validation"
 )
 
 const (
@@ -81,12 +83,22 @@ type PeerSpec struct {
 
 // PeerEndpoint represents a WireGuard enpoint, which is a ip:port tuple.
 type PeerEndpoint struct {
-	// IP must be a valid IP address.
-	IP string `json:"ip"`
+	DNSOrIP
 	// Port must be a valid port number.
 	Port uint32 `json:"port"`
 }
 
+// DNSOrIP represents either a DNS name or an IP address.
+// IPs, as they are more specific, are preferred.
+type DNSOrIP struct {
+	// DNS must be a valid RFC 1123 subdomain.
+	// +optional
+	DNS string `json:"dns,omitempty"`
+	// IP must be a valid IP address.
+	// +optional
+	IP string `json:"ip,omitempty"`
+}
+
 // PeerName is the peer resource's FQDN.
 var PeerName = PeerPlural + "." + GroupName
 
@@ -127,10 +139,18 @@ func (p *Peer) Validate() error {
 		}
 	}
 	if p.Spec.Endpoint != nil {
-		if net.ParseIP(p.Spec.Endpoint.IP) == nil {
+		if p.Spec.Endpoint.IP == "" && p.Spec.Endpoint.DNS == "" {
+			return errors.New("either an endpoint DNS name IP address must be given")
+		}
+		if p.Spec.Endpoint.DNS != "" {
+			if errs := validation.IsDNS1123Subdomain(p.Spec.Endpoint.DNS); len(errs) != 0 {
+				return errors.New(strings.Join(errs, "; "))
+			}
+		}
+		if p.Spec.Endpoint.IP != "" && net.ParseIP(p.Spec.Endpoint.IP) == nil {
 			return fmt.Errorf("failed to parse %q as a valid IP address", p.Spec.Endpoint.IP)
 		}
-		if p.Spec.Endpoint.Port == 0 {
+		if 1 > p.Spec.Endpoint.Port || p.Spec.Endpoint.Port > 65535 {
 			return fmt.Errorf("port must be a valid UDP port number, got %d", p.Spec.Endpoint.Port)
 		}
 	}

+ 17 - 0
pkg/k8s/apis/kilo/v1alpha1/zz_generated.deepcopy.go

@@ -22,6 +22,22 @@ import (
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DNSOrIP) DeepCopyInto(out *DNSOrIP) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSOrIP.
+func (in *DNSOrIP) DeepCopy() *DNSOrIP {
+	if in == nil {
+		return nil
+	}
+	out := new(DNSOrIP)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Peer) DeepCopyInto(out *Peer) {
 	*out = *in
@@ -52,6 +68,7 @@ func (in *Peer) DeepCopyObject() runtime.Object {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PeerEndpoint) DeepCopyInto(out *PeerEndpoint) {
 	*out = *in
+	out.DNSOrIP = in.DNSOrIP
 	return
 }
 

+ 14 - 4
pkg/k8s/backend.go

@@ -325,10 +325,13 @@ func translatePeer(peer *v1alpha1.Peer) *mesh.Peer {
 		} else {
 			ip = ip.To16()
 		}
-		if peer.Spec.Endpoint.Port > 0 && ip != nil {
+		if peer.Spec.Endpoint.Port > 0 && (ip != nil || peer.Spec.Endpoint.DNS != "") {
 			endpoint = &wireguard.Endpoint{
-				DNSOrIP: wireguard.DNSOrIP{IP: ip},
-				Port:    peer.Spec.Endpoint.Port,
+				DNSOrIP: wireguard.DNSOrIP{
+					DNS: peer.Spec.Endpoint.DNS,
+					IP:  ip,
+				},
+				Port: peer.Spec.Endpoint.Port,
 			}
 		}
 	}
@@ -464,8 +467,15 @@ func (pb *peerBackend) Set(name string, peer *mesh.Peer) error {
 		p.Spec.AllowedIPs[i] = peer.AllowedIPs[i].String()
 	}
 	if peer.Endpoint != nil {
+		var ip string
+		if peer.Endpoint.IP != nil {
+			ip = peer.Endpoint.IP.String()
+		}
 		p.Spec.Endpoint = &v1alpha1.PeerEndpoint{
-			IP:   peer.Endpoint.IP.String(),
+			DNSOrIP: v1alpha1.DNSOrIP{
+				IP:  ip,
+				DNS: peer.Endpoint.DNS,
+			},
 			Port: peer.Endpoint.Port,
 		}
 	}

+ 35 - 3
pkg/k8s/backend_test.go

@@ -240,17 +240,30 @@ func TestTranslatePeer(t *testing.T) {
 			name: "invalid endpoint ip",
 			spec: v1alpha1.PeerSpec{
 				Endpoint: &v1alpha1.PeerEndpoint{
-					IP:   "foo",
+					DNSOrIP: v1alpha1.DNSOrIP{
+						IP: "foo",
+					},
 					Port: mesh.DefaultKiloPort,
 				},
 			},
 			out: &mesh.Peer{},
 		},
 		{
-			name: "valid endpoint",
+			name: "only endpoint port",
 			spec: v1alpha1.PeerSpec{
 				Endpoint: &v1alpha1.PeerEndpoint{
-					IP:   "10.0.0.1",
+					Port: mesh.DefaultKiloPort,
+				},
+			},
+			out: &mesh.Peer{},
+		},
+		{
+			name: "valid endpoint ip",
+			spec: v1alpha1.PeerSpec{
+				Endpoint: &v1alpha1.PeerEndpoint{
+					DNSOrIP: v1alpha1.DNSOrIP{
+						IP: "10.0.0.1",
+					},
 					Port: mesh.DefaultKiloPort,
 				},
 			},
@@ -263,6 +276,25 @@ func TestTranslatePeer(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "valid endpoint DNS",
+			spec: v1alpha1.PeerSpec{
+				Endpoint: &v1alpha1.PeerEndpoint{
+					DNSOrIP: v1alpha1.DNSOrIP{
+						DNS: "example.com",
+					},
+					Port: mesh.DefaultKiloPort,
+				},
+			},
+			out: &mesh.Peer{
+				Peer: wireguard.Peer{
+					Endpoint: &wireguard.Endpoint{
+						DNSOrIP: wireguard.DNSOrIP{DNS: "example.com"},
+						Port:    mesh.DefaultKiloPort,
+					},
+				},
+			},
+		},
 		{
 			name: "empty key",
 			spec: v1alpha1.PeerSpec{

+ 3 - 2
pkg/mesh/topology.go

@@ -19,11 +19,12 @@ import (
 	"net"
 	"sort"
 
+	"github.com/vishvananda/netlink"
+	"golang.org/x/sys/unix"
+
 	"github.com/squat/kilo/pkg/encapsulation"
 	"github.com/squat/kilo/pkg/iptables"
 	"github.com/squat/kilo/pkg/wireguard"
-	"github.com/vishvananda/netlink"
-	"golang.org/x/sys/unix"
 )
 
 const kiloTableIndex = 1107