From e5a3d3c5890f0891052217c6365c2bb5c8959708 Mon Sep 17 00:00:00 2001 From: Johan Siebens Date: Wed, 28 Sep 2022 11:50:31 +0200 Subject: [PATCH] fix: sanitize tailnet name properly --- internal/domain/tailnet.go | 20 ++++++++++++++++++++ internal/domain/tailnet_test.go | 15 +++++++++++++++ internal/handlers/poll_net_map.go | 5 ++--- internal/mapping/mapping.go | 5 ++--- internal/service/dns.go | 3 +-- 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 internal/domain/tailnet_test.go diff --git a/internal/domain/tailnet.go b/internal/domain/tailnet.go index 1885342..0c4bae6 100644 --- a/internal/domain/tailnet.go +++ b/internal/domain/tailnet.go @@ -5,6 +5,9 @@ import ( "errors" "github.com/jsiebens/ionscale/internal/util" "gorm.io/gorm" + "net/mail" + "strings" + "tailscale.com/util/dnsname" ) type Tailnet struct { @@ -15,6 +18,23 @@ type Tailnet struct { ACLPolicy ACLPolicy } +func SanitizeTailnetName(name string) string { + name = strings.ToLower(name) + + a, err := mail.ParseAddress(name) + if err == nil && a.Address == name { + s := strings.Split(name, "@") + return strings.Join([]string{dnsname.SanitizeLabel(s[0]), s[1]}, ".") + } + + labels := strings.Split(name, ".") + for i, s := range labels { + labels[i] = dnsname.SanitizeLabel(s) + } + + return strings.Join(labels, ".") +} + func (r *repository) SaveTailnet(ctx context.Context, tailnet *Tailnet) error { tx := r.withContext(ctx).Save(tailnet) diff --git a/internal/domain/tailnet_test.go b/internal/domain/tailnet_test.go new file mode 100644 index 0000000..8bbb630 --- /dev/null +++ b/internal/domain/tailnet_test.go @@ -0,0 +1,15 @@ +package domain + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSanitizeTailnetName(t *testing.T) { + assert.Equal(t, "john.example.com", SanitizeTailnetName("john@example.com")) + assert.Equal(t, "john.example.com", SanitizeTailnetName("john@examPle.Com")) + assert.Equal(t, "john-doe.example.com", SanitizeTailnetName("john.doe@example.com")) + assert.Equal(t, "johns-network", SanitizeTailnetName("John's Network")) + assert.Equal(t, "example.com", SanitizeTailnetName("example.com")) + assert.Equal(t, "johns-example.com", SanitizeTailnetName("John's example.com")) +} diff --git a/internal/handlers/poll_net_map.go b/internal/handlers/poll_net_map.go index 7c0c827..7cbd230 100644 --- a/internal/handlers/poll_net_map.go +++ b/internal/handlers/poll_net_map.go @@ -10,7 +10,6 @@ import ( "github.com/labstack/echo/v4" "net/http" "tailscale.com/tailcfg" - "tailscale.com/util/dnsname" "time" ) @@ -286,7 +285,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin DNSConfig: mapping.ToDNSConfig(&m.Tailnet, &dnsConfig), PacketFilter: rules, DERPMap: derpMap, - Domain: dnsname.SanitizeHostname(m.Tailnet.Name), + Domain: domain.SanitizeTailnetName(m.Tailnet.Name), Peers: changedPeers, UserProfiles: users, ControlTime: &controlTime, @@ -300,7 +299,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin DNSConfig: mapping.ToDNSConfig(&m.Tailnet, &dnsConfig), PacketFilter: rules, DERPMap: derpMap, - Domain: dnsname.SanitizeHostname(m.Tailnet.Name), + Domain: domain.SanitizeTailnetName(m.Tailnet.Name), PeersChanged: changedPeers, PeersRemoved: removedPeers, UserProfiles: users, diff --git a/internal/mapping/mapping.go b/internal/mapping/mapping.go index 6ce4ffd..042d77d 100644 --- a/internal/mapping/mapping.go +++ b/internal/mapping/mapping.go @@ -11,7 +11,6 @@ import ( "tailscale.com/tailcfg" "tailscale.com/types/dnstype" "tailscale.com/types/key" - "tailscale.com/util/dnsname" "time" ) @@ -29,7 +28,7 @@ func CopyViaJson[F any, T any](f F, t T) error { } func ToDNSConfig(tailnet *domain.Tailnet, c *domain.DNSConfig) *tailcfg.DNSConfig { - tailnetDomain := dnsname.SanitizeHostname(tailnet.Name) + tailnetDomain := domain.SanitizeTailnetName(tailnet.Name) resolvers := []*dnstype.Resolver{} for _, r := range c.Nameservers { resolver := &dnstype.Resolver{ @@ -131,7 +130,7 @@ func ToNode(m *domain.Machine) (*tailcfg.Node, *tailcfg.UserProfile, error) { name = fmt.Sprintf("%s-%d", m.Name, m.NameIdx) } - sanitizedTailnetName := dnsname.SanitizeHostname(m.Tailnet.Name) + sanitizedTailnetName := domain.SanitizeTailnetName(m.Tailnet.Name) hostInfo := tailcfg.Hostinfo{ OS: hostinfo.OS, diff --git a/internal/service/dns.go b/internal/service/dns.go index a36e4f0..0b430d4 100644 --- a/internal/service/dns.go +++ b/internal/service/dns.go @@ -9,7 +9,6 @@ import ( "github.com/jsiebens/ionscale/internal/config" "github.com/jsiebens/ionscale/internal/domain" api "github.com/jsiebens/ionscale/pkg/gen/ionscale/v1" - "tailscale.com/util/dnsname" ) func (s *Service) GetDNSConfig(ctx context.Context, req *connect.Request[api.GetDNSConfigRequest]) (*connect.Response[api.GetDNSConfigResponse], error) { @@ -27,7 +26,7 @@ func (s *Service) GetDNSConfig(ctx context.Context, req *connect.Request[api.Get } dnsConfig := tailnet.DNSConfig - tailnetDomain := dnsname.SanitizeHostname(tailnet.Name) + tailnetDomain := domain.SanitizeTailnetName(tailnet.Name) resp := &api.GetDNSConfigResponse{ Config: &api.DNSConfig{