TUN-3578: cloudflared tunnel route dns should allow wildcard subdomains

This commit is contained in:
Adam Chalmers 2020-11-20 16:22:32 -06:00
parent 87203bbe25
commit a08a7030d1
2 changed files with 76 additions and 17 deletions

View File

@ -431,7 +431,7 @@ func dnsRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
userHostname := c.Args().Get(userHostnameIndex) userHostname := c.Args().Get(userHostnameIndex)
if userHostname == "" { if userHostname == "" {
return nil, cliutil.UsageError("The third argument should be the hostname") return nil, cliutil.UsageError("The third argument should be the hostname")
} else if !validateHostname(userHostname) { } else if !validateHostname(userHostname, true) {
return nil, errors.Errorf("%s is not a valid hostname", userHostname) return nil, errors.Errorf("%s is not a valid hostname", userHostname)
} }
return tunnelstore.NewDNSRoute(userHostname), nil return tunnelstore.NewDNSRoute(userHostname), nil
@ -449,14 +449,14 @@ func lbRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
lbName := c.Args().Get(lbNameIndex) lbName := c.Args().Get(lbNameIndex)
if lbName == "" { if lbName == "" {
return nil, cliutil.UsageError("The third argument should be the load balancer name") return nil, cliutil.UsageError("The third argument should be the load balancer name")
} else if !validateHostname(lbName) { } else if !validateHostname(lbName, true) {
return nil, errors.Errorf("%s is not a valid load balancer name", lbName) return nil, errors.Errorf("%s is not a valid load balancer name", lbName)
} }
lbPool := c.Args().Get(lbPoolIndex) lbPool := c.Args().Get(lbPoolIndex)
if lbPool == "" { if lbPool == "" {
return nil, cliutil.UsageError("The fourth argument should be the pool name") return nil, cliutil.UsageError("The fourth argument should be the pool name")
} else if !validateName(lbPool) { } else if !validateName(lbPool, false) {
return nil, errors.Errorf("%s is not a valid pool name", lbPool) return nil, errors.Errorf("%s is not a valid pool name", lbPool)
} }
@ -464,19 +464,23 @@ func lbRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
} }
var nameRegex = regexp.MustCompile("^[_a-zA-Z0-9][-_.a-zA-Z0-9]*$") var nameRegex = regexp.MustCompile("^[_a-zA-Z0-9][-_.a-zA-Z0-9]*$")
var hostNameRegex = regexp.MustCompile("^[*_a-zA-Z0-9][-_.a-zA-Z0-9]*$")
func validateName(s string) bool { func validateName(s string, allowWildcardSubdomain bool) bool {
if allowWildcardSubdomain {
return hostNameRegex.MatchString(s)
}
return nameRegex.MatchString(s) return nameRegex.MatchString(s)
} }
func validateHostname(s string) bool { func validateHostname(s string, allowWildcardSubdomain bool) bool {
// Slightly stricter than PunyCodeProfile // Slightly stricter than PunyCodeProfile
idnaProfile := idna.New( idnaProfile := idna.New(
idna.ValidateLabels(true), idna.ValidateLabels(true),
idna.VerifyDNSLength(true)) idna.VerifyDNSLength(true))
puny, err := idnaProfile.ToASCII(s) puny, err := idnaProfile.ToASCII(s)
return err == nil && validateName(puny) return err == nil && validateName(puny, allowWildcardSubdomain)
} }
func routeCommand(c *cli.Context) error { func routeCommand(c *cli.Context) error {

View File

@ -6,9 +6,8 @@ import (
"testing" "testing"
"github.com/cloudflare/cloudflared/tunnelstore" "github.com/cloudflare/cloudflared/tunnelstore"
"github.com/mitchellh/go-homedir"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/mitchellh/go-homedir"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -117,8 +116,64 @@ func TestValidateName(t *testing.T) {
{name: "_ab_c.-d-ef", want: true}, {name: "_ab_c.-d-ef", want: true},
} }
for _, tt := range tests { for _, tt := range tests {
if got := validateName(tt.name); got != tt.want { if got := validateName(tt.name, false); got != tt.want {
t.Errorf("validateName() = %v, want %v", got, tt.want) t.Errorf("validateName() = %v, want %v", got, tt.want)
} }
} }
} }
func Test_validateHostname(t *testing.T) {
type args struct {
s string
allowWildcardSubdomain bool
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Normal",
args: args{
s: "example.com",
allowWildcardSubdomain: true,
},
want: true,
},
{
name: "wildcard subdomain for TUN-358",
args: args{
s: "*.ehrig.io",
allowWildcardSubdomain: true,
},
want: true,
},
{
name: "Misplaced wildcard",
args: args{
s: "subdomain.*.ehrig.io",
allowWildcardSubdomain: true,
},
},
{
name: "Invalid domain",
args: args{
s: "..",
allowWildcardSubdomain: true,
},
},
{
name: "Invalid domain",
args: args{
s: "..",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := validateHostname(tt.args.s, tt.args.allowWildcardSubdomain); got != tt.want {
t.Errorf("validateHostname() = %v, want %v", got, tt.want)
}
})
}
}