2023-03-10 11:44:28 -08:00
|
|
|
// Copyright (c) Tailscale Inc & AUTHORS
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
2025-06-16 12:02:20 -07:00
|
|
|
|
2023-03-10 11:44:28 -08:00
|
|
|
package ipn
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2023-09-27 23:01:09 -07:00
|
|
|
"tailscale.com/ipn/ipnstate"
|
2023-03-10 11:44:28 -08:00
|
|
|
"tailscale.com/tailcfg"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCheckFunnelAccess(t *testing.T) {
|
2023-09-06 10:17:25 -07:00
|
|
|
caps := func(c ...tailcfg.NodeCapability) []tailcfg.NodeCapability { return c }
|
|
|
|
const portAttr tailcfg.NodeCapability = "https://tailscale.com/cap/funnel-ports?ports=443,8080-8090,8443,"
|
2023-03-10 11:44:28 -08:00
|
|
|
tests := []struct {
|
2023-03-11 08:45:40 -08:00
|
|
|
port uint16
|
2023-09-06 10:17:25 -07:00
|
|
|
caps []tailcfg.NodeCapability
|
2023-03-10 11:44:28 -08:00
|
|
|
wantErr bool
|
|
|
|
}{
|
2023-09-06 10:17:25 -07:00
|
|
|
{443, caps(portAttr), true}, // No "funnel" attribute
|
|
|
|
{443, caps(portAttr, tailcfg.NodeAttrFunnel), true},
|
|
|
|
{443, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), false},
|
|
|
|
{8443, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), false},
|
|
|
|
{8321, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), true},
|
|
|
|
{8083, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), false},
|
|
|
|
{8091, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), true},
|
|
|
|
{3000, caps(portAttr, tailcfg.CapabilityHTTPS, tailcfg.NodeAttrFunnel), true},
|
2023-03-10 11:44:28 -08:00
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
2023-09-27 23:01:09 -07:00
|
|
|
cm := tailcfg.NodeCapMap{}
|
|
|
|
for _, c := range tt.caps {
|
|
|
|
cm[c] = nil
|
|
|
|
}
|
|
|
|
err := CheckFunnelAccess(tt.port, &ipnstate.PeerStatus{CapMap: cm})
|
2023-03-10 11:44:28 -08:00
|
|
|
switch {
|
|
|
|
case err != nil && tt.wantErr,
|
|
|
|
err == nil && !tt.wantErr:
|
|
|
|
continue
|
|
|
|
case tt.wantErr:
|
|
|
|
t.Fatalf("got no error, want error")
|
|
|
|
case !tt.wantErr:
|
|
|
|
t.Fatalf("got error %v, want no error", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-26 14:40:44 -07:00
|
|
|
|
|
|
|
func TestHasPathHandler(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
cfg ServeConfig
|
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "empty-config",
|
|
|
|
cfg: ServeConfig{},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with-bg-path-handler",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {HTTP: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:80": {Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Path: "/tmp"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with-fg-path-handler",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{
|
|
|
|
443: {HTTPS: true},
|
|
|
|
},
|
|
|
|
Foreground: map[string]*ServeConfig{
|
|
|
|
"abc123": {
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {HTTP: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:80": {Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Path: "/tmp"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with-no-bg-path-handler",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{443: {HTTPS: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:443": {Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Proxy: "http://127.0.0.1:3000"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
AllowFunnel: map[HostPort]bool{"foo.test.ts.net:443": true},
|
|
|
|
},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "with-no-fg-path-handler",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
Foreground: map[string]*ServeConfig{
|
|
|
|
"abc123": {
|
|
|
|
TCP: map[uint16]*TCPPortHandler{443: {HTTPS: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:443": {Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Proxy: "http://127.0.0.1:3000"},
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
AllowFunnel: map[HostPort]bool{"foo.test.ts.net:443": true},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got := tt.cfg.HasPathHandler()
|
|
|
|
if tt.want != got {
|
|
|
|
t.Errorf("HasPathHandler() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-03-05 13:54:37 -05:00
|
|
|
|
cmd/tailscale/cli: Add service flag to serve command (#16191)
* cmd/tailscale/cli: Add service flag to serve command
This commit adds the service flag to serve command which allows serving a service and add the service
to the advertisedServices field in prefs (What advertise command does that will be removed later).
When adding proxies, TCP proxies and WEB proxies work the same way as normal serve, just under a
different DNSname. There is a services specific L3 serving mode called Tun, can be set via --tun flag.
Serving a service is always in --bg mode. If --bg is explicitly set t o false, an error message will
be sent out. The restriction on proxy target being localhost or 127.0.0.1 also applies to services.
When removing proxies, TCP proxies can be removed with type and port flag and off argument. Web proxies
can be removed with type, port, setPath flag and off argument. To align with normal serve, when setPath
is not set, all handler under the hostport will be removed. When flags are not set but off argument was
passed by user, it will be a noop. Removing all config for a service will be available later with a new
subcommand clear.
Updates tailscale/corp#22954
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: fix ai comments and fix a test
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: Add a test for addServiceToPrefs
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: fix comment
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* add dnsName in error message
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* change the cli input flag variable type
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* replace FindServiceConfig with map lookup
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* some code simplification and add asServiceName
This commit cotains code simplification for IsServingHTTPS, SetWebHandler, SetTCPForwarding
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* replace IsServiceName with tailcfg.AsServiceName
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* replace all assemble of host name for service with strings.Join
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: adjust parameter order and update output message
This commit updates the parameter order for IsTCPForwardingOnPort and SetWebHandler.
Also updated the message msgServiceIPNotAssigned to msgServiceWaitingApproval to adapt to
latest terminologies around services.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: flip bool condition
This commit fixes a previous bug added that throws error when serve funnel without service.
It should've been the opposite, which throws error when serve funnel with service.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: change parameter of IsTCPForwardingOnPort
This commit changes the dnsName string parameter for IsTCPForwardingOnPort to
svcName tailcfg.ServiceName. This change is made to reduce ambiguity when
a single service might have different dnsNames
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* ipn/ipnlocal: replace the key to webHandler for services
This commit changes the way we get the webhandler for vipServices. It used to use the host name
from request to find the webHandler, now everything targeting the vipService IP have the same
set of handlers. This commit also stores service:port instead of FQDN:port as the key in serviceConfig
for Web map.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: Updated use of service name.
This commit removes serviceName.IsEmpty and use direct comparison to instead. In legacy code, when an empty service
name needs to be passed, a new constant noService is passed. Removed redundant code for checking service name validity
and string method for serviceNameFlag.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: Update bgBoolFlag
This commit update field name, set and string method of bgBoolFlag to make code cleaner.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: remove isDefaultService output from srvTypeAndPortFromFlags
This commit removes the isDefaultService out put as it's no longer needed. Also deleted redundant code.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: remove unnessesary variable declare in messageForPort
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* replace bool output for AsServiceName with err
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: Replace DNSName with NoService if DNSname only used to identify service
This commit moves noService constant to tailcfg, updates AsServiceName to return tailcfg.NoService if the input
is not a valid service name. This commit also removes using the local DNSName as scvName parameter. When a function
is only using DNSName to identify if it's working with a service, the input in replaced with svcName and expect
caller to pass tailcfg.NoService if it's a local serve. This commit also replaces some use of Sprintf with
net.JoinHostPort for ipn.HostPort creation.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: Remove the returned error for AsServiceName
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* apply suggested code and comment
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* replace local dnsName in test with tailcfg.NoService
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* cmd/tailscale/cli: move noService back and use else where
The constant serves the purpose of provide readability for passing as a function parameter. It's
more meaningful comparing to a . It can just be an empty string in other places.
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
* ipn: Make WebHandlerExists and RemoveTCPForwarding accept svcName
This commit replaces two functions' string input with svcName input since they only use the dnsName to
identify service. Also did some minor cleanups
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
---------
Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
2025-07-16 19:37:46 -04:00
|
|
|
func TestIsTCPForwardingOnPort(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
cfg ServeConfig
|
|
|
|
svcName tailcfg.ServiceName
|
|
|
|
port uint16
|
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "empty-config",
|
|
|
|
cfg: ServeConfig{},
|
|
|
|
svcName: "",
|
|
|
|
port: 80,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "node-tcp-config-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {TCPForward: "10.0.0.123:3000"}},
|
|
|
|
},
|
|
|
|
svcName: "",
|
|
|
|
port: 80,
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "node-tcp-config-no-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {TCPForward: "10.0.0.123:3000"}},
|
|
|
|
},
|
|
|
|
svcName: "",
|
|
|
|
port: 443,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "node-tcp-config-no-match-with-service",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {TCPForward: "10.0.0.123:3000"}},
|
|
|
|
},
|
|
|
|
svcName: "svc:bar",
|
|
|
|
port: 80,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "node-web-config-no-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {HTTPS: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:80": {
|
|
|
|
Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Text: "Hello, world!"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
svcName: "",
|
|
|
|
port: 80,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "service-tcp-config-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
Services: map[tailcfg.ServiceName]*ServiceConfig{
|
|
|
|
"svc:foo": {
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {TCPForward: "10.0.0.123:3000"}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
svcName: "svc:foo",
|
|
|
|
port: 80,
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "service-tcp-config-no-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
Services: map[tailcfg.ServiceName]*ServiceConfig{
|
|
|
|
"svc:foo": {
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {TCPForward: "10.0.0.123:3000"}},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
svcName: "svc:bar",
|
|
|
|
port: 80,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "service-web-config-no-match",
|
|
|
|
cfg: ServeConfig{
|
|
|
|
Services: map[tailcfg.ServiceName]*ServiceConfig{
|
|
|
|
"svc:foo": {
|
|
|
|
TCP: map[uint16]*TCPPortHandler{80: {HTTPS: true}},
|
|
|
|
Web: map[HostPort]*WebServerConfig{
|
|
|
|
"foo.test.ts.net:80": {
|
|
|
|
Handlers: map[string]*HTTPHandler{
|
|
|
|
"/": {Text: "Hello, world!"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
svcName: "svc:foo",
|
|
|
|
port: 80,
|
|
|
|
want: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
got := tt.cfg.IsTCPForwardingOnPort(tt.port, tt.svcName)
|
|
|
|
if tt.want != got {
|
|
|
|
t.Errorf("IsTCPForwardingOnPort() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 13:54:37 -05:00
|
|
|
func TestExpandProxyTargetDev(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
input string
|
|
|
|
defaultScheme string
|
|
|
|
supportedSchemes []string
|
|
|
|
expected string
|
|
|
|
wantErr bool
|
|
|
|
}{
|
|
|
|
{name: "port-only", input: "8080", expected: "http://127.0.0.1:8080"},
|
2024-05-20 17:38:08 -07:00
|
|
|
{name: "hostname+port", input: "localhost:8080", expected: "http://localhost:8080"},
|
2024-03-05 13:54:37 -05:00
|
|
|
{name: "no-change", input: "http://127.0.0.1:8080", expected: "http://127.0.0.1:8080"},
|
|
|
|
{name: "include-path", input: "http://127.0.0.1:8080/foo", expected: "http://127.0.0.1:8080/foo"},
|
2024-05-20 17:38:08 -07:00
|
|
|
{name: "https-scheme", input: "https://localhost:8080", expected: "https://localhost:8080"},
|
|
|
|
{name: "https+insecure-scheme", input: "https+insecure://localhost:8080", expected: "https+insecure://localhost:8080"},
|
|
|
|
{name: "change-default-scheme", input: "localhost:8080", defaultScheme: "https", expected: "https://localhost:8080"},
|
|
|
|
{name: "change-supported-schemes", input: "localhost:8080", defaultScheme: "tcp", supportedSchemes: []string{"tcp"}, expected: "tcp://localhost:8080"},
|
2024-03-05 13:54:37 -05:00
|
|
|
|
|
|
|
// errors
|
|
|
|
{name: "invalid-port", input: "localhost:9999999", wantErr: true},
|
|
|
|
{name: "unsupported-scheme", input: "ftp://localhost:8080", expected: "", wantErr: true},
|
|
|
|
{name: "not-localhost", input: "https://tailscale.com:8080", expected: "", wantErr: true},
|
|
|
|
{name: "empty-input", input: "", expected: "", wantErr: true},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
defaultScheme := "http"
|
|
|
|
supportedSchemes := []string{"http", "https", "https+insecure"}
|
|
|
|
|
|
|
|
if tt.supportedSchemes != nil {
|
|
|
|
supportedSchemes = tt.supportedSchemes
|
|
|
|
}
|
|
|
|
if tt.defaultScheme != "" {
|
|
|
|
defaultScheme = tt.defaultScheme
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
actual, err := ExpandProxyTargetValue(tt.input, supportedSchemes, defaultScheme)
|
|
|
|
|
|
|
|
if tt.wantErr == true && err == nil {
|
|
|
|
t.Errorf("Expected an error but got none")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if tt.wantErr == false && err != nil {
|
|
|
|
t.Errorf("Got an error, but didn't expect one: %v", err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if actual != tt.expected {
|
|
|
|
t.Errorf("Got: %q; expected: %q", actual, tt.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2025-01-19 19:00:21 +00:00
|
|
|
|
|
|
|
func TestIsFunnelOn(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
sc *ServeConfig
|
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "nil_config",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "empty_config",
|
|
|
|
sc: &ServeConfig{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "funnel_enabled_in_background",
|
|
|
|
sc: &ServeConfig{
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:443": true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "funnel_disabled_in_background",
|
|
|
|
sc: &ServeConfig{
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:443": false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "funnel_enabled_in_foreground",
|
|
|
|
sc: &ServeConfig{
|
|
|
|
Foreground: map[string]*ServeConfig{
|
|
|
|
"abc123": {
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:443": true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "funnel_disabled_in_both",
|
|
|
|
sc: &ServeConfig{
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:443": false,
|
|
|
|
},
|
|
|
|
Foreground: map[string]*ServeConfig{
|
|
|
|
"abc123": {
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:8443": false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "funnel_enabled_in_both",
|
|
|
|
sc: &ServeConfig{
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:443": true,
|
|
|
|
},
|
|
|
|
Foreground: map[string]*ServeConfig{
|
|
|
|
"abc123": {
|
|
|
|
AllowFunnel: map[HostPort]bool{
|
|
|
|
"tailnet.xyz:8443": true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
want: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if got := tt.sc.IsFunnelOn(); got != tt.want {
|
|
|
|
t.Errorf("ServeConfig.IsFunnelOn() = %v, want %v", got, tt.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|