cmd/tailscale/cli: chage port flags to uint for serve and funnel

This PR changes the -https, -http, -tcp, and -tls-terminated-tcp
flags from string to int and also updates the validation to ensure
they fit the uint16 size as the flag library does not have a Uint16Var
method.

Updates #8489

Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
pull/9965/head
Marwan Sulaiman 8 months ago committed by Marwan Sulaiman
parent 741d7bcefe
commit 5f3cdaf283

@ -159,10 +159,10 @@ type serveEnv struct {
// v2 specific flags // v2 specific flags
bg bool // background mode bg bool // background mode
setPath string // serve path setPath string // serve path
https string // HTTP port https uint // HTTP port
http string // HTTP port http uint // HTTP port
tcp string // TCP port tcp uint // TCP port
tlsTerminatedTCP string // a TLS terminated TCP port tlsTerminatedTCP uint // a TLS terminated TCP port
subcmd serveMode // subcommand subcmd serveMode // subcommand
yes bool // update without prompt yes bool // update without prompt

@ -11,6 +11,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"math"
"net" "net"
"net/url" "net/url"
"os" "os"
@ -126,15 +127,15 @@ func newServeV2Command(e *serveEnv, subcmd serveMode) *ffcli.Command {
Exec: e.runServeCombined(subcmd), Exec: e.runServeCombined(subcmd),
FlagSet: e.newFlags("serve-set", func(fs *flag.FlagSet) { FlagSet: e.newFlags("serve-set", func(fs *flag.FlagSet) {
fs.BoolVar(&e.bg, "bg", false, "Run the command as a background process") fs.BoolVar(&e.bg, "bg", false, "Run the command as a background process (default false)")
fs.StringVar(&e.setPath, "set-path", "", "Appends the specified path to the base URL for accessing the underlying service") fs.StringVar(&e.setPath, "set-path", "", "Appends the specified path to the base URL for accessing the underlying service")
fs.StringVar(&e.https, "https", "", "Expose an HTTPS server at the specified port (default") fs.UintVar(&e.https, "https", 0, "Expose an HTTPS server at the specified port (default mode)")
fs.StringVar(&e.http, "http", "", "Expose an HTTP server at the specified port") fs.UintVar(&e.http, "http", 0, "Expose an HTTP server at the specified port")
fs.StringVar(&e.tcp, "tcp", "", "Expose a TCP forwarder to forward raw TCP packets at the specified port") fs.UintVar(&e.tcp, "tcp", 0, "Expose a TCP forwarder to forward raw TCP packets at the specified port")
fs.StringVar(&e.tlsTerminatedTCP, "tls-terminated-tcp", "", "Expose a TCP forwarder to forward TLS-terminated TCP packets at the specified port") fs.UintVar(&e.tlsTerminatedTCP, "tls-terminated-tcp", 0, "Expose a TCP forwarder to forward TLS-terminated TCP packets at the specified port")
fs.BoolVar(&e.yes, "yes", false, "Update without interactive prompts") fs.BoolVar(&e.yes, "yes", false, "Update without interactive prompts (default false)")
}), }),
UsageFunc: usageFunc, UsageFunc: usageFuncNoDefaultValues,
Subcommands: []*ffcli.Command{ Subcommands: []*ffcli.Command{
{ {
Name: "status", Name: "status",
@ -649,7 +650,7 @@ func (e *serveEnv) unsetServe(sc *ipn.ServeConfig, dnsName string, srvType serve
} }
func srvTypeAndPortFromFlags(e *serveEnv) (srvType serveType, srvPort uint16, err error) { func srvTypeAndPortFromFlags(e *serveEnv) (srvType serveType, srvPort uint16, err error) {
sourceMap := map[serveType]string{ sourceMap := map[serveType]uint{
serveTypeHTTP: e.http, serveTypeHTTP: e.http,
serveTypeHTTPS: e.https, serveTypeHTTPS: e.https,
serveTypeTCP: e.tcp, serveTypeTCP: e.tcp,
@ -657,13 +658,15 @@ func srvTypeAndPortFromFlags(e *serveEnv) (srvType serveType, srvPort uint16, er
} }
var srcTypeCount int var srcTypeCount int
var srcValue string
for k, v := range sourceMap { for k, v := range sourceMap {
if v != "" { if v != 0 {
if v > math.MaxUint16 {
return 0, 0, fmt.Errorf("port number %d is too high for %s flag", v, srvType)
}
srcTypeCount++ srcTypeCount++
srvType = k srvType = k
srcValue = v srvPort = uint16(v)
} }
} }
@ -671,12 +674,7 @@ func srvTypeAndPortFromFlags(e *serveEnv) (srvType serveType, srvPort uint16, er
return 0, 0, fmt.Errorf("cannot serve multiple types for a single mount point") return 0, 0, fmt.Errorf("cannot serve multiple types for a single mount point")
} else if srcTypeCount == 0 { } else if srcTypeCount == 0 {
srvType = serveTypeHTTPS srvType = serveTypeHTTPS
srcValue = "443" srvPort = 443
}
srvPort, err = parseServePort(srcValue)
if err != nil {
return 0, 0, fmt.Errorf("invalid port %q: %w", srcValue, err)
} }
return srvType, srvPort, nil return srvType, srvPort, nil

@ -207,6 +207,13 @@ func TestServeDevConfigMutations(t *testing.T) {
wantErr: anyErr(), wantErr: anyErr(),
}}, }},
}, },
{
name: "invalid_mount_port_too_high",
steps: []step{{
command: cmd("serve --https=65536 --bg http://localhost:3000"), // invalid port, too high
wantErr: anyErr(),
}},
},
{ {
name: "invalid_host", name: "invalid_host",
steps: []step{{ steps: []step{{
@ -948,28 +955,28 @@ func TestSrcTypeFromFlags(t *testing.T) {
}{ }{
{ {
name: "only http set", name: "only http set",
env: &serveEnv{http: "80"}, env: &serveEnv{http: 80},
expectedType: serveTypeHTTP, expectedType: serveTypeHTTP,
expectedPort: 80, expectedPort: 80,
expectedErr: false, expectedErr: false,
}, },
{ {
name: "only https set", name: "only https set",
env: &serveEnv{https: "10000"}, env: &serveEnv{https: 10000},
expectedType: serveTypeHTTPS, expectedType: serveTypeHTTPS,
expectedPort: 10000, expectedPort: 10000,
expectedErr: false, expectedErr: false,
}, },
{ {
name: "only tcp set", name: "only tcp set",
env: &serveEnv{tcp: "8000"}, env: &serveEnv{tcp: 8000},
expectedType: serveTypeTCP, expectedType: serveTypeTCP,
expectedPort: 8000, expectedPort: 8000,
expectedErr: false, expectedErr: false,
}, },
{ {
name: "only tls-terminated-tcp set", name: "only tls-terminated-tcp set",
env: &serveEnv{tlsTerminatedTCP: "8080"}, env: &serveEnv{tlsTerminatedTCP: 8080},
expectedType: serveTypeTLSTerminatedTCP, expectedType: serveTypeTLSTerminatedTCP,
expectedPort: 8080, expectedPort: 8080,
expectedErr: false, expectedErr: false,
@ -983,7 +990,7 @@ func TestSrcTypeFromFlags(t *testing.T) {
}, },
{ {
name: "multiple types set", name: "multiple types set",
env: &serveEnv{http: "80", https: "443"}, env: &serveEnv{http: 80, https: 443},
expectedPort: 0, expectedPort: 0,
expectedErr: true, expectedErr: true,
}, },

Loading…
Cancel
Save