Skip to content

Commit 5753aa9

Browse files
committed
TUN-3294: Perform basic validation on arguments of route command; remove default pool name which wasn't valid
1 parent bfae120 commit 5753aa9

File tree

2 files changed

+54
-17
lines changed

2 files changed

+54
-17
lines changed

cmd/cloudflared/tunnel/subcommands.go

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"io/ioutil"
88
"os"
99
"path/filepath"
10+
"regexp"
1011
"sort"
1112
"strings"
1213
"text/tabwriter"
@@ -355,50 +356,65 @@ func buildRouteCommand() *cli.Command {
355356
Name: "route",
356357
Action: cliutil.ErrorHandler(routeCommand),
357358
Usage: "Define what hostname or load balancer can route to this tunnel",
358-
Description: `The route defines what hostname or load balancer can route to this tunnel.
359+
Description: `The route defines what hostname or load balancer will proxy requests to this tunnel.
359360
360-
To route a hostname: cloudflared tunnel route dns <tunnel ID> <hostname>
361-
To use this tunnel as a load balancer origin: cloudflared tunnel route lb <tunnel ID> <load balancer name> <load balancer pool>`,
361+
To route a hostname by creating a CNAME to tunnel's address:
362+
cloudflared tunnel route dns <tunnel ID> <hostname>
363+
To use this tunnel as a load balancer origin, creating pool and load balancer if necessary:
364+
cloudflared tunnel route lb <tunnel ID> <load balancer name> <load balancer pool>`,
362365
ArgsUsage: "dns|lb TUNNEL HOSTNAME [LB-POOL]",
363366
}
364367
}
365368

366-
func dnsRouteFromArg(c *cli.Context, tunnelID uuid.UUID) (tunnelstore.Route, error) {
369+
func dnsRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
367370
const (
368371
userHostnameIndex = 2
369-
expectArgs = 3
372+
expectedNArgs = 3
370373
)
371-
if c.NArg() != expectArgs {
372-
return nil, cliutil.UsageError("Expect %d arguments, got %d", expectArgs, c.NArg())
374+
if c.NArg() != expectedNArgs {
375+
return nil, cliutil.UsageError("Expected %d arguments, got %d", expectedNArgs, c.NArg())
373376
}
374377
userHostname := c.Args().Get(userHostnameIndex)
375378
if userHostname == "" {
376379
return nil, cliutil.UsageError("The third argument should be the hostname")
380+
} else if !validateName(userHostname) {
381+
return nil, errors.Errorf("%s is not a valid hostname", userHostname)
377382
}
378383
return tunnelstore.NewDNSRoute(userHostname), nil
379384
}
380385

381-
func lbRouteFromArg(c *cli.Context, tunnelID uuid.UUID) (tunnelstore.Route, error) {
386+
func lbRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
382387
const (
383388
lbNameIndex = 2
384389
lbPoolIndex = 3
385-
expectMinArgs = 3
390+
expectedNArgs = 4
386391
)
387-
if c.NArg() < expectMinArgs {
388-
return nil, cliutil.UsageError("Expect at least %d arguments, got %d", expectMinArgs, c.NArg())
392+
if c.NArg() != expectedNArgs {
393+
return nil, cliutil.UsageError("Expected %d arguments, got %d", expectedNArgs, c.NArg())
389394
}
390395
lbName := c.Args().Get(lbNameIndex)
391396
if lbName == "" {
392397
return nil, cliutil.UsageError("The third argument should be the load balancer name")
398+
} else if !validateName(lbName) {
399+
return nil, errors.Errorf("%s is not a valid load balancer name", lbName)
393400
}
401+
394402
lbPool := c.Args().Get(lbPoolIndex)
395403
if lbPool == "" {
396-
lbPool = defaultPoolName(tunnelID)
404+
return nil, cliutil.UsageError("The fourth argument should be the pool name")
405+
} else if !validateName(lbPool) {
406+
return nil, errors.Errorf("%s is not a valid pool name", lbPool)
397407
}
398408

399409
return tunnelstore.NewLBRoute(lbName, lbPool), nil
400410
}
401411

412+
var nameRegex = regexp.MustCompile("^[_a-zA-Z0-9][-_.a-zA-Z0-9]*$")
413+
414+
func validateName(s string) bool {
415+
return nameRegex.MatchString(s)
416+
}
417+
402418
func routeCommand(c *cli.Context) error {
403419
if c.NArg() < 2 {
404420
return cliutil.UsageError(`"cloudflared tunnel route" requires the first argument to be the route type(dns or lb), followed by the ID or name of the tunnel`)
@@ -419,7 +435,7 @@ func routeCommand(c *cli.Context) error {
419435
if err != nil {
420436
return err
421437
}
422-
r, err = dnsRouteFromArg(c, tunnelID)
438+
r, err = dnsRouteFromArg(c)
423439
if err != nil {
424440
return err
425441
}
@@ -428,7 +444,7 @@ func routeCommand(c *cli.Context) error {
428444
if err != nil {
429445
return err
430446
}
431-
r, err = lbRouteFromArg(c, tunnelID)
447+
r, err = lbRouteFromArg(c)
432448
if err != nil {
433449
return err
434450
}
@@ -443,6 +459,3 @@ func routeCommand(c *cli.Context) error {
443459
return nil
444460
}
445461

446-
func defaultPoolName(tunnelID uuid.UUID) string {
447-
return fmt.Sprintf("tunnel:%v", tunnelID)
448-
}

cmd/cloudflared/tunnel/subcommands_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,27 @@ func TestTunnelfilePath(t *testing.T) {
9898
expected := fmt.Sprintf("%s/.cloudflared/%v.json", homeDir, tunnelID)
9999
assert.Equal(t, expected, actual)
100100
}
101+
102+
func TestValidateName(t *testing.T) {
103+
tests := []struct {
104+
name string
105+
want bool
106+
}{
107+
{name: "", want: false},
108+
{name: "-", want: false},
109+
{name: ".", want: false},
110+
{name: "a b", want: false},
111+
{name: "a+b", want: false},
112+
{name: "-ab", want: false},
113+
114+
{name: "ab", want: true},
115+
{name: "ab-c", want: true},
116+
{name: "abc.def", want: true},
117+
{name: "_ab_c.-d-ef", want: true},
118+
}
119+
for _, tt := range tests {
120+
if got := validateName(tt.name); got != tt.want {
121+
t.Errorf("validateName() = %v, want %v", got, tt.want)
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)