From 29efd5e6c6ca742a6ef2f498ecea43a5d59cea40 Mon Sep 17 00:00:00 2001 From: Damian Debkowski Date: Fri, 20 Sep 2024 11:30:27 -0700 Subject: [PATCH] test: ensure ipv6 compatability (#5110) --- internal/cmd/base/server_test.go | 64 ++++++++- internal/cmd/base/servers.go | 12 ++ internal/cmd/config/config.go | 12 ++ internal/cmd/config/config_test.go | 218 ++++++++++++++++++++++++++++- internal/cmd/ops/server_test.go | 18 ++- 5 files changed, 314 insertions(+), 10 deletions(-) diff --git a/internal/cmd/base/server_test.go b/internal/cmd/base/server_test.go index 7784f5f450..3fbb20b0ef 100644 --- a/internal/cmd/base/server_test.go +++ b/internal/cmd/base/server_test.go @@ -496,7 +496,7 @@ func TestSetupWorkerPublicAddress(t *testing.T) { expPublicAddress: ":9202", }, { - name: "setting public address directly with ip", + name: "setting public address directly with ipv4", inputConfig: &config.Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{}, @@ -511,7 +511,7 @@ func TestSetupWorkerPublicAddress(t *testing.T) { expPublicAddress: "127.0.0.1:9202", }, { - name: "setting public address directly with ip:port", + name: "setting public address directly with ipv4:port", inputConfig: &config.Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{}, @@ -525,6 +525,66 @@ func TestSetupWorkerPublicAddress(t *testing.T) { expErrStr: "", expPublicAddress: "127.0.0.1:8080", }, + { + name: "setting public address directly with ipv6", + inputConfig: &config.Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Worker: &config.Worker{ + PublicAddr: "[2001:4860:4860:0:0:0:0:8888]", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicAddress: "[2001:4860:4860:0:0:0:0:8888]:9202", + }, + { + name: "setting public address directly with ipv6:port", + inputConfig: &config.Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Worker: &config.Worker{ + PublicAddr: "[2001:4860:4860:0:0:0:0:8888]:8080", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicAddress: "[2001:4860:4860:0:0:0:0:8888]:8080", + }, + { + name: "setting public address directly with abbreviated ipv6", + inputConfig: &config.Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Worker: &config.Worker{ + PublicAddr: "[2001:4860:4860::8888]", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicAddress: "[2001:4860:4860::8888]:9202", + }, + { + name: "setting public address directly with abbreviated ipv6:port", + inputConfig: &config.Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Worker: &config.Worker{ + PublicAddr: "[2001:4860:4860::8888]:8080", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicAddress: "[2001:4860:4860::8888]:8080", + }, { name: "setting public address to env var", inputConfig: &config.Config{ diff --git a/internal/cmd/base/servers.go b/internal/cmd/base/servers.go index 185d7a55df..24bf55fa0e 100644 --- a/internal/cmd/base/servers.go +++ b/internal/cmd/base/servers.go @@ -14,6 +14,7 @@ import ( "os" "os/signal" "path/filepath" + "regexp" "sort" "strconv" "strings" @@ -57,6 +58,12 @@ const ( WorkerAuthReqFile = "auth_request_token" ) +var ( + // This regular expression is used to find all instances of square brackets within a string. + // This regular expression is used to remove the square brackets from an IPv6 address. + squareBrackets = regexp.MustCompile("\\[|\\]") +) + func init() { metric.InitializeBuildInfo(prometheus.DefaultRegisterer) } @@ -845,7 +852,12 @@ func (b *Server) SetupWorkerPublicAddress(conf *config.Config, flagValue string) return fmt.Errorf("Error splitting public adddress host/port: %w", err) } } + + // remove the square brackets from the ipv6 address because the method + // net.JoinHostPort() will add a second pair of square brackets. + host = squareBrackets.ReplaceAllString(host, "") conf.Worker.PublicAddr = net.JoinHostPort(host, port) + return nil } diff --git a/internal/cmd/config/config.go b/internal/cmd/config/config.go index 7e900c4b1b..58781ee252 100644 --- a/internal/cmd/config/config.go +++ b/internal/cmd/config/config.go @@ -15,6 +15,7 @@ import ( "net" "os" "reflect" + "regexp" "strconv" "strings" "time" @@ -132,6 +133,12 @@ kms "aead" { defaultCsp = "default-src 'none'; script-src 'self' 'wasm-unsafe-eval'; frame-src 'self'; font-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self'; media-src 'self'; manifest-src 'self'; style-src-attr 'self'; frame-ancestors 'self'" ) +var ( + // This regular expression is used to find all instances of square brackets within a string. + // This regular expression is used to remove the square brackets from an IPv6 address. + squareBrackets = regexp.MustCompile("\\[|\\]") +) + // Config is the configuration for the boundary controller type Config struct { *configutil.SharedConfig `hcl:"-"` @@ -1278,7 +1285,12 @@ func (c *Config) SetupControllerPublicClusterAddress(flagValue string) error { return fmt.Errorf("Error splitting public cluster adddress host/port: %w", err) } } + + // remove the square brackets from the ipv6 address because the method + // net.JoinHostPort() will add a second pair of square brackets. + host = squareBrackets.ReplaceAllString(host, "") c.Controller.PublicClusterAddr = net.JoinHostPort(host, port) + return nil } diff --git a/internal/cmd/config/config_test.go b/internal/cmd/config/config_test.go index d6aa6e6ae5..65cdf88eca 100644 --- a/internal/cmd/config/config_test.go +++ b/internal/cmd/config/config_test.go @@ -1495,7 +1495,7 @@ func TestWorkerUpstreams(t *testing.T) { expErr: false, }, { - name: "One Upstream", + name: "ipv4 Upstream", in: ` worker { name = "test" @@ -1505,6 +1505,28 @@ func TestWorkerUpstreams(t *testing.T) { expWorkerUpstreams: []string{"127.0.0.1"}, expErr: false, }, + { + name: "ipv6 Upstream", + in: ` + worker { + name = "test" + initial_upstreams = ["[2001:4860:4860:0:0:0:0:8888]"] + } + `, + expWorkerUpstreams: []string{"[2001:4860:4860:0:0:0:0:8888]"}, + expErr: false, + }, + { + name: "abbreviated ipv6 Upstream", + in: ` + worker { + name = "test" + initial_upstreams = ["[2001:4860:4860::8888]"] + } + `, + expWorkerUpstreams: []string{"[2001:4860:4860::8888]"}, + expErr: false, + }, { name: "Multiple Upstreams", in: ` @@ -2346,7 +2368,7 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expPublicClusterAddress: ":9201", }, { - name: "setting public cluster address directly with ip", + name: "setting public cluster address directly with ipv4", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{}, @@ -2361,7 +2383,7 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expPublicClusterAddress: "127.0.0.1:9201", }, { - name: "setting public cluster address directly with ip:port", + name: "setting public cluster address directly with ipv4:port", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{}, @@ -2375,6 +2397,66 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expErrStr: "", expPublicClusterAddress: "127.0.0.1:8080", }, + { + name: "setting public cluster address directly with ipv6", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860:0:0:0:0:8888]", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860:0:0:0:0:8888]:9201", + }, + { + name: "setting public cluster address directly with ipv6:port", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860:0:0:0:0:8888]:8080", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860:0:0:0:0:8888]:8080", + }, + { + name: "setting public cluster address directly with abbreviated ipv6", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860::8888]", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860::8888]:9201", + }, + { + name: "setting public cluster address directly with abbreviated ipv6:port", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860::8888]:8080", + }, + }, + inputFlagValue: "", + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860::8888]:8080", + }, { name: "setting public cluster address to env var", inputConfig: &Config{ @@ -2530,7 +2612,7 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expPublicClusterAddress: "127.0.0.1:8080", }, { - name: "read address from listeners ip only", + name: "read address from listeners ipv4 only", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{ @@ -2544,7 +2626,7 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expPublicClusterAddress: "127.0.0.1:9201", }, { - name: "read address from listeners ip:port", + name: "read address from listeners ipv4:port", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{ @@ -2557,6 +2639,62 @@ func TestSetupControllerPublicClusterAddress(t *testing.T) { expErrStr: "", expPublicClusterAddress: "127.0.0.1:8080", }, + { + name: "read address from listeners ipv6 only", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + {Purpose: []string{"cluster"}, Address: "[2001:4860:4860:0:0:0:0:8888]"}, + }, + }, + Controller: &Controller{}, + }, + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860:0:0:0:0:8888]:9201", + }, + { + name: "read address from listeners ipv6:port", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + {Purpose: []string{"cluster"}, Address: "[2001:4860:4860:0:0:0:0:8888]:8080"}, + }, + }, + Controller: &Controller{}, + }, + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860:0:0:0:0:8888]:8080", + }, + { + name: "read address from listeners abbreviated ipv6 only", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + {Purpose: []string{"cluster"}, Address: "[2001:4860:4860::8888]"}, + }, + }, + Controller: &Controller{}, + }, + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860::8888]:9201", + }, + { + name: "read address from listeners abbreviated ipv6:port", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + {Purpose: []string{"cluster"}, Address: "[2001:4860:4860::8888]:8080"}, + }, + }, + Controller: &Controller{}, + }, + expErr: false, + expErrStr: "", + expPublicClusterAddress: "[2001:4860:4860::8888]:8080", + }, { name: "read address from listeners is ignored on different purpose", inputConfig: &Config{ @@ -2671,7 +2809,7 @@ func TestSetupWorkerInitialUpstreams(t *testing.T) { expInitialUpstreams: nil, }, { - name: "PublicClusterAddr", + name: "ipv4 PublicClusterAddr", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{}, @@ -2685,6 +2823,36 @@ func TestSetupWorkerInitialUpstreams(t *testing.T) { expErrStr: "", expInitialUpstreams: []string{"192.168.0.4:9201"}, }, + { + name: "ipv6 PublicClusterAddr", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860:0:0:0:0:8888]:9201", + }, + Worker: &Worker{}, + }, + expErr: false, + expErrStr: "", + expInitialUpstreams: []string{"[2001:4860:4860:0:0:0:0:8888]:9201"}, + }, + { + name: "abbreviated ipv6 PublicClusterAddr", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{}, + }, + Controller: &Controller{ + PublicClusterAddr: "[2001:4860:4860::8888]:9201", + }, + Worker: &Worker{}, + }, + expErr: false, + expErrStr: "", + expInitialUpstreams: []string{"[2001:4860:4860::8888]:9201"}, + }, { name: "ListenerNoAddr", inputConfig: &Config{ @@ -2703,7 +2871,7 @@ func TestSetupWorkerInitialUpstreams(t *testing.T) { expInitialUpstreams: []string{"127.0.0.1:9201"}, }, { - name: "ListenerAddr", + name: "ipv4 ListenerAddr", inputConfig: &Config{ SharedConfig: &configutil.SharedConfig{ Listeners: []*listenerutil.ListenerConfig{ @@ -2720,6 +2888,42 @@ func TestSetupWorkerInitialUpstreams(t *testing.T) { expErrStr: "", expInitialUpstreams: []string{"192.168.0.5:9201"}, }, + { + name: "ipv6 ListenerAddr", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + { + Purpose: []string{"cluster"}, + Address: "[2001:4860:4860:0:0:0:0:8888]:9201", + }, + }, + }, + Controller: &Controller{}, + Worker: &Worker{}, + }, + expErr: false, + expErrStr: "", + expInitialUpstreams: []string{"[2001:4860:4860:0:0:0:0:8888]:9201"}, + }, + { + name: "abbreviated ipv6 ListenerAddr", + inputConfig: &Config{ + SharedConfig: &configutil.SharedConfig{ + Listeners: []*listenerutil.ListenerConfig{ + { + Purpose: []string{"cluster"}, + Address: "[2001:4860:4860::8888]:9201", + }, + }, + }, + Controller: &Controller{}, + Worker: &Worker{}, + }, + expErr: false, + expErrStr: "", + expInitialUpstreams: []string{"[2001:4860:4860::8888]:9201"}, + }, { name: "ListenerAddrDomain", inputConfig: &Config{ diff --git a/internal/cmd/ops/server_test.go b/internal/cmd/ops/server_test.go index 42766b6829..65cbc03606 100644 --- a/internal/cmd/ops/server_test.go +++ b/internal/cmd/ops/server_test.go @@ -133,7 +133,7 @@ func TestNewServerIntegration(t *testing.T) { expErrMsg string }{ { - name: "one tcp ops listener", + name: "one tcp ops ipv4 listener", listeners: []*listenerutil.ListenerConfig{ { Type: "tcp", @@ -148,6 +148,22 @@ func TestNewServerIntegration(t *testing.T) { require.NoError(t, err) }, }, + { + name: "one tcp ops ipv6 listener", + listeners: []*listenerutil.ListenerConfig{ + { + Type: "tcp", + Purpose: []string{"ops"}, + Address: "[::1]:0", + TLSDisable: true, + }, + }, + assertions: func(t *testing.T, addrs []string) { + resp, err := http.Get("http://" + addrs[0]) + resp.Body.Close() + require.NoError(t, err) + }, + }, { name: "multiple tcp ops listeners", listeners: []*listenerutil.ListenerConfig{