From 8351e5cc793255bfc971b33ccd43f3012dad787c Mon Sep 17 00:00:00 2001 From: Daniel Kimsey Date: Thu, 19 Aug 2021 09:15:44 -0500 Subject: [PATCH 1/2] Auto-join support for IPv6 discovery The go-discover library returns IP addresses and not URLs. It just so happens net.URL parses "127.0.0.1", which isn't a valid URL. Instead, we construct the URL ourselves. Being careful to check if it's an ipv6 address and making sure it's in explicit form if so. Fixes #12323 --- changelog/12366.txt | 3 +++ vault/raft.go | 43 ++++++++++++++++--------------------------- 2 files changed, 19 insertions(+), 27 deletions(-) create mode 100644 changelog/12366.txt diff --git a/changelog/12366.txt b/changelog/12366.txt new file mode 100644 index 000000000000..e8c16d148d49 --- /dev/null +++ b/changelog/12366.txt @@ -0,0 +1,3 @@ +```release-note:bug +storage/raft: Support `addr_type=public_v6` in auto-join +``` diff --git a/vault/raft.go b/vault/raft.go index 8a0cd58dff41..016cc5168f7f 100644 --- a/vault/raft.go +++ b/vault/raft.go @@ -947,39 +947,28 @@ func (c *Core) JoinRaftCluster(ctx context.Context, leaderInfos []*raft.LeaderJo } case leaderInfo.AutoJoin != "": + // go-discover returns IPs addrs, err := disco.Addrs(leaderInfo.AutoJoin, c.logger.StandardLogger(nil)) if err != nil { c.logger.Error("failed to parse addresses from auto-join metadata", "error", err) } - + scheme := leaderInfo.AutoJoinScheme + if scheme == "" { + // default to HTTPS when no scheme is provided + scheme = "https" + } + port := leaderInfo.AutoJoinPort + if port == 0 { + // default to 8200 when no port is provided + port = 8200 + } for _, addr := range addrs { - u, err := url.Parse(addr) - if err != nil { - c.logger.Error("failed to parse discovered address", "error", err) - continue - } - - if u.Scheme == "" { - scheme := leaderInfo.AutoJoinScheme - if scheme == "" { - // default to HTTPS when no scheme is provided - scheme = "https" - } - - addr = fmt.Sprintf("%s://%s", scheme, addr) + if strings.Count(addr, ":") != 0 { + // ipv6, make it explicit + addr = fmt.Sprintf("[%s]", addr) } - - if u.Port() == "" { - port := leaderInfo.AutoJoinPort - if port == 0 { - // default to 8200 when no port is provided - port = 8200 - } - - addr = fmt.Sprintf("%s:%d", addr, port) - } - - if err := joinLeader(leaderInfo, addr); err != nil { + u := fmt.Sprintf("%s://%s:%d", scheme, addr, port) + if err := joinLeader(leaderInfo, u); err != nil { c.logger.Warn("join attempt failed", "error", err) } else { // successfully joined leader From 56822114be245581a79518f783ed3b9236e4caa5 Mon Sep 17 00:00:00 2001 From: Daniel Kimsey Date: Fri, 3 Sep 2021 13:34:50 -0500 Subject: [PATCH 2/2] feedback: addrs & ipv6 test Rename addrs to clusterIPs to improve clarity and intent Tighten up our IPv6 address detection to be more correct and to ensure it's actually in implicit form --- vault/raft.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/vault/raft.go b/vault/raft.go index 016cc5168f7f..8c5c6ed0c07b 100644 --- a/vault/raft.go +++ b/vault/raft.go @@ -947,11 +947,6 @@ func (c *Core) JoinRaftCluster(ctx context.Context, leaderInfos []*raft.LeaderJo } case leaderInfo.AutoJoin != "": - // go-discover returns IPs - addrs, err := disco.Addrs(leaderInfo.AutoJoin, c.logger.StandardLogger(nil)) - if err != nil { - c.logger.Error("failed to parse addresses from auto-join metadata", "error", err) - } scheme := leaderInfo.AutoJoinScheme if scheme == "" { // default to HTTPS when no scheme is provided @@ -962,12 +957,17 @@ func (c *Core) JoinRaftCluster(ctx context.Context, leaderInfos []*raft.LeaderJo // default to 8200 when no port is provided port = 8200 } - for _, addr := range addrs { - if strings.Count(addr, ":") != 0 { - // ipv6, make it explicit - addr = fmt.Sprintf("[%s]", addr) + // Addrs returns either IPv4 or IPv6 address sans scheme or port + clusterIPs, err := disco.Addrs(leaderInfo.AutoJoin, c.logger.StandardLogger(nil)) + if err != nil { + c.logger.Error("failed to parse addresses from auto-join metadata", "error", err) + } + for _, ip := range clusterIPs { + if strings.Count(ip, ":") >= 2 && !strings.HasPrefix(ip, "["){ + // An IPv6 address in implicit form, however we need it in explicit form to use in a URL. + ip = fmt.Sprintf("[%s]", ip) } - u := fmt.Sprintf("%s://%s:%d", scheme, addr, port) + u := fmt.Sprintf("%s://%s:%d", scheme, ip, port) if err := joinLeader(leaderInfo, u); err != nil { c.logger.Warn("join attempt failed", "error", err) } else {