From 7f057d7489b4dff16e1b4c3c7b33bc487bb92e8c Mon Sep 17 00:00:00 2001 From: License Updater Date: Mon, 17 Apr 2023 22:39:41 +0000 Subject: [PATCH 001/331] licenses: update tailscale{,d} licenses Signed-off-by: License Updater --- licenses/tailscale.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/licenses/tailscale.md b/licenses/tailscale.md index ce5e9c589166d..38a55a0b56083 100644 --- a/licenses/tailscale.md +++ b/licenses/tailscale.md @@ -53,8 +53,8 @@ Some packages may only be included on certain architectures or operating systems - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.15.4/zstd/internal/xxhash/LICENSE.txt)) - [github.com/kortschak/wol](https://pkg.go.dev/github.com/kortschak/wol) ([BSD-3-Clause](https://github.com/kortschak/wol/blob/da482cc4850a/LICENSE)) - [github.com/kr/fs](https://pkg.go.dev/github.com/kr/fs) ([BSD-3-Clause](https://github.com/kr/fs/blob/v0.1.0/LICENSE)) - - [github.com/mattn/go-colorable](https://pkg.go.dev/github.com/mattn/go-colorable) ([MIT](https://github.com/mattn/go-colorable/blob/v0.1.12/LICENSE)) - - [github.com/mattn/go-isatty](https://pkg.go.dev/github.com/mattn/go-isatty) ([MIT](https://github.com/mattn/go-isatty/blob/v0.0.14/LICENSE)) + - [github.com/mattn/go-colorable](https://pkg.go.dev/github.com/mattn/go-colorable) ([MIT](https://github.com/mattn/go-colorable/blob/v0.1.13/LICENSE)) + - [github.com/mattn/go-isatty](https://pkg.go.dev/github.com/mattn/go-isatty) ([MIT](https://github.com/mattn/go-isatty/blob/v0.0.17/LICENSE)) - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.2.0/LICENSE.md)) - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.1/LICENSE.md)) - [github.com/mdlayher/sdnotify](https://pkg.go.dev/github.com/mdlayher/sdnotify) ([MIT](https://github.com/mdlayher/sdnotify/blob/v1.0.0/LICENSE.md)) @@ -79,11 +79,11 @@ Some packages may only be included on certain architectures or operating systems - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47842c84:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.7.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/a3b23cc7:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.5.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.7.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) - [golang.zx2c4.com/wireguard/windows/tunnel/winipcfg](https://pkg.go.dev/golang.zx2c4.com/wireguard/windows/tunnel/winipcfg) ([MIT](https://git.zx2c4.com/wireguard-windows/tree/COPYING?h=v0.5.3)) From 7c386ca6d27fc76f8e9608b19067c5d32e068ad5 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Wed, 19 Apr 2023 12:56:52 -0700 Subject: [PATCH 002/331] net/sockstats: fix calculation of radio power usage When splitting the radio monitor usage array, we were splitting at now % 3600 to get values into chronological order. This caused the value for the final second to be included at the beginning of the ordered slice rather than the end. If there was activity during that final second, an extra five seconds of high power usage would get recorded in some cases. This could result in a final calculation of greater than 100% usage. This corrects that by splitting values at (now+1 % 3600). This also simplifies the percentage calculation by always rounding values down, which is sufficient for our usage. Signed-off-by: Will Norris --- net/sockstats/sockstats_tsgo.go | 14 +++++++++----- net/sockstats/sockstats_tsgo_test.go | 12 ++++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/net/sockstats/sockstats_tsgo.go b/net/sockstats/sockstats_tsgo.go index c243b816183bb..80ff7084af3bb 100644 --- a/net/sockstats/sockstats_tsgo.go +++ b/net/sockstats/sockstats_tsgo.go @@ -8,7 +8,6 @@ package sockstats import ( "context" "fmt" - "math" "net" "strings" "sync" @@ -347,10 +346,12 @@ func (rm *radioMonitor) radioHighPercent() int64 { } periodStart := now - periodLength // start of current reporting period - // slices of radio usage, with values in chronological order + // split into slices of radio usage, with values in chronological order. + // split at now+1 so that the current second is in the second slice. + split := (now + 1) % radioSampleSize slices := [2][]int64{ - rm.usage[now%radioSampleSize:], - rm.usage[:now%radioSampleSize], + rm.usage[split:], + rm.usage[:split], } var highPowerSec int64 // total seconds radio was in high power (active or idle) var c int // counter @@ -369,5 +370,8 @@ func (rm *radioMonitor) radioHighPercent() int64 { } } - return int64(math.Round(float64(highPowerSec) / float64(periodLength) * 100)) + if highPowerSec == 0 { + return 0 + } + return highPowerSec * 100 / periodLength } diff --git a/net/sockstats/sockstats_tsgo_test.go b/net/sockstats/sockstats_tsgo_test.go index 5f4c04d921a3a..f85ab9fca7f74 100644 --- a/net/sockstats/sockstats_tsgo_test.go +++ b/net/sockstats/sockstats_tsgo_test.go @@ -39,7 +39,7 @@ func TestRadioMonitor(t *testing.T) { rm.active() tt.Add(10 * time.Second) }, - 50, // radio on 5 seconds of every 10 seconds + 50, // radio on 5 seconds of 10 seconds }, { "400 iterations: 2 sec active, 1 min idle", @@ -49,11 +49,19 @@ func TestRadioMonitor(t *testing.T) { rm.active() tt.Add(1 * time.Second) rm.active() - tt.Add(1 * time.Minute) + tt.Add(59 * time.Second) } }, 10, // radio on 6 seconds of every minute }, + { + "activity at end of time window", + func(tt *testTime, rm *radioMonitor) { + tt.Add(2 * time.Second) + rm.active() + }, + 50, + }, } for _, tt := range tests { From d0906cda97b116c33f191af4fcb81ac88ab7c7b6 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Wed, 19 Apr 2023 13:45:02 -0700 Subject: [PATCH 003/331] net/sockstats: expose debug info Exposes some internal state of the sockstats package via the C2N and PeerAPI endpoints, so that it can be used for debugging. For now this includes the estimated radio on percentage and a second-by-second view of the times the radio was active. Also fixes another off-by-one error in the radio on percentage that was leading to >100% values (if n seconds have passed since we started to monitor, there may be n + 1 possible seconds where the radio could have been on). Updates tailscale/corp#9230 Signed-off-by: Mihai Parparita --- ipn/ipnlocal/c2n.go | 4 +- ipn/ipnlocal/peerapi.go | 6 +++ net/sockstats/sockstats.go | 6 +++ net/sockstats/sockstats_noop.go | 4 ++ net/sockstats/sockstats_tsgo.go | 76 +++++++++++++++++++++------- net/sockstats/sockstats_tsgo_test.go | 13 ++++- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/ipn/ipnlocal/c2n.go b/ipn/ipnlocal/c2n.go index 68c1e7e72767f..54428d38e5ed5 100644 --- a/ipn/ipnlocal/c2n.go +++ b/ipn/ipnlocal/c2n.go @@ -17,6 +17,7 @@ import ( "time" "tailscale.com/envknob" + "tailscale.com/net/sockstats" "tailscale.com/tailcfg" "tailscale.com/util/clientmetric" "tailscale.com/util/goroutines" @@ -94,7 +95,8 @@ func (b *LocalBackend) handleC2N(w http.ResponseWriter, r *http.Request) { return } b.sockstatLogger.Flush() - fmt.Fprintln(w, b.sockstatLogger.LogID()) + fmt.Fprintf(w, "logid: %s\n", b.sockstatLogger.LogID()) + fmt.Fprintf(w, "debug info: %v\n", sockstats.DebugInfo()) default: http.Error(w, "unknown c2n path", http.StatusBadRequest) } diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index fcacad0c9638b..d28206418b955 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -947,6 +947,12 @@ func (h *peerAPIHandler) handleServeSockStats(w http.ResponseWriter, r *http.Req fmt.Fprintln(w, "") fmt.Fprintln(w, "") + + fmt.Fprintln(w, "

Debug Info

") + + fmt.Fprintln(w, "
")
+	fmt.Fprintln(w, html.EscapeString(sockstats.DebugInfo()))
+	fmt.Fprintln(w, "
") } type incomingFile struct { diff --git a/net/sockstats/sockstats.go b/net/sockstats/sockstats.go index 97aa0236ce9e3..468fa70058f22 100644 --- a/net/sockstats/sockstats.go +++ b/net/sockstats/sockstats.go @@ -119,3 +119,9 @@ type LinkMonitor interface { func SetLinkMonitor(lm LinkMonitor) { setLinkMonitor(lm) } + +// DebugInfo returns a string containing debug information about the tracked +// statistics. +func DebugInfo() string { + return debugInfo() +} diff --git a/net/sockstats/sockstats_noop.go b/net/sockstats/sockstats_noop.go index c988249b85be3..96fd0da9b0cc7 100644 --- a/net/sockstats/sockstats_noop.go +++ b/net/sockstats/sockstats_noop.go @@ -31,3 +31,7 @@ func getValidation() *ValidationSockStats { func setLinkMonitor(lm LinkMonitor) { } + +func debugInfo() string { + return "" +} diff --git a/net/sockstats/sockstats_tsgo.go b/net/sockstats/sockstats_tsgo.go index 80ff7084af3bb..de162e7e7ea99 100644 --- a/net/sockstats/sockstats_tsgo.go +++ b/net/sockstats/sockstats_tsgo.go @@ -288,6 +288,19 @@ func setLinkMonitor(lm LinkMonitor) { }) } +func debugInfo() string { + var b strings.Builder + fmt.Fprintf(&b, "radio high percent: %d\n", radio.radioHighPercent()) + fmt.Fprintf(&b, "radio activity for the last hour (one minute per line):\n") + for i, a := range radio.radioActive() { + fmt.Fprintf(&b, "%d", a) + if i%60 == 59 { + fmt.Fprintf(&b, "\n") + } + } + return b.String() +} + func isLikelyCellularInterface(ifName string) bool { return strings.HasPrefix(ifName, "rmnet") || // Android strings.HasPrefix(ifName, "ww") || // systemd naming scheme for WWAN @@ -331,18 +344,56 @@ const ( radioLowIdle = 12 // seconds radio idles in low power state before transitioning to off ) +// radioActive returns a slice of 1s samples (one per second) for the past hour +// indicating whether the radio was active (1) or idle (0). +func (rm *radioMonitor) radioActive() (active [radioSampleSize]int64) { + rm.forEachSample(func(c int, isActive bool) { + if isActive { + active[c] = 1 + } + }) + return +} + // radioHighPercent returns the percentage of time (as an int from 0 to 100) // that the cellular radio was in high power mode during the past hour. // If the radio has been monitored for less than an hour, // the percentage is calculated based on the time monitored. func (rm *radioMonitor) radioHighPercent() int64 { + var highPowerSec int64 // total seconds radio was in high power (active or idle) + lastActive := -1 // counter when radio was last active + + periodLength := rm.forEachSample(func(c int, isActive bool) { + if isActive { + // radio on and active + highPowerSec++ + lastActive = c + } else if lastActive != -1 && c-lastActive < radioHighIdle { + // radio on but idle + highPowerSec++ + } + }) + + if periodLength == 0 { + return 0 + } + + if highPowerSec == 0 { + return 0 + } + return highPowerSec * 100 / periodLength +} + +// forEachSample calls f for each sample in the past hour (or less if less time +// has passed -- the evaluated period is returned) +func (rm *radioMonitor) forEachSample(f func(c int, isActive bool)) (periodLength int64) { now := rm.now().Unix() - var periodLength int64 = radioSampleSize + periodLength = radioSampleSize if t := now - rm.startTime; t < periodLength { if t <= 0 { return 0 } - periodLength = t + periodLength = t + 1 // we want an inclusive range (with the current second) } periodStart := now - periodLength // start of current reporting period @@ -353,25 +404,14 @@ func (rm *radioMonitor) radioHighPercent() int64 { rm.usage[split:], rm.usage[:split], } - var highPowerSec int64 // total seconds radio was in high power (active or idle) - var c int // counter - var lastActive int // counter when radio was last active + + var c int // counter for _, slice := range slices { for _, v := range slice { - c++ // increment first so we don't have zero values - if v >= periodStart { - // radio on and active - highPowerSec++ - lastActive = c - } else if lastActive > 0 && c-lastActive < radioHighIdle { - // radio on but idle - highPowerSec++ - } + f(c, v >= periodStart) + c++ } } - if highPowerSec == 0 { - return 0 - } - return highPowerSec * 100 / periodLength + return periodLength } diff --git a/net/sockstats/sockstats_tsgo_test.go b/net/sockstats/sockstats_tsgo_test.go index f85ab9fca7f74..9e3a5a86af826 100644 --- a/net/sockstats/sockstats_tsgo_test.go +++ b/net/sockstats/sockstats_tsgo_test.go @@ -37,10 +37,19 @@ func TestRadioMonitor(t *testing.T) { "active, 10 sec idle", func(tt *testTime, rm *radioMonitor) { rm.active() - tt.Add(10 * time.Second) + tt.Add(9 * time.Second) }, 50, // radio on 5 seconds of 10 seconds }, + { + "active, spanning two seconds", + func(tt *testTime, rm *radioMonitor) { + rm.active() + tt.Add(1100 * time.Millisecond) + rm.active() + }, + 100, // radio on for 2 seconds + }, { "400 iterations: 2 sec active, 1 min idle", func(tt *testTime, rm *radioMonitor) { @@ -57,7 +66,7 @@ func TestRadioMonitor(t *testing.T) { { "activity at end of time window", func(tt *testTime, rm *radioMonitor) { - tt.Add(2 * time.Second) + tt.Add(1 * time.Second) rm.active() }, 50, From 85de5804557dc8d2e7a9a83adbb44ca498e74b45 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Wed, 19 Apr 2023 15:20:43 -0700 Subject: [PATCH 004/331] net/tsdial: do not use proxies when dialing out to PeerAPI Found this when adding a test that does a ping over PeerAPI. Our integration tests set up a trafficTrap to ensure that tailscaled does not call out to the internet, and it does so via a HTTP_PROXY. When adding a test for pings over PeerAPI, it triggered the trap and investigation lead to the realization that we were not removing the Proxy when trying to dial out to the PeerAPI. Updates tailscale/corp#8020 Signed-off-by: Maisem Ali --- net/tsdial/tsdial.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index 225033271742f..3c3db009ca4ee 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -367,6 +367,8 @@ func (d *Dialer) PeerAPIHTTPClient() *http.Client { t := http.DefaultTransport.(*http.Transport).Clone() t.Dial = nil t.DialContext = d.dialPeerAPI + // Do not use the environment proxy for PeerAPI. + t.Proxy = nil d.peerClient = &http.Client{Transport: t} }) return d.peerClient From c3ef6fb4ee2a8d423d85e3e0b2abcada9319e2c9 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Wed, 19 Apr 2023 15:23:26 -0700 Subject: [PATCH 005/331] ipn/ipnlocal: handle masquerade addresses in PeerAPI Without this, the peer fails to do anything over the PeerAPI if it has a masquerade address. ``` Apr 19 13:58:15 hydrogen tailscaled[6696]: peerapi: invalid request from :58334: 100.64.0.1/32 not found in self addresses ``` Updates #8020 Signed-off-by: Maisem Ali --- ipn/ipnlocal/peerapi.go | 15 ++++++++++++--- tstest/integration/integration_test.go | 8 ++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index d28206418b955..fa749d995f53b 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -605,6 +605,16 @@ func (h *peerAPIHandler) logf(format string, a ...any) { h.ps.b.logf("peerapi: "+format, a...) } +// isAddressValid reports whether addr is a valid destination address for this +// node originating from the peer. +func (h *peerAPIHandler) isAddressValid(addr netip.Addr) bool { + if h.peerNode.SelfNodeV4MasqAddrForThisPeer != nil { + return *h.peerNode.SelfNodeV4MasqAddrForThisPeer == addr + } + pfx := netip.PrefixFrom(addr, addr.BitLen()) + return slices.Contains(h.selfNode.Addresses, pfx) +} + func (h *peerAPIHandler) validateHost(r *http.Request) error { if r.Host == "peer" { return nil @@ -613,9 +623,8 @@ func (h *peerAPIHandler) validateHost(r *http.Request) error { if err != nil { return err } - hostIPPfx := netip.PrefixFrom(ap.Addr(), ap.Addr().BitLen()) - if !slices.Contains(h.selfNode.Addresses, hostIPPfx) { - return fmt.Errorf("%v not found in self addresses", hostIPPfx) + if !h.isAddressValid(ap.Addr()) { + return fmt.Errorf("%v not found in self addresses", ap.Addr()) } return nil } diff --git a/tstest/integration/integration_test.go b/tstest/integration/integration_test.go index e790d045462a6..486b894921acd 100644 --- a/tstest/integration/integration_test.go +++ b/tstest/integration/integration_test.go @@ -601,9 +601,17 @@ func TestNATPing(t *testing.T) { t.Fatal(err) } + if err := n1.Tailscale("ping", "-peerapi", tc.n1SeesN2IP.String()).Run(); err != nil { + t.Fatal(err) + } + if err := n2.Tailscale("ping", tc.n2SeesN1IP.String()).Run(); err != nil { t.Fatal(err) } + + if err := n2.Tailscale("ping", "-peerapi", tc.n2SeesN1IP.String()).Run(); err != nil { + t.Fatal(err) + } }) } } From 588a234fdc829e9eef1449d49c3067a7194523f6 Mon Sep 17 00:00:00 2001 From: License Updater Date: Wed, 19 Apr 2023 23:32:04 +0000 Subject: [PATCH 006/331] licenses: update win/apple licenses Signed-off-by: License Updater --- licenses/apple.md | 8 ++++---- licenses/windows.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/licenses/apple.md b/licenses/apple.md index 44d983a8ee209..93585566c87a0 100644 --- a/licenses/apple.md +++ b/licenses/apple.md @@ -59,11 +59,11 @@ and [iOS][]. See also the dependencies in the [Tailscale CLI][]. - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.7.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/a3b23cc7:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.5.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.7.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) diff --git a/licenses/windows.md b/licenses/windows.md index e8a156c05b03b..709af28d63e5b 100644 --- a/licenses/windows.md +++ b/licenses/windows.md @@ -41,12 +41,12 @@ Windows][]. See also the dependencies in the [Tailscale CLI][]. - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) - [golang.org/x/image/bmp](https://pkg.go.dev/golang.org/x/image/bmp) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.5.0:LICENSE)) - - [golang.org/x/mod](https://pkg.go.dev/golang.org/x/mod) ([BSD-3-Clause](https://cs.opensource.google/go/x/mod/+/v0.7.0:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.7.0:LICENSE)) + - [golang.org/x/mod](https://pkg.go.dev/golang.org/x/mod) ([BSD-3-Clause](https://cs.opensource.google/go/x/mod/+/v0.9.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/a3b23cc7:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.5.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.7.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) - [golang.zx2c4.com/wireguard/windows/tunnel/winipcfg](https://pkg.go.dev/golang.zx2c4.com/wireguard/windows/tunnel/winipcfg) ([MIT](https://git.zx2c4.com/wireguard-windows/tree/COPYING?h=v0.5.3)) - [gopkg.in/Knetic/govaluate.v3](https://pkg.go.dev/gopkg.in/Knetic/govaluate.v3) ([MIT](https://github.com/Knetic/govaluate/blob/v3.0.0/LICENSE)) From c32877018493215a797b0ca881e83600ace61d4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 11:57:16 +0000 Subject: [PATCH 007/331] .github: Bump peter-evans/create-pull-request from 4.2.4 to 5.0.0 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.4 to 5.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/38e0b6e68b4c852a5500a94740f0e535e0d7ba54...5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/go-licenses.yml | 2 +- .github/workflows/update-flake.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-licenses.yml b/.github/workflows/go-licenses.yml index bbad04c9526f6..c1bd05ec1dd8e 100644 --- a/.github/workflows/go-licenses.yml +++ b/.github/workflows/go-licenses.yml @@ -50,7 +50,7 @@ jobs: private_key: ${{ secrets.LICENSING_APP_PRIVATE_KEY }} - name: Send pull request - uses: peter-evans/create-pull-request@38e0b6e68b4c852a5500a94740f0e535e0d7ba54 #v4.2.4 + uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 #v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} author: License Updater diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 438a3d7354797..6d6dee2b72772 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -35,7 +35,7 @@ jobs: private_key: ${{ secrets.LICENSING_APP_PRIVATE_KEY }} - name: Send pull request - uses: peter-evans/create-pull-request@38e0b6e68b4c852a5500a94740f0e535e0d7ba54 #v4.2.4 + uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 #v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} author: Flakes Updater From 5acc7c4b1e2aaa493b2532f28dde107a0b616424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 11:58:08 +0000 Subject: [PATCH 008/331] .github: Bump ruby/action-slack from 3.0.0 to 3.2.1 Bumps [ruby/action-slack](https://github.com/ruby/action-slack) from 3.0.0 to 3.2.1. - [Release notes](https://github.com/ruby/action-slack/releases) - [Commits](https://github.com/ruby/action-slack/compare/v3.0.0...v3.2.1) --- updated-dependencies: - dependency-name: ruby/action-slack dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1c38142bc45d5..6f0a9bb641675 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -450,7 +450,7 @@ jobs: # By having the job always run, but skipping its only step as needed, we # let the CI output collapse nicely in PRs. if: failure() && github.event_name == 'push' - uses: ruby/action-slack@v3.0.0 + uses: ruby/action-slack@v3.2.1 with: payload: | { From f85dc6f97c3c8cd7ee975153052757d5037911c5 Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Wed, 19 Apr 2023 21:54:19 -0400 Subject: [PATCH 009/331] ci: add more lints (#7909) This is a follow-up to #7905 that adds two more linters and fixes the corresponding findings. As per the previous PR, this only flags things that are "obviously" wrong, and fixes the issues found. Signed-off-by: Andrew Dunham Change-Id: I8739bdb7bc4f75666a7385a7a26d56ec13741b7c --- .golangci.yml | 28 ++++++++++++++++++ cmd/k8s-operator/operator_test.go | 5 ++-- cmd/tailscale/cli/netcheck.go | 1 - hostinfo/hostinfo.go | 2 +- ipn/ipnlocal/expiry_test.go | 4 +-- ipn/ipnlocal/local.go | 2 +- ipn/ipnlocal/serve.go | 13 ++++----- net/dns/resolver/tsdns_test.go | 47 +++++++++++++++---------------- wgengine/magicsock/magicsock.go | 1 - 9 files changed, 63 insertions(+), 40 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d752fd3ee7738..1c88a7110d897 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,9 +3,11 @@ linters: # enable in the list below. disable-all: true enable: + - bidichk - gofmt - goimports - misspell + - revive # Configuration for how we run golangci-lint run: @@ -23,6 +25,9 @@ issues: # Per-linter settings are contained in this top-level key linters-settings: + # Enable all rules by default; we don't use invisible unicode runes. + bidichk: + gofmt: rewrite-rules: - pattern: 'interface{}' @@ -31,3 +36,26 @@ linters-settings: goimports: misspell: + + revive: + enable-all-rules: false + ignore-generated-header: true + rules: + - name: atomic + - name: context-keys-type + - name: defer + arguments: [[ + # Calling 'recover' at the time a defer is registered (i.e. "defer recover()") has no effect. + "immediate-recover", + # Calling 'recover' outside of a deferred function has no effect + "recover", + # Returning values from a deferred function has no effect + "return", + ]] + - name: duplicated-imports + - name: errorf + - name: string-of-int + - name: time-equal + - name: unconditional-recursion + - name: useless-break + - name: waitgroup-by-value diff --git a/cmd/k8s-operator/operator_test.go b/cmd/k8s-operator/operator_test.go index b3206e0dc8d4f..25167961c83e3 100644 --- a/cmd/k8s-operator/operator_test.go +++ b/cmd/k8s-operator/operator_test.go @@ -14,7 +14,6 @@ import ( "go.uber.org/zap" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -670,11 +669,11 @@ func expectedSTS(stsName, secretName, hostname string) *appsv1.StatefulSet { }, }, }, - Containers: []v1.Container{ + Containers: []corev1.Container{ { Name: "tailscale", Image: "tailscale/tailscale", - Env: []v1.EnvVar{ + Env: []corev1.EnvVar{ {Name: "TS_USERSPACE", Value: "false"}, {Name: "TS_AUTH_ONCE", Value: "true"}, {Name: "TS_DEST_IP", Value: "10.20.30.40"}, diff --git a/cmd/tailscale/cli/netcheck.go b/cmd/tailscale/cli/netcheck.go index a1f79b1fe317f..0c2f7acd1d0cc 100644 --- a/cmd/tailscale/cli/netcheck.go +++ b/cmd/tailscale/cli/netcheck.go @@ -97,7 +97,6 @@ func printReport(dm *tailcfg.DERPMap, report *netcheck.Report) error { var err error switch netcheckArgs.format { case "": - break case "json": j, err = json.MarshalIndent(report, "", "\t") case "json-line": diff --git a/hostinfo/hostinfo.go b/hostinfo/hostinfo.go index 7994c90fdcef1..9ca8418ef05c6 100644 --- a/hostinfo/hostinfo.go +++ b/hostinfo/hostinfo.go @@ -405,7 +405,7 @@ func DisabledEtcAptSource() bool { return false } mod := fi.ModTime() - if c, ok := etcAptSrcCache.Load().(etcAptSrcResult); ok && c.mod == mod { + if c, ok := etcAptSrcCache.Load().(etcAptSrcResult); ok && c.mod.Equal(mod) { return c.disabled } f, err := os.Open(path) diff --git a/ipn/ipnlocal/expiry_test.go b/ipn/ipnlocal/expiry_test.go index c39bc62bbea43..32ef44ab207f4 100644 --- a/ipn/ipnlocal/expiry_test.go +++ b/ipn/ipnlocal/expiry_test.go @@ -243,7 +243,7 @@ func TestNextPeerExpiry(t *testing.T) { em := newExpiryManager(t.Logf) em.timeNow = func() time.Time { return now } got := em.nextPeerExpiry(tt.netmap, now) - if got != tt.want { + if !got.Equal(tt.want) { t.Errorf("got %q, want %q", got.Format(time.RFC3339), tt.want.Format(time.RFC3339)) } else if !got.IsZero() && got.Before(now) { t.Errorf("unexpectedly got expiry %q before now %q", got.Format(time.RFC3339), now.Format(time.RFC3339)) @@ -269,7 +269,7 @@ func TestNextPeerExpiry(t *testing.T) { } got := em.nextPeerExpiry(nm, now) want := now.Add(30 * time.Second) - if got != want { + if !got.Equal(want) { t.Errorf("got %q, want %q", got.Format(time.RFC3339), want.Format(time.RFC3339)) } }) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index ddb95d481df78..07decb04dd555 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -438,7 +438,7 @@ func (b *LocalBackend) SetComponentDebugLogging(component string, until time.Tim // unchanged when the timer actually fires. b.mu.Lock() defer b.mu.Unlock() - if ls := b.componentLogUntil[component]; ls.until == until { + if ls := b.componentLogUntil[component]; ls.until.Equal(until) { setEnabled(false) b.logf("debugging logging for component %q disabled (by timer)", component) } diff --git a/ipn/ipnlocal/serve.go b/ipn/ipnlocal/serve.go index 7b49db5ee7915..a9058dec20990 100644 --- a/ipn/ipnlocal/serve.go +++ b/ipn/ipnlocal/serve.go @@ -17,7 +17,6 @@ import ( "net/url" "os" "path" - pathpkg "path" "strconv" "strings" "sync" @@ -420,19 +419,19 @@ func (b *LocalBackend) getServeHandler(r *http.Request) (_ ipn.HTTPHandlerView, if h, ok := wsc.Handlers().GetOk(r.URL.Path); ok { return h, r.URL.Path, true } - path := path.Clean(r.URL.Path) + pth := path.Clean(r.URL.Path) for { - withSlash := path + "/" + withSlash := pth + "/" if h, ok := wsc.Handlers().GetOk(withSlash); ok { return h, withSlash, true } - if h, ok := wsc.Handlers().GetOk(path); ok { - return h, path, true + if h, ok := wsc.Handlers().GetOk(pth); ok { + return h, pth, true } - if path == "/" { + if pth == "/" { return z, "", false } - path = pathpkg.Dir(path) + pth = path.Dir(pth) } } diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index 3980cfa335c07..9862da8fb2431 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -22,7 +22,6 @@ import ( "time" miekdns "github.com/miekg/dns" - "golang.org/x/net/dns/dnsmessage" dns "golang.org/x/net/dns/dnsmessage" "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" @@ -1121,15 +1120,15 @@ func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) { t.Run("no_such_host", func(t *testing.T) { res, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), t.Logf, backResolver, &response{ - Header: dnsmessage.Header{ + Header: dns.Header{ ID: 123, Response: true, OpCode: 0, // query }, - Question: dnsmessage.Question{ - Name: dnsmessage.MustNewName("nx-domain.test."), - Type: dnsmessage.TypeA, - Class: dnsmessage.ClassINET, + Question: dns.Question{ + Name: dns.MustNewName("nx-domain.test."), + Type: dns.TypeA, + Class: dns.ClassINET, }, }) if err != nil { @@ -1156,74 +1155,74 @@ func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) { } tests := []struct { - Type dnsmessage.Type + Type dns.Type Name string Check func(t testing.TB, got []byte) }{ { - Type: dnsmessage.TypeA, + Type: dns.TypeA, Name: "one-a.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05one-a\x04test\x00\x00\x01\x00\x01\x05one-a\x04test\x00\x00\x01\x00\x01\x00\x00\x02X\x00\x04\x01\x02\x03\x04"), }, { - Type: dnsmessage.TypeA, + Type: dns.TypeA, Name: "two-a.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x02\x00\x00\x00\x00\x05two-a\x04test\x00\x00\x01\x00\x01\xc0\f\x00\x01\x00\x01\x00\x00\x02X\x00\x04\x01\x02\x03\x04\xc0\f\x00\x01\x00\x01\x00\x00\x02X\x00\x04\x05\x06\a\b"), }, { - Type: dnsmessage.TypeAAAA, + Type: dns.TypeAAAA, Name: "one-aaaa.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\bone-aaaa\x04test\x00\x00\x1c\x00\x01\bone-aaaa\x04test\x00\x00\x1c\x00\x01\x00\x00\x02X\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"), }, { - Type: dnsmessage.TypeAAAA, + Type: dns.TypeAAAA, Name: "two-aaaa.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x02\x00\x00\x00\x00\btwo-aaaa\x04test\x00\x00\x1c\x00\x01\xc0\f\x00\x1c\x00\x01\x00\x00\x02X\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc0\f\x00\x1c\x00\x01\x00\x00\x02X\x00\x10\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"), }, { - Type: dnsmessage.TypePTR, + Type: dns.TypePTR, Name: "4.3.2.1.in-addr.arpa.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x014\x013\x012\x011\ain-addr\x04arpa\x00\x00\f\x00\x01\x014\x013\x012\x011\ain-addr\x04arpa\x00\x00\f\x00\x01\x00\x00\x02X\x00\t\x03foo\x03com\x00"), }, { - Type: dnsmessage.TypeCNAME, + Type: dns.TypeCNAME, Name: "cname.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05cname\x04test\x00\x00\x05\x00\x01\x05cname\x04test\x00\x00\x05\x00\x01\x00\x00\x02X\x00\x10\nthe-target\x03foo\x00"), }, // No records of various types { - Type: dnsmessage.TypeA, + Type: dns.TypeA, Name: "no-records.test.", Check: matchPacked("\x00{\x84\x03\x00\x01\x00\x00\x00\x00\x00\x00\nno-records\x04test\x00\x00\x01\x00\x01"), }, { - Type: dnsmessage.TypeAAAA, + Type: dns.TypeAAAA, Name: "no-records.test.", Check: matchPacked("\x00{\x84\x03\x00\x01\x00\x00\x00\x00\x00\x00\nno-records\x04test\x00\x00\x1c\x00\x01"), }, { - Type: dnsmessage.TypeCNAME, + Type: dns.TypeCNAME, Name: "no-records.test.", Check: matchPacked("\x00{\x84\x03\x00\x01\x00\x00\x00\x00\x00\x00\nno-records\x04test\x00\x00\x05\x00\x01"), }, { - Type: dnsmessage.TypeSRV, + Type: dns.TypeSRV, Name: "no-records.test.", Check: matchPacked("\x00{\x84\x03\x00\x01\x00\x00\x00\x00\x00\x00\nno-records\x04test\x00\x00!\x00\x01"), }, { - Type: dnsmessage.TypeTXT, + Type: dns.TypeTXT, Name: "txt.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x03\x00\x00\x00\x00\x03txt\x04test\x00\x00\x10\x00\x01\x03txt\x04test\x00\x00\x10\x00\x01\x00\x00\x02X\x00\t\btxt1=one\x03txt\x04test\x00\x00\x10\x00\x01\x00\x00\x02X\x00\t\btxt2=two\x03txt\x04test\x00\x00\x10\x00\x01\x00\x00\x02X\x00\v\ntxt3=three"), }, { - Type: dnsmessage.TypeSRV, + Type: dns.TypeSRV, Name: "srv.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x02\x00\x00\x00\x00\x03srv\x04test\x00\x00!\x00\x01\x03srv\x04test\x00\x00!\x00\x01\x00\x00\x02X\x00\x0f\x00\x01\x00\x02\x00\x03\x03foo\x03com\x00\x03srv\x04test\x00\x00!\x00\x01\x00\x00\x02X\x00\x0f\x00\x04\x00\x05\x00\x06\x03bar\x03com\x00"), }, { - Type: dnsmessage.TypeNS, + Type: dns.TypeNS, Name: "ns.test.", Check: matchPacked("\x00{\x84\x00\x00\x01\x00\x02\x00\x00\x00\x00\x02ns\x04test\x00\x00\x02\x00\x01\x02ns\x04test\x00\x00\x02\x00\x01\x00\x00\x02X\x00\t\x03ns1\x03foo\x00\x02ns\x04test\x00\x00\x02\x00\x01\x00\x00\x02X\x00\t\x03ns2\x03bar\x00"), }, @@ -1232,15 +1231,15 @@ func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) { for _, tt := range tests { t.Run(fmt.Sprintf("%v_%v", tt.Type, strings.Trim(tt.Name, ".")), func(t *testing.T) { got, err := handleExitNodeDNSQueryWithNetPkg(context.Background(), t.Logf, backResolver, &response{ - Header: dnsmessage.Header{ + Header: dns.Header{ ID: 123, Response: true, OpCode: 0, // query }, - Question: dnsmessage.Question{ - Name: dnsmessage.MustNewName(tt.Name), + Question: dns.Question{ + Name: dns.MustNewName(tt.Name), Type: tt.Type, - Class: dnsmessage.ClassINET, + Class: dns.ClassINET, }, }) if err != nil { diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index f315e88b630a8..d8595e2bad536 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3160,7 +3160,6 @@ func (c *Conn) goroutinesRunningLocked() bool { if c.activeDerp != nil { select { case <-c.derpStarted: - break default: return true } From cd35a79136b8d8d3f452e93a6e3eb1a77ac78a53 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Fri, 14 Apr 2023 17:01:29 -0700 Subject: [PATCH 010/331] syncs: relax TestWatchMultipleValues timing on Windows The test is re-enabled for Windows with a relaxed time assertion. On Windows the runtime poller currently does not have sufficient resolution to meet the normal requirements for this test. See https://github.com/golang/go/issues/44343 for background. Updates #7876 Signed-off-by: James Tucker --- syncs/watchdog_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/syncs/watchdog_test.go b/syncs/watchdog_test.go index 4a45a4faa7cd5..e85e6cd754497 100644 --- a/syncs/watchdog_test.go +++ b/syncs/watchdog_test.go @@ -46,9 +46,6 @@ func TestWatchContended(t *testing.T) { } func TestWatchMultipleValues(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } mu := new(sync.Mutex) ctx, cancel := context.WithCancel(context.Background()) defer cancel() // not necessary, but keep vet happy @@ -68,7 +65,13 @@ func TestWatchMultipleValues(t *testing.T) { cancel() } } - if elapsed := time.Since(start); elapsed > 100*time.Millisecond { + // See https://github.com/golang/go/issues/44343 - on Windows the Go runtime timer resolution is currently too coarse. Allow longer in that case. + want := 100 * time.Millisecond + if runtime.GOOS == "windows" { + want = 500 * time.Millisecond + } + + if elapsed := time.Since(start); elapsed > want { t.Errorf("expected 1 event per millisecond, got only %v events in %v", n, elapsed) } } From f844791e151d1db73277727fffb1c9ab062471bd Mon Sep 17 00:00:00 2001 From: James Tucker Date: Fri, 14 Apr 2023 16:52:44 -0700 Subject: [PATCH 011/331] safesocket: enable test to run on Windows unpriviliged I manually tested that the code path that relaxes pipe permissions is not executed when run with elevated priviliges, and the test also passes in that case. Updates #7876 Signed-off-by: James Tucker --- safesocket/basic_test.go | 7 ++++--- safesocket/pipe_windows.go | 3 ++- safesocket/pipe_windows_test.go | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 safesocket/pipe_windows_test.go diff --git a/safesocket/basic_test.go b/safesocket/basic_test.go index e19bcb9ef68bd..ebb5f2f3aaa25 100644 --- a/safesocket/basic_test.go +++ b/safesocket/basic_test.go @@ -10,10 +10,10 @@ import ( "testing" ) +// downgradeSDDL is a no-op test helper on non-Windows systems. +var downgradeSDDL = func() func() { return func() {} } + func TestBasics(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } // Make the socket in a temp dir rather than the cwd // so that the test can be run from a mounted filesystem (#2367). dir := t.TempDir() @@ -22,6 +22,7 @@ func TestBasics(t *testing.T) { sock = filepath.Join(dir, "test") } else { sock = fmt.Sprintf(`\\.\pipe\tailscale-test`) + t.Cleanup(downgradeSDDL()) } l, err := Listen(sock) diff --git a/safesocket/pipe_windows.go b/safesocket/pipe_windows.go index c5c7b8b0948a1..a110f5f2be806 100644 --- a/safesocket/pipe_windows.go +++ b/safesocket/pipe_windows.go @@ -24,7 +24,8 @@ func setFlags(network, address string, c syscall.RawConn) error { // windowsSDDL is the Security Descriptor set on the namedpipe. // It provides read/write access to all users and the local system. -const windowsSDDL = "O:BAG:BAD:PAI(A;OICI;GWGR;;;BU)(A;OICI;GWGR;;;SY)" +// It is a var for testing, do not change this value. +var windowsSDDL = "O:BAG:BAD:PAI(A;OICI;GWGR;;;BU)(A;OICI;GWGR;;;SY)" func listen(path string) (net.Listener, error) { lc, err := winio.ListenPipe( diff --git a/safesocket/pipe_windows_test.go b/safesocket/pipe_windows_test.go new file mode 100644 index 0000000000000..6028adbe838d8 --- /dev/null +++ b/safesocket/pipe_windows_test.go @@ -0,0 +1,22 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package safesocket + +import "tailscale.com/util/winutil" + +func init() { + // downgradeSDDL is a test helper that downgrades the windowsSDDL variable if + // the currently running user does not have sufficient priviliges to set the + // SDDL. + downgradeSDDL = func() (cleanup func()) { + // The current default descriptor can not be set by mere mortal users, + // so we need to undo that for executing tests as a regular user. + if !winutil.IsCurrentProcessElevated() { + var orig string + orig, windowsSDDL = windowsSDDL, "" + return func() { windowsSDDL = orig } + } + return func() {} + } +} From 3ede3aafe4e090c76532f8cf9ee01e7c92ff44d6 Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Wed, 19 Apr 2023 14:26:21 -0400 Subject: [PATCH 012/331] ipn/localapi: also verify STUN queries work in 'debug derp' Updates #6526 Signed-off-by: Andrew Dunham Change-Id: I274b7ed53ee0be3fb94fdb00cafe06a1d676e1cf --- ipn/localapi/debugderp.go | 98 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/ipn/localapi/debugderp.go b/ipn/localapi/debugderp.go index 2db3e4f2f8c0e..f7ae887871680 100644 --- a/ipn/localapi/debugderp.go +++ b/ipn/localapi/debugderp.go @@ -4,17 +4,24 @@ package localapi import ( + "context" "crypto/tls" "encoding/json" "fmt" "net" "net/http" + "net/netip" "strconv" + "time" "tailscale.com/derp/derphttp" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" + "tailscale.com/net/netns" + "tailscale.com/net/stun" "tailscale.com/tailcfg" "tailscale.com/types/key" + "tailscale.com/types/nettype" ) func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { @@ -132,6 +139,92 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { return hasIPv4 || hasIPv6 } + checkSTUN4 := func(derpNode *tailcfg.DERPNode) { + u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(h.logf)).ListenPacket(ctx, "udp4", ":0") + if err != nil { + st.Errors = append(st.Errors, fmt.Sprintf("Error creating IPv4 STUN listener: %v", err)) + return + } + defer u4.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + var addr netip.Addr + if derpNode.IPv4 != "" { + addr, err = netip.ParseAddr(derpNode.IPv4) + if err != nil { + // Error printed elsewhere + return + } + } else { + addrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip4", derpNode.HostName) + if err != nil { + st.Errors = append(st.Errors, fmt.Sprintf("Error resolving node %q IPv4 addresses: %v", derpNode.HostName, err)) + return + } + addr = addrs[0] + } + + addrPort := netip.AddrPortFrom(addr, uint16(firstNonzero(derpNode.STUNPort, 3478))) + + txID := stun.NewTxID() + req := stun.Request(txID) + + done := make(chan struct{}) + defer close(done) + + go func() { + select { + case <-ctx.Done(): + case <-done: + } + u4.Close() + }() + + gotResponse := make(chan netip.AddrPort, 1) + go func() { + defer u4.Close() + + var buf [64 << 10]byte + for { + n, addr, err := u4.ReadFromUDPAddrPort(buf[:]) + if err != nil { + return + } + pkt := buf[:n] + if !stun.Is(pkt) { + continue + } + ap := netaddr.Unmap(addr) + if !ap.IsValid() { + continue + } + tx, addrPort, err := stun.ParseResponse(pkt) + if err != nil { + continue + } + if tx == txID { + gotResponse <- addrPort + return + } + } + }() + + _, err = u4.WriteToUDPAddrPort(req, addrPort) + if err != nil { + st.Errors = append(st.Errors, fmt.Sprintf("Error sending IPv4 STUN packet to %v (%q): %v", addrPort, derpNode.HostName, err)) + return + } + + select { + case resp := <-gotResponse: + st.Info = append(st.Info, fmt.Sprintf("Node %q returned IPv4 STUN response: %v", derpNode.HostName, resp)) + case <-ctx.Done(): + st.Warnings = append(st.Warnings, fmt.Sprintf("Node %q did not return a IPv4 STUN response", derpNode.HostName)) + } + } + // Start by checking whether we can establish a HTTP connection for _, derpNode := range reg.Nodes { connSuccess := checkConn(derpNode) @@ -178,6 +271,10 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { if len(serverPubKeys) > 1 { st.Errors = append(st.Errors, fmt.Sprintf("Received multiple server public keys (%d); is the DERP server behind a load balancer?", len(serverPubKeys))) } + + // Send a STUN query to this node to verify whether or not it + // correctly returns an IP address. + checkSTUN4(derpNode) } // TODO(bradfitz): finish: @@ -191,7 +288,6 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { // protocol to say how many peers it's meshed with. Should match count // in DERPRegion. Or maybe even list all their server pub keys that it's peered // with. - // * try STUN queries // * If their certificate is bad, either expired or just wrongly // issued in the first place, tell them specifically that the // cert is bad not just that the connection failed. From 4722f7e32283c383f397076799959e246103f02a Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Tue, 18 Apr 2023 14:26:58 -0700 Subject: [PATCH 013/331] all: move network monitoring from wgengine/monitor to net/netmon We're using it in more and more places, and it's not really specific to our use of Wireguard (and does more just link/interface monitoring). Also removes the separate interface we had for it in sockstats -- it's a small enough package (we already pull in all of its dependencies via other paths) that it's not worth the extra complexity. Updates #7621 Updates #7850 Signed-off-by: Mihai Parparita --- cmd/derper/depaware.txt | 5 +- cmd/tailscale/depaware.txt | 3 +- cmd/tailscaled/debug.go | 10 +-- cmd/tailscaled/depaware.txt | 2 +- cmd/tailscaled/tailscaled.go | 24 +++--- control/controlclient/direct.go | 12 +-- ipn/ipnlocal/local.go | 16 ++-- ipn/ipnlocal/serve.go | 2 +- ipn/localapi/localapi.go | 8 +- logtail/logtail.go | 16 ++-- net/dns/manager.go | 6 +- net/dns/resolver/forwarder.go | 12 +-- net/dns/resolver/macios_ext.go | 4 +- net/dns/resolver/tsdns.go | 12 +-- net/dns/resolver/tsdns_test.go | 6 +- net/interfaces/interfaces.go | 6 -- net/interfaces/interfaces_linux.go | 4 +- .../monitor.go => net/netmon/netmon.go | 49 ++++++----- .../netmon/netmon_darwin.go | 4 +- .../netmon/netmon_darwin_test.go | 2 +- .../netmon/netmon_freebsd.go | 4 +- .../netmon/netmon_linux.go | 4 +- .../netmon/netmon_linux_test.go | 2 +- .../netmon/netmon_polling.go | 4 +- .../netmon/netmon_test.go | 2 +- .../netmon/netmon_windows.go | 4 +- {wgengine/monitor => net/netmon}/polling.go | 6 +- net/sockstats/sockstats.go | 15 +--- net/sockstats/sockstats_noop.go | 3 +- net/sockstats/sockstats_tsgo.go | 5 +- net/tsdial/tsdial.go | 44 +++++----- tsnet/tsnet.go | 18 ++-- .../tailscaled_deps_test_darwin.go | 2 +- .../tailscaled_deps_test_freebsd.go | 2 +- .../integration/tailscaled_deps_test_linux.go | 2 +- .../tailscaled_deps_test_openbsd.go | 2 +- .../tailscaled_deps_test_windows.go | 2 +- wgengine/bench/wg.go | 16 ++-- wgengine/magicsock/magicsock.go | 18 ++-- wgengine/router/router.go | 8 +- wgengine/router/router_darwin.go | 6 +- wgengine/router/router_default.go | 4 +- wgengine/router/router_freebsd.go | 6 +- wgengine/router/router_linux.go | 26 +++--- wgengine/router/router_linux_test.go | 8 +- wgengine/router/router_openbsd.go | 8 +- wgengine/router/router_userspace_bsd.go | 8 +- wgengine/router/router_windows.go | 8 +- wgengine/userspace.go | 82 +++++++++---------- wgengine/watchdog.go | 6 +- wgengine/wgengine.go | 8 +- 51 files changed, 266 insertions(+), 270 deletions(-) rename wgengine/monitor/monitor.go => net/netmon/netmon.go (87%) rename wgengine/monitor/monitor_darwin.go => net/netmon/netmon_darwin.go (98%) rename wgengine/monitor/monitor_darwin_test.go => net/netmon/netmon_darwin_test.go (97%) rename wgengine/monitor/monitor_freebsd.go => net/netmon/netmon_freebsd.go (94%) rename wgengine/monitor/monitor_linux.go => net/netmon/netmon_linux.go (99%) rename wgengine/monitor/monitor_linux_test.go => net/netmon/netmon_linux_test.go (99%) rename wgengine/monitor/monitor_polling.go => net/netmon/netmon_polling.go (86%) rename wgengine/monitor/monitor_test.go => net/netmon/netmon_test.go (99%) rename wgengine/monitor/monitor_windows.go => net/netmon/netmon_windows.go (98%) rename {wgengine/monitor => net/netmon}/polling.go (95%) diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 7f60654b09483..7e82305d1253a 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -16,7 +16,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa github.com/golang/protobuf/ptypes/timestamp from github.com/prometheus/client_model/go github.com/hdevalence/ed25519consensus from tailscale.com/tka L github.com/josharian/native from github.com/mdlayher/netlink+ - L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces + L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces+ L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink github.com/klauspost/compress/flate from nhooyr.io/websocket github.com/matttproud/golang_protobuf_extensions/pbutil from github.com/prometheus/common/expfmt @@ -86,6 +86,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa 💣 tailscale.com/net/interfaces from tailscale.com/net/netns+ tailscale.com/net/netaddr from tailscale.com/ipn+ tailscale.com/net/netknob from tailscale.com/net/netns + tailscale.com/net/netmon from tailscale.com/net/sockstats tailscale.com/net/netns from tailscale.com/derp/derphttp tailscale.com/net/netutil from tailscale.com/client/tailscale tailscale.com/net/packet from tailscale.com/wgengine/filter @@ -129,7 +130,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa tailscale.com/util/lineread from tailscale.com/hostinfo+ tailscale.com/util/mak from tailscale.com/syncs+ tailscale.com/util/multierr from tailscale.com/health - tailscale.com/util/set from tailscale.com/health + tailscale.com/util/set from tailscale.com/health+ tailscale.com/util/singleflight from tailscale.com/net/dnscache tailscale.com/util/slicesx from tailscale.com/cmd/derper+ tailscale.com/util/vizerror from tailscale.com/tsweb diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 93d29fe20ec47..b146ec5679ebd 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -13,7 +13,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep github.com/google/uuid from tailscale.com/util/quarantine+ github.com/hdevalence/ed25519consensus from tailscale.com/tka L github.com/josharian/native from github.com/mdlayher/netlink+ - L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces + L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces+ L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink github.com/kballard/go-shellquote from tailscale.com/cmd/tailscale/cli github.com/klauspost/compress/flate from nhooyr.io/websocket @@ -74,6 +74,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli tailscale.com/net/neterror from tailscale.com/net/netcheck+ tailscale.com/net/netknob from tailscale.com/net/netns + tailscale.com/net/netmon from tailscale.com/net/sockstats tailscale.com/net/netns from tailscale.com/derp/derphttp+ tailscale.com/net/netutil from tailscale.com/client/tailscale+ tailscale.com/net/packet from tailscale.com/wgengine/filter+ diff --git a/cmd/tailscaled/debug.go b/cmd/tailscaled/debug.go index 4cc3af129ac9f..8c1ad88b17ff5 100644 --- a/cmd/tailscaled/debug.go +++ b/cmd/tailscaled/debug.go @@ -23,10 +23,10 @@ import ( "tailscale.com/derp/derphttp" "tailscale.com/ipn" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/net/tshttpproxy" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/wgengine/monitor" ) var debugArgs struct { @@ -42,7 +42,7 @@ var debugModeFunc = debugMode // so it can be addressable func debugMode(args []string) error { fs := flag.NewFlagSet("debug", flag.ExitOnError) fs.BoolVar(&debugArgs.ifconfig, "ifconfig", false, "If true, print network interface state") - fs.BoolVar(&debugArgs.monitor, "monitor", false, "If true, run link monitor forever. Precludes all other options.") + fs.BoolVar(&debugArgs.monitor, "monitor", false, "If true, run network monitor forever. Precludes all other options.") fs.BoolVar(&debugArgs.portmap, "portmap", false, "If true, run portmap debugging. Precludes all other options.") fs.StringVar(&debugArgs.getURL, "get-url", "", "If non-empty, fetch provided URL.") fs.StringVar(&debugArgs.derpCheck, "derp", "", "if non-empty, test a DERP ping via named region code") @@ -76,7 +76,7 @@ func runMonitor(ctx context.Context, loop bool) error { j, _ := json.MarshalIndent(st, "", " ") os.Stderr.Write(j) } - mon, err := monitor.New(log.Printf) + mon, err := netmon.New(log.Printf) if err != nil { return err } @@ -84,10 +84,10 @@ func runMonitor(ctx context.Context, loop bool) error { mon.RegisterChangeCallback(func(changed bool, st *interfaces.State) { if !changed { - log.Printf("Link monitor fired; no change") + log.Printf("Network monitor fired; no change") return } - log.Printf("Link monitor fired. New state:") + log.Printf("Network monitor fired. New state:") dump(st) }) if loop { diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 1d53813d06ea0..b51b3a3de0790 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -240,6 +240,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock tailscale.com/net/neterror from tailscale.com/net/dns/resolver+ tailscale.com/net/netknob from tailscale.com/net/netns+ + tailscale.com/net/netmon from tailscale.com/cmd/tailscaled+ tailscale.com/net/netns from tailscale.com/derp/derphttp+ 💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnauth+ tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+ @@ -324,7 +325,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/wgengine/capture from tailscale.com/ipn/ipnlocal+ tailscale.com/wgengine/filter from tailscale.com/control/controlclient+ 💣 tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+ - tailscale.com/wgengine/monitor from tailscale.com/control/controlclient+ tailscale.com/wgengine/netlog from tailscale.com/wgengine tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+ diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 5db801fb71e0f..3bae560a291d8 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -39,6 +39,7 @@ import ( "tailscale.com/logtail" "tailscale.com/net/dns" "tailscale.com/net/dnsfallback" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/proxymux" "tailscale.com/net/socks5" @@ -59,7 +60,6 @@ import ( "tailscale.com/version" "tailscale.com/version/distro" "tailscale.com/wgengine" - "tailscale.com/wgengine/monitor" "tailscale.com/wgengine/netstack" "tailscale.com/wgengine/router" ) @@ -451,18 +451,18 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID) } func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID) (_ *ipnlocal.LocalBackend, retErr error) { - linkMon, err := monitor.New(logf) + netMon, err := netmon.New(logf) if err != nil { - return nil, fmt.Errorf("monitor.New: %w", err) + return nil, fmt.Errorf("netmon.New: %w", err) } if logPol != nil { - logPol.Logtail.SetLinkMonitor(linkMon) + logPol.Logtail.SetNetMon(netMon) } socksListener, httpProxyListener := mustStartProxyListeners(args.socksAddr, args.httpProxyAddr) dialer := &tsdial.Dialer{Logf: logf} // mutated below (before used) - e, onlyNetstack, err := createEngine(logf, linkMon, dialer) + e, onlyNetstack, err := createEngine(logf, netMon, dialer) if err != nil { return nil, fmt.Errorf("createEngine: %w", err) } @@ -551,14 +551,14 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID // // onlyNetstack is true if the user has explicitly requested that we use netstack // for all networking. -func createEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer) (e wgengine.Engine, onlyNetstack bool, err error) { +func createEngine(logf logger.Logf, netMon *netmon.Monitor, dialer *tsdial.Dialer) (e wgengine.Engine, onlyNetstack bool, err error) { if args.tunname == "" { return nil, false, errors.New("no --tun value specified") } var errs []error for _, name := range strings.Split(args.tunname, ",") { logf("wgengine.NewUserspaceEngine(tun %q) ...", name) - e, onlyNetstack, err = tryEngine(logf, linkMon, dialer, name) + e, onlyNetstack, err = tryEngine(logf, netMon, dialer, name) if err == nil { return e, onlyNetstack, nil } @@ -590,11 +590,11 @@ func handleSubnetsInNetstack() bool { var tstunNew = tstun.New -func tryEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer, name string) (e wgengine.Engine, onlyNetstack bool, err error) { +func tryEngine(logf logger.Logf, netMon *netmon.Monitor, dialer *tsdial.Dialer, name string) (e wgengine.Engine, onlyNetstack bool, err error) { conf := wgengine.Config{ - ListenPort: args.port, - LinkMonitor: linkMon, - Dialer: dialer, + ListenPort: args.port, + NetMon: netMon, + Dialer: dialer, } onlyNetstack = name == "userspace-networking" @@ -633,7 +633,7 @@ func tryEngine(logf logger.Logf, linkMon *monitor.Mon, dialer *tsdial.Dialer, na return e, false, err } - r, err := router.New(logf, dev, linkMon) + r, err := router.New(logf, dev, netMon) if err != nil { dev.Close() return nil, false, fmt.Errorf("creating router: %w", err) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 15c26cc788397..85bd7f07b07f7 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -37,6 +37,7 @@ import ( "tailscale.com/net/dnscache" "tailscale.com/net/dnsfallback" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/net/netutil" "tailscale.com/net/tlsdial" "tailscale.com/net/tsdial" @@ -54,7 +55,6 @@ import ( "tailscale.com/util/multierr" "tailscale.com/util/singleflight" "tailscale.com/util/systemd" - "tailscale.com/wgengine/monitor" ) // Direct is the client that connects to a tailcontrol server for a node. @@ -67,7 +67,7 @@ type Direct struct { newDecompressor func() (Decompressor, error) keepAlive bool logf logger.Logf - linkMon *monitor.Mon // or nil + netMon *netmon.Monitor // or nil discoPubKey key.DiscoPublic getMachinePrivKey func() (key.MachinePrivate, error) debugFlags []string @@ -113,7 +113,7 @@ type Options struct { HTTPTestClient *http.Client // optional HTTP client to use (for tests only) NoiseTestClient *http.Client // optional HTTP client to use for noise RPCs (tests only) DebugFlags []string // debug settings to send to control - LinkMonitor *monitor.Mon // optional link monitor + NetMon *netmon.Monitor // optional network monitor PopBrowserURL func(url string) // optional func to open browser OnClientVersion func(*tailcfg.ClientVersion) // optional func to inform GUI of client version status OnControlTime func(time.Time) // optional func to notify callers of new time from control @@ -241,7 +241,7 @@ func NewDirect(opts Options) (*Direct, error) { discoPubKey: opts.DiscoPublicKey, debugFlags: opts.DebugFlags, keepSharerAndUserSplit: opts.KeepSharerAndUserSplit, - linkMon: opts.LinkMonitor, + netMon: opts.NetMon, skipIPForwardingCheck: opts.SkipIPForwardingCheck, pinger: opts.Pinger, popBrowser: opts.PopBrowserURL, @@ -871,8 +871,8 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, readOnly bool ReadOnly: readOnly && !allowStream, } var extraDebugFlags []string - if hi != nil && c.linkMon != nil && !c.skipIPForwardingCheck && - ipForwardingBroken(hi.RoutableIPs, c.linkMon.InterfaceState()) { + if hi != nil && c.netMon != nil && !c.skipIPForwardingCheck && + ipForwardingBroken(hi.RoutableIPs, c.netMon.InterfaceState()) { extraDebugFlags = append(extraDebugFlags, "warn-ip-forwarding-off") } if health.RouterHealth() != nil { diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 07decb04dd555..532e68d1922c0 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -142,7 +142,7 @@ type LocalBackend struct { store ipn.StateStore dialer *tsdial.Dialer // non-nil backendLogID logid.PublicID - unregisterLinkMon func() + unregisterNetMon func() unregisterHealthWatch func() portpoll *portlist.Poller // may be nil portpollOnce sync.Once // guards starting readPoller @@ -330,12 +330,12 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor b.statusChanged = sync.NewCond(&b.statusLock) b.e.SetStatusCallback(b.setWgengineStatus) - linkMon := e.GetLinkMonitor() - b.prevIfState = linkMon.InterfaceState() + netMon := e.GetNetMon() + b.prevIfState = netMon.InterfaceState() // Call our linkChange code once with the current state, and // then also whenever it changes: - b.linkChange(false, linkMon.InterfaceState()) - b.unregisterLinkMon = linkMon.RegisterChangeCallback(b.linkChange) + b.linkChange(false, netMon.InterfaceState()) + b.unregisterNetMon = netMon.RegisterChangeCallback(b.linkChange) b.unregisterHealthWatch = health.RegisterWatcher(b.onHealthChange) @@ -499,7 +499,7 @@ func (b *LocalBackend) maybePauseControlClientLocked() { b.cc.SetPaused((b.state == ipn.Stopped && b.netMap != nil) || !networkUp) } -// linkChange is our link monitor callback, called whenever the network changes. +// linkChange is our network monitor callback, called whenever the network changes. // major is whether ifst is different than earlier. func (b *LocalBackend) linkChange(major bool, ifst *interfaces.State) { b.mu.Lock() @@ -576,7 +576,7 @@ func (b *LocalBackend) Shutdown() { b.sockstatLogger.Shutdown() } - b.unregisterLinkMon() + b.unregisterNetMon() b.unregisterHealthWatch() if cc != nil { cc.Shutdown() @@ -1423,7 +1423,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { HTTPTestClient: httpTestClient, DiscoPublicKey: discoPublic, DebugFlags: debugFlags, - LinkMonitor: b.e.GetLinkMonitor(), + NetMon: b.e.GetNetMon(), Pinger: b, PopBrowserURL: b.tellClientToBrowseToURL, OnClientVersion: b.onClientVersion, diff --git a/ipn/ipnlocal/serve.go b/ipn/ipnlocal/serve.go index a9058dec20990..e6d1d010455a4 100644 --- a/ipn/ipnlocal/serve.go +++ b/ipn/ipnlocal/serve.go @@ -143,7 +143,7 @@ func (s *serveListener) Run() { } func (s *serveListener) shouldWarnAboutListenError(err error) bool { - if !s.b.e.GetLinkMonitor().InterfaceState().HasIP(s.ap.Addr()) { + if !s.b.e.GetNetMon().InterfaceState().HasIP(s.ap.Addr()) { // Machine likely doesn't have IPv6 enabled (or the IP is still being // assigned). No need to warn. Notably, WSL2 (Issue 6303). return false diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index 5d7b36e9aab9a..be15cbe08bfce 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -34,6 +34,7 @@ import ( "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/ipnstate" "tailscale.com/logtail" + "tailscale.com/net/netmon" "tailscale.com/net/netutil" "tailscale.com/net/portmapper" "tailscale.com/tailcfg" @@ -46,7 +47,6 @@ import ( "tailscale.com/util/httpm" "tailscale.com/util/mak" "tailscale.com/version" - "tailscale.com/wgengine/monitor" ) type localAPIHandler func(*Handler, http.ResponseWriter, *http.Request) @@ -695,7 +695,7 @@ func (h *Handler) serveDebugPortmap(w http.ResponseWriter, r *http.Request) { }) defer c.Close() - linkMon, err := monitor.New(logger.WithPrefix(logf, "monitor: ")) + netMon, err := netmon.New(logger.WithPrefix(logf, "monitor: ")) if err != nil { logf("error creating monitor: %v", err) return @@ -707,14 +707,14 @@ func (h *Handler) serveDebugPortmap(w http.ResponseWriter, r *http.Request) { self = netip.MustParseAddr(b) return gw, self, true } - return linkMon.GatewayAndSelfIP() + return netMon.GatewayAndSelfIP() } c.SetGatewayLookupFunc(gatewayAndSelfIP) gw, selfIP, ok := gatewayAndSelfIP() if !ok { - logf("no gateway or self IP; %v", linkMon.InterfaceState()) + logf("no gateway or self IP; %v", netMon.InterfaceState()) return } logf("gw=%v; self=%v", gw, selfIP) diff --git a/logtail/logtail.go b/logtail/logtail.go index 92e544fed682f..3c32df3a0e0af 100644 --- a/logtail/logtail.go +++ b/logtail/logtail.go @@ -24,11 +24,11 @@ import ( "tailscale.com/envknob" "tailscale.com/logtail/backoff" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/net/sockstats" tslogger "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/util/set" - "tailscale.com/wgengine/monitor" ) // DefaultHost is the default host name to upload logs to when @@ -179,7 +179,7 @@ type Logger struct { url string lowMem bool skipClientTime bool - linkMonitor *monitor.Mon + netMonitor *netmon.Monitor buffer Buffer drainWake chan struct{} // signal to speed up drain flushDelayFn func() time.Duration // negative or zero return value to upload aggressively, or >0 to batch at this delay @@ -214,12 +214,12 @@ func (l *Logger) SetVerbosityLevel(level int) { atomic.StoreInt64(&l.stderrLevel, int64(level)) } -// SetLinkMonitor sets the optional the link monitor. +// SetNetMon sets the optional the network monitor. // // It should not be changed concurrently with log writes and should // only be set once. -func (l *Logger) SetLinkMonitor(lm *monitor.Mon) { - l.linkMonitor = lm +func (l *Logger) SetNetMon(lm *netmon.Monitor) { + l.netMonitor = lm } // SetSockstatsLabel sets the label used in sockstat logs to identify network traffic from this logger. @@ -403,16 +403,16 @@ func (l *Logger) uploading(ctx context.Context) { } func (l *Logger) internetUp() bool { - if l.linkMonitor == nil { + if l.netMonitor == nil { // No way to tell, so assume it is. return true } - return l.linkMonitor.InterfaceState().AnyInterfaceUp() + return l.netMonitor.InterfaceState().AnyInterfaceUp() } func (l *Logger) awaitInternetUp(ctx context.Context) { upc := make(chan bool, 1) - defer l.linkMonitor.RegisterChangeCallback(func(changed bool, st *interfaces.State) { + defer l.netMonitor.RegisterChangeCallback(func(changed bool, st *interfaces.State) { if st.AnyInterfaceUp() { select { case upc <- true: diff --git a/net/dns/manager.go b/net/dns/manager.go index a4366d52d3f38..e909cbe5d1059 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -18,12 +18,12 @@ import ( "golang.org/x/exp/slices" "tailscale.com/health" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netmon" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" "tailscale.com/types/logger" "tailscale.com/util/clientmetric" "tailscale.com/util/dnsname" - "tailscale.com/wgengine/monitor" ) var ( @@ -64,14 +64,14 @@ type Manager struct { } // NewManagers created a new manager from the given config. -func NewManager(logf logger.Logf, oscfg OSConfigurator, linkMon *monitor.Mon, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector) *Manager { +func NewManager(logf logger.Logf, oscfg OSConfigurator, netMon *netmon.Monitor, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector) *Manager { if dialer == nil { panic("nil Dialer") } logf = logger.WithPrefix(logf, "dns: ") m := &Manager{ logf: logf, - resolver: resolver.New(logf, linkMon, linkSel, dialer), + resolver: resolver.New(logf, netMon, linkSel, dialer), os: oscfg, } m.ctx, m.ctxCancel = context.WithCancel(context.Background()) diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 0a02e6edb79d1..3373ffcf147c5 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -25,6 +25,7 @@ import ( "tailscale.com/net/dns/publicdns" "tailscale.com/net/dnscache" "tailscale.com/net/neterror" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/sockstats" "tailscale.com/net/tsdial" @@ -34,7 +35,6 @@ import ( "tailscale.com/util/cloudenv" "tailscale.com/util/dnsname" "tailscale.com/version" - "tailscale.com/wgengine/monitor" ) // headerBytes is the number of bytes in a DNS message header. @@ -176,7 +176,7 @@ type resolverAndDelay struct { // forwarder forwards DNS packets to a number of upstream nameservers. type forwarder struct { logf logger.Logf - linkMon *monitor.Mon + netMon *netmon.Monitor linkSel ForwardLinkSelector // TODO(bradfitz): remove this when tsdial.Dialer absorbs it dialer *tsdial.Dialer @@ -206,10 +206,10 @@ func init() { rand.Seed(time.Now().UnixNano()) } -func newForwarder(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *forwarder { +func newForwarder(logf logger.Logf, netMon *netmon.Monitor, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *forwarder { f := &forwarder{ logf: logger.WithPrefix(logf, "forward: "), - linkMon: linkMon, + netMon: netMon, linkSel: linkSel, dialer: dialer, } @@ -355,7 +355,7 @@ func (f *forwarder) packetListener(ip netip.Addr) (nettype.PacketListenerWithNet return stdNetPacketListener, nil } lc := new(net.ListenConfig) - if err := initListenConfig(lc, f.linkMon, linkName); err != nil { + if err := initListenConfig(lc, f.netMon, linkName); err != nil { return nil, err } return nettype.MakePacketListenerWithNetIP(lc), nil @@ -763,7 +763,7 @@ func (f *forwarder) forwardWithDestChan(ctx context.Context, query packet, respo } } -var initListenConfig func(_ *net.ListenConfig, _ *monitor.Mon, tunName string) error +var initListenConfig func(_ *net.ListenConfig, _ *netmon.Monitor, tunName string) error // nameFromQuery extracts the normalized query name from bs. func nameFromQuery(bs []byte) (dnsname.FQDN, error) { diff --git a/net/dns/resolver/macios_ext.go b/net/dns/resolver/macios_ext.go index ee3efa6666fef..895b8714f6382 100644 --- a/net/dns/resolver/macios_ext.go +++ b/net/dns/resolver/macios_ext.go @@ -9,15 +9,15 @@ import ( "errors" "net" + "tailscale.com/net/netmon" "tailscale.com/net/netns" - "tailscale.com/wgengine/monitor" ) func init() { initListenConfig = initListenConfigNetworkExtension } -func initListenConfigNetworkExtension(nc *net.ListenConfig, mon *monitor.Mon, tunName string) error { +func initListenConfigNetworkExtension(nc *net.ListenConfig, mon *netmon.Monitor, tunName string) error { nif, ok := mon.InterfaceState().Interface[tunName] if !ok { return errors.New("utun not found") diff --git a/net/dns/resolver/tsdns.go b/net/dns/resolver/tsdns.go index 6344328b70625..4ed0e57ba0928 100644 --- a/net/dns/resolver/tsdns.go +++ b/net/dns/resolver/tsdns.go @@ -26,6 +26,7 @@ import ( "tailscale.com/envknob" "tailscale.com/net/dns/resolvconffile" "tailscale.com/net/netaddr" + "tailscale.com/net/netmon" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" "tailscale.com/syncs" @@ -34,7 +35,6 @@ import ( "tailscale.com/util/clientmetric" "tailscale.com/util/cloudenv" "tailscale.com/util/dnsname" - "tailscale.com/wgengine/monitor" ) const dnsSymbolicFQDN = "magicdns.localhost-tailscale-daemon." @@ -179,7 +179,7 @@ func WriteRoutes(w *bufio.Writer, routes map[dnsname.FQDN][]*dnstype.Resolver) { // it delegates to upstream nameservers if any are set. type Resolver struct { logf logger.Logf - linkMon *monitor.Mon // or nil + netMon *netmon.Monitor // or nil dialer *tsdial.Dialer // non-nil saveConfigForTests func(cfg Config) // used in tests to capture resolver config // forwarder forwards requests to upstream nameservers. @@ -205,20 +205,20 @@ type ForwardLinkSelector interface { } // New returns a new resolver. -// linkMon optionally specifies a link monitor to use for socket rebinding. -func New(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *Resolver { +// netMon optionally specifies a network monitor to use for socket rebinding. +func New(logf logger.Logf, netMon *netmon.Monitor, linkSel ForwardLinkSelector, dialer *tsdial.Dialer) *Resolver { if dialer == nil { panic("nil Dialer") } r := &Resolver{ logf: logger.WithPrefix(logf, "resolver: "), - linkMon: linkMon, + netMon: netMon, closed: make(chan struct{}), hostToIP: map[dnsname.FQDN][]netip.Addr{}, ipToHost: map[netip.Addr]dnsname.FQDN{}, dialer: dialer, } - r.forwarder = newForwarder(r.logf, linkMon, linkSel, dialer) + r.forwarder = newForwarder(r.logf, netMon, linkSel, dialer) return r } diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index 9862da8fb2431..ad3d36c99a2b7 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -24,11 +24,11 @@ import ( miekdns "github.com/miekg/dns" dns "golang.org/x/net/dns/dnsmessage" "tailscale.com/net/netaddr" + "tailscale.com/net/netmon" "tailscale.com/net/tsdial" "tailscale.com/tstest" "tailscale.com/types/dnstype" "tailscale.com/util/dnsname" - "tailscale.com/wgengine/monitor" ) var ( @@ -315,7 +315,7 @@ func TestRDNSNameToIPv6(t *testing.T) { } func newResolver(t testing.TB) *Resolver { - return New(t.Logf, nil /* no link monitor */, nil /* no link selector */, new(tsdial.Dialer)) + return New(t.Logf, nil /* no network monitor */, nil /* no link selector */, new(tsdial.Dialer)) } func TestResolveLocal(t *testing.T) { @@ -997,7 +997,7 @@ func TestMarshalResponseFormatError(t *testing.T) { func TestForwardLinkSelection(t *testing.T) { configCall := make(chan string, 1) - tstest.Replace(t, &initListenConfig, func(nc *net.ListenConfig, mon *monitor.Mon, tunName string) error { + tstest.Replace(t, &initListenConfig, func(nc *net.ListenConfig, mon *netmon.Monitor, tunName string) error { select { case configCall <- tunName: return nil diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index fbde96190c78d..e9e21eabca437 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -351,12 +351,6 @@ func (s *State) String() string { return sb.String() } -// ChangeFunc is a callback function (usually registered with -// wgengine/monitor's Mon) that's called when the network -// changed. The changed parameter is whether the network changed -// enough for State to have changed since the last callback. -type ChangeFunc func(changed bool, state *State) - // An InterfaceFilter indicates whether EqualFiltered should use i when deciding whether two States are equal. // ips are all the IPPrefixes associated with i. type InterfaceFilter func(i Interface, ips []netip.Prefix) bool diff --git a/net/interfaces/interfaces_linux.go b/net/interfaces/interfaces_linux.go index b7d405828a9d6..cad5d4a4aacd2 100644 --- a/net/interfaces/interfaces_linux.go +++ b/net/interfaces/interfaces_linux.go @@ -167,8 +167,8 @@ func defaultRoute() (d DefaultRouteDetails, err error) { // /proc/net/route. Use netlink to find the default route. // // TODO(bradfitz): this allocates a fair bit. We should track - // this in wgengine/monitor instead and have - // interfaces.GetState take a link monitor or similar so the + // this in net/interfaces/monitor instead and have + // interfaces.GetState take a netmon.Monitor or similar so the // routing table can be cached and the monitor's existing // subscription to route changes can update the cached state, // rather than querying the whole thing every time like diff --git a/wgengine/monitor/monitor.go b/net/netmon/netmon.go similarity index 87% rename from wgengine/monitor/monitor.go rename to net/netmon/netmon.go index fc318d35880be..4de8a47f477a5 100644 --- a/wgengine/monitor/monitor.go +++ b/net/netmon/netmon.go @@ -4,7 +4,7 @@ // Package monitor provides facilities for monitoring network // interface and route changes. It primarily exists to know when // portable devices move between different networks. -package monitor +package netmon import ( "encoding/json" @@ -48,15 +48,15 @@ type osMon interface { IsInterestingInterface(iface string) bool } -// Mon represents a monitoring instance. -type Mon struct { +// Monitor represents a monitoring instance. +type Monitor struct { logf logger.Logf om osMon // nil means not supported on this platform change chan struct{} stop chan struct{} // closed on Stop mu sync.Mutex // guards all following fields - cbs set.HandleSet[interfaces.ChangeFunc] + cbs set.HandleSet[ChangeFunc] ruleDelCB set.HandleSet[RuleDeleteCallback] ifState *interfaces.State gwValid bool // whether gw and gwSelfIP are valid @@ -70,12 +70,17 @@ type Mon struct { timeJumped bool // whether we need to send a changed=true after a big time jump } +// ChangeFunc is a callback function registered with Monitor that's called when the +// network changed. The changed parameter is whether the network changed +// enough for State to have changed since the last callback. +type ChangeFunc func(changed bool, state *interfaces.State) + // New instantiates and starts a monitoring instance. // The returned monitor is inactive until it's started by the Start method. // Use RegisterChangeCallback to get notified of network changes. -func New(logf logger.Logf) (*Mon, error) { +func New(logf logger.Logf) (*Monitor, error) { logf = logger.WithPrefix(logf, "monitor: ") - m := &Mon{ + m := &Monitor{ logf: logf, change: make(chan struct{}, 1), stop: make(chan struct{}), @@ -102,13 +107,13 @@ func New(logf logger.Logf) (*Mon, error) { // interfaces. // // The returned value is owned by Mon; it must not be modified. -func (m *Mon) InterfaceState() *interfaces.State { +func (m *Monitor) InterfaceState() *interfaces.State { m.mu.Lock() defer m.mu.Unlock() return m.ifState } -func (m *Mon) interfaceStateUncached() (*interfaces.State, error) { +func (m *Monitor) interfaceStateUncached() (*interfaces.State, error) { return interfaces.GetState() } @@ -117,7 +122,7 @@ func (m *Mon) interfaceStateUncached() (*interfaces.State, error) { // // It's the same as interfaces.LikelyHomeRouterIP, but it caches the // result until the monitor detects a network change. -func (m *Mon) GatewayAndSelfIP() (gw, myIP netip.Addr, ok bool) { +func (m *Monitor) GatewayAndSelfIP() (gw, myIP netip.Addr, ok bool) { m.mu.Lock() defer m.mu.Unlock() if m.gwValid { @@ -133,7 +138,7 @@ func (m *Mon) GatewayAndSelfIP() (gw, myIP netip.Addr, ok bool) { // RegisterChangeCallback adds callback to the set of parties to be // notified (in their own goroutine) when the network state changes. // To remove this callback, call unregister (or close the monitor). -func (m *Mon) RegisterChangeCallback(callback interfaces.ChangeFunc) (unregister func()) { +func (m *Monitor) RegisterChangeCallback(callback ChangeFunc) (unregister func()) { m.mu.Lock() defer m.mu.Unlock() handle := m.cbs.Add(callback) @@ -153,7 +158,7 @@ type RuleDeleteCallback func(table uint8, priority uint32) // RegisterRuleDeleteCallback adds callback to the set of parties to be // notified (in their own goroutine) when a Linux ip rule is deleted. // To remove this callback, call unregister (or close the monitor). -func (m *Mon) RegisterRuleDeleteCallback(callback RuleDeleteCallback) (unregister func()) { +func (m *Monitor) RegisterRuleDeleteCallback(callback RuleDeleteCallback) (unregister func()) { m.mu.Lock() defer m.mu.Unlock() handle := m.ruleDelCB.Add(callback) @@ -166,7 +171,7 @@ func (m *Mon) RegisterRuleDeleteCallback(callback RuleDeleteCallback) (unregiste // Start starts the monitor. // A monitor can only be started & closed once. -func (m *Mon) Start() { +func (m *Monitor) Start() { m.mu.Lock() defer m.mu.Unlock() if m.started || m.closed { @@ -187,7 +192,7 @@ func (m *Mon) Start() { } // Close closes the monitor. -func (m *Mon) Close() error { +func (m *Monitor) Close() error { m.mu.Lock() if m.closed { m.mu.Unlock() @@ -218,7 +223,7 @@ func (m *Mon) Close() error { // change and re-check the state of the network. Any registered // ChangeFunc callbacks will be called within the event coalescing // period (under a fraction of a second). -func (m *Mon) InjectEvent() { +func (m *Monitor) InjectEvent() { select { case m.change <- struct{}{}: default: @@ -228,7 +233,7 @@ func (m *Mon) InjectEvent() { } } -func (m *Mon) stopped() bool { +func (m *Monitor) stopped() bool { select { case <-m.stop: return true @@ -239,7 +244,7 @@ func (m *Mon) stopped() bool { // pump continuously retrieves messages from the connection, notifying // the change channel of changes, and stopping when a stop is issued. -func (m *Mon) pump() { +func (m *Monitor) pump() { defer m.goroutines.Done() for !m.stopped() { msg, err := m.om.Receive() @@ -263,7 +268,7 @@ func (m *Mon) pump() { } } -func (m *Mon) notifyRuleDeleted(rdm ipRuleDeletedMessage) { +func (m *Monitor) notifyRuleDeleted(rdm ipRuleDeletedMessage) { m.mu.Lock() defer m.mu.Unlock() for _, cb := range m.ruleDelCB { @@ -274,13 +279,13 @@ func (m *Mon) notifyRuleDeleted(rdm ipRuleDeletedMessage) { // isInterestingInterface reports whether the provided interface should be // considered when checking for network state changes. // The ips parameter should be the IPs of the provided interface. -func (m *Mon) isInterestingInterface(i interfaces.Interface, ips []netip.Prefix) bool { +func (m *Monitor) isInterestingInterface(i interfaces.Interface, ips []netip.Prefix) bool { return m.om.IsInterestingInterface(i.Name) && interfaces.UseInterestingInterfaces(i, ips) } // debounce calls the callback function with a delay between events // and exits when a stop is issued. -func (m *Mon) debounce() { +func (m *Monitor) debounce() { defer m.goroutines.Done() for { select { @@ -343,7 +348,7 @@ func wallTime() time.Time { return time.Now().Round(0) } -func (m *Mon) pollWallTime() { +func (m *Monitor) pollWallTime() { m.mu.Lock() defer m.mu.Unlock() if m.closed { @@ -365,7 +370,7 @@ const shouldMonitorTimeJump = runtime.GOOS != "android" && runtime.GOOS != "ios" // checkWallTimeAdvanceLocked reports whether wall time jumped more than 150% of // pollWallTimeInterval, indicating we probably just came out of sleep. Once a // time jump is detected it must be reset by calling resetTimeJumpedLocked. -func (m *Mon) checkWallTimeAdvanceLocked() bool { +func (m *Monitor) checkWallTimeAdvanceLocked() bool { if !shouldMonitorTimeJump { panic("unreachable") // if callers are correct } @@ -378,7 +383,7 @@ func (m *Mon) checkWallTimeAdvanceLocked() bool { } // resetTimeJumpedLocked consumes the signal set by checkWallTimeAdvanceLocked. -func (m *Mon) resetTimeJumpedLocked() { +func (m *Monitor) resetTimeJumpedLocked() { m.timeJumped = false } diff --git a/wgengine/monitor/monitor_darwin.go b/net/netmon/netmon_darwin.go similarity index 98% rename from wgengine/monitor/monitor_darwin.go rename to net/netmon/netmon_darwin.go index da720f5d66937..cc630112523fa 100644 --- a/wgengine/monitor/monitor_darwin.go +++ b/net/netmon/netmon_darwin.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "fmt" @@ -24,7 +24,7 @@ type unspecifiedMessage struct{} func (unspecifiedMessage) ignore() bool { return false } -func newOSMon(logf logger.Logf, _ *Mon) (osMon, error) { +func newOSMon(logf logger.Logf, _ *Monitor) (osMon, error) { fd, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, 0) if err != nil { return nil, err diff --git a/wgengine/monitor/monitor_darwin_test.go b/net/netmon/netmon_darwin_test.go similarity index 97% rename from wgengine/monitor/monitor_darwin_test.go rename to net/netmon/netmon_darwin_test.go index 375cd87a72d1b..84c67cf6fa3e2 100644 --- a/wgengine/monitor/monitor_darwin_test.go +++ b/net/netmon/netmon_darwin_test.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "encoding/hex" diff --git a/wgengine/monitor/monitor_freebsd.go b/net/netmon/netmon_freebsd.go similarity index 94% rename from wgengine/monitor/monitor_freebsd.go rename to net/netmon/netmon_freebsd.go index 5acd8e098473a..30480a1d3387e 100644 --- a/wgengine/monitor/monitor_freebsd.go +++ b/net/netmon/netmon_freebsd.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "bufio" @@ -24,7 +24,7 @@ type devdConn struct { conn net.Conn } -func newOSMon(logf logger.Logf, m *Mon) (osMon, error) { +func newOSMon(logf logger.Logf, m *Monitor) (osMon, error) { conn, err := net.Dial("unixpacket", "/var/run/devd.seqpacket.pipe") if err != nil { logf("devd dial error: %v, falling back to polling method", err) diff --git a/wgengine/monitor/monitor_linux.go b/net/netmon/netmon_linux.go similarity index 99% rename from wgengine/monitor/monitor_linux.go rename to net/netmon/netmon_linux.go index 4acb798878391..9065b99532b06 100644 --- a/wgengine/monitor/monitor_linux.go +++ b/net/netmon/netmon_linux.go @@ -3,7 +3,7 @@ //go:build !android -package monitor +package netmon import ( "net" @@ -44,7 +44,7 @@ type nlConn struct { addrCache map[uint32]map[netip.Addr]bool } -func newOSMon(logf logger.Logf, m *Mon) (osMon, error) { +func newOSMon(logf logger.Logf, m *Monitor) (osMon, error) { conn, err := netlink.Dial(unix.NETLINK_ROUTE, &netlink.Config{ // Routes get us most of the events of interest, but we need // address as well to cover things like DHCP deciding to give diff --git a/wgengine/monitor/monitor_linux_test.go b/net/netmon/netmon_linux_test.go similarity index 99% rename from wgengine/monitor/monitor_linux_test.go rename to net/netmon/netmon_linux_test.go index 56beb0019ed4d..d09fac26aecee 100644 --- a/wgengine/monitor/monitor_linux_test.go +++ b/net/netmon/netmon_linux_test.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "net" diff --git a/wgengine/monitor/monitor_polling.go b/net/netmon/netmon_polling.go similarity index 86% rename from wgengine/monitor/monitor_polling.go rename to net/netmon/netmon_polling.go index 0f807d053504a..3d6f94731077a 100644 --- a/wgengine/monitor/monitor_polling.go +++ b/net/netmon/netmon_polling.go @@ -3,13 +3,13 @@ //go:build (!linux && !freebsd && !windows && !darwin) || android -package monitor +package netmon import ( "tailscale.com/types/logger" ) -func newOSMon(logf logger.Logf, m *Mon) (osMon, error) { +func newOSMon(logf logger.Logf, m *Monitor) (osMon, error) { return newPollingMon(logf, m) } diff --git a/wgengine/monitor/monitor_test.go b/net/netmon/netmon_test.go similarity index 99% rename from wgengine/monitor/monitor_test.go rename to net/netmon/netmon_test.go index 30c0ac52a18f0..7d25164048d70 100644 --- a/wgengine/monitor/monitor_test.go +++ b/net/netmon/netmon_test.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "flag" diff --git a/wgengine/monitor/monitor_windows.go b/net/netmon/netmon_windows.go similarity index 98% rename from wgengine/monitor/monitor_windows.go rename to net/netmon/netmon_windows.go index 6242d7418b3e9..8369222063dcf 100644 --- a/wgengine/monitor/monitor_windows.go +++ b/net/netmon/netmon_windows.go @@ -1,7 +1,7 @@ // Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause -package monitor +package netmon import ( "context" @@ -44,7 +44,7 @@ type winMon struct { noDeadlockTicker *time.Ticker } -func newOSMon(logf logger.Logf, _ *Mon) (osMon, error) { +func newOSMon(logf logger.Logf, _ *Monitor) (osMon, error) { m := &winMon{ logf: logf, messagec: make(chan eventMessage, 1), diff --git a/wgengine/monitor/polling.go b/net/netmon/polling.go similarity index 95% rename from wgengine/monitor/polling.go rename to net/netmon/polling.go index b1028de732ef9..9332bdde98885 100644 --- a/wgengine/monitor/polling.go +++ b/net/netmon/polling.go @@ -3,7 +3,7 @@ //go:build !windows && !darwin -package monitor +package netmon import ( "bytes" @@ -17,7 +17,7 @@ import ( "tailscale.com/types/logger" ) -func newPollingMon(logf logger.Logf, m *Mon) (osMon, error) { +func newPollingMon(logf logger.Logf, m *Monitor) (osMon, error) { return &pollingMon{ logf: logf, m: m, @@ -30,7 +30,7 @@ func newPollingMon(logf logger.Logf, m *Mon) (osMon, error) { // of anything to subscribe to. type pollingMon struct { logf logger.Logf - m *Mon + m *Monitor closeOnce sync.Once stop chan struct{} diff --git a/net/sockstats/sockstats.go b/net/sockstats/sockstats.go index 468fa70058f22..e968ac7bfb010 100644 --- a/net/sockstats/sockstats.go +++ b/net/sockstats/sockstats.go @@ -11,7 +11,7 @@ package sockstats import ( "context" - "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -107,17 +107,10 @@ func GetValidation() *ValidationSockStats { return getValidation() } -// LinkMonitor is the interface for the parts of wgengine/mointor's Mon that we -// need, to avoid the dependency. -type LinkMonitor interface { - InterfaceState() *interfaces.State - RegisterChangeCallback(interfaces.ChangeFunc) (unregister func()) -} - -// SetLinkMonitor configures the sockstats package to monitor the active +// SetNetMon configures the sockstats package to monitor the active // interface, so that per-interface stats can be collected. -func SetLinkMonitor(lm LinkMonitor) { - setLinkMonitor(lm) +func SetNetMon(lm *netmon.Monitor) { + setNetMon(lm) } // DebugInfo returns a string containing debug information about the tracked diff --git a/net/sockstats/sockstats_noop.go b/net/sockstats/sockstats_noop.go index 96fd0da9b0cc7..46b5ceaefeb1b 100644 --- a/net/sockstats/sockstats_noop.go +++ b/net/sockstats/sockstats_noop.go @@ -8,6 +8,7 @@ package sockstats import ( "context" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -29,7 +30,7 @@ func getValidation() *ValidationSockStats { return nil } -func setLinkMonitor(lm LinkMonitor) { +func setNetMon(lm *netmon.Monitor) { } func debugInfo() string { diff --git a/net/sockstats/sockstats_tsgo.go b/net/sockstats/sockstats_tsgo.go index de162e7e7ea99..e2dd05f222f21 100644 --- a/net/sockstats/sockstats_tsgo.go +++ b/net/sockstats/sockstats_tsgo.go @@ -16,6 +16,7 @@ import ( "time" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/util/clientmetric" ) @@ -84,7 +85,7 @@ func withSockStats(ctx context.Context, label Label, logf logger.Logf) context.C rxBytesCellularMetric: clientmetric.NewCounter(fmt.Sprintf("sockstats_rx_bytes_cellular_%s", label)), } - // We might be called before setLinkMonitor has been called (and we've + // We might be called before setNetMon has been called (and we've // had a chance to populate knownInterfaces). In that case, we'll have // to get the list of interfaces ourselves. if len(sockStats.knownInterfaces) == 0 { @@ -248,7 +249,7 @@ func getValidation() *ValidationSockStats { return r } -func setLinkMonitor(lm LinkMonitor) { +func setNetMon(lm *netmon.Monitor) { sockStats.mu.Lock() defer sockStats.mu.Unlock() diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index 3c3db009ca4ee..bb1dde397f81d 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -20,11 +20,11 @@ import ( "tailscale.com/net/dnscache" "tailscale.com/net/interfaces" "tailscale.com/net/netknob" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/types/logger" "tailscale.com/types/netmap" "tailscale.com/util/mak" - "tailscale.com/wgengine/monitor" ) // Dialer dials out of tailscaled, while taking care of details while @@ -50,16 +50,16 @@ type Dialer struct { netnsDialerOnce sync.Once netnsDialer netns.Dialer - mu sync.Mutex - closed bool - dns dnsMap - tunName string // tun device name - linkMon *monitor.Mon - linkMonUnregister func() - exitDNSDoHBase string // non-empty if DoH-proxying exit node in use; base URL+path (without '?') - dnsCache *dnscache.MessageCache // nil until first non-empty SetExitDNSDoH - nextSysConnID int - activeSysConns map[int]net.Conn // active connections not yet closed + mu sync.Mutex + closed bool + dns dnsMap + tunName string // tun device name + netMon *netmon.Monitor + netMonUnregister func() + exitDNSDoHBase string // non-empty if DoH-proxying exit node in use; base URL+path (without '?') + dnsCache *dnscache.MessageCache // nil until first non-empty SetExitDNSDoH + nextSysConnID int + activeSysConns map[int]net.Conn // active connections not yet closed } // sysConn wraps a net.Conn that was created using d.SystemDial. @@ -117,9 +117,9 @@ func (d *Dialer) Close() error { d.mu.Lock() defer d.mu.Unlock() d.closed = true - if d.linkMonUnregister != nil { - d.linkMonUnregister() - d.linkMonUnregister = nil + if d.netMonUnregister != nil { + d.netMonUnregister() + d.netMonUnregister = nil } for _, c := range d.activeSysConns { c.Close() @@ -128,15 +128,15 @@ func (d *Dialer) Close() error { return nil } -func (d *Dialer) SetLinkMonitor(mon *monitor.Mon) { +func (d *Dialer) SetNetMon(mon *netmon.Monitor) { d.mu.Lock() defer d.mu.Unlock() - if d.linkMonUnregister != nil { - go d.linkMonUnregister() - d.linkMonUnregister = nil + if d.netMonUnregister != nil { + go d.netMonUnregister() + d.netMonUnregister = nil } - d.linkMon = mon - d.linkMonUnregister = d.linkMon.RegisterChangeCallback(d.linkChanged) + d.netMon = mon + d.netMonUnregister = d.netMon.RegisterChangeCallback(d.linkChanged) } func (d *Dialer) linkChanged(major bool, state *interfaces.State) { @@ -163,10 +163,10 @@ func (d *Dialer) closeSysConn(id int) { } func (d *Dialer) interfaceIndexLocked(ifName string) (index int, ok bool) { - if d.linkMon == nil { + if d.netMon == nil { return 0, false } - st := d.linkMon.InterfaceState() + st := d.netMon.InterfaceState() iface, ok := st.Interface[ifName] if !ok { return 0, false diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 7e5236d8f82ba..6e7db9440a7ec 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -42,6 +42,7 @@ import ( "tailscale.com/logtail" "tailscale.com/logtail/filch" "tailscale.com/net/memnet" + "tailscale.com/net/netmon" "tailscale.com/net/proxymux" "tailscale.com/net/socks5" "tailscale.com/net/tsdial" @@ -51,7 +52,6 @@ import ( "tailscale.com/types/nettype" "tailscale.com/util/mak" "tailscale.com/wgengine" - "tailscale.com/wgengine/monitor" "tailscale.com/wgengine/netstack" ) @@ -106,7 +106,7 @@ type Server struct { initErr error lb *ipnlocal.LocalBackend netstack *netstack.Impl - linkMon *monitor.Mon + netMon *netmon.Monitor rootPath string // the state directory hostname string shutdownCtx context.Context @@ -356,8 +356,8 @@ func (s *Server) Close() error { if s.lb != nil { s.lb.Shutdown() } - if s.linkMon != nil { - s.linkMon.Close() + if s.netMon != nil { + s.netMon.Close() } if s.dialer != nil { s.dialer.Close() @@ -476,17 +476,17 @@ func (s *Server) start() (reterr error) { return err } - s.linkMon, err = monitor.New(logf) + s.netMon, err = netmon.New(logf) if err != nil { return err } - closePool.add(s.linkMon) + closePool.add(s.netMon) s.dialer = &tsdial.Dialer{Logf: logf} // mutated below (before used) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - ListenPort: 0, - LinkMonitor: s.linkMon, - Dialer: s.dialer, + ListenPort: 0, + NetMon: s.netMon, + Dialer: s.dialer, }) if err != nil { return err diff --git a/tstest/integration/tailscaled_deps_test_darwin.go b/tstest/integration/tailscaled_deps_test_darwin.go index edb891ee945c3..ed2e6e5ffce6b 100644 --- a/tstest/integration/tailscaled_deps_test_darwin.go +++ b/tstest/integration/tailscaled_deps_test_darwin.go @@ -24,6 +24,7 @@ import ( _ "tailscale.com/net/dns" _ "tailscale.com/net/dnsfallback" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netmon" _ "tailscale.com/net/netns" _ "tailscale.com/net/proxymux" _ "tailscale.com/net/socks5" @@ -47,7 +48,6 @@ import ( _ "tailscale.com/version" _ "tailscale.com/version/distro" _ "tailscale.com/wgengine" - _ "tailscale.com/wgengine/monitor" _ "tailscale.com/wgengine/netstack" _ "tailscale.com/wgengine/router" ) diff --git a/tstest/integration/tailscaled_deps_test_freebsd.go b/tstest/integration/tailscaled_deps_test_freebsd.go index edb891ee945c3..ed2e6e5ffce6b 100644 --- a/tstest/integration/tailscaled_deps_test_freebsd.go +++ b/tstest/integration/tailscaled_deps_test_freebsd.go @@ -24,6 +24,7 @@ import ( _ "tailscale.com/net/dns" _ "tailscale.com/net/dnsfallback" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netmon" _ "tailscale.com/net/netns" _ "tailscale.com/net/proxymux" _ "tailscale.com/net/socks5" @@ -47,7 +48,6 @@ import ( _ "tailscale.com/version" _ "tailscale.com/version/distro" _ "tailscale.com/wgengine" - _ "tailscale.com/wgengine/monitor" _ "tailscale.com/wgengine/netstack" _ "tailscale.com/wgengine/router" ) diff --git a/tstest/integration/tailscaled_deps_test_linux.go b/tstest/integration/tailscaled_deps_test_linux.go index edb891ee945c3..ed2e6e5ffce6b 100644 --- a/tstest/integration/tailscaled_deps_test_linux.go +++ b/tstest/integration/tailscaled_deps_test_linux.go @@ -24,6 +24,7 @@ import ( _ "tailscale.com/net/dns" _ "tailscale.com/net/dnsfallback" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netmon" _ "tailscale.com/net/netns" _ "tailscale.com/net/proxymux" _ "tailscale.com/net/socks5" @@ -47,7 +48,6 @@ import ( _ "tailscale.com/version" _ "tailscale.com/version/distro" _ "tailscale.com/wgengine" - _ "tailscale.com/wgengine/monitor" _ "tailscale.com/wgengine/netstack" _ "tailscale.com/wgengine/router" ) diff --git a/tstest/integration/tailscaled_deps_test_openbsd.go b/tstest/integration/tailscaled_deps_test_openbsd.go index edb891ee945c3..ed2e6e5ffce6b 100644 --- a/tstest/integration/tailscaled_deps_test_openbsd.go +++ b/tstest/integration/tailscaled_deps_test_openbsd.go @@ -24,6 +24,7 @@ import ( _ "tailscale.com/net/dns" _ "tailscale.com/net/dnsfallback" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netmon" _ "tailscale.com/net/netns" _ "tailscale.com/net/proxymux" _ "tailscale.com/net/socks5" @@ -47,7 +48,6 @@ import ( _ "tailscale.com/version" _ "tailscale.com/version/distro" _ "tailscale.com/wgengine" - _ "tailscale.com/wgengine/monitor" _ "tailscale.com/wgengine/netstack" _ "tailscale.com/wgengine/router" ) diff --git a/tstest/integration/tailscaled_deps_test_windows.go b/tstest/integration/tailscaled_deps_test_windows.go index ef995d88ef7af..33620c9d9260e 100644 --- a/tstest/integration/tailscaled_deps_test_windows.go +++ b/tstest/integration/tailscaled_deps_test_windows.go @@ -32,6 +32,7 @@ import ( _ "tailscale.com/net/dns" _ "tailscale.com/net/dnsfallback" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netmon" _ "tailscale.com/net/netns" _ "tailscale.com/net/proxymux" _ "tailscale.com/net/socks5" @@ -56,7 +57,6 @@ import ( _ "tailscale.com/version/distro" _ "tailscale.com/wf" _ "tailscale.com/wgengine" - _ "tailscale.com/wgengine/monitor" _ "tailscale.com/wgengine/netstack" _ "tailscale.com/wgengine/router" ) diff --git a/wgengine/bench/wg.go b/wgengine/bench/wg.go index c7b01af28a2aa..dd73d560f0df9 100644 --- a/wgengine/bench/wg.go +++ b/wgengine/bench/wg.go @@ -39,10 +39,10 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip. traf: traf, } e1, err := wgengine.NewUserspaceEngine(l1, wgengine.Config{ - Router: router.NewFake(l1), - LinkMonitor: nil, - ListenPort: 0, - Tun: t1, + Router: router.NewFake(l1), + NetMon: nil, + ListenPort: 0, + Tun: t1, }) if err != nil { log.Fatalf("e1 init: %v", err) @@ -63,10 +63,10 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip. traf: traf, } e2, err := wgengine.NewUserspaceEngine(l2, wgengine.Config{ - Router: router.NewFake(l2), - LinkMonitor: nil, - ListenPort: 0, - Tun: t2, + Router: router.NewFake(l2), + NetMon: nil, + ListenPort: 0, + Tun: t2, }) if err != nil { log.Fatalf("e2 init: %v", err) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index d8595e2bad536..5a0a2bf0dd2a1 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -47,6 +47,7 @@ import ( "tailscale.com/net/netaddr" "tailscale.com/net/netcheck" "tailscale.com/net/neterror" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/packet" "tailscale.com/net/portmapper" @@ -69,7 +70,6 @@ import ( "tailscale.com/util/uniq" "tailscale.com/version" "tailscale.com/wgengine/capture" - "tailscale.com/wgengine/monitor" ) const ( @@ -279,7 +279,7 @@ type Conn struct { idleFunc func() time.Duration // nil means unknown testOnlyPacketListener nettype.PacketListener noteRecvActivity func(key.NodePublic) // or nil, see Options.NoteRecvActivity - linkMon *monitor.Mon // or nil + netMon *netmon.Monitor // or nil // ================================================================ // No locking required to access these fields, either because @@ -573,9 +573,9 @@ type Options struct { // not hold Conn.mu while calling it. NoteRecvActivity func(key.NodePublic) - // LinkMonitor is the link monitor to use. + // NetMon is the network monitor to use. // With one, the portmapper won't be used. - LinkMonitor *monitor.Mon + NetMon *netmon.Monitor } func (o *Options) logf() logger.Logf { @@ -643,10 +643,10 @@ func NewConn(opts Options) (*Conn, error) { c.testOnlyPacketListener = opts.TestOnlyPacketListener c.noteRecvActivity = opts.NoteRecvActivity c.portMapper = portmapper.NewClient(logger.WithPrefix(c.logf, "portmapper: "), nil, c.onPortMapChanged) - if opts.LinkMonitor != nil { - c.portMapper.SetGatewayLookupFunc(opts.LinkMonitor.GatewayAndSelfIP) + if opts.NetMon != nil { + c.portMapper.SetGatewayLookupFunc(opts.NetMon.GatewayAndSelfIP) } - c.linkMon = opts.LinkMonitor + c.netMon = opts.NetMon if err := c.rebind(keepCurrentPort); err != nil { return nil, err @@ -3369,8 +3369,8 @@ func (c *Conn) Rebind() { } var ifIPs []netip.Prefix - if c.linkMon != nil { - st := c.linkMon.InterfaceState() + if c.netMon != nil { + st := c.netMon.InterfaceState() defIf := st.DefaultRouteInterface ifIPs = st.InterfaceIPs[defIf] c.logf("Rebind; defIf=%q, ips=%v", defIf, ifIPs) diff --git a/wgengine/router/router.go b/wgengine/router/router.go index f6e55b7d9e6e0..11668a70e96a9 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -10,9 +10,9 @@ import ( "reflect" "github.com/tailscale/wireguard-go/tun" + "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/types/preftype" - "tailscale.com/wgengine/monitor" ) // Router is responsible for managing the system network stack. @@ -34,11 +34,11 @@ type Router interface { // New returns a new Router for the current platform, using the // provided tun device. // -// If linkMon is nil, it's not used. It's currently (2021-07-20) only +// If netMon is nil, it's not used. It's currently (2021-07-20) only // used on Linux in some situations. -func New(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { +func New(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { logf = logger.WithPrefix(logf, "router: ") - return newUserspaceRouter(logf, tundev, linkMon) + return newUserspaceRouter(logf, tundev, netMon) } // Cleanup restores the system network configuration to its original state diff --git a/wgengine/router/router_darwin.go b/wgengine/router/router_darwin.go index 96076e6e66953..38fc78f82eed3 100644 --- a/wgengine/router/router_darwin.go +++ b/wgengine/router/router_darwin.go @@ -5,12 +5,12 @@ package router import ( "github.com/tailscale/wireguard-go/tun" + "tailscale.com/net/netmon" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { - return newUserspaceBSDRouter(logf, tundev, linkMon) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, netMon) } func cleanup(logger.Logf, string) { diff --git a/wgengine/router/router_default.go b/wgengine/router/router_default.go index 4fcf65ad8acba..9fee5d8f2a304 100644 --- a/wgengine/router/router_default.go +++ b/wgengine/router/router_default.go @@ -10,11 +10,11 @@ import ( "runtime" "github.com/tailscale/wireguard-go/tun" + "tailscale.com/net/netmon" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) -func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, linkMon *monitor.Mon) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor) (Router, error) { return nil, fmt.Errorf("unsupported OS %q", runtime.GOOS) } diff --git a/wgengine/router/router_freebsd.go b/wgengine/router/router_freebsd.go index 13e88696906f6..84dccbca07f2f 100644 --- a/wgengine/router/router_freebsd.go +++ b/wgengine/router/router_freebsd.go @@ -5,8 +5,8 @@ package router import ( "github.com/tailscale/wireguard-go/tun" + "tailscale.com/net/netmon" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) // For now this router only supports the userspace WireGuard implementations. @@ -14,8 +14,8 @@ import ( // Work is currently underway for an in-kernel FreeBSD implementation of wireguard // https://svnweb.freebsd.org/base?view=revision&revision=357986 -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { - return newUserspaceBSDRouter(logf, tundev, linkMon) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, netMon) } func cleanup(logf logger.Logf, interfaceName string) { diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 1fd733fa0efeb..85c3799c42e33 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -24,12 +24,12 @@ import ( "golang.org/x/sys/unix" "golang.org/x/time/rate" "tailscale.com/envknob" + "tailscale.com/net/netmon" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/types/preftype" "tailscale.com/util/multierr" "tailscale.com/version/distro" - "tailscale.com/wgengine/monitor" ) const ( @@ -94,8 +94,8 @@ type linuxRouter struct { closed atomic.Bool logf func(fmt string, args ...any) tunname string - linkMon *monitor.Mon - unregLinkMon func() + netMon *netmon.Monitor + unregNetMon func() addrs map[netip.Prefix]bool routes map[netip.Prefix]bool localRoutes map[netip.Prefix]bool @@ -121,7 +121,7 @@ type linuxRouter struct { cmd commandRunner } -func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, linkMon *monitor.Mon) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor) (Router, error) { tunname, err := tunDev.Name() if err != nil { return nil, err @@ -156,15 +156,15 @@ func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, linkMon *monitor.Mo ambientCapNetAdmin: useAmbientCaps(), } - return newUserspaceRouterAdvanced(logf, tunname, linkMon, ipt4, ipt6, cmd, supportsV6, supportsV6NAT) + return newUserspaceRouterAdvanced(logf, tunname, netMon, ipt4, ipt6, cmd, supportsV6, supportsV6NAT) } -func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monitor.Mon, netfilter4, netfilter6 netfilterRunner, cmd commandRunner, supportsV6, supportsV6NAT bool) (Router, error) { +func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, netMon *netmon.Monitor, netfilter4, netfilter6 netfilterRunner, cmd commandRunner, supportsV6, supportsV6NAT bool) (Router, error) { r := &linuxRouter{ logf: logf, tunname: tunname, netfilterMode: netfilterOff, - linkMon: linkMon, + netMon: netMon, v6Available: supportsV6, v6NATAvailable: supportsV6NAT, @@ -336,8 +336,8 @@ func (r *linuxRouter) useIPCommand() bool { return !ok } -// onIPRuleDeleted is the callback from the link monitor for when an IP policy -// rule is deleted. See Issue 1591. +// onIPRuleDeleted is the callback from the network monitor for when an IP +// policy rule is deleted. See Issue 1591. // // If an ip rule is deleted (with pref number 52xx, as Tailscale sets), then // set a timer to restore our rules, in case they were deleted. The timer lets @@ -372,8 +372,8 @@ func (r *linuxRouter) onIPRuleDeleted(table uint8, priority uint32) { } func (r *linuxRouter) Up() error { - if r.unregLinkMon == nil && r.linkMon != nil { - r.unregLinkMon = r.linkMon.RegisterRuleDeleteCallback(r.onIPRuleDeleted) + if r.unregNetMon == nil && r.netMon != nil { + r.unregNetMon = r.netMon.RegisterRuleDeleteCallback(r.onIPRuleDeleted) } if err := r.addIPRules(); err != nil { return fmt.Errorf("adding IP rules: %w", err) @@ -390,8 +390,8 @@ func (r *linuxRouter) Up() error { func (r *linuxRouter) Close() error { r.closed.Store(true) - if r.unregLinkMon != nil { - r.unregLinkMon() + if r.unregNetMon != nil { + r.unregNetMon() } if err := r.downInterface(); err != nil { return err diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index 1883e6b4b462d..acd2e6c10365b 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -21,9 +21,9 @@ import ( "github.com/tailscale/wireguard-go/tun" "github.com/vishvananda/netlink" "golang.org/x/exp/slices" + "tailscale.com/net/netmon" "tailscale.com/tstest" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) func TestRouterStates(t *testing.T) { @@ -320,7 +320,7 @@ ip route add throw 192.168.0.0/24 table 52` + basic, }, } - mon, err := monitor.New(logger.Discard) + mon, err := netmon.New(logger.Discard) if err != nil { t.Fatal(err) } @@ -659,7 +659,7 @@ func createTestTUN(t *testing.T) tun.Device { type linuxTest struct { tun tun.Device - mon *monitor.Mon + mon *netmon.Monitor r *linuxRouter logOutput tstest.MemLogger } @@ -684,7 +684,7 @@ func newLinuxRootTest(t *testing.T) *linuxTest { logf := lt.logOutput.Logf - mon, err := monitor.New(logger.Discard) + mon, err := netmon.New(logger.Discard) if err != nil { lt.Close() t.Fatal(err) diff --git a/wgengine/router/router_openbsd.go b/wgengine/router/router_openbsd.go index 6bbd0e06cbfd5..c23d37e474b67 100644 --- a/wgengine/router/router_openbsd.go +++ b/wgengine/router/router_openbsd.go @@ -12,8 +12,8 @@ import ( "github.com/tailscale/wireguard-go/tun" "go4.org/netipx" + "tailscale.com/net/netmon" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) // For now this router only supports the WireGuard userspace implementation. @@ -22,14 +22,14 @@ import ( type openbsdRouter struct { logf logger.Logf - linkMon *monitor.Mon + netMon *netmon.Monitor tunname string local4 netip.Prefix local6 netip.Prefix routes map[netip.Prefix]struct{} } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err @@ -37,7 +37,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mo return &openbsdRouter{ logf: logf, - linkMon: linkMon, + netMon: netMon, tunname: tunname, }, nil } diff --git a/wgengine/router/router_userspace_bsd.go b/wgengine/router/router_userspace_bsd.go index b1f2d63679f1a..61c06037deb2d 100644 --- a/wgengine/router/router_userspace_bsd.go +++ b/wgengine/router/router_userspace_bsd.go @@ -14,21 +14,21 @@ import ( "github.com/tailscale/wireguard-go/tun" "go4.org/netipx" + "tailscale.com/net/netmon" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/version" - "tailscale.com/wgengine/monitor" ) type userspaceBSDRouter struct { logf logger.Logf - linkMon *monitor.Mon + netMon *netmon.Monitor tunname string local []netip.Prefix routes map[netip.Prefix]bool } -func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { +func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err @@ -36,7 +36,7 @@ func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor return &userspaceBSDRouter{ logf: logf, - linkMon: linkMon, + netMon: netMon, tunname: tunname, }, nil } diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index 8657bf26bbdba..155c29b469821 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -22,19 +22,19 @@ import ( "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "tailscale.com/logtail/backoff" "tailscale.com/net/dns" + "tailscale.com/net/netmon" "tailscale.com/types/logger" - "tailscale.com/wgengine/monitor" ) type winRouter struct { logf func(fmt string, args ...any) - linkMon *monitor.Mon // may be nil + netMon *netmon.Monitor // may be nil nativeTun *tun.NativeTun routeChangeCallback *winipcfg.RouteChangeCallback firewall *firewallTweaker } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { nativeTun := tundev.(*tun.NativeTun) luid := winipcfg.LUID(nativeTun.LUID()) guid, err := luid.GUID() @@ -44,7 +44,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mo return &winRouter{ logf: logf, - linkMon: linkMon, + netMon: netMon, nativeTun: nativeTun, firewall: &firewallTweaker{ logf: logger.WithPrefix(logf, "firewall: "), diff --git a/wgengine/userspace.go b/wgengine/userspace.go index d60c12dffab2e..c7caf1492623b 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -28,6 +28,7 @@ import ( "tailscale.com/net/dns/resolver" "tailscale.com/net/flowtrack" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/net/packet" "tailscale.com/net/sockstats" "tailscale.com/net/tsaddr" @@ -48,7 +49,6 @@ import ( "tailscale.com/wgengine/capture" "tailscale.com/wgengine/filter" "tailscale.com/wgengine/magicsock" - "tailscale.com/wgengine/monitor" "tailscale.com/wgengine/netlog" "tailscale.com/wgengine/router" "tailscale.com/wgengine/wgcfg" @@ -84,21 +84,21 @@ const statusPollInterval = 1 * time.Minute const networkLoggerUploadTimeout = 5 * time.Second type userspaceEngine struct { - logf logger.Logf - wgLogger *wglog.Logger //a wireguard-go logging wrapper - reqCh chan struct{} - waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool - timeNow func() mono.Time - tundev *tstun.Wrapper - wgdev *device.Device - router router.Router - confListenPort uint16 // original conf.ListenPort - dns *dns.Manager - magicConn *magicsock.Conn - linkMon *monitor.Mon - linkMonOwned bool // whether we created linkMon (and thus need to close it) - linkMonUnregister func() // unsubscribes from changes; used regardless of linkMonOwned - birdClient BIRDClient // or nil + logf logger.Logf + wgLogger *wglog.Logger //a wireguard-go logging wrapper + reqCh chan struct{} + waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool + timeNow func() mono.Time + tundev *tstun.Wrapper + wgdev *device.Device + router router.Router + confListenPort uint16 // original conf.ListenPort + dns *dns.Manager + magicConn *magicsock.Conn + netMon *netmon.Monitor + netMonOwned bool // whether we created netMon (and thus need to close it) + netMonUnregister func() // unsubscribes from changes; used regardless of netMonOwned + birdClient BIRDClient // or nil testMaybeReconfigHook func() // for tests; if non-nil, fires if maybeReconfigWireguardLocked called @@ -199,9 +199,9 @@ type Config struct { // If nil, a fake OSConfigurator that does nothing is used. DNS dns.OSConfigurator - // LinkMonitor optionally provides an existing link monitor to re-use. - // If nil, a new link monitor is created. - LinkMonitor *monitor.Mon + // NetMon optionally provides an existing network monitor to re-use. + // If nil, a new network monitor is created. + NetMon *netmon.Monitor // Dialer is the dialer to use for outbound connections. // If nil, a new Dialer is created @@ -316,34 +316,34 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(nil)) e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(nil)) - if conf.LinkMonitor != nil { - e.linkMon = conf.LinkMonitor + if conf.NetMon != nil { + e.netMon = conf.NetMon } else { - mon, err := monitor.New(logf) + mon, err := netmon.New(logf) if err != nil { return nil, err } closePool.add(mon) - e.linkMon = mon - e.linkMonOwned = true + e.netMon = mon + e.netMonOwned = true } tunName, _ := conf.Tun.Name() conf.Dialer.SetTUNName(tunName) - conf.Dialer.SetLinkMonitor(e.linkMon) - e.dns = dns.NewManager(logf, conf.DNS, e.linkMon, conf.Dialer, fwdDNSLinkSelector{e, tunName}) + conf.Dialer.SetNetMon(e.netMon) + e.dns = dns.NewManager(logf, conf.DNS, e.netMon, conf.Dialer, fwdDNSLinkSelector{e, tunName}) // TODO: there's probably a better place for this - sockstats.SetLinkMonitor(e.linkMon) + sockstats.SetNetMon(e.netMon) - logf("link state: %+v", e.linkMon.InterfaceState()) + logf("link state: %+v", e.netMon.InterfaceState()) - unregisterMonWatch := e.linkMon.RegisterChangeCallback(func(changed bool, st *interfaces.State) { + unregisterMonWatch := e.netMon.RegisterChangeCallback(func(changed bool, st *interfaces.State) { tshttpproxy.InvalidateCache() e.linkChange(changed, st) }) closePool.addFunc(unregisterMonWatch) - e.linkMonUnregister = unregisterMonWatch + e.netMonUnregister = unregisterMonWatch endpointsFn := func(endpoints []tailcfg.Endpoint) { e.mu.Lock() @@ -359,7 +359,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) DERPActiveFunc: e.RequestStatus, IdleFunc: e.tundev.IdleDuration, NoteRecvActivity: e.noteRecvActivity, - LinkMonitor: e.linkMon, + NetMon: e.netMon, } var err error @@ -368,7 +368,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) return nil, fmt.Errorf("wgengine: %v", err) } closePool.add(e.magicConn) - e.magicConn.SetNetworkUp(e.linkMon.InterfaceState().AnyInterfaceUp()) + e.magicConn.SetNetworkUp(e.netMon.InterfaceState().AnyInterfaceUp()) tsTUNDev.SetDiscoKey(e.magicConn.DiscoPublicKey()) @@ -455,8 +455,8 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) if err := e.router.Set(nil); err != nil { return nil, fmt.Errorf("router.Set(nil): %w", err) } - e.logf("Starting link monitor...") - e.linkMon.Start() + e.logf("Starting network monitor...") + e.netMon.Start() e.logf("Engine created.") return e, nil @@ -1094,9 +1094,9 @@ func (e *userspaceEngine) Close() { r := bufio.NewReader(strings.NewReader("")) e.wgdev.IpcSetOperation(r) e.magicConn.Close() - e.linkMonUnregister() - if e.linkMonOwned { - e.linkMon.Close() + e.netMonUnregister() + if e.netMonOwned { + e.netMon.Close() } e.dns.Down() e.router.Close() @@ -1119,15 +1119,15 @@ func (e *userspaceEngine) Wait() { <-e.waitCh } -func (e *userspaceEngine) GetLinkMonitor() *monitor.Mon { - return e.linkMon +func (e *userspaceEngine) GetNetMon() *netmon.Monitor { + return e.netMon } // LinkChange signals a network change event. It's currently -// (2021-03-03) only called on Android. On other platforms, linkMon +// (2021-03-03) only called on Android. On other platforms, netMon // generates link change events for us. func (e *userspaceEngine) LinkChange(_ bool) { - e.linkMon.InjectEvent() + e.netMon.InjectEvent() } func (e *userspaceEngine) linkChange(changed bool, cur *interfaces.State) { diff --git a/wgengine/watchdog.go b/wgengine/watchdog.go index c0129bd141590..76abfa8cc0914 100644 --- a/wgengine/watchdog.go +++ b/wgengine/watchdog.go @@ -18,6 +18,7 @@ import ( "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netmon" "tailscale.com/net/tstun" "tailscale.com/tailcfg" "tailscale.com/types/key" @@ -25,7 +26,6 @@ import ( "tailscale.com/wgengine/capture" "tailscale.com/wgengine/filter" "tailscale.com/wgengine/magicsock" - "tailscale.com/wgengine/monitor" "tailscale.com/wgengine/router" "tailscale.com/wgengine/wgcfg" ) @@ -126,8 +126,8 @@ func (e *watchdogEngine) watchdog(name string, fn func()) { func (e *watchdogEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *dns.Config, debug *tailcfg.Debug) error { return e.watchdogErr("Reconfig", func() error { return e.wrap.Reconfig(cfg, routerCfg, dnsCfg, debug) }) } -func (e *watchdogEngine) GetLinkMonitor() *monitor.Mon { - return e.wrap.GetLinkMonitor() +func (e *watchdogEngine) GetNetMon() *netmon.Monitor { + return e.wrap.GetNetMon() } func (e *watchdogEngine) GetFilter() *filter.Filter { return e.wrap.GetFilter() diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go index 4178ec619c04b..4d4e240c1ec49 100644 --- a/wgengine/wgengine.go +++ b/wgengine/wgengine.go @@ -10,12 +10,12 @@ import ( "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" + "tailscale.com/net/netmon" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/netmap" "tailscale.com/wgengine/capture" "tailscale.com/wgengine/filter" - "tailscale.com/wgengine/monitor" "tailscale.com/wgengine/router" "tailscale.com/wgengine/wgcfg" ) @@ -92,8 +92,8 @@ type Engine interface { // WireGuard status changes. SetStatusCallback(StatusCallback) - // GetLinkMonitor returns the link monitor. - GetLinkMonitor() *monitor.Mon + // GetNetMon returns the network monitor. + GetNetMon() *netmon.Monitor // RequestStatus requests a WireGuard status update right // away, sent to the callback registered via SetStatusCallback. @@ -119,7 +119,7 @@ type Engine interface { // // Deprecated: don't use this method. It was removed shortly // before the Tailscale 1.6 release when we remembered that - // Android doesn't use the Linux-based link monitor and has + // Android doesn't use the Linux-based network monitor and has // its own mechanism that uses LinkChange. Android is the only // caller of this method now. Don't add more. LinkChange(isExpensive bool) From 7f17e04a5a7952f9c1ed0e23b799a21a124a5a51 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Thu, 20 Apr 2023 10:53:02 -0700 Subject: [PATCH 014/331] log/sockstatlog: bump logInterval to 10 seconds We are seeing indications that some devices are still getting into an upload loop. Bump logInterval in case these devices are on slow connections that are taking more than 3 seconds to uploads sockstats. Updates #7719 Signed-off-by: Will Norris --- log/sockstatlog/logger.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/log/sockstatlog/logger.go b/log/sockstatlog/logger.go index 9aed1deb0ab44..683342a08000a 100644 --- a/log/sockstatlog/logger.go +++ b/log/sockstatlog/logger.go @@ -33,7 +33,7 @@ const pollInterval = time.Second / 10 // logInterval specifies how often to log sockstat events to disk. // This delay is added to prevent an infinite loop when logs are uploaded, // which itself creates additional sockstat events. -const logInterval = 3 * time.Second +const logInterval = 10 * time.Second // maxLogFileSize specifies the maximum size of a log file before it is rotated. // Our logs are fairly compact, and we are mostly only looking at a few hours of data. @@ -83,7 +83,7 @@ type event struct { // SockstatLogID reproducibly derives a new logid.PrivateID for sockstat logging from a node's public backend log ID. // The returned PrivateID is the sha256 sum of logID + "sockstat". // If a node's public log ID becomes known, it is trivial to spoof sockstat logs for that node. -// Given the this is just for debugging, we're not too concerned about that. +// Given that this is just for debugging, we're not too concerned about that. func SockstatLogID(logID logid.PublicID) logid.PrivateID { return logid.PrivateID(sha256.Sum256([]byte(logID.String() + "sockstat"))) } From 7330aa593e3701cb193ceff0bc26eda3bc62df83 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Mon, 17 Apr 2023 16:01:41 -0700 Subject: [PATCH 015/331] all: avoid repeated default interface lookups On some platforms (notably macOS and iOS) we look up the default interface to bind outgoing connections to. This is both duplicated work and results in logspam when the default interface is not available (i.e. when a phone has no connectivity, we log an error and thus cause more things that we will try to upload and fail). Fixed by passing around a netmon.Monitor to more places, so that we can use its cached interface state. Fixes #7850 Updates #7621 Signed-off-by: Mihai Parparita --- cmd/derper/depaware.txt | 2 +- cmd/tailscale/cli/netcheck.go | 8 +++++- cmd/tailscale/depaware.txt | 2 +- cmd/tailscaled/debug.go | 4 +-- cmd/tailscaled/tailscaled.go | 25 +++++++++-------- cmd/tailscaled/tailscaled_windows.go | 8 +++++- cmd/tsconnect/wasm/wasm_js.go | 2 +- control/controlclient/direct.go | 5 ++-- control/controlclient/noise.go | 12 +++++++- control/controlclient/noise_test.go | 2 +- control/controlhttp/client.go | 4 ++- control/controlhttp/constants.go | 3 ++ derp/derphttp/derphttp_client.go | 10 +++++-- ipn/ipnlocal/local.go | 2 +- ipn/ipnserver/proxyconnect.go | 3 +- ipn/ipnserver/server.go | 9 ++++-- ipn/localapi/debugderp.go | 4 +-- ipn/localapi/localapi.go | 9 ++++-- log/sockstatlog/logger.go | 6 ++-- log/sockstatlog/logger_test.go | 2 +- logpolicy/logpolicy.go | 35 +++++++++++++++-------- net/dns/manager.go | 1 + net/dns/resolver/forwarder.go | 3 +- net/dns/resolver/macios_ext.go | 4 +-- net/dns/resolver/tsdns_test.go | 2 +- net/dnscache/dnscache.go | 6 ++++ net/dnsfallback/dnsfallback.go | 16 +++++++---- net/netcheck/netcheck.go | 32 +++++++++++++++------ net/netns/netns.go | 16 +++++++---- net/netns/netns_android.go | 3 +- net/netns/netns_darwin.go | 42 ++++++++++++++++++---------- net/netns/netns_darwin_test.go | 4 +-- net/netns/netns_default.go | 3 +- net/netns/netns_linux.go | 3 +- net/netns/netns_test.go | 2 +- net/netns/netns_windows.go | 3 +- net/ping/ping.go | 10 ++++--- net/portmapper/igd_test.go | 2 +- net/portmapper/portmapper.go | 10 +++++-- net/portmapper/portmapper_test.go | 6 ++-- net/portmapper/upnp.go | 2 +- net/sockstats/sockstats.go | 4 +-- net/sockstats/sockstats_noop.go | 2 +- net/sockstats/sockstats_tsgo.go | 6 ++-- net/tsdial/tsdial.go | 6 ++-- prober/derp.go | 2 +- tsnet/tsnet.go | 6 ++-- wgengine/magicsock/magicsock.go | 7 +++-- wgengine/netlog/logger.go | 6 ++-- wgengine/userspace.go | 2 +- 50 files changed, 242 insertions(+), 126 deletions(-) diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 7e82305d1253a..b40ca360a95bc 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -86,7 +86,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa 💣 tailscale.com/net/interfaces from tailscale.com/net/netns+ tailscale.com/net/netaddr from tailscale.com/ipn+ tailscale.com/net/netknob from tailscale.com/net/netns - tailscale.com/net/netmon from tailscale.com/net/sockstats + tailscale.com/net/netmon from tailscale.com/net/sockstats+ tailscale.com/net/netns from tailscale.com/derp/derphttp tailscale.com/net/netutil from tailscale.com/client/tailscale tailscale.com/net/packet from tailscale.com/wgengine/filter diff --git a/cmd/tailscale/cli/netcheck.go b/cmd/tailscale/cli/netcheck.go index 0c2f7acd1d0cc..bac5a0a483c14 100644 --- a/cmd/tailscale/cli/netcheck.go +++ b/cmd/tailscale/cli/netcheck.go @@ -19,6 +19,7 @@ import ( "tailscale.com/envknob" "tailscale.com/ipn" "tailscale.com/net/netcheck" + "tailscale.com/net/netmon" "tailscale.com/net/portmapper" "tailscale.com/tailcfg" "tailscale.com/types/logger" @@ -45,9 +46,14 @@ var netcheckArgs struct { } func runNetcheck(ctx context.Context, args []string) error { + logf := logger.WithPrefix(log.Printf, "portmap: ") + netMon, err := netmon.New(logf) + if err != nil { + return err + } c := &netcheck.Client{ UDPBindAddr: envknob.String("TS_DEBUG_NETCHECK_UDP_BIND"), - PortMapper: portmapper.NewClient(logger.WithPrefix(log.Printf, "portmap: "), nil, nil), + PortMapper: portmapper.NewClient(logf, netMon, nil, nil), UseDNSCache: false, // always resolve, don't cache } if netcheckArgs.verbose { diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index b146ec5679ebd..5b644992e7106 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -74,7 +74,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli tailscale.com/net/neterror from tailscale.com/net/netcheck+ tailscale.com/net/netknob from tailscale.com/net/netns - tailscale.com/net/netmon from tailscale.com/net/sockstats + tailscale.com/net/netmon from tailscale.com/net/sockstats+ tailscale.com/net/netns from tailscale.com/derp/derphttp+ tailscale.com/net/netutil from tailscale.com/client/tailscale+ tailscale.com/net/packet from tailscale.com/wgengine/filter+ diff --git a/cmd/tailscaled/debug.go b/cmd/tailscaled/debug.go index 8c1ad88b17ff5..b6a95ba495616 100644 --- a/cmd/tailscaled/debug.go +++ b/cmd/tailscaled/debug.go @@ -193,8 +193,8 @@ func checkDerp(ctx context.Context, derpRegion string) (err error) { priv1 := key.NewNode() priv2 := key.NewNode() - c1 := derphttp.NewRegionClient(priv1, log.Printf, getRegion) - c2 := derphttp.NewRegionClient(priv2, log.Printf, getRegion) + c1 := derphttp.NewRegionClient(priv1, log.Printf, nil, getRegion) + c2 := derphttp.NewRegionClient(priv2, log.Printf, nil, getRegion) defer func() { if err != nil { c1.Close() diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 3bae560a291d8..d2c28de99ee3d 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -329,7 +329,15 @@ var logPol *logpolicy.Policy var debugMux *http.ServeMux func run() error { - pol := logpolicy.New(logtail.CollectionNode) + var logf logger.Logf = log.Printf + netMon, err := netmon.New(func(format string, args ...any) { + logf(format, args...) + }) + if err != nil { + return fmt.Errorf("netmon.New: %w", err) + } + + pol := logpolicy.New(logtail.CollectionNode, netMon) pol.SetVerbosityLevel(args.verbose) logPol = pol defer func() { @@ -353,7 +361,6 @@ func run() error { return nil } - var logf logger.Logf = log.Printf if envknob.Bool("TS_DEBUG_MEMORY") { logf = logger.RusagePrefixLog(logf) } @@ -379,10 +386,10 @@ func run() error { debugMux = newDebugMux() } - return startIPNServer(context.Background(), logf, pol.PublicID) + return startIPNServer(context.Background(), logf, pol.PublicID, netMon) } -func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID) error { +func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) error { ln, err := safesocket.Listen(args.socketpath) if err != nil { return fmt.Errorf("safesocket.Listen: %v", err) @@ -408,7 +415,7 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID) } }() - srv := ipnserver.New(logf, logID) + srv := ipnserver.New(logf, logID, netMon) if debugMux != nil { debugMux.HandleFunc("/debug/ipn", srv.ServeHTMLStatus) } @@ -426,7 +433,7 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID) return } } - lb, err := getLocalBackend(ctx, logf, logID) + lb, err := getLocalBackend(ctx, logf, logID, netMon) if err == nil { logf("got LocalBackend in %v", time.Since(t0).Round(time.Millisecond)) srv.SetLocalBackend(lb) @@ -450,11 +457,7 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID) return nil } -func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID) (_ *ipnlocal.LocalBackend, retErr error) { - netMon, err := netmon.New(logf) - if err != nil { - return nil, fmt.Errorf("netmon.New: %w", err) - } +func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) (_ *ipnlocal.LocalBackend, retErr error) { if logPol != nil { logPol.Logtail.SetNetMon(netMon) } diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go index a654dadf40d14..077d3f99f2c7f 100644 --- a/cmd/tailscaled/tailscaled_windows.go +++ b/cmd/tailscaled/tailscaled_windows.go @@ -45,6 +45,7 @@ import ( "tailscale.com/logpolicy" "tailscale.com/logtail/backoff" "tailscale.com/net/dns" + "tailscale.com/net/netmon" "tailscale.com/net/tstun" "tailscale.com/types/logger" "tailscale.com/types/logid" @@ -291,8 +292,13 @@ func beWindowsSubprocess() bool { } }() + netMon, err := netmon.New(log.Printf) + if err != nil { + log.Printf("Could not create netMon: %v", err) + netMon = nil + } publicLogID, _ := logid.ParsePublicID(logID) - err := startIPNServer(ctx, log.Printf, publicLogID) + err = startIPNServer(ctx, log.Printf, publicLogID, netMon) if err != nil { log.Fatalf("ipnserver: %v", err) } diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index f94b850a2ba4d..a1b0fd95e0a15 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -123,7 +123,7 @@ func newIPN(jsConfig js.Value) map[string]any { } logid := lpc.PublicID - srv := ipnserver.New(logf, logid) + srv := ipnserver.New(logf, logid, nil /* no netMon */) lb, err := ipnlocal.NewLocalBackend(logf, logid, store, dialer, eng, controlclient.LoginEphemeral) if err != nil { log.Fatalf("ipnlocal.NewLocalBackend: %v", err) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 85bd7f07b07f7..cf6fd998762cb 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -211,8 +211,9 @@ func NewDirect(opts Options) (*Direct, error) { dnsCache := &dnscache.Resolver{ Forward: dnscache.Get().Forward, // use default cache's forwarder UseLastGood: true, - LookupIPFallback: dnsfallback.Lookup(opts.Logf), + LookupIPFallback: dnsfallback.MakeLookupFunc(opts.Logf, opts.NetMon), Logf: opts.Logf, + NetMon: opts.NetMon, } tr := http.DefaultTransport.(*http.Transport).Clone() tr.Proxy = tshttpproxy.ProxyFromEnvironment @@ -1508,7 +1509,7 @@ func (c *Direct) getNoiseClient() (*NoiseClient, error) { return nil, err } c.logf("creating new noise client") - nc, err := NewNoiseClient(k, serverNoiseKey, c.serverURL, c.dialer, dp) + nc, err := NewNoiseClient(k, serverNoiseKey, c.serverURL, c.dialer, c.logf, c.netMon, dp) if err != nil { return nil, err } diff --git a/control/controlclient/noise.go b/control/controlclient/noise.go index 826b0c24924a2..61c472a356dc3 100644 --- a/control/controlclient/noise.go +++ b/control/controlclient/noise.go @@ -19,9 +19,11 @@ import ( "golang.org/x/net/http2" "tailscale.com/control/controlbase" "tailscale.com/control/controlhttp" + "tailscale.com/net/netmon" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/types/key" + "tailscale.com/types/logger" "tailscale.com/util/mak" "tailscale.com/util/multierr" "tailscale.com/util/singleflight" @@ -167,6 +169,9 @@ type NoiseClient struct { // be nil. dialPlan func() *tailcfg.ControlDialPlan + logf logger.Logf + netMon *netmon.Monitor + // mu only protects the following variables. mu sync.Mutex last *noiseConn // or nil @@ -177,8 +182,9 @@ type NoiseClient struct { // NewNoiseClient returns a new noiseClient for the provided server and machine key. // serverURL is of the form https://: (no trailing slash). // +// netMon may be nil, if non-nil it's used to do faster interface lookups. // dialPlan may be nil -func NewNoiseClient(privKey key.MachinePrivate, serverPubKey key.MachinePublic, serverURL string, dialer *tsdial.Dialer, dialPlan func() *tailcfg.ControlDialPlan) (*NoiseClient, error) { +func NewNoiseClient(privKey key.MachinePrivate, serverPubKey key.MachinePublic, serverURL string, dialer *tsdial.Dialer, logf logger.Logf, netMon *netmon.Monitor, dialPlan func() *tailcfg.ControlDialPlan) (*NoiseClient, error) { u, err := url.Parse(serverURL) if err != nil { return nil, err @@ -207,6 +213,8 @@ func NewNoiseClient(privKey key.MachinePrivate, serverPubKey key.MachinePublic, httpsPort: httpsPort, dialer: dialer, dialPlan: dialPlan, + logf: logf, + netMon: netMon, } // Create the HTTP/2 Transport using a net/http.Transport @@ -366,6 +374,8 @@ func (nc *NoiseClient) dial() (*noiseConn, error) { ProtocolVersion: uint16(tailcfg.CurrentCapabilityVersion), Dialer: nc.dialer.SystemDial, DialPlan: dialPlan, + Logf: nc.logf, + NetMon: nc.netMon, }).Dial(ctx) if err != nil { return nil, err diff --git a/control/controlclient/noise_test.go b/control/controlclient/noise_test.go index 049e260fe6596..11e35f0af8879 100644 --- a/control/controlclient/noise_test.go +++ b/control/controlclient/noise_test.go @@ -74,7 +74,7 @@ func (tt noiseClientTest) run(t *testing.T) { defer hs.Close() dialer := new(tsdial.Dialer) - nc, err := NewNoiseClient(clientPrivate, serverPrivate.Public(), hs.URL, dialer, nil) + nc, err := NewNoiseClient(clientPrivate, serverPrivate.Public(), hs.URL, dialer, nil, nil, nil) if err != nil { t.Fatal(err) } diff --git a/control/controlhttp/client.go b/control/controlhttp/client.go index 02b5a78214cc3..d04aac5188650 100644 --- a/control/controlhttp/client.go +++ b/control/controlhttp/client.go @@ -389,13 +389,15 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr, SingleHostStaticResult: []netip.Addr{addr}, SingleHost: u.Hostname(), Logf: a.Logf, // not a.logf method; we want to propagate nil-ness + NetMon: a.NetMon, } } else { dns = &dnscache.Resolver{ Forward: dnscache.Get().Forward, - LookupIPFallback: dnsfallback.Lookup(a.logf), + LookupIPFallback: dnsfallback.MakeLookupFunc(a.logf, a.NetMon), UseLastGood: true, Logf: a.Logf, // not a.logf method; we want to propagate nil-ness + NetMon: a.NetMon, } } diff --git a/control/controlhttp/constants.go b/control/controlhttp/constants.go index 045eeba7f0cf0..a58ee5374a7d4 100644 --- a/control/controlhttp/constants.go +++ b/control/controlhttp/constants.go @@ -9,6 +9,7 @@ import ( "time" "tailscale.com/net/dnscache" + "tailscale.com/net/netmon" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -70,6 +71,8 @@ type Dialer struct { // dropped. Logf logger.Logf + NetMon *netmon.Monitor + // DialPlan, if set, contains instructions from the control server on // how to connect to it. If present, we will try the methods in this // plan before falling back to DNS. diff --git a/derp/derphttp/derphttp_client.go b/derp/derphttp/derphttp_client.go index 349838dfae280..2ea86b6867c9d 100644 --- a/derp/derphttp/derphttp_client.go +++ b/derp/derphttp/derphttp_client.go @@ -31,6 +31,7 @@ import ( "tailscale.com/derp" "tailscale.com/envknob" "tailscale.com/net/dnscache" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/sockstats" "tailscale.com/net/tlsdial" @@ -55,6 +56,7 @@ type Client struct { privateKey key.NodePrivate logf logger.Logf + netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand dialer func(ctx context.Context, network, addr string) (net.Conn, error) // Either url or getRegion is non-nil: @@ -88,11 +90,13 @@ func (c *Client) String() string { // NewRegionClient returns a new DERP-over-HTTP client. It connects lazily. // To trigger a connection, use Connect. -func NewRegionClient(privateKey key.NodePrivate, logf logger.Logf, getRegion func() *tailcfg.DERPRegion) *Client { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func NewRegionClient(privateKey key.NodePrivate, logf logger.Logf, netMon *netmon.Monitor, getRegion func() *tailcfg.DERPRegion) *Client { ctx, cancel := context.WithCancel(context.Background()) c := &Client{ privateKey: privateKey, logf: logf, + netMon: netMon, getRegion: getRegion, ctx: ctx, cancelCtx: cancel, @@ -492,7 +496,7 @@ func (c *Client) dialURL(ctx context.Context) (net.Conn, error) { return c.dialer(ctx, "tcp", net.JoinHostPort(host, urlPort(c.url))) } hostOrIP := host - dialer := netns.NewDialer(c.logf) + dialer := netns.NewDialer(c.logf, c.netMon) if c.DNSCache != nil { ip, _, _, err := c.DNSCache.LookupIP(ctx, host) @@ -587,7 +591,7 @@ func (c *Client) DialRegionTLS(ctx context.Context, reg *tailcfg.DERPRegion) (tl } func (c *Client) dialContext(ctx context.Context, proto, addr string) (net.Conn, error) { - return netns.NewDialer(c.logf).DialContext(ctx, proto, addr) + return netns.NewDialer(c.logf, c.netMon).DialContext(ctx, proto, addr) } // shouldDialProto reports whether an explicitly provided IPv4 or IPv6 diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 532e68d1922c0..d1aaf6b89529e 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -313,7 +313,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor loginFlags: loginFlags, } - b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID) + b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID, e.GetNetMon()) if err != nil { log.Printf("error setting up sockstat logger: %v", err) } diff --git a/ipn/ipnserver/proxyconnect.go b/ipn/ipnserver/proxyconnect.go index 8f330add1f634..5ac7e89db1476 100644 --- a/ipn/ipnserver/proxyconnect.go +++ b/ipn/ipnserver/proxyconnect.go @@ -37,7 +37,8 @@ func (s *Server) handleProxyConnectConn(w http.ResponseWriter, r *http.Request) return } - back, err := logpolicy.DialContext(ctx, "tcp", hostPort) + dialContext := logpolicy.MakeDialFunc(s.netMon) + back, err := dialContext(ctx, "tcp", hostPort) if err != nil { s.logf("error CONNECT dialing %v: %v", hostPort, err) http.Error(w, "Connect failure", http.StatusBadGateway) diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 0123d9e9e4ce9..3abfa93646f91 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -24,6 +24,7 @@ import ( "tailscale.com/ipn/ipnauth" "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/localapi" + "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/util/mak" @@ -36,6 +37,7 @@ import ( type Server struct { lb atomic.Pointer[ipnlocal.LocalBackend] logf logger.Logf + netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand backendLogID logid.PublicID // resetOnZero is whether to call bs.Reset on transition from // 1->0 active HTTP requests. That is, this is whether the backend is @@ -197,7 +199,7 @@ func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) { defer onDone() if strings.HasPrefix(r.URL.Path, "/localapi/") { - lah := localapi.NewHandler(lb, s.logf, s.backendLogID) + lah := localapi.NewHandler(lb, s.logf, s.netMon, s.backendLogID) lah.PermitRead, lah.PermitWrite = s.localAPIPermissions(ci) lah.PermitCert = s.connCanFetchCerts(ci) lah.ServeHTTP(w, r) @@ -408,15 +410,18 @@ func (s *Server) addActiveHTTPRequest(req *http.Request, ci *ipnauth.ConnIdentit } // New returns a new Server. +// The netMon parameter is optional; if non-nil it's used to do faster interface +// lookups. // // To start it, use the Server.Run method. // // At some point, either before or after Run, the Server's SetLocalBackend // method must also be called before Server can do anything useful. -func New(logf logger.Logf, logID logid.PublicID) *Server { +func New(logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) *Server { return &Server{ backendLogID: logID, logf: logf, + netMon: netMon, resetOnZero: envknob.GOOS() == "windows", } } diff --git a/ipn/localapi/debugderp.go b/ipn/localapi/debugderp.go index f7ae887871680..af2527ee80ea9 100644 --- a/ipn/localapi/debugderp.go +++ b/ipn/localapi/debugderp.go @@ -140,7 +140,7 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { } checkSTUN4 := func(derpNode *tailcfg.DERPNode) { - u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(h.logf)).ListenPacket(ctx, "udp4", ":0") + u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(h.logf, h.netMon)).ListenPacket(ctx, "udp4", ":0") if err != nil { st.Errors = append(st.Errors, fmt.Sprintf("Error creating IPv4 STUN listener: %v", err)) return @@ -249,7 +249,7 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) { serverPubKeys := make(map[key.NodePublic]bool) for i := 0; i < 5; i++ { func() { - rc := derphttp.NewRegionClient(fakePrivKey, h.logf, func() *tailcfg.DERPRegion { + rc := derphttp.NewRegionClient(fakePrivKey, h.logf, h.netMon, func() *tailcfg.DERPRegion { return &tailcfg.DERPRegion{ RegionID: reg.RegionID, RegionCode: reg.RegionCode, diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index be15cbe08bfce..28371a45df762 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -125,8 +125,10 @@ var ( metrics = map[string]*clientmetric.Metric{} ) -func NewHandler(b *ipnlocal.LocalBackend, logf logger.Logf, logID logid.PublicID) *Handler { - return &Handler{b: b, logf: logf, backendLogID: logID} +// NewHandler creates a new LocalAPI HTTP handler. All parameters except netMon +// are required (if non-nil it's used to do faster interface lookups). +func NewHandler(b *ipnlocal.LocalBackend, logf logger.Logf, netMon *netmon.Monitor, logID logid.PublicID) *Handler { + return &Handler{b: b, logf: logf, netMon: netMon, backendLogID: logID} } type Handler struct { @@ -150,6 +152,7 @@ type Handler struct { b *ipnlocal.LocalBackend logf logger.Logf + netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand backendLogID logid.PublicID } @@ -679,7 +682,7 @@ func (h *Handler) serveDebugPortmap(w http.ResponseWriter, r *http.Request) { done := make(chan bool, 1) var c *portmapper.Client - c = portmapper.NewClient(logger.WithPrefix(logf, "portmapper: "), debugKnobs, func() { + c = portmapper.NewClient(logger.WithPrefix(logf, "portmapper: "), h.netMon, debugKnobs, func() { logf("portmapping changed.") logf("have mapping: %v", c.HaveMapping()) diff --git a/log/sockstatlog/logger.go b/log/sockstatlog/logger.go index 683342a08000a..4f522f17d3ab9 100644 --- a/log/sockstatlog/logger.go +++ b/log/sockstatlog/logger.go @@ -20,6 +20,7 @@ import ( "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/logtail/filch" + "tailscale.com/net/netmon" "tailscale.com/net/sockstats" "tailscale.com/smallzstd" "tailscale.com/types/logger" @@ -92,7 +93,8 @@ func SockstatLogID(logID logid.PublicID) logid.PrivateID { // On platforms that do not support sockstat logging, a nil Logger will be returned. // The returned Logger is not yet enabled, and must be shut down with Shutdown when it is no longer needed. // Logs will be uploaded to the log server using a new log ID derived from the provided backend logID. -func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger, error) { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) (*Logger, error) { if !sockstats.IsAvailable { return nil, nil } @@ -112,7 +114,7 @@ func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID) (*Logger, logger := &Logger{ logf: logf, filch: filch, - tr: logpolicy.NewLogtailTransport(logtail.DefaultHost), + tr: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon), } logger.logger = logtail.NewLogger(logtail.Config{ BaseURL: logpolicy.LogURL(), diff --git a/log/sockstatlog/logger_test.go b/log/sockstatlog/logger_test.go index e64a5de8be3ec..1e2d67d973fb7 100644 --- a/log/sockstatlog/logger_test.go +++ b/log/sockstatlog/logger_test.go @@ -23,7 +23,7 @@ func TestResourceCleanup(t *testing.T) { if err != nil { t.Fatal(err) } - lg, err := NewLogger(td, logger.Discard, id.Public()) + lg, err := NewLogger(td, logger.Discard, id.Public(), nil) if err != nil { t.Fatal(err) } diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index 84da5f31a7e18..7becc934fd3c9 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -37,6 +37,7 @@ import ( "tailscale.com/net/dnscache" "tailscale.com/net/dnsfallback" "tailscale.com/net/netknob" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/tlsdial" "tailscale.com/net/tshttpproxy" @@ -450,14 +451,15 @@ func tryFixLogStateLocation(dir, cmdname string) { // New returns a new log policy (a logger and its instance ID) for a // given collection name. -func New(collection string) *Policy { - return NewWithConfigPath(collection, "", "") +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func New(collection string, netMon *netmon.Monitor) *Policy { + return NewWithConfigPath(collection, "", "", netMon) } // NewWithConfigPath is identical to New, // but uses the specified directory and command name. // If either is empty, it derives them automatically. -func NewWithConfigPath(collection, dir, cmdName string) *Policy { +func NewWithConfigPath(collection, dir, cmdName string, netMon *netmon.Monitor) *Policy { var lflags int if term.IsTerminal(2) || runtime.GOOS == "windows" { lflags = 0 @@ -554,7 +556,7 @@ func NewWithConfigPath(collection, dir, cmdName string) *Policy { } return w }, - HTTPC: &http.Client{Transport: NewLogtailTransport(logtail.DefaultHost)}, + HTTPC: &http.Client{Transport: NewLogtailTransport(logtail.DefaultHost, netMon)}, } if collection == logtail.CollectionNode { conf.MetricsDelta = clientmetric.EncodeLogTailMetricsDelta @@ -569,7 +571,7 @@ func NewWithConfigPath(collection, dir, cmdName string) *Policy { log.Println("You have enabled a non-default log target. Doing without being told to by Tailscale staff or your network administrator will make getting support difficult.") conf.BaseURL = val u, _ := url.Parse(val) - conf.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host)} + conf.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host, netMon)} } filchOptions := filch.Options{ @@ -670,13 +672,22 @@ func (p *Policy) Shutdown(ctx context.Context) error { return nil } -// DialContext is a net.Dialer.DialContext specialized for use by logtail. +// MakeDialFunc creates a net.Dialer.DialContext function specialized for use +// by logtail. // It does the following: // - If DNS lookup fails, consults the bootstrap DNS list of Tailscale hostnames. // - If TLS connection fails, try again using LetsEncrypt's built-in root certificate, // for the benefit of older OS platforms which might not include it. -func DialContext(ctx context.Context, netw, addr string) (net.Conn, error) { - nd := netns.FromDialer(log.Printf, &net.Dialer{ +// +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func MakeDialFunc(netMon *netmon.Monitor) func(ctx context.Context, netw, addr string) (net.Conn, error) { + return func(ctx context.Context, netw, addr string) (net.Conn, error) { + return dialContext(ctx, netw, addr, netMon) + } +} + +func dialContext(ctx context.Context, netw, addr string, netMon *netmon.Monitor) (net.Conn, error) { + nd := netns.FromDialer(log.Printf, netMon, &net.Dialer{ Timeout: 30 * time.Second, KeepAlive: netknob.PlatformTCPKeepAlive(), }) @@ -711,7 +722,8 @@ func DialContext(ctx context.Context, netw, addr string) (net.Conn, error) { dnsCache := &dnscache.Resolver{ Forward: dnscache.Get().Forward, // use default cache's forwarder UseLastGood: true, - LookupIPFallback: dnsfallback.Lookup(log.Printf), + LookupIPFallback: dnsfallback.MakeLookupFunc(log.Printf, netMon), + NetMon: netMon, } dialer := dnscache.Dialer(nd.DialContext, dnsCache) c, err = dialer(ctx, netw, addr) @@ -723,7 +735,8 @@ func DialContext(ctx context.Context, netw, addr string) (net.Conn, error) { // NewLogtailTransport returns an HTTP Transport particularly suited to uploading // logs to the given host name. See DialContext for details on how it works. -func NewLogtailTransport(host string) http.RoundTripper { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func NewLogtailTransport(host string, netMon *netmon.Monitor) http.RoundTripper { if inTest() { return noopPretendSuccessTransport{} } @@ -739,7 +752,7 @@ func NewLogtailTransport(host string) http.RoundTripper { tr.DisableCompression = true // Log whenever we dial: - tr.DialContext = DialContext + tr.DialContext = MakeDialFunc(netMon) // We're contacting exactly 1 hostname, so the default's 100 // max idle conns is very high for our needs. Even 2 is diff --git a/net/dns/manager.go b/net/dns/manager.go index e909cbe5d1059..d1aa73ca67c92 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -64,6 +64,7 @@ type Manager struct { } // NewManagers created a new manager from the given config. +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. func NewManager(logf logger.Logf, oscfg OSConfigurator, netMon *netmon.Monitor, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector) *Manager { if dialer == nil { panic("nil Dialer") diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 3373ffcf147c5..85670e1d61af4 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -380,11 +380,12 @@ func (f *forwarder) getKnownDoHClientForProvider(urlBase string) (c *http.Client if err != nil { return nil, false } - nsDialer := netns.NewDialer(f.logf) + nsDialer := netns.NewDialer(f.logf, f.netMon) dialer := dnscache.Dialer(nsDialer.DialContext, &dnscache.Resolver{ SingleHost: dohURL.Hostname(), SingleHostStaticResult: allIPs, Logf: f.logf, + NetMon: f.netMon, }) c = &http.Client{ Transport: &http.Transport{ diff --git a/net/dns/resolver/macios_ext.go b/net/dns/resolver/macios_ext.go index 895b8714f6382..e3f979c194d91 100644 --- a/net/dns/resolver/macios_ext.go +++ b/net/dns/resolver/macios_ext.go @@ -17,8 +17,8 @@ func init() { initListenConfig = initListenConfigNetworkExtension } -func initListenConfigNetworkExtension(nc *net.ListenConfig, mon *netmon.Monitor, tunName string) error { - nif, ok := mon.InterfaceState().Interface[tunName] +func initListenConfigNetworkExtension(nc *net.ListenConfig, netMon *netmon.Monitor, tunName string) error { + nif, ok := netMon.InterfaceState().Interface[tunName] if !ok { return errors.New("utun not found") } diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index ad3d36c99a2b7..8db97f49a2154 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -997,7 +997,7 @@ func TestMarshalResponseFormatError(t *testing.T) { func TestForwardLinkSelection(t *testing.T) { configCall := make(chan string, 1) - tstest.Replace(t, &initListenConfig, func(nc *net.ListenConfig, mon *netmon.Monitor, tunName string) error { + tstest.Replace(t, &initListenConfig, func(nc *net.ListenConfig, netMon *netmon.Monitor, tunName string) error { select { case configCall <- tunName: return nil diff --git a/net/dnscache/dnscache.go b/net/dnscache/dnscache.go index 5a5978f5f5a5d..0983ae8752e9d 100644 --- a/net/dnscache/dnscache.go +++ b/net/dnscache/dnscache.go @@ -21,6 +21,7 @@ import ( "time" "tailscale.com/envknob" + "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/util/cloudenv" "tailscale.com/util/singleflight" @@ -91,6 +92,11 @@ type Resolver struct { // be added to all log messages printed with this logger. Logf logger.Logf + // NetMon optionally provides a netmon.Monitor to use to get the current + // (cached) network interface. + // If nil, the interface will be looked up dynamically. + NetMon *netmon.Monitor + sf singleflight.Group[string, ipRes] mu sync.Mutex diff --git a/net/dnsfallback/dnsfallback.go b/net/dnsfallback/dnsfallback.go index 9ac22b9dc3240..5e80c79c9fdcd 100644 --- a/net/dnsfallback/dnsfallback.go +++ b/net/dnsfallback/dnsfallback.go @@ -23,6 +23,7 @@ import ( "time" "tailscale.com/atomicfile" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/tlsdial" "tailscale.com/net/tshttpproxy" @@ -31,13 +32,16 @@ import ( "tailscale.com/util/slicesx" ) -func Lookup(logf logger.Logf) func(ctx context.Context, host string) ([]netip.Addr, error) { +// MakeLookupFunc creates a function that can be used to resolve hostnames +// (e.g. as a LookupIPFallback from dnscache.Resolver). +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func MakeLookupFunc(logf logger.Logf, netMon *netmon.Monitor) func(ctx context.Context, host string) ([]netip.Addr, error) { return func(ctx context.Context, host string) ([]netip.Addr, error) { - return lookup(ctx, host, logf) + return lookup(ctx, host, logf, netMon) } } -func lookup(ctx context.Context, host string, logf logger.Logf) ([]netip.Addr, error) { +func lookup(ctx context.Context, host string, logf logger.Logf, netMon *netmon.Monitor) ([]netip.Addr, error) { if ip, err := netip.ParseAddr(host); err == nil && ip.IsValid() { return []netip.Addr{ip}, nil } @@ -85,7 +89,7 @@ func lookup(ctx context.Context, host string, logf logger.Logf) ([]netip.Addr, e logf("trying bootstrapDNS(%q, %q) for %q ...", cand.dnsName, cand.ip, host) ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() - dm, err := bootstrapDNSMap(ctx, cand.dnsName, cand.ip, host, logf) + dm, err := bootstrapDNSMap(ctx, cand.dnsName, cand.ip, host, logf, netMon) if err != nil { logf("bootstrapDNS(%q, %q) for %q error: %v", cand.dnsName, cand.ip, host, err) continue @@ -104,8 +108,8 @@ func lookup(ctx context.Context, host string, logf logger.Logf) ([]netip.Addr, e // serverName and serverIP of are, say, "derpN.tailscale.com". // queryName is the name being sought (e.g. "controlplane.tailscale.com"), passed as hint. -func bootstrapDNSMap(ctx context.Context, serverName string, serverIP netip.Addr, queryName string, logf logger.Logf) (dnsMap, error) { - dialer := netns.NewDialer(logf) +func bootstrapDNSMap(ctx context.Context, serverName string, serverIP netip.Addr, queryName string, logf logger.Logf, netMon *netmon.Monitor) (dnsMap, error) { + dialer := netns.NewDialer(logf, netMon) tr := http.DefaultTransport.(*http.Transport).Clone() tr.Proxy = tshttpproxy.ProxyFromEnvironment tr.DialContext = func(ctx context.Context, netw, addr string) (net.Conn, error) { diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 687aa6a8bfbd0..a61343ebe5796 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -29,6 +29,7 @@ import ( "tailscale.com/net/interfaces" "tailscale.com/net/netaddr" "tailscale.com/net/neterror" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/ping" "tailscale.com/net/portmapper" @@ -158,6 +159,11 @@ type Client struct { // If nil, log.Printf is used. Logf logger.Logf + // NetMon optionally provides a netmon.Monitor to use to get the current + // (cached) network interface. + // If nil, the interface will be looked up dynamically. + NetMon *netmon.Monitor + // TimeNow, if non-nil, is used instead of time.Now. TimeNow func() time.Time @@ -864,22 +870,29 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, return c.finishAndStoreReport(rs, dm), nil } - ifState, err := interfaces.GetState() - if err != nil { - c.logf("[v1] interfaces: %v", err) - return nil, err + var ifState *interfaces.State + if c.NetMon == nil { + directState, err := interfaces.GetState() + if err != nil { + c.logf("[v1] interfaces: %v", err) + return nil, err + } else { + ifState = directState + } + } else { + ifState = c.NetMon.InterfaceState() } // See if IPv6 works at all, or if it's been hard disabled at the // OS level. - v6udp, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp6", "[::1]:0") + v6udp, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, c.NetMon)).ListenPacket(ctx, "udp6", "[::1]:0") if err == nil { rs.report.OSHasIPv6 = true v6udp.Close() } // Create a UDP4 socket used for sending to our discovered IPv4 address. - rs.pc4Hair, err = nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp4", ":0") + rs.pc4Hair, err = nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, c.NetMon)).ListenPacket(ctx, "udp4", ":0") if err != nil { c.logf("udp4: %v", err) return nil, err @@ -909,7 +922,7 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, if f := c.GetSTUNConn4; f != nil { rs.pc4 = f() } else { - u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp4", c.udpBindAddr()) + u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, nil)).ListenPacket(ctx, "udp4", c.udpBindAddr()) if err != nil { c.logf("udp4: %v", err) return nil, err @@ -922,7 +935,7 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, if f := c.GetSTUNConn6; f != nil { rs.pc6 = f() } else { - u6, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp6", c.udpBindAddr()) + u6, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, nil)).ListenPacket(ctx, "udp6", c.udpBindAddr()) if err != nil { c.logf("udp6: %v", err) } else { @@ -1297,7 +1310,7 @@ func (c *Client) measureAllICMPLatency(ctx context.Context, rs *reportState, nee ctx, done := context.WithTimeout(ctx, icmpProbeTimeout) defer done() - p, err := ping.New(ctx, c.logf) + p, err := ping.New(ctx, c.logf, c.NetMon) if err != nil { return err } @@ -1635,6 +1648,7 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP Forward: net.DefaultResolver, UseLastGood: true, Logf: c.logf, + NetMon: c.NetMon, } } resolver := c.resolver diff --git a/net/netns/netns.go b/net/netns/netns.go index 86aafcac2c2c6..2acb151298e25 100644 --- a/net/netns/netns.go +++ b/net/netns/netns.go @@ -20,6 +20,7 @@ import ( "sync/atomic" "tailscale.com/net/netknob" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -55,19 +56,21 @@ func SetDisableBindConnToInterface(v bool) { // Listener returns a new net.Listener with its Control hook func // initialized as necessary to run in logical network namespace that // doesn't route back into Tailscale. -func Listener(logf logger.Logf) *net.ListenConfig { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func Listener(logf logger.Logf, netMon *netmon.Monitor) *net.ListenConfig { if disabled.Load() { return new(net.ListenConfig) } - return &net.ListenConfig{Control: control(logf)} + return &net.ListenConfig{Control: control(logf, netMon)} } // NewDialer returns a new Dialer using a net.Dialer with its Control // hook func initialized as necessary to run in a logical network // namespace that doesn't route back into Tailscale. It also handles // using a SOCKS if configured in the environment with ALL_PROXY. -func NewDialer(logf logger.Logf) Dialer { - return FromDialer(logf, &net.Dialer{ +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func NewDialer(logf logger.Logf, netMon *netmon.Monitor) Dialer { + return FromDialer(logf, netMon, &net.Dialer{ KeepAlive: netknob.PlatformTCPKeepAlive(), }) } @@ -76,11 +79,12 @@ func NewDialer(logf logger.Logf) Dialer { // network namespace that doesn't route back into Tailscale. It also // handles using a SOCKS if configured in the environment with // ALL_PROXY. -func FromDialer(logf logger.Logf, d *net.Dialer) Dialer { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func FromDialer(logf logger.Logf, netMon *netmon.Monitor, d *net.Dialer) Dialer { if disabled.Load() { return d } - d.Control = control(logf) + d.Control = control(logf, netMon) if wrapDialer != nil { return wrapDialer(d) } diff --git a/net/netns/netns_android.go b/net/netns/netns_android.go index 218b132e34300..162e5c79a62fa 100644 --- a/net/netns/netns_android.go +++ b/net/netns/netns_android.go @@ -10,6 +10,7 @@ import ( "sync" "syscall" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -49,7 +50,7 @@ func SetAndroidProtectFunc(f func(fd int) error) { androidProtectFunc = f } -func control(logger.Logf) func(network, address string, c syscall.RawConn) error { +func control(logger.Logf, *netmon.Monitor) func(network, address string, c syscall.RawConn) error { return controlC } diff --git a/net/netns/netns_darwin.go b/net/netns/netns_darwin.go index c24c51102de20..7315dff4052af 100644 --- a/net/netns/netns_darwin.go +++ b/net/netns/netns_darwin.go @@ -19,24 +19,25 @@ import ( "golang.org/x/sys/unix" "tailscale.com/envknob" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) -func control(logf logger.Logf) func(network, address string, c syscall.RawConn) error { +func control(logf logger.Logf, netMon *netmon.Monitor) func(network, address string, c syscall.RawConn) error { return func(network, address string, c syscall.RawConn) error { - return controlLogf(logf, network, address, c) + return controlLogf(logf, netMon, network, address, c) } } var bindToInterfaceByRouteEnv = envknob.RegisterBool("TS_BIND_TO_INTERFACE_BY_ROUTE") -var errInterfaceIndexInvalid = errors.New("interface index invalid") +var errInterfaceStateInvalid = errors.New("interface state invalid") // controlLogf marks c as necessary to dial in a separate network namespace. // // It's intentionally the same signature as net.Dialer.Control // and net.ListenConfig.Control. -func controlLogf(logf logger.Logf, network, address string, c syscall.RawConn) error { +func controlLogf(logf logger.Logf, netMon *netmon.Monitor, network, address string, c syscall.RawConn) error { if isLocalhost(address) { // Don't bind to an interface for localhost connections. return nil @@ -47,7 +48,7 @@ func controlLogf(logf logger.Logf, network, address string, c syscall.RawConn) e return nil } - idx, err := getInterfaceIndex(logf, address) + idx, err := getInterfaceIndex(logf, netMon, address) if err != nil { // callee logged return nil @@ -56,20 +57,31 @@ func controlLogf(logf logger.Logf, network, address string, c syscall.RawConn) e return bindConnToInterface(c, network, address, idx, logf) } -func getInterfaceIndex(logf logger.Logf, address string) (int, error) { +func getInterfaceIndex(logf logger.Logf, netMon *netmon.Monitor, address string) (int, error) { // Helper so we can log errors. defaultIdx := func() (int, error) { - idx, err := interfaces.DefaultRouteInterfaceIndex() - if err != nil { - // It's somewhat common for there to be no default gateway route - // (e.g. on a phone with no connectivity), don't log those errors - // since they are expected. - if !errors.Is(err, interfaces.ErrNoGatewayIndexFound) { - logf("[unexpected] netns: DefaultRouteInterfaceIndex: %v", err) + if netMon == nil { + idx, err := interfaces.DefaultRouteInterfaceIndex() + if err != nil { + // It's somewhat common for there to be no default gateway route + // (e.g. on a phone with no connectivity), don't log those errors + // since they are expected. + if !errors.Is(err, interfaces.ErrNoGatewayIndexFound) { + logf("[unexpected] netns: DefaultRouteInterfaceIndex: %v", err) + } + return -1, err } - return -1, err + return idx, nil } - return idx, nil + state := netMon.InterfaceState() + if state == nil { + return -1, errInterfaceStateInvalid + } + + if iface, ok := state.Interface[state.DefaultRouteInterface]; ok { + return iface.Index, nil + } + return -1, errInterfaceStateInvalid } useRoute := bindToInterfaceByRoute.Load() || bindToInterfaceByRouteEnv() diff --git a/net/netns/netns_darwin_test.go b/net/netns/netns_darwin_test.go index e1dc00b423a03..0fc92f6f3888f 100644 --- a/net/netns/netns_darwin_test.go +++ b/net/netns/netns_darwin_test.go @@ -34,7 +34,7 @@ func TestGetInterfaceIndex(t *testing.T) { } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - idx, err := getInterfaceIndex(t.Logf, tc.addr) + idx, err := getInterfaceIndex(t.Logf, nil, tc.addr) if err != nil { if tc.err == "" { t.Fatalf("got unexpected error: %v", err) @@ -68,7 +68,7 @@ func TestGetInterfaceIndex(t *testing.T) { t.Fatal(err) } - idx, err := getInterfaceIndex(t.Logf, "100.100.100.100:53") + idx, err := getInterfaceIndex(t.Logf, nil, "100.100.100.100:53") if err != nil { t.Fatal(err) } diff --git a/net/netns/netns_default.go b/net/netns/netns_default.go index 43a573959db1f..94f24d8fa4e19 100644 --- a/net/netns/netns_default.go +++ b/net/netns/netns_default.go @@ -8,10 +8,11 @@ package netns import ( "syscall" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) -func control(logger.Logf) func(network, address string, c syscall.RawConn) error { +func control(logger.Logf, *netmon.Monitor) func(network, address string, c syscall.RawConn) error { return controlC } diff --git a/net/netns/netns_linux.go b/net/netns/netns_linux.go index dea6a9e8df221..5d09d7d192d4e 100644 --- a/net/netns/netns_linux.go +++ b/net/netns/netns_linux.go @@ -15,6 +15,7 @@ import ( "golang.org/x/sys/unix" "tailscale.com/envknob" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -85,7 +86,7 @@ func ignoreErrors() bool { return false } -func control(logger.Logf) func(network, address string, c syscall.RawConn) error { +func control(logger.Logf, *netmon.Monitor) func(network, address string, c syscall.RawConn) error { return controlC } diff --git a/net/netns/netns_test.go b/net/netns/netns_test.go index d95c049818ab7..82f919b946d4a 100644 --- a/net/netns/netns_test.go +++ b/net/netns/netns_test.go @@ -24,7 +24,7 @@ func TestDial(t *testing.T) { if !*extNetwork { t.Skip("skipping test without --use-external-network") } - d := NewDialer(t.Logf) + d := NewDialer(t.Logf, nil) c, err := d.Dial("tcp", "google.com:80") if err != nil { t.Fatal(err) diff --git a/net/netns/netns_windows.go b/net/netns/netns_windows.go index 147a762ecbab4..8aa1da18d5a7d 100644 --- a/net/netns/netns_windows.go +++ b/net/netns/netns_windows.go @@ -12,6 +12,7 @@ import ( "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "tailscale.com/net/interfaces" + "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -26,7 +27,7 @@ func interfaceIndex(iface *winipcfg.IPAdapterAddresses) uint32 { return iface.IfIndex } -func control(logger.Logf) func(network, address string, c syscall.RawConn) error { +func control(logger.Logf, *netmon.Monitor) func(network, address string, c syscall.RawConn) error { return controlC } diff --git a/net/ping/ping.go b/net/ping/ping.go index f4bd7f0e0c628..9b9618e0ff34c 100644 --- a/net/ping/ping.go +++ b/net/ping/ping.go @@ -18,6 +18,7 @@ import ( "golang.org/x/net/icmp" "golang.org/x/net/ipv4" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/types/logger" ) @@ -52,8 +53,9 @@ type Pinger struct { // New creates a new Pinger. The Context provided will be used to create // network listeners, and to set an absolute deadline (if any) on the net.Conn -func New(ctx context.Context, logf logger.Logf) (*Pinger, error) { - p, err := newUnstarted(ctx, logf) +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func New(ctx context.Context, logf logger.Logf, netMon *netmon.Monitor) (*Pinger, error) { + p, err := newUnstarted(ctx, logf, netMon) if err != nil { return nil, err } @@ -72,14 +74,14 @@ func New(ctx context.Context, logf logger.Logf) (*Pinger, error) { return p, nil } -func newUnstarted(ctx context.Context, logf logger.Logf) (*Pinger, error) { +func newUnstarted(ctx context.Context, logf logger.Logf, netMon *netmon.Monitor) (*Pinger, error) { var id [2]byte _, err := rand.Read(id[:]) if err != nil { return nil, err } - conn, err := netns.Listener(logf).ListenPacket(ctx, "ip4:icmp", "0.0.0.0") + conn, err := netns.Listener(logf, netMon).ListenPacket(ctx, "ip4:icmp", "0.0.0.0") if err != nil { return nil, err } diff --git a/net/portmapper/igd_test.go b/net/portmapper/igd_test.go index f4895963193f4..57c0d7aa6a03e 100644 --- a/net/portmapper/igd_test.go +++ b/net/portmapper/igd_test.go @@ -249,7 +249,7 @@ func (d *TestIGD) handlePCPQuery(pkt []byte, src netip.AddrPort) { func newTestClient(t *testing.T, igd *TestIGD) *Client { var c *Client - c = NewClient(t.Logf, nil, func() { + c = NewClient(t.Logf, nil, nil, func() { t.Logf("port map changed") t.Logf("have mapping: %v", c.HaveMapping()) }) diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index 2d8c06591e87f..2e500b5553a8b 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -21,6 +21,7 @@ import ( "tailscale.com/net/interfaces" "tailscale.com/net/netaddr" "tailscale.com/net/neterror" + "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/sockstats" "tailscale.com/types/logger" @@ -59,6 +60,7 @@ const trustServiceStillAvailableDuration = 10 * time.Minute // Client is a port mapping client. type Client struct { logf logger.Logf + netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand ipAndGateway func() (gw, ip netip.Addr, ok bool) onChange func() // or nil debug DebugKnobs @@ -153,15 +155,19 @@ func (m *pmpMapping) Release(ctx context.Context) { // NewClient returns a new portmapping client. // +// The netMon parameter is optional; if non-nil it's used to do faster interface +// lookups. +// // The debug argument allows configuring the behaviour of the portmapper for // debugging; if nil, a sensible set of defaults will be used. // // The optional onChange argument specifies a func to run in a new // goroutine whenever the port mapping status has changed. If nil, // it doesn't make a callback. -func NewClient(logf logger.Logf, debug *DebugKnobs, onChange func()) *Client { +func NewClient(logf logger.Logf, netMon *netmon.Monitor, debug *DebugKnobs, onChange func()) *Client { ret := &Client{ logf: logf, + netMon: netMon, ipAndGateway: interfaces.LikelyHomeRouterIP, onChange: onChange, } @@ -271,7 +277,7 @@ func (c *Client) listenPacket(ctx context.Context, network, addr string) (nettyp } return pc.(*net.UDPConn), nil } - pc, err := netns.Listener(c.logf).ListenPacket(ctx, network, addr) + pc, err := netns.Listener(c.logf, c.netMon).ListenPacket(ctx, network, addr) if err != nil { return nil, err } diff --git a/net/portmapper/portmapper_test.go b/net/portmapper/portmapper_test.go index 67c37f8bdd5b3..15f2849fc8d35 100644 --- a/net/portmapper/portmapper_test.go +++ b/net/portmapper/portmapper_test.go @@ -16,7 +16,7 @@ func TestCreateOrGetMapping(t *testing.T) { if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v { t.Skip("skipping test without HIT_NETWORK=1") } - c := NewClient(t.Logf, nil, nil) + c := NewClient(t.Logf, nil, nil, nil) defer c.Close() c.SetLocalPort(1234) for i := 0; i < 2; i++ { @@ -32,7 +32,7 @@ func TestClientProbe(t *testing.T) { if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v { t.Skip("skipping test without HIT_NETWORK=1") } - c := NewClient(t.Logf, nil, nil) + c := NewClient(t.Logf, nil, nil, nil) defer c.Close() for i := 0; i < 3; i++ { if i > 0 { @@ -47,7 +47,7 @@ func TestClientProbeThenMap(t *testing.T) { if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v { t.Skip("skipping test without HIT_NETWORK=1") } - c := NewClient(t.Logf, nil, nil) + c := NewClient(t.Logf, nil, nil, nil) defer c.Close() c.SetLocalPort(1234) res, err := c.Probe(context.Background()) diff --git a/net/portmapper/upnp.go b/net/portmapper/upnp.go index 5844d7428b8c9..6a525c54ff297 100644 --- a/net/portmapper/upnp.go +++ b/net/portmapper/upnp.go @@ -237,7 +237,7 @@ func (c *Client) upnpHTTPClientLocked() *http.Client { if c.uPnPHTTPClient == nil { c.uPnPHTTPClient = &http.Client{ Transport: &http.Transport{ - DialContext: netns.NewDialer(c.logf).DialContext, + DialContext: netns.NewDialer(c.logf, c.netMon).DialContext, IdleConnTimeout: 2 * time.Second, // LAN is cheap }, } diff --git a/net/sockstats/sockstats.go b/net/sockstats/sockstats.go index e968ac7bfb010..b39d60afbbb20 100644 --- a/net/sockstats/sockstats.go +++ b/net/sockstats/sockstats.go @@ -109,8 +109,8 @@ func GetValidation() *ValidationSockStats { // SetNetMon configures the sockstats package to monitor the active // interface, so that per-interface stats can be collected. -func SetNetMon(lm *netmon.Monitor) { - setNetMon(lm) +func SetNetMon(netMon *netmon.Monitor) { + setNetMon(netMon) } // DebugInfo returns a string containing debug information about the tracked diff --git a/net/sockstats/sockstats_noop.go b/net/sockstats/sockstats_noop.go index 46b5ceaefeb1b..96723111ade7a 100644 --- a/net/sockstats/sockstats_noop.go +++ b/net/sockstats/sockstats_noop.go @@ -30,7 +30,7 @@ func getValidation() *ValidationSockStats { return nil } -func setNetMon(lm *netmon.Monitor) { +func setNetMon(netMon *netmon.Monitor) { } func debugInfo() string { diff --git a/net/sockstats/sockstats_tsgo.go b/net/sockstats/sockstats_tsgo.go index e2dd05f222f21..26211958f81aa 100644 --- a/net/sockstats/sockstats_tsgo.go +++ b/net/sockstats/sockstats_tsgo.go @@ -249,13 +249,13 @@ func getValidation() *ValidationSockStats { return r } -func setNetMon(lm *netmon.Monitor) { +func setNetMon(netMon *netmon.Monitor) { sockStats.mu.Lock() defer sockStats.mu.Unlock() // We intentionally populate all known interfaces now, so that we can // increment stats for them without holding mu. - state := lm.InterfaceState() + state := netMon.InterfaceState() for ifName, iface := range state.Interface { sockStats.knownInterfaces[iface.Index] = ifName } @@ -266,7 +266,7 @@ func setNetMon(lm *netmon.Monitor) { sockStats.usedInterfaces[ifIndex] = 1 } - lm.RegisterChangeCallback(func(changed bool, state *interfaces.State) { + netMon.RegisterChangeCallback(func(changed bool, state *interfaces.State) { if changed { if ifName := state.DefaultRouteInterface; ifName != "" { ifIndex := state.Interface[ifName].Index diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index bb1dde397f81d..54e91ca13cd16 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -128,14 +128,14 @@ func (d *Dialer) Close() error { return nil } -func (d *Dialer) SetNetMon(mon *netmon.Monitor) { +func (d *Dialer) SetNetMon(netMon *netmon.Monitor) { d.mu.Lock() defer d.mu.Unlock() if d.netMonUnregister != nil { go d.netMonUnregister() d.netMonUnregister = nil } - d.netMon = mon + d.netMon = netMon d.netMonUnregister = d.netMon.RegisterChangeCallback(d.linkChanged) } @@ -279,7 +279,7 @@ func (d *Dialer) SystemDial(ctx context.Context, network, addr string) (net.Conn if logf == nil { logf = logger.Discard } - d.netnsDialer = netns.NewDialer(logf) + d.netnsDialer = netns.NewDialer(logf, d.netMon) }) c, err := d.netnsDialer.DialContext(ctx, network, addr) if err != nil { diff --git a/prober/derp.go b/prober/derp.go index 21583a9bfa595..cd267e27e23cb 100644 --- a/prober/derp.go +++ b/prober/derp.go @@ -346,7 +346,7 @@ func newConn(ctx context.Context, dm *tailcfg.DERPMap, n *tailcfg.DERPNode) (*de return !strings.Contains(s, "derphttp.Client.Connect: connecting to") }) priv := key.NewNode() - dc := derphttp.NewRegionClient(priv, l, func() *tailcfg.DERPRegion { + dc := derphttp.NewRegionClient(priv, l, nil /* no netMon */, func() *tailcfg.DERPRegion { rid := n.RegionID return &tailcfg.DERPRegion{ RegionID: rid, diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 6e7db9440a7ec..2bea9026b6462 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -203,7 +203,7 @@ func (s *Server) Loopback() (addr string, proxyCred, localAPICred string, err er // out the CONNECT code from tailscaled/proxy.go that uses // httputil.ReverseProxy and adding auth support. go func() { - lah := localapi.NewHandler(s.lb, s.logf, s.logid) + lah := localapi.NewHandler(s.lb, s.logf, s.netMon, s.logid) lah.PermitWrite = true lah.PermitRead = true lah.RequiredPassword = s.localAPICred @@ -564,7 +564,7 @@ func (s *Server) start() (reterr error) { go s.printAuthURLLoop() // Run the localapi handler, to allow fetching LetsEncrypt certs. - lah := localapi.NewHandler(lb, logf, s.logid) + lah := localapi.NewHandler(lb, logf, s.netMon, s.logid) lah.PermitWrite = true lah.PermitRead = true @@ -620,7 +620,7 @@ func (s *Server) startLogger(closePool *closeOnErrorPool) error { } return w }, - HTTPC: &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost)}, + HTTPC: &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, s.netMon)}, } s.logtail = logtail.NewLogger(c, s.logf) closePool.addFunc(func() { s.logtail.Shutdown(context.Background()) }) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 5a0a2bf0dd2a1..123b2e70b91e3 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -642,7 +642,7 @@ func NewConn(opts Options) (*Conn, error) { c.idleFunc = opts.IdleFunc c.testOnlyPacketListener = opts.TestOnlyPacketListener c.noteRecvActivity = opts.NoteRecvActivity - c.portMapper = portmapper.NewClient(logger.WithPrefix(c.logf, "portmapper: "), nil, c.onPortMapChanged) + c.portMapper = portmapper.NewClient(logger.WithPrefix(c.logf, "portmapper: "), opts.NetMon, nil, c.onPortMapChanged) if opts.NetMon != nil { c.portMapper.SetGatewayLookupFunc(opts.NetMon.GatewayAndSelfIP) } @@ -656,6 +656,7 @@ func NewConn(opts Options) (*Conn, error) { c.donec = c.connCtx.Done() c.netChecker = &netcheck.Client{ Logf: logger.WithPrefix(c.logf, "netcheck: "), + NetMon: c.netMon, GetSTUNConn4: func() netcheck.STUNConn { return &c.pconn4 }, GetSTUNConn6: func() netcheck.STUNConn { return &c.pconn6 }, SkipExternalNetwork: inTest(), @@ -1554,7 +1555,7 @@ func (c *Conn) derpWriteChanOfAddr(addr netip.AddrPort, peer key.NodePublic) cha // Note that derphttp.NewRegionClient does not dial the server // (it doesn't block) so it is safe to do under the c.mu lock. - dc := derphttp.NewRegionClient(c.privateKey, c.logf, func() *tailcfg.DERPRegion { + dc := derphttp.NewRegionClient(c.privateKey, c.logf, c.netMon, func() *tailcfg.DERPRegion { // Warning: it is not legal to acquire // magicsock.Conn.mu from this callback. // It's run from derphttp.Client.connect (via Send, etc) @@ -3251,7 +3252,7 @@ func (c *Conn) listenPacket(network string, port uint16) (nettype.PacketConn, er if c.testOnlyPacketListener != nil { return nettype.MakePacketListenerWithNetIP(c.testOnlyPacketListener).ListenPacket(ctx, network, addr) } - return nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, network, addr) + return nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf, c.netMon)).ListenPacket(ctx, network, addr) } var debugBindSocket = envknob.RegisterBool("TS_DEBUG_MAGICSOCK_BIND_SOCKET") diff --git a/wgengine/netlog/logger.go b/wgengine/netlog/logger.go index bb3f667a38603..a694308e60f10 100644 --- a/wgengine/netlog/logger.go +++ b/wgengine/netlog/logger.go @@ -19,6 +19,7 @@ import ( "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/net/connstats" + "tailscale.com/net/netmon" "tailscale.com/net/sockstats" "tailscale.com/net/tsaddr" "tailscale.com/smallzstd" @@ -91,7 +92,8 @@ var testClient *http.Client // is a non-tailscale IP address to contact for that particular tailscale node. // The IP protocol and source port are always zero. // The sock is used to populated the PhysicalTraffic field in Message. -func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID logid.PrivateID, tun, sock Device) error { +// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. +func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID logid.PrivateID, tun, sock Device, netMon *netmon.Monitor) error { nl.mu.Lock() defer nl.mu.Unlock() if nl.logger != nil { @@ -99,7 +101,7 @@ func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID lo } // Startup a log stream to Tailscale's logging service. - httpc := &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost)} + httpc := &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon)} if testClient != nil { httpc = testClient } diff --git a/wgengine/userspace.go b/wgengine/userspace.go index c7caf1492623b..1356b36dfdf8e 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -917,7 +917,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, nid := cfg.NetworkLogging.NodeID tid := cfg.NetworkLogging.DomainID e.logf("wgengine: Reconfig: starting up network logger (node:%s tailnet:%s)", nid.Public(), tid.Public()) - if err := e.networkLogger.Startup(cfg.NodeID, nid, tid, e.tundev, e.magicConn); err != nil { + if err := e.networkLogger.Startup(cfg.NodeID, nid, tid, e.tundev, e.magicConn, e.netMon); err != nil { e.logf("wgengine: Reconfig: error starting up network logger: %v", err) } e.networkLogger.ReconfigRoutes(routerCfg) From c791e648818d2f07ff052fb8b21c5b7eb01eb09e Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Wed, 19 Apr 2023 20:36:23 -0700 Subject: [PATCH 016/331] scripts/installer: add Deepin, RisiOS. Fixes https://github.com/tailscale/tailscale/issues/7862 Fixes https://github.com/tailscale/tailscale/issues/7899 Signed-off-by: Denton Gentry --- scripts/installer.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/installer.sh b/scripts/installer.sh index 0fb2d89a50e5f..5ae0a2f695cb3 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -154,6 +154,15 @@ main() { APT_KEY_TYPE="keyring" fi ;; + Deepin) # https://github.com/tailscale/tailscale/issues/7862 + OS="debian" + PACKAGETYPE="apt" + if [ "$VERSION_ID" -lt 20 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; centos) OS="$ID" VERSION="$VERSION_ID" @@ -183,7 +192,7 @@ main() { VERSION="" PACKAGETYPE="dnf" ;; - rocky|almalinux|nobara|openmandriva|sangoma) + rocky|almalinux|nobara|openmandriva|sangoma|risios) OS="fedora" VERSION="" PACKAGETYPE="dnf" From 04a3118d45c993fbed896f696e7d911de2724537 Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Fri, 21 Apr 2023 10:27:15 -0400 Subject: [PATCH 017/331] net/tstun: add tests for captureHook Signed-off-by: Andrew Dunham Change-Id: I630f852d9f16c951c721b34f2bc4128e68fe9475 --- net/tstun/wrap.go | 28 +++++++++---- net/tstun/wrap_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 8 deletions(-) diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index 2c4dd0f57eca3..450885fbf5eb1 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -93,6 +93,9 @@ type Wrapper struct { destMACAtomic syncs.AtomicValue[[6]byte] discoKey syncs.AtomicValue[key.DiscoPublic] + // timeNow, if non-nil, will be used to obtain the current time. + timeNow func() time.Time + // natV4Config stores the current NAT configuration. natV4Config atomic.Pointer[natV4Config] @@ -258,6 +261,15 @@ func wrap(logf logger.Logf, tdev tun.Device, isTAP bool) *Wrapper { return w } +// now returns the current time, either by calling t.timeNow if set or time.Now +// if not. +func (t *Wrapper) now() time.Time { + if t.timeNow != nil { + return t.timeNow() + } + return time.Now() +} + // SetDestIPActivityFuncs sets a map of funcs to run per packet // destination (the map keys). // @@ -724,7 +736,7 @@ func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error) { } } if captHook != nil { - captHook(capture.FromLocal, time.Now(), p.Buffer(), p.CaptureMeta) + captHook(capture.FromLocal, t.now(), p.Buffer(), p.CaptureMeta) } if !t.disableFilter { response := t.filterPacketOutboundToWireGuard(p) @@ -791,7 +803,7 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, buf []byte, offset int) (int func (t *Wrapper) filterPacketInboundFromWireGuard(p *packet.Parsed, captHook capture.Callback) filter.Response { if captHook != nil { - captHook(capture.FromPeer, time.Now(), p.Buffer(), p.CaptureMeta) + captHook(capture.FromPeer, t.now(), p.Buffer(), p.CaptureMeta) } if p.IPProto == ipproto.TSMP { @@ -959,7 +971,7 @@ func (t *Wrapper) InjectInboundPacketBuffer(pkt stack.PacketBufferPtr) error { p.Decode(buf[PacketStartOffset:]) captHook := t.captureHook.Load() if captHook != nil { - captHook(capture.SynthesizedToLocal, time.Now(), p.Buffer(), p.CaptureMeta) + captHook(capture.SynthesizedToLocal, t.now(), p.Buffer(), p.CaptureMeta) } t.dnatV4(p) @@ -1037,14 +1049,14 @@ func (t *Wrapper) injectOutboundPong(pp *packet.Parsed, req packet.TSMPPingReque // It does not block, but takes ownership of the packet. // The injected packet will not pass through outbound filters. // Injecting an empty packet is a no-op. -func (t *Wrapper) InjectOutbound(packet []byte) error { - if len(packet) > MaxPacketSize { +func (t *Wrapper) InjectOutbound(pkt []byte) error { + if len(pkt) > MaxPacketSize { return errPacketTooBig } - if len(packet) == 0 { + if len(pkt) == 0 { return nil } - t.injectOutbound(tunInjectedRead{data: packet}) + t.injectOutbound(tunInjectedRead{data: pkt}) return nil } @@ -1063,7 +1075,7 @@ func (t *Wrapper) InjectOutboundPacketBuffer(pkt stack.PacketBufferPtr) error { } if capt := t.captureHook.Load(); capt != nil { b := pkt.ToBuffer() - capt(capture.SynthesizedToPeer, time.Now(), b.Flatten(), packet.CaptureMeta{}) + capt(capture.SynthesizedToPeer, t.now(), b.Flatten(), packet.CaptureMeta{}) } t.injectOutbound(tunInjectedRead{packet: pkt}) diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index baf0eff568f6b..f2ae0a6145a7c 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -10,9 +10,11 @@ import ( "encoding/hex" "fmt" "net/netip" + "reflect" "strconv" "strings" "testing" + "time" "unicode" "unsafe" @@ -21,6 +23,8 @@ import ( "github.com/tailscale/wireguard-go/tun/tuntest" "go4.org/mem" "go4.org/netipx" + "gvisor.dev/gvisor/pkg/bufferv2" + "gvisor.dev/gvisor/pkg/tcpip/stack" "tailscale.com/disco" "tailscale.com/net/connstats" "tailscale.com/net/netaddr" @@ -33,6 +37,7 @@ import ( "tailscale.com/types/netlogtype" "tailscale.com/types/ptr" "tailscale.com/util/must" + "tailscale.com/wgengine/capture" "tailscale.com/wgengine/filter" "tailscale.com/wgengine/wgcfg" ) @@ -766,3 +771,93 @@ func TestNATCfg(t *testing.T) { }) } } + +// TestCaptureHook verifies that the Wrapper.captureHook callback is called +// with the correct parameters when various packet operations are performed. +func TestCaptureHook(t *testing.T) { + type captureRecord struct { + path capture.Path + now time.Time + pkt []byte + meta packet.CaptureMeta + } + + var captured []captureRecord + hook := func(path capture.Path, now time.Time, pkt []byte, meta packet.CaptureMeta) { + captured = append(captured, captureRecord{ + path: path, + now: now, + pkt: pkt, + meta: meta, + }) + } + + now := time.Unix(1682085856, 0) + + _, w := newFakeTUN(t.Logf, true) + w.timeNow = func() time.Time { + return now + } + w.InstallCaptureHook(hook) + defer w.Close() + + // Loop reading and discarding packets; this ensures that we don't have + // packets stuck in vectorOutbound + go func() { + var ( + buf [MaxPacketSize]byte + sizes = make([]int, 1) + ) + for { + _, err := w.Read([][]byte{buf[:]}, sizes, 0) + if err != nil { + return + } + } + }() + + // Do operations that should result in a packet being captured. + w.Write([][]byte{ + []byte("Write1"), + []byte("Write2"), + }, 0) + packetBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{ + Payload: bufferv2.MakeWithData([]byte("InjectInboundPacketBuffer")), + }) + w.InjectInboundPacketBuffer(packetBuf) + + packetBuf = stack.NewPacketBuffer(stack.PacketBufferOptions{ + Payload: bufferv2.MakeWithData([]byte("InjectOutboundPacketBuffer")), + }) + w.InjectOutboundPacketBuffer(packetBuf) + + // TODO: test Read + // TODO: determine if we want InjectOutbound to log + + // Assert that the right packets are captured. + want := []captureRecord{ + { + path: capture.FromPeer, + pkt: []byte("Write1"), + }, + { + path: capture.FromPeer, + pkt: []byte("Write2"), + }, + { + path: capture.SynthesizedToLocal, + pkt: []byte("InjectInboundPacketBuffer"), + }, + { + path: capture.SynthesizedToPeer, + pkt: []byte("InjectOutboundPacketBuffer"), + }, + } + for i := 0; i < len(want); i++ { + want[i].now = now + } + if !reflect.DeepEqual(captured, want) { + t.Errorf("mismatch between captured and expected packets\ngot: %+v\nwant: %+v", + captured, want) + } +} From 6f521c138dc381b0404027d8f1eca96661ded73d Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Thu, 20 Apr 2023 10:21:46 -0400 Subject: [PATCH 018/331] tailcfg: add CanPort80 field to DERPNode A follow-up PR will start using this field after we set it in our production DERPMap. Updates #7925 Signed-off-by: Andrew Dunham Change-Id: Idb41b79e6055dddb8944f79d91ad4a186ace98c7 --- tailcfg/derpmap.go | 4 ++++ tailcfg/tailcfg_clone.go | 1 + tailcfg/tailcfg_view.go | 2 ++ 3 files changed, 7 insertions(+) diff --git a/tailcfg/derpmap.go b/tailcfg/derpmap.go index 1a22e888042ef..abc763e47ee82 100644 --- a/tailcfg/derpmap.go +++ b/tailcfg/derpmap.go @@ -142,6 +142,10 @@ type DERPNode struct { // STUNTestIP is used in tests to override the STUN server's IP. // If empty, it's assumed to be the same as the DERP server. STUNTestIP string `json:",omitempty"` + + // CanPort80 specifies whether this DERP node is accessible over HTTP + // on port 80 specifically. This is used for captive portal checks. + CanPort80 bool `json:",omitempty"` } // DotInvalid is a fake DNS TLD used in tests for an invalid hostname. diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 5326c495cd05f..3f54d96d721a1 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -353,6 +353,7 @@ var _DERPNodeCloneNeedsRegeneration = DERPNode(struct { DERPPort int InsecureForTests bool STUNTestIP string + CanPort80 bool }{}) // Clone makes a deep copy of SSHRule. diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index b32ccc3656537..3771881f691e0 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -802,6 +802,7 @@ func (v DERPNodeView) STUNOnly() bool { return v.ж.STUNOnly } func (v DERPNodeView) DERPPort() int { return v.ж.DERPPort } func (v DERPNodeView) InsecureForTests() bool { return v.ж.InsecureForTests } func (v DERPNodeView) STUNTestIP() string { return v.ж.STUNTestIP } +func (v DERPNodeView) CanPort80() bool { return v.ж.CanPort80 } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _DERPNodeViewNeedsRegeneration = DERPNode(struct { @@ -816,6 +817,7 @@ var _DERPNodeViewNeedsRegeneration = DERPNode(struct { DERPPort int InsecureForTests bool STUNTestIP string + CanPort80 bool }{}) // View returns a readonly view of SSHRule. From e3b2250e2654dfea9dc0f80925790f48331e8225 Mon Sep 17 00:00:00 2001 From: Flakes Updater Date: Mon, 17 Apr 2023 22:39:32 +0000 Subject: [PATCH 019/331] go.mod.sri: update SRI hash for go.mod changes Signed-off-by: Flakes Updater --- flake.nix | 2 +- go.mod.sri | 2 +- shell.nix | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index 92e6eb2a015a8..70d9da2058713 100644 --- a/flake.nix +++ b/flake.nix @@ -115,4 +115,4 @@ in flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system); } -# nix-direnv cache busting line: sha256-LfHkNXQbg7/u6y882gtINuQtwinYakg3abKJTDrrADo= +# nix-direnv cache busting line: sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= diff --git a/go.mod.sri b/go.mod.sri index df3028f558f79..5bb984a0378f8 100644 --- a/go.mod.sri +++ b/go.mod.sri @@ -1 +1 @@ -sha256-LfHkNXQbg7/u6y882gtINuQtwinYakg3abKJTDrrADo= +sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= diff --git a/shell.nix b/shell.nix index a697ab8fa0901..73a3e9d20cf4e 100644 --- a/shell.nix +++ b/shell.nix @@ -16,4 +16,4 @@ ) { src = ./.; }).shellNix -# nix-direnv cache busting line: sha256-LfHkNXQbg7/u6y882gtINuQtwinYakg3abKJTDrrADo= +# nix-direnv cache busting line: sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= From f66ddb544cfc568125b1afedd1da97c9ecc61b6b Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Wed, 19 Apr 2023 21:10:55 -0700 Subject: [PATCH 020/331] tailcfg: add SSHRecorderFailureAction and SSHRecordingFailureNotifyRequest This allows control to specify how to handle situations where the recorder isn't available. Updates tailscale/corp#9967 Signed-off-by: Maisem Ali --- tailcfg/tailcfg.go | 56 +++++++++++++++++++++++++++++++++++++++- tailcfg/tailcfg_clone.go | 5 ++++ tailcfg/tailcfg_view.go | 8 ++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 620151f11682c..95057d490ccdd 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2048,7 +2048,61 @@ type SSHAction struct { // Recorders defines the destinations of the SSH session recorders. // The recording will be uploaded to http://addr:port/record. - Recorders []netip.AddrPort `json:"recorders"` + Recorders []netip.AddrPort `json:"recorders,omitempty"` + + // OnRecorderFailure is the action to take if recording fails. + // If nil, the default action is to fail open. + OnRecordingFailure *SSHRecorderFailureAction `json:"onRecordingFailure,omitempty"` +} + +// SSHRecorderFailureAction is the action to take if recording fails. +type SSHRecorderFailureAction struct { + // RejectSessionWithMessage, if not empty, specifies that the session should + // be rejected if the recording fails to start. + // The message will be shown to the user before the session is rejected. + RejectSessionWithMessage string `json:",omitempty"` + + // TerminateSessionWithMessage, if not empty, specifies that the session + // should be terminated if the recording fails after it has started. The + // message will be shown to the user before the session is terminated. + TerminateSessionWithMessage string `json:",omitempty"` + + // NotifyURL, if non-empty, specifies a HTTP POST URL to notify when the + // recording fails. The payload is the JSON encoded + // SSHRecordingFailureNotifyRequest struct. The host field in the URL is + // ignored, and it will be sent to control over the Noise transport. + NotifyURL string `json:",omitempty"` +} + +// SSHRecordingFailureNotifyRequest is the JSON payload sent to the NotifyURL +// when a recording fails. +type SSHRecordingFailureNotifyRequest struct { + // CapVersion is the client's current CapabilityVersion. + CapVersion CapabilityVersion + + // NodeKey is the client's current node key. + NodeKey key.NodePublic + + // SrcNode is the ID of the node that initiated the SSH session. + SrcNode NodeID + + // SSHUser is the user that was presented to the SSH server. + SSHUser string + + // LocalUser is the user that was resolved from the SSHUser for the local machine. + LocalUser string + + // Attempts is the list of recorders that were attempted, in order. + Attempts []SSHRecordingAttempt +} + +// SSHRecordingAttempt is a single attempt to start a recording. +type SSHRecordingAttempt struct { + // Recorder is the address of the recorder that was attempted. + Recorder netip.AddrPort + + // FailureMessage is the error message of the failed attempt. + FailureMessage string } // OverTLSPublicKeyResponse is the JSON response to /key?v= diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 3f54d96d721a1..a678cb47b8426 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -399,6 +399,10 @@ func (src *SSHAction) Clone() *SSHAction { dst := new(SSHAction) *dst = *src dst.Recorders = append(src.Recorders[:0:0], src.Recorders...) + if dst.OnRecordingFailure != nil { + dst.OnRecordingFailure = new(SSHRecorderFailureAction) + *dst.OnRecordingFailure = *src.OnRecordingFailure + } return dst } @@ -412,6 +416,7 @@ var _SSHActionCloneNeedsRegeneration = SSHAction(struct { HoldAndDelegate string AllowLocalPortForwarding bool Recorders []netip.AddrPort + OnRecordingFailure *SSHRecorderFailureAction }{}) // Clone makes a deep copy of SSHPrincipal. diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 3771881f691e0..b4ff3b738ee8b 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -941,6 +941,13 @@ func (v SSHActionView) AllowAgentForwarding() bool { return v.ж.All func (v SSHActionView) HoldAndDelegate() string { return v.ж.HoldAndDelegate } func (v SSHActionView) AllowLocalPortForwarding() bool { return v.ж.AllowLocalPortForwarding } func (v SSHActionView) Recorders() views.Slice[netip.AddrPort] { return views.SliceOf(v.ж.Recorders) } +func (v SSHActionView) OnRecordingFailure() *SSHRecorderFailureAction { + if v.ж.OnRecordingFailure == nil { + return nil + } + x := *v.ж.OnRecordingFailure + return &x +} // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _SSHActionViewNeedsRegeneration = SSHAction(struct { @@ -952,6 +959,7 @@ var _SSHActionViewNeedsRegeneration = SSHAction(struct { HoldAndDelegate string AllowLocalPortForwarding bool Recorders []netip.AddrPort + OnRecordingFailure *SSHRecorderFailureAction }{}) // View returns a readonly view of SSHPrincipal. From 7778d708a6a443dc03f8afc342f1b310b019b662 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Wed, 19 Apr 2023 21:33:33 -0700 Subject: [PATCH 021/331] ssh/tailssh: handle dialing multiple recorders and failing open This adds support to try dialing out to multiple recorders each with a 5s timeout and an overall 30s timeout. It also starts respecting the actions `OnRecordingFailure` field if set, if it is not set it fails open. Updates tailscale/corp#9967 Signed-off-by: Maisem Ali --- ssh/tailssh/tailssh.go | 207 +++++++++++++++++++++++++----------- ssh/tailssh/tailssh_test.go | 117 ++++++++++++++++++-- tailcfg/tailcfg.go | 3 +- 3 files changed, 255 insertions(+), 72 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 5430b02faaa29..3865a50ba6b20 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -17,6 +17,7 @@ import ( "io" "net" "net/http" + "net/http/httptrace" "net/netip" "net/url" "os" @@ -42,6 +43,7 @@ import ( "tailscale.com/types/netmap" "tailscale.com/util/clientmetric" "tailscale.com/util/mak" + "tailscale.com/util/multierr" "tailscale.com/version/distro" ) @@ -79,33 +81,11 @@ type server struct { // mu protects the following mu sync.Mutex - httpc *http.Client // for calling out to peers. activeConns map[*conn]bool // set; value is always true fetchPublicKeysCache map[string]pubKeyCacheEntry // by https URL shutdownCalled bool } -// sessionRecordingClient returns an http.Client that uses srv.lb.Dialer() to -// dial connections. This is used to make requests to the session recording -// server to upload session recordings. -func (srv *server) sessionRecordingClient() *http.Client { - srv.mu.Lock() - defer srv.mu.Unlock() - if srv.httpc != nil { - return srv.httpc - } - tr := http.DefaultTransport.(*http.Transport).Clone() - tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - return srv.lb.Dialer().UserDial(ctx, network, addr) - } - srv.httpc = &http.Client{ - Transport: tr, - } - return srv.httpc -} - func (srv *server) now() time.Time { if srv != nil && srv.timeNow != nil { return srv.timeNow() @@ -1078,7 +1058,7 @@ func (ss *sshSession) run() { if err != nil { var uve userVisibleError if errors.As(err, &uve) { - fmt.Fprintf(ss, "%s\r\n", uve) + fmt.Fprintf(ss, "%s\r\n", uve.SSHTerminationMessage()) } else { fmt.Fprintf(ss, "can't start new recording\r\n") } @@ -1086,7 +1066,9 @@ func (ss *sshSession) run() { ss.Exit(1) return } - defer rec.Close() + if rec != nil { + defer rec.Close() + } } } @@ -1169,15 +1151,16 @@ func (ss *sshSession) run() { // If the final action has a non-empty list of recorders, that list is // returned. Otherwise, the list of recorders from the initial action // is returned. -func (ss *sshSession) recorders() []netip.AddrPort { +func (ss *sshSession) recorders() ([]netip.AddrPort, *tailcfg.SSHRecorderFailureAction) { if len(ss.conn.finalAction.Recorders) > 0 { - return ss.conn.finalAction.Recorders + return ss.conn.finalAction.Recorders, ss.conn.finalAction.OnRecordingFailure } - return ss.conn.action0.Recorders + return ss.conn.action0.Recorders, ss.conn.action0.OnRecordingFailure } func (ss *sshSession) shouldRecord() bool { - return len(ss.recorders()) > 0 + recs, _ := ss.recorders() + return len(recs) > 0 } type sshConnInfo struct { @@ -1409,16 +1392,120 @@ type CastHeader struct { LocalUser string `json:"localUser"` } +// sessionRecordingClient returns an http.Client that uses srv.lb.Dialer() to +// dial connections. This is used to make requests to the session recording +// server to upload session recordings. +// It uses the provided dialCtx to dial connections, and limits a single dial +// to 5 seconds. +func (ss *sshSession) sessionRecordingClient(dialCtx context.Context) (*http.Client, error) { + dialer := ss.conn.srv.lb.Dialer() + if dialer == nil { + return nil, errors.New("no peer API transport") + } + tr := dialer.PeerAPITransport().Clone() + dialContextFn := tr.DialContext + + tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { + perAttemptCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + go func() { + select { + case <-perAttemptCtx.Done(): + case <-dialCtx.Done(): + cancel() + } + }() + return dialContextFn(perAttemptCtx, network, addr) + } + return &http.Client{ + Transport: tr, + }, nil +} + +// connectToRecorder connects to the recorder at any of the provided addresses. +// It returns the first successful response, or a multierr if all attempts fail. +// +// On success, it returns a WriteCloser that can be used to upload the +// recording, and a channel that will be sent an error (or nil) when the upload +// fails or completes. +func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPort) (io.WriteCloser, <-chan error, error) { + if len(recs) == 0 { + return nil, nil, errors.New("no recorders configured") + } + + // We use a special context for dialing the recorder, so that we can + // limit the time we spend dialing to 30 seconds and still have an + // unbounded context for the upload. + dialCtx, dialCancel := context.WithTimeout(ctx, 30*time.Second) + defer dialCancel() + hc, err := ss.sessionRecordingClient(dialCtx) + if err != nil { + return nil, nil, err + } + var errs []error + for _, ap := range recs { + // We dial the recorder and wait for it to send a 100-continue + // response before returning from this function. This ensures that + // the recorder is ready to accept the recording. + + // got100 is closed when we receive the 100-continue response. + got100 := make(chan struct{}) + ctx = httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{ + Got100Continue: func() { + close(got100) + }, + }) + + pr, pw := io.Pipe() + req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://%s:%d/record", ap.Addr(), ap.Port()), pr) + if err != nil { + errs = append(errs, fmt.Errorf("recording: error starting recording: %w", err)) + continue + } + // We set the Expect header to 100-continue, so that the recorder + // will send a 100-continue response before it starts reading the + // request body. + req.Header.Set("Expect", "100-continue") + + // errChan is used to indicate the result of the request. + errChan := make(chan error, 1) + go func() { + resp, err := hc.Do(req) + if err != nil { + errChan <- fmt.Errorf("recording: error starting recording: %w", err) + return + } + if resp.StatusCode != 200 { + errChan <- fmt.Errorf("recording: unexpected status: %v", resp.Status) + return + } + errChan <- nil + }() + select { + case <-got100: + case err := <-errChan: + // If we get an error before we get the 100-continue response, + // we need to try another recorder. + if err == nil { + // If the error is nil, we got a 200 response, which + // is unexpected as we haven't sent any data yet. + err = errors.New("recording: unexpected EOF") + } + errs = append(errs, err) + continue + } + return pw, errChan, nil + } + return nil, nil, multierr.New(errs...) +} + // startNewRecording starts a new SSH session recording. +// It may return a nil recording if recording is not available. func (ss *sshSession) startNewRecording() (_ *recording, err error) { - recorders := ss.recorders() + recorders, onFailure := ss.recorders() if len(recorders) == 0 { return nil, errors.New("no recorders configured") } - recorder := recorders[0] - if len(recorders) > 1 { - ss.logf("warning: multiple recorders configured, using first one: %v", recorder) - } var w ssh.Window if ptyReq, _, isPtyReq := ss.Pty(); isPtyReq { @@ -1436,51 +1523,43 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { start: now, } - pr, pw := io.Pipe() - // We want to use a background context for uploading and not ss.ctx. // ss.ctx is closed when the session closes, but we don't want to break the upload at that time. // Instead we want to wait for the session to close the writer when it finishes. ctx := context.Background() - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://%s:%d/record", recorder.Addr(), recorder.Port()), pr) + wc, errChan, err := ss.connectToRecorder(ctx, recorders) if err != nil { - pr.Close() - pw.Close() - return nil, err + // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.RejectSessionWithMessage != "" { + ss.logf("recording: error starting recording (rejecting session): %v", err) + return nil, userVisibleError{ + error: err, + msg: onFailure.RejectSessionWithMessage, + } + } + ss.logf("recording: error starting recording (failing open): %v", err) + return nil, nil } - // We want to wait for the server to respond with 100 Continue to notifiy us - // that it's ready to receive data. We do this to block the session from - // starting until the server is ready to receive data. - // It also allows the server to reject the request before we start sending - // data. - req.Header.Set("Expect", "100-continue") + go func() { - defer pw.Close() - ss.logf("starting asciinema recording to %s", recorder) - hc := ss.conn.srv.sessionRecordingClient() - resp, err := hc.Do(req) - if err != nil { - err := fmt.Errorf("recording: error sending recording: %w", err) - ss.logf("%v", err) - ss.cancelCtx(userVisibleError{ - msg: "recording: error sending recording", - error: err, - }) + err := <-errChan + if err == nil { + // Success. return } - defer resp.Body.Close() - defer ss.cancelCtx(errors.New("recording: done")) - if resp.StatusCode != http.StatusOK { - err := fmt.Errorf("recording: server responded with %s", resp.Status) - ss.logf("%v", err) + // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.TerminateSessionWithMessage != "" { + ss.logf("recording: error uploading recording (closing session): %v", err) ss.cancelCtx(userVisibleError{ - msg: "recording server responded with: " + resp.Status, error: err, + msg: onFailure.TerminateSessionWithMessage, }) + return } + ss.logf("recording: error uploading recording (failing open): %v", err) }() - rec.out = pw + rec.out = wc ch := CastHeader{ Version: 2, @@ -1515,7 +1594,7 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { return nil, err } j = append(j, '\n') - if _, err := pw.Write(j); err != nil { + if _, err := rec.out.Write(j); err != nil { if errors.Is(err, io.ErrClosedPipe) && ss.ctx.Err() != nil { // If we got an io.ErrClosedPipe, it's likely because // the recording server closed the connection on us. Return diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index d262093ec8a24..c0935d24bc01f 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -240,7 +240,7 @@ var ( ) func (ts *localState) Dialer() *tsdial.Dialer { - return nil + return &tsdial.Dialer{} } func (ts *localState) GetSSH_HostKeys() ([]gossh.Signer, error) { @@ -338,8 +338,7 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) { defer recordingServer.Close() s := &server{ - logf: t.Logf, - httpc: recordingServer.Client(), + logf: t.Logf, lb: &localState{ sshEnabled: true, matchingRule: newSSHRule( @@ -348,6 +347,10 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) { Recorders: []netip.AddrPort{ netip.MustParseAddrPort(recordingServer.Listener.Addr().String()), }, + OnRecordingFailure: &tailcfg.SSHRecorderFailureAction{ + RejectSessionWithMessage: "session rejected", + TerminateSessionWithMessage: "session terminated", + }, }, ), }, @@ -374,7 +377,7 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) { w.WriteHeader(http.StatusForbidden) }, sshCommand: "echo hello", - wantClientOutput: "recording: server responded with 403 Forbidden\r\n", + wantClientOutput: "session rejected\r\n", clientOutputMustNotContain: []string{"hello"}, }, @@ -386,7 +389,7 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) { w.WriteHeader(http.StatusInternalServerError) }, sshCommand: "echo hello && sleep 1 && echo world", - wantClientOutput: "\r\n\r\nrecording server responded with: 500 Internal Server Error\r\n\r\n", + wantClientOutput: "\r\n\r\nsession terminated\r\n\r\n", clientOutputMustNotContain: []string{"world"}, }, @@ -440,6 +443,103 @@ func TestSSHRecordingCancelsSessionsOnUploadFailure(t *testing.T) { } } +func TestMultipleRecorders(t *testing.T) { + if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { + t.Skipf("skipping on %q; only runs on linux and darwin", runtime.GOOS) + } + done := make(chan struct{}) + recordingServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer close(done) + io.ReadAll(r.Body) + w.WriteHeader(http.StatusOK) + })) + defer recordingServer.Close() + badRecorder, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatal(err) + } + badRecorderAddr := badRecorder.Addr().String() + badRecorder.Close() + + badRecordingServer500 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + defer badRecordingServer500.Close() + + badRecordingServer200 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + })) + defer badRecordingServer200.Close() + + s := &server{ + logf: t.Logf, + lb: &localState{ + sshEnabled: true, + matchingRule: newSSHRule( + &tailcfg.SSHAction{ + Accept: true, + Recorders: []netip.AddrPort{ + netip.MustParseAddrPort(badRecorderAddr), + netip.MustParseAddrPort(badRecordingServer500.Listener.Addr().String()), + netip.MustParseAddrPort(badRecordingServer200.Listener.Addr().String()), + netip.MustParseAddrPort(recordingServer.Listener.Addr().String()), + }, + OnRecordingFailure: &tailcfg.SSHRecorderFailureAction{ + RejectSessionWithMessage: "session rejected", + TerminateSessionWithMessage: "session terminated", + }, + }, + ), + }, + } + defer s.Shutdown() + + src, dst := must.Get(netip.ParseAddrPort("100.100.100.101:2231")), must.Get(netip.ParseAddrPort("100.100.100.102:22")) + sc, dc := memnet.NewTCPConn(src, dst, 1024) + + const sshUser = "alice" + cfg := &gossh.ClientConfig{ + User: sshUser, + HostKeyCallback: gossh.InsecureIgnoreHostKey(), + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + c, chans, reqs, err := gossh.NewClientConn(sc, sc.RemoteAddr().String(), cfg) + if err != nil { + t.Errorf("client: %v", err) + return + } + client := gossh.NewClient(c, chans, reqs) + defer client.Close() + session, err := client.NewSession() + if err != nil { + t.Errorf("client: %v", err) + return + } + defer session.Close() + t.Logf("client established session") + out, err := session.CombinedOutput("echo Ran echo!") + if err != nil { + t.Errorf("client: %v", err) + } + if string(out) != "Ran echo!\n" { + t.Errorf("client: unexpected output: %q", out) + } + }() + if err := s.HandleSSHConn(dc); err != nil { + t.Errorf("unexpected error: %v", err) + } + wg.Wait() + select { + case <-done: + case <-time.After(1 * time.Second): + t.Fatal("timed out waiting for recording") + } +} + // TestSSHRecordingNonInteractive tests that the SSH server records the SSH session // when the client is not interactive (i.e. no PTY). // It starts a local SSH server and a recording server. The recording server @@ -464,8 +564,7 @@ func TestSSHRecordingNonInteractive(t *testing.T) { defer recordingServer.Close() s := &server{ - logf: logger.Discard, - httpc: recordingServer.Client(), + logf: logger.Discard, lb: &localState{ sshEnabled: true, matchingRule: newSSHRule( @@ -474,6 +573,10 @@ func TestSSHRecordingNonInteractive(t *testing.T) { Recorders: []netip.AddrPort{ must.Get(netip.ParseAddrPort(recordingServer.Listener.Addr().String())), }, + OnRecordingFailure: &tailcfg.SSHRecorderFailureAction{ + RejectSessionWithMessage: "session rejected", + TerminateSessionWithMessage: "session terminated", + }, }, ), }, diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 95057d490ccdd..b77193f2b9902 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -97,7 +97,8 @@ type CapabilityVersion int // - 58: 2023-03-10: Client retries lite map updates before restarting map poll. // - 59: 2023-03-16: Client understands Peers[].SelfNodeV4MasqAddrForThisPeer // - 60: 2023-04-06: Client understands IsWireGuardOnly -const CurrentCapabilityVersion CapabilityVersion = 60 +// - 61: 2023-04-18: Client understand SSHAction.SSHRecorderFailureAction +const CurrentCapabilityVersion CapabilityVersion = 61 type StableID string From 90ba26cea1b4ddea7314cebafc27d033bda1d772 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 22 Apr 2023 17:39:11 -0700 Subject: [PATCH 022/331] net/netcheck: fix crash when IPv6 kinda but not really works Looks like on some systems there's an IPv6 address, but then opening a IPv6 UDP socket fails later. Probably some firewall. Tolerate it better and don't crash. To repro: check the "udp6" to something like "udp7" (something that'll fail) and run "go run ./cmd/tailscale netcheck" on a machine with active IPv6. It used to crash and now it doesn't. Fixes #7949 Signed-off-by: Brad Fitzpatrick --- net/netcheck/netcheck.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index a61343ebe5796..603fa3a4162c4 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -40,6 +40,7 @@ import ( "tailscale.com/types/logger" "tailscale.com/types/nettype" "tailscale.com/types/opt" + "tailscale.com/types/ptr" "tailscale.com/util/clientmetric" "tailscale.com/util/mak" ) @@ -943,6 +944,16 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, go c.readPackets(ctx, u6) } } + + // If our interfaces.State suggested we have IPv6 support but then we + // failed to get an IPv6 sending socket (as in + // https://github.com/tailscale/tailscale/issues/7949), then change + // ifState.HaveV6 before we make a probe plan that involves sending IPv6 + // packets and thus assuming rs.pc6 is non-nil. + if rs.pc6 == nil { + ifState = ptr.To(*ifState) // shallow clone + ifState.HaveV6 = false + } } plan := makeProbePlan(dm, ifState, last) From ce11c82d51cc42202b3c8987f279f16c4edf88bd Mon Sep 17 00:00:00 2001 From: Marwan Sulaiman Date: Mon, 24 Apr 2023 08:54:48 -0400 Subject: [PATCH 023/331] ipn/store/awsstore: persist state with intelligent tiering Fixes #6784 This PR makes it so that we can persist the tailscaled state with intelligent tiering which increases the capacity from 4kb to 8kb Signed-off-by: Marwan Sulaiman --- ipn/store/awsstore/store_aws.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ipn/store/awsstore/store_aws.go b/ipn/store/awsstore/store_aws.go index 1741cfe02eb51..0fb78d45a6a53 100644 --- a/ipn/store/awsstore/store_aws.go +++ b/ipn/store/awsstore/store_aws.go @@ -51,6 +51,12 @@ type awsStore struct { // New returns a new ipn.StateStore using the AWS SSM storage // location given by ssmARN. +// +// Note that we store the entire store in a single parameter +// key, therefore if the state is above 8kb, it can cause +// Tailscaled to only only store new state in-memory and +// restarting Tailscaled can fail until you delete your state +// from the AWS Parameter Store. func New(_ logger.Logf, ssmARN string) (ipn.StateStore, error) { return newStore(ssmARN, nil) } @@ -160,14 +166,19 @@ func (s *awsStore) persistState() error { return err } - // Store in AWS SSM parameter store + // Store in AWS SSM parameter store. + // + // We use intelligent tiering so that when the state is below 4kb, it uses Standard tiering + // which is free. However, if it exceeds 4kb it switches the parameter to advanced tiering + // doubling the capacity to 8kb per the following docs: + // https://aws.amazon.com/about-aws/whats-new/2019/08/aws-systems-manager-parameter-store-announces-intelligent-tiering-to-enable-automatic-parameter-tier-selection/ _, err = s.ssmClient.PutParameter( context.TODO(), &ssm.PutParameterInput{ Name: aws.String(s.ParameterName()), Value: aws.String(string(bs)), Overwrite: aws.Bool(true), - Tier: ssmTypes.ParameterTierStandard, + Tier: ssmTypes.ParameterTierIntelligentTiering, Type: ssmTypes.ParameterTypeSecureString, }, ) From f58751eb2b6e564b204446390d805bf8f36f683e Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Mon, 24 Apr 2023 11:54:25 -0700 Subject: [PATCH 024/331] net/packet: add NAT support for DCCP and GRE Updates tailscale/corp#8020 Signed-off-by: Maisem Ali --- net/packet/packet.go | 39 +++++++++++++++++++++++++++++++-------- net/packet/packet_test.go | 13 +++++++++++++ types/ipproto/ipproto.go | 6 ++++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/net/packet/packet.go b/net/packet/packet.go index 780349ddfb1f7..e3784a571dbf8 100644 --- a/net/packet/packet.go +++ b/net/packet/packet.go @@ -558,19 +558,42 @@ func withPort(ap netip.AddrPort, port uint16) netip.AddrPort { // Currently (2023-03-01) only TCP/UDP/ICMP over IPv4 is supported. // p is modified in place. // If p.IPProto is unknown, only the IP header checksum is updated. -// TODO(maisem): more protocols (sctp, gre, dccp) func updateV4PacketChecksums(p *Parsed, old, new netip.Addr) { + if len(p.Buffer()) < 12 { + // Not enough space for an IPv4 header. + return + } o4, n4 := old.As4(), new.As4() - updateV4Checksum(p.Buffer()[10:12], o4[:], n4[:]) // header + + // First update the checksum in the IP header. + updateV4Checksum(p.Buffer()[10:12], o4[:], n4[:]) + + // Now update the transport layer checksums, where applicable. + tr := p.Transport() switch p.IPProto { - case ipproto.UDP: - updateV4Checksum(p.Transport()[6:8], o4[:], n4[:]) + case ipproto.UDP, ipproto.DCCP: + if len(tr) < 8 { + // Not enough space for a UDP header. + return + } + updateV4Checksum(tr[6:8], o4[:], n4[:]) case ipproto.TCP: - updateV4Checksum(p.Transport()[16:18], o4[:], n4[:]) - case ipproto.ICMPv4: - // Nothing to do. + if len(tr) < 18 { + // Not enough space for a TCP header. + return + } + updateV4Checksum(tr[16:18], o4[:], n4[:]) + case ipproto.GRE: + if len(tr) < 6 { + // Not enough space for a GRE header. + return + } + if tr[0] == 1 { // checksum present + updateV4Checksum(tr[4:6], o4[:], n4[:]) + } + case ipproto.SCTP, ipproto.ICMPv4: + // No transport layer update required. } - // TODO(maisem): more protocols (sctp, gre, dccp) } // updateV4Checksum calculates and updates the checksum in the packet buffer for diff --git a/net/packet/packet_test.go b/net/packet/packet_test.go index acf8782964c9e..4bc2be77acdad 100644 --- a/net/packet/packet_test.go +++ b/net/packet/packet_test.go @@ -72,6 +72,19 @@ func TestHeaderChecksums(t *testing.T) { 0x45, 0x00, 0x00, 0x74, 0xe2, 0x85, 0x00, 0x00, 0x40, 0x11, 0x96, 0xb5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x42, 0xd4, 0x33, 0x00, 0x35, 0xec, 0x55, 0x00, 0x60, 0xd9, 0x19, 0xed, 0xfd, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x0c, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x01, 0x6c, 0xc0, 0x15, 0xc0, 0x31, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x04, 0x8e, 0xfa, 0xbd, 0xce, 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, + { + name: "DCCP", + packet: []byte{ + 0x45, 0x00, 0x00, 0x28, 0x15, 0x06, 0x40, 0x00, 0x40, 0x21, 0x5f, 0x2f, 0xc0, 0xa8, 0x01, 0x1f, 0xc9, 0x0b, 0x3b, 0xad, 0x80, 0x04, 0x13, 0x89, 0x05, 0x00, 0x08, 0xdb, 0x01, 0x00, 0x00, 0x04, 0x29, 0x01, 0x6d, 0xdc, 0x00, 0x00, 0x00, 0x00, + }, + }, + { + name: "SCTP", + packet: []byte{ + 0x45, 0x00, 0x00, 0x30, 0x09, 0xd9, 0x40, 0x00, 0xff, 0x84, 0x50, 0xe2, 0x0a, 0x1c, 0x06, 0x2c, 0x0a, 0x1c, 0x06, 0x2b, 0x0b, 0x80, 0x40, 0x00, 0x21, 0x44, 0x15, 0x23, 0x2b, 0xf2, 0x02, 0x4e, 0x03, 0x00, 0x00, 0x10, 0x28, 0x02, 0x43, 0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + }, + // TODO(maisem): add test for GRE. } var p Parsed for _, tt := range tests { diff --git a/types/ipproto/ipproto.go b/types/ipproto/ipproto.go index 66258f1ab5ef7..a6b1e0c48a1c6 100644 --- a/types/ipproto/ipproto.go +++ b/types/ipproto/ipproto.go @@ -25,6 +25,8 @@ const ( ICMPv6 Proto = 0x3a TCP Proto = 0x06 UDP Proto = 0x11 + DCCP Proto = 0x21 + GRE Proto = 0x2f SCTP Proto = 0x84 // TSMP is the Tailscale Message Protocol (our ICMP-ish @@ -67,6 +69,10 @@ func (p Proto) String() string { return "SCTP" case TSMP: return "TSMP" + case GRE: + return "GRE" + case DCCP: + return "DCCP" default: return fmt.Sprintf("IPProto-%d", int(p)) } From aa87e999dc680bfb84d75848fd6c1bcc6b1cdd86 Mon Sep 17 00:00:00 2001 From: License Updater Date: Mon, 24 Apr 2023 18:19:39 +0000 Subject: [PATCH 025/331] licenses: update win/apple licenses Signed-off-by: License Updater --- licenses/windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/licenses/windows.md b/licenses/windows.md index 709af28d63e5b..ef7784806099b 100644 --- a/licenses/windows.md +++ b/licenses/windows.md @@ -32,7 +32,7 @@ Windows][]. See also the dependencies in the [Tailscale CLI][]. - [github.com/nfnt/resize](https://pkg.go.dev/github.com/nfnt/resize) ([ISC](https://github.com/nfnt/resize/blob/83c6a9932646/LICENSE)) - [github.com/peterbourgon/diskv](https://pkg.go.dev/github.com/peterbourgon/diskv) ([MIT](https://github.com/peterbourgon/diskv/blob/v2.0.1/LICENSE)) - [github.com/skip2/go-qrcode](https://pkg.go.dev/github.com/skip2/go-qrcode) ([MIT](https://github.com/skip2/go-qrcode/blob/da1b6568686e/LICENSE)) - - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/f6f2f17d9da1/LICENSE)) + - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/188cb8eef03f/LICENSE)) - [github.com/tailscale/win](https://pkg.go.dev/github.com/tailscale/win) ([BSD-3-Clause](https://github.com/tailscale/win/blob/ad93eed16885/LICENSE)) - [github.com/tc-hib/winres](https://pkg.go.dev/github.com/tc-hib/winres) ([0BSD](https://github.com/tc-hib/winres/blob/v0.1.6/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) From 2e072453848238f3391c932a5dfa488ba49581d9 Mon Sep 17 00:00:00 2001 From: License Updater Date: Sat, 22 Apr 2023 08:39:59 +0000 Subject: [PATCH 026/331] licenses: update android licenses Signed-off-by: License Updater --- licenses/android.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/licenses/android.md b/licenses/android.md index 49ce42ca7b585..87d88b08de486 100644 --- a/licenses/android.md +++ b/licenses/android.md @@ -71,11 +71,11 @@ Client][]. See also the dependencies in the [Tailscale CLI][]. - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47842c84:LICENSE)) - [golang.org/x/exp/shiny](https://pkg.go.dev/golang.org/x/exp/shiny) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/334a2380:shiny/LICENSE)) - [golang.org/x/image](https://pkg.go.dev/golang.org/x/image) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.5.0:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.7.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/a3b23cc7:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.5.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.7.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) - [inet.af/netaddr](https://pkg.go.dev/inet.af/netaddr) ([BSD-3-Clause](https://github.com/inetaf/netaddr/blob/097006376321/LICENSE)) From 018a38272959f391d36ebb7bf77827465d2caffe Mon Sep 17 00:00:00 2001 From: shayne Date: Tue, 25 Apr 2023 13:07:17 -0400 Subject: [PATCH 027/331] cmd/tailscale/cli: [serve] fix MinGW path conversion (#7964) Fixes #7963 Signed-off-by: Shayne Sweeney --- cmd/tailscale/cli/serve.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cmd/tailscale/cli/serve.go b/cmd/tailscale/cli/serve.go index 7691c7497f2b7..59518feccbfda 100644 --- a/cmd/tailscale/cli/serve.go +++ b/cmd/tailscale/cli/serve.go @@ -16,6 +16,7 @@ import ( "path" "path/filepath" "reflect" + "runtime" "sort" "strconv" "strings" @@ -412,6 +413,7 @@ func cleanMountPoint(mount string) (string, error) { if mount == "" { return "", errors.New("mount point cannot be empty") } + mount = cleanMinGWPathConversionIfNeeded(mount) if !strings.HasPrefix(mount, "/") { mount = "/" + mount } @@ -422,6 +424,26 @@ func cleanMountPoint(mount string) (string, error) { return "", fmt.Errorf("invalid mount point %q", mount) } +// cleanMinGWPathConversionIfNeeded strips the EXEPATH prefix from the given +// path if the path is a MinGW(ish) (Windows) shell arg. +// +// MinGW(ish) (Windows) shells perform POSIX-to-Windows path conversion +// converting the leading "/" of any shell arg to the EXEPATH, which mangles the +// mount point. Strip the EXEPATH prefix if it exists. #7963 +// +// "/C:/Program Files/Git/foo" -> "/foo" +func cleanMinGWPathConversionIfNeeded(path string) string { + // Only do this on Windows. + if runtime.GOOS != "windows" { + return path + } + if _, ok := os.LookupEnv("MSYSTEM"); ok { + exepath := filepath.ToSlash(os.Getenv("EXEPATH")) + path = strings.TrimPrefix(path, exepath) + } + return path +} + func expandProxyTarget(source string) (string, error) { if !strings.Contains(source, "://") { source = "http://" + source From 1b8a0dfe5e39beb199c2c1939d87292d15608bc7 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Tue, 25 Apr 2023 18:13:35 -0700 Subject: [PATCH 028/331] ssh/tailssh: also handle recording upload failure during writes Previously we would error out when the recording server disappeared after the in memory buffer filled up for the io.Copy. This makes it so that we handle failing open correctly in that path. Updates tailscale/corp#9967 Signed-off-by: Maisem Ali --- ssh/tailssh/tailssh.go | 45 ++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 3865a50ba6b20..37e73e1401217 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -1519,8 +1519,9 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { now := time.Now() rec := &recording{ - ss: ss, - start: now, + ss: ss, + start: now, + failOpen: onFailure == nil || onFailure.TerminateSessionWithMessage == "", } // We want to use a background context for uploading and not ss.ctx. @@ -1611,6 +1612,10 @@ type recording struct { ss *sshSession start time.Time + // failOpen specifies whether the session should be allowed to + // continue if writing to the recording fails. + failOpen bool + mu sync.Mutex // guards writes to, close of out out io.WriteCloser } @@ -1642,7 +1647,7 @@ func (r *recording) writer(dir string, w io.Writer) io.Writer { // passwords. return w } - return &loggingWriter{r, dir, w} + return &loggingWriter{r: r, dir: dir, w: w} } // loggingWriter is an io.Writer wrapper that writes first an @@ -1651,20 +1656,30 @@ type loggingWriter struct { r *recording dir string // "i" or "o" (input or output) w io.Writer // underlying Writer, after writing to r.out + + // recordingFailedOpen specifies whether we've failed to write to + // r.out and should stop trying. It is set to true if we fail to write + // to r.out and r.failOpen is set. + recordingFailedOpen bool } -func (w loggingWriter) Write(p []byte) (n int, err error) { - j, err := json.Marshal([]any{ - time.Since(w.r.start).Seconds(), - w.dir, - string(p), - }) - if err != nil { - return 0, err - } - j = append(j, '\n') - if err := w.writeCastLine(j); err != nil { - return 0, err +func (w *loggingWriter) Write(p []byte) (n int, err error) { + if !w.recordingFailedOpen { + j, err := json.Marshal([]any{ + time.Since(w.r.start).Seconds(), + w.dir, + string(p), + }) + if err != nil { + return 0, err + } + j = append(j, '\n') + if err := w.writeCastLine(j); err != nil { + if !w.r.failOpen { + return 0, err + } + w.recordingFailedOpen = true + } } return w.w.Write(p) } From 43819309e18ac7d496643fcd86489a2ee0927964 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 26 Apr 2023 09:40:19 -0700 Subject: [PATCH 029/331] .github/workflows: split tests and benchmarks for caching Benchmark flags prevent test caching, so benchmarks are now executed independently of tests. Fixes #7975 Signed-off-by: James Tucker --- .github/workflows/test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f0a9bb641675..8e2d9b5b15c20 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -89,7 +89,11 @@ jobs: - name: build test wrapper run: ./tool/go build -o /tmp/testwrapper ./cmd/testwrapper - name: test all - run: ./tool/go test ${{matrix.buildflags}} -exec=/tmp/testwrapper -bench=. -benchtime=1x ./... + run: ./tool/go test ${{matrix.buildflags}} -exec=/tmp/testwrapper + env: + GOARCH: ${{ matrix.goarch }} + - name: bench all + run: ./tool/go test ${{matrix.buildflags}} -exec=/tmp/testwrapper -test.bench=. -test.benchtime=1x -test.run=^$ env: GOARCH: ${{ matrix.goarch }} - name: check that no tracked files changed From 095d3edd3316b459de27033f69b246001d515290 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Fri, 14 Apr 2023 16:13:06 -0700 Subject: [PATCH 030/331] ipn/ipnlocal: reenable profile tests on Windows This fix does not seem ideal, but the test infrastructure using a local goos doesn't seem to avoid all of the associated challenges, but is somewhat deeply tied to the setup. The core issue this addresses for now is that when run on Windows there can be no code paths that attempt to use an invalid UID string, which on Windows is described in [1]. For the goos="linux" tests, we now explicitly skip the affected migration code if runtime.GOOS=="windows", and for the Windows test we explicitly use the running users uid, rather than just the string "user1". We also now make the case where a profile exists and has already been migrated a non-error condition toward the outer API. Updates #7876 [1] https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers Signed-off-by: James Tucker --- ipn/ipnlocal/profiles.go | 15 ++++++++++++--- ipn/ipnlocal/profiles_test.go | 32 ++++++++++++-------------------- ipn/ipnlocal/profiles_windows.go | 6 ++++-- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/ipn/ipnlocal/profiles.go b/ipn/ipnlocal/profiles.go index 1c16ee30b0bc0..8cdedad7c6438 100644 --- a/ipn/ipnlocal/profiles.go +++ b/ipn/ipnlocal/profiles.go @@ -22,6 +22,8 @@ import ( "tailscale.com/util/winutil" ) +var errAlreadyMigrated = errors.New("profile migration already completed") + // profileManager is a wrapper around a StateStore that manages // multiple profiles and the current profile. type profileManager struct { @@ -66,7 +68,7 @@ func (pm *profileManager) SetCurrentUserID(uid ipn.WindowsUserID) error { b, err := pm.store.ReadState(ipn.CurrentProfileKey(string(uid))) if err == ipn.ErrStateNotExist || len(b) == 0 { if runtime.GOOS == "windows" { - if err := pm.migrateFromLegacyPrefs(); err != nil { + if err := pm.migrateFromLegacyPrefs(); err != nil && !errors.Is(err, errAlreadyMigrated) { return err } } else { @@ -544,7 +546,14 @@ func newProfileManagerWithGOOS(store ipn.StateStore, logf logger.Logf, goos stri if err := pm.setPrefsLocked(prefs); err != nil { return nil, err } - } else if len(knownProfiles) == 0 && goos != "windows" { + // Most platform behavior is controlled by the goos parameter, however + // some behavior is implied by build tag and fails when run on Windows, + // so we explicitly avoid that behavior when running on Windows. + // Specifically this reaches down into legacy preference loading that is + // specialized by profiles_windows.go and fails in tests on an invalid + // uid passed in from the unix tests. The uid's used for Windows tests + // and runtime must be valid Windows security identifier structures. + } else if len(knownProfiles) == 0 && goos != "windows" && runtime.GOOS != "windows" { // No known profiles, try a migration. if err := pm.migrateFromLegacyPrefs(); err != nil { return nil, err @@ -562,7 +571,7 @@ func (pm *profileManager) migrateFromLegacyPrefs() error { sentinel, prefs, err := pm.loadLegacyPrefs() if err != nil { metricMigrationError.Add(1) - return err + return fmt.Errorf("load legacy prefs: %w", err) } if err := pm.SetPrefs(prefs); err != nil { metricMigrationError.Add(1) diff --git a/ipn/ipnlocal/profiles_test.go b/ipn/ipnlocal/profiles_test.go index f3027c3a8e3f8..7090b8a0fc8be 100644 --- a/ipn/ipnlocal/profiles_test.go +++ b/ipn/ipnlocal/profiles_test.go @@ -5,7 +5,7 @@ package ipnlocal import ( "fmt" - "runtime" + "os/user" "strconv" "testing" @@ -18,9 +18,6 @@ import ( ) func TestProfileCurrentUserSwitch(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } store := new(mem.Store) pm, err := newProfileManagerWithGOOS(store, logger.Discard, "linux") @@ -77,9 +74,6 @@ func TestProfileCurrentUserSwitch(t *testing.T) { } func TestProfileList(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } store := new(mem.Store) pm, err := newProfileManagerWithGOOS(store, logger.Discard, "linux") @@ -158,9 +152,6 @@ func TestProfileList(t *testing.T) { // TestProfileManagement tests creating, loading, and switching profiles. func TestProfileManagement(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } store := new(mem.Store) pm, err := newProfileManagerWithGOOS(store, logger.Discard, "linux") @@ -312,10 +303,11 @@ func TestProfileManagement(t *testing.T) { // TestProfileManagementWindows tests going into and out of Unattended mode on // Windows. func TestProfileManagementWindows(t *testing.T) { - - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") + u, err := user.Current() + if err != nil { + t.Fatal(err) } + uid := ipn.WindowsUserID(u.Uid) store := new(mem.Store) @@ -365,8 +357,8 @@ func TestProfileManagementWindows(t *testing.T) { { t.Logf("Set user1 as logged in user") - if err := pm.SetCurrentUserID("user1"); err != nil { - t.Fatal(err) + if err := pm.SetCurrentUserID(uid); err != nil { + t.Fatalf("can't set user id: %s", err) } checkProfiles(t) t.Logf("Save prefs for user1") @@ -401,7 +393,7 @@ func TestProfileManagementWindows(t *testing.T) { { t.Logf("Set user1 as current user") - if err := pm.SetCurrentUserID("user1"); err != nil { + if err := pm.SetCurrentUserID(uid); err != nil { t.Fatal(err) } wantCurProfile = "test" @@ -411,8 +403,8 @@ func TestProfileManagementWindows(t *testing.T) { t.Logf("set unattended mode") wantProfiles["test"] = setPrefs(t, "test", true) } - if pm.CurrentUserID() != "user1" { - t.Fatalf("CurrentUserID = %q; want %q", pm.CurrentUserID(), "user1") + if pm.CurrentUserID() != uid { + t.Fatalf("CurrentUserID = %q; want %q", pm.CurrentUserID(), uid) } // Recreate the profile manager to ensure that it starts with test profile. @@ -421,7 +413,7 @@ func TestProfileManagementWindows(t *testing.T) { t.Fatal(err) } checkProfiles(t) - if pm.CurrentUserID() != "user1" { - t.Fatalf("CurrentUserID = %q; want %q", pm.CurrentUserID(), "user1") + if pm.CurrentUserID() != uid { + t.Fatalf("CurrentUserID = %q; want %q", pm.CurrentUserID(), uid) } } diff --git a/ipn/ipnlocal/profiles_windows.go b/ipn/ipnlocal/profiles_windows.go index bc47e154e0569..1661c08d3e766 100644 --- a/ipn/ipnlocal/profiles_windows.go +++ b/ipn/ipnlocal/profiles_windows.go @@ -6,6 +6,7 @@ package ipnlocal import ( "errors" "fmt" + "io/fs" "os" "os/user" "path/filepath" @@ -21,8 +22,6 @@ const ( legacyPrefsExt = ".conf" ) -var errAlreadyMigrated = errors.New("profile migration already completed") - func legacyPrefsDir(uid ipn.WindowsUserID) (string, error) { // TODO(aaron): Ideally we'd have the impersonation token for the pipe's // client and use it to call SHGetKnownFolderPath, thus yielding the correct @@ -56,6 +55,9 @@ func (pm *profileManager) loadLegacyPrefs() (string, ipn.PrefsView, error) { prefsPath := filepath.Join(userLegacyPrefsDir, legacyPrefsFile+legacyPrefsExt) prefs, err := ipn.LoadPrefs(prefsPath) + if errors.Is(err, fs.ErrNotExist) { + return "", ipn.PrefsView{}, errAlreadyMigrated + } if err != nil { return "", ipn.PrefsView{}, err } From 13de36303d9d5d3b872c51199663916e4563eb4b Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 26 Apr 2023 11:34:28 -0700 Subject: [PATCH 031/331] cmd/tailscale/cli: [up] add experimental oauth2 authkey support Updates #7982 Signed-off-by: Brad Fitzpatrick --- cmd/get-authkey/main.go | 16 +++--- cmd/tailscale/cli/up.go | 109 +++++++++++++++++++++++++++++++++++++ cmd/tailscale/depaware.txt | 3 + 3 files changed, 120 insertions(+), 8 deletions(-) diff --git a/cmd/get-authkey/main.go b/cmd/get-authkey/main.go index fb8f6abe7caa1..5f5e85186ee4d 100644 --- a/cmd/get-authkey/main.go +++ b/cmd/get-authkey/main.go @@ -29,9 +29,9 @@ func main() { tags := flag.String("tags", "", "comma-separated list of tags to apply to the authkey") flag.Parse() - clientId := os.Getenv("TS_API_CLIENT_ID") + clientID := os.Getenv("TS_API_CLIENT_ID") clientSecret := os.Getenv("TS_API_CLIENT_SECRET") - if clientId == "" || clientSecret == "" { + if clientID == "" || clientSecret == "" { log.Fatal("TS_API_CLIENT_ID and TS_API_CLIENT_SECRET must be set") } @@ -39,22 +39,22 @@ func main() { log.Fatal("at least one tag must be specified") } - baseUrl := os.Getenv("TS_BASE_URL") - if baseUrl == "" { - baseUrl = "https://api.tailscale.com" + baseURL := os.Getenv("TS_BASE_URL") + if baseURL == "" { + baseURL = "https://api.tailscale.com" } credentials := clientcredentials.Config{ - ClientID: clientId, + ClientID: clientID, ClientSecret: clientSecret, - TokenURL: baseUrl + "/api/v2/oauth/token", + TokenURL: baseURL + "/api/v2/oauth/token", Scopes: []string{"device"}, } ctx := context.Background() tsClient := tailscale.NewClient("-", nil) tsClient.HTTPClient = credentials.Client(ctx) - tsClient.BaseURL = baseUrl + tsClient.BaseURL = baseURL caps := tailscale.KeyCapabilities{ Devices: tailscale.KeyDeviceCapabilities{ diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 92241748b8b25..7a4fb5b6cf5f7 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -13,11 +13,13 @@ import ( "fmt" "log" "net/netip" + "net/url" "os" "os/signal" "reflect" "runtime" "sort" + "strconv" "strings" "sync" "syscall" @@ -26,6 +28,9 @@ import ( shellquote "github.com/kballard/go-shellquote" "github.com/peterbourgon/ff/v3/ffcli" qrcode "github.com/skip2/go-qrcode" + "golang.org/x/oauth2/clientcredentials" + "tailscale.com/client/tailscale" + "tailscale.com/envknob" "tailscale.com/health/healthmsg" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" @@ -663,6 +668,10 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE if err != nil { return err } + authKey, err = resolveAuthKey(ctx, authKey) + if err != nil { + return err + } if err := localClient.Start(ctx, ipn.Options{ AuthKey: authKey, UpdatePrefs: prefs, @@ -1102,3 +1111,103 @@ func anyPeerAdvertisingRoutes(st *ipnstate.Status) bool { } return false } + +func init() { + // Required to use our client API. We're fine with the instability since the + // client lives in the same repo as this code. + tailscale.I_Acknowledge_This_API_Is_Unstable = true +} + +// resolveAuthKey either returns v unchanged (in the common case) +// or, if it starts with "oauth:" parses it as one of: +// +// oauth2:CLIENT_ID:CLIENT_SECRET?ephemeral=false&tags=foo,bar&preauthorized=BOOL +// oauth2:CLIENT_ID:CLIENT_SECRET:BASE_URL?... +// +// and does the OAuth2 dance to get and return an authkey. The "ephemeral" property +// defaults to true if unspecified. The "preauthorized" defaults to false. +// +// If the BASE_URL argument is not provided, it defaults to https://api.tailscale.com. +func resolveAuthKey(ctx context.Context, v string) (string, error) { + suff, ok := strings.CutPrefix(v, "oauth:") + if !ok { + return v, nil + } + if !envknob.Bool("TS_EXPERIMENT_OAUTH_AUTHKEY") { + return "", errors.New("oauth authkeys are in experimental status") + } + + pos, named, _ := strings.Cut(suff, "?") + attrs, err := url.ParseQuery(named) + if err != nil { + return "", err + } + for k := range attrs { + switch k { + case "ephemeral", "preauthorized", "tags": + default: + return "", fmt.Errorf("unknown attribute %q", k) + } + } + getBool := func(name string, def bool) (bool, error) { + v := attrs.Get(name) + if v == "" { + return def, nil + } + ret, err := strconv.ParseBool(v) + if err != nil { + return false, fmt.Errorf("invalid attribute boolean attribute %s value %q", name, v) + } + return ret, nil + } + ephemeral, err := getBool("ephemeral", true) + if err != nil { + return "", err + } + preauth, err := getBool("preauthorized", false) + if err != nil { + return "", err + } + var tags []string + if v := attrs.Get("tags"); v != "" { + tags = strings.Split(v, ",") + } + + f := strings.SplitN(pos, ":", 3) + if len(f) < 2 || len(f) > 3 { + return "", errors.New("invalid auth key format; want oauth2:CLIENT_ID:CLIENT_SECRET[:BASE_URL]") + } + clientID, clientSecret := f[0], f[1] + baseURL := "https://api.tailscale.com" + if len(f) == 3 { + baseURL = f[2] + } + + credentials := clientcredentials.Config{ + ClientID: clientID, + ClientSecret: clientSecret, + TokenURL: baseURL + "/api/v2/oauth/token", + Scopes: []string{"device"}, + } + + tsClient := tailscale.NewClient("-", nil) + tsClient.HTTPClient = credentials.Client(ctx) + tsClient.BaseURL = baseURL + + caps := tailscale.KeyCapabilities{ + Devices: tailscale.KeyDeviceCapabilities{ + Create: tailscale.KeyDeviceCreateCapabilities{ + Reusable: false, + Ephemeral: ephemeral, + Preauthorized: preauth, + Tags: tags, + }, + }, + } + + authkey, _, err := tsClient.CreateKey(ctx, caps) + if err != nil { + return "", err + } + return authkey, nil +} diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 5b644992e7106..da38ff9dbd685 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -155,6 +155,9 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/net/ipv6 from golang.org/x/net/icmp golang.org/x/net/proxy from tailscale.com/net/netns D golang.org/x/net/route from net+ + golang.org/x/oauth2 from golang.org/x/oauth2/clientcredentials + golang.org/x/oauth2/clientcredentials from tailscale.com/cmd/tailscale/cli + golang.org/x/oauth2/internal from golang.org/x/oauth2+ golang.org/x/sync/errgroup from tailscale.com/derp+ golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+ LD golang.org/x/sys/unix from tailscale.com/net/netns+ From b2b53793485416f921a2643776db4ef4af05df40 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 26 Apr 2023 13:20:58 -0700 Subject: [PATCH 032/331] cmd/tailscale/cli: [up] change oauth authkey format Updates #7982 Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/up.go | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 7a4fb5b6cf5f7..462b18b6ec92f 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -1118,33 +1118,31 @@ func init() { tailscale.I_Acknowledge_This_API_Is_Unstable = true } -// resolveAuthKey either returns v unchanged (in the common case) -// or, if it starts with "oauth:" parses it as one of: +// resolveAuthKey either returns v unchanged (in the common case) or, if it +// starts with "tskey-client-" (as Tailscale OAuth secrets do) parses it like // -// oauth2:CLIENT_ID:CLIENT_SECRET?ephemeral=false&tags=foo,bar&preauthorized=BOOL -// oauth2:CLIENT_ID:CLIENT_SECRET:BASE_URL?... +// tskey-client-xxxx[?ephemeral=false&tags=foo,bar&preauthorized=BOOL&baseURL=...] // -// and does the OAuth2 dance to get and return an authkey. The "ephemeral" property -// defaults to true if unspecified. The "preauthorized" defaults to false. -// -// If the BASE_URL argument is not provided, it defaults to https://api.tailscale.com. +// and does the OAuth2 dance to get and return an authkey. The "ephemeral" +// property defaults to true if unspecified. The "preauthorized" defaults to +// false. The "baseURL" defaults to +// https://api.tailscale.com. func resolveAuthKey(ctx context.Context, v string) (string, error) { - suff, ok := strings.CutPrefix(v, "oauth:") - if !ok { + if !strings.HasPrefix(v, "tskey-client-") { return v, nil } if !envknob.Bool("TS_EXPERIMENT_OAUTH_AUTHKEY") { return "", errors.New("oauth authkeys are in experimental status") } - pos, named, _ := strings.Cut(suff, "?") + clientSecret, named, _ := strings.Cut(v, "?") attrs, err := url.ParseQuery(named) if err != nil { return "", err } for k := range attrs { switch k { - case "ephemeral", "preauthorized", "tags": + case "ephemeral", "preauthorized", "tags", "baseURL": default: return "", fmt.Errorf("unknown attribute %q", k) } @@ -1173,18 +1171,13 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { tags = strings.Split(v, ",") } - f := strings.SplitN(pos, ":", 3) - if len(f) < 2 || len(f) > 3 { - return "", errors.New("invalid auth key format; want oauth2:CLIENT_ID:CLIENT_SECRET[:BASE_URL]") - } - clientID, clientSecret := f[0], f[1] baseURL := "https://api.tailscale.com" - if len(f) == 3 { - baseURL = f[2] + if v := attrs.Get("baseURL"); v != "" { + baseURL = v } credentials := clientcredentials.Config{ - ClientID: clientID, + ClientID: "some-client-id", // ignored ClientSecret: clientSecret, TokenURL: baseURL + "/api/v2/oauth/token", Scopes: []string{"device"}, From a8f10c23b2e289db27e28d10df4f2a15a61d6c2d Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Wed, 26 Apr 2023 13:51:45 -0700 Subject: [PATCH 033/331] cmd/tailscale/cli: [up] reuse --advertise-tags for OAuth key generation We need to always specify tags when creating an AuthKey from an OAuth key. Check for that, and reuse the `--advertise-tags` param. Updates #7982 Signed-off-by: Maisem Ali --- cmd/tailscale/cli/up.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 462b18b6ec92f..06d9b5ff8a5dc 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -668,7 +668,7 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE if err != nil { return err } - authKey, err = resolveAuthKey(ctx, authKey) + authKey, err = resolveAuthKey(ctx, authKey, upArgs.advertiseTags) if err != nil { return err } @@ -1121,19 +1121,23 @@ func init() { // resolveAuthKey either returns v unchanged (in the common case) or, if it // starts with "tskey-client-" (as Tailscale OAuth secrets do) parses it like // -// tskey-client-xxxx[?ephemeral=false&tags=foo,bar&preauthorized=BOOL&baseURL=...] +// tskey-client-xxxx[?ephemeral=false&bar&preauthorized=BOOL&baseURL=...] // // and does the OAuth2 dance to get and return an authkey. The "ephemeral" // property defaults to true if unspecified. The "preauthorized" defaults to -// false. The "baseURL" defaults to -// https://api.tailscale.com. -func resolveAuthKey(ctx context.Context, v string) (string, error) { +// false. The "baseURL" defaults to https://api.tailscale.com. +// The passed in tags are required, and must be non-empty. These will be +// set on the authkey generated by the OAuth2 dance. +func resolveAuthKey(ctx context.Context, v, tags string) (string, error) { if !strings.HasPrefix(v, "tskey-client-") { return v, nil } if !envknob.Bool("TS_EXPERIMENT_OAUTH_AUTHKEY") { return "", errors.New("oauth authkeys are in experimental status") } + if tags == "" { + return "", errors.New("oauth authkeys require --advertise-tags") + } clientSecret, named, _ := strings.Cut(v, "?") attrs, err := url.ParseQuery(named) @@ -1142,7 +1146,7 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { } for k := range attrs { switch k { - case "ephemeral", "preauthorized", "tags", "baseURL": + case "ephemeral", "preauthorized", "baseURL": default: return "", fmt.Errorf("unknown attribute %q", k) } @@ -1166,10 +1170,6 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { if err != nil { return "", err } - var tags []string - if v := attrs.Get("tags"); v != "" { - tags = strings.Split(v, ",") - } baseURL := "https://api.tailscale.com" if v := attrs.Get("baseURL"); v != "" { @@ -1193,7 +1193,7 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { Reusable: false, Ephemeral: ephemeral, Preauthorized: preauth, - Tags: tags, + Tags: strings.Split(tags, ","), }, }, } From 1e876a3c1d0fbd4ec8a388b528465f44ad4ed72a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 26 Apr 2023 10:04:06 -0700 Subject: [PATCH 034/331] ipn/ipnlocal: fix fmt format arg type mismatch in log line It was printing like "v0xxxxxxxx" after version.Long became a func in 8b2ae47c31c9574d. Fixes #7976 Signed-off-by: Brad Fitzpatrick --- ipn/ipnlocal/local.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index d1aaf6b89529e..e2894e6633ca4 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -2479,7 +2479,7 @@ func (b *LocalBackend) parseWgStatusLocked(s *wgengine.Status) (ret ipn.EngineSt // [GRINDER STATS LINES] - please don't remove (used for log parsing) if peerStats.Len() > 0 { b.keyLogf("[v1] peer keys: %s", strings.TrimSpace(peerKeys.String())) - b.statsLogf("[v1] v%v peers: %v", version.Long, strings.TrimSpace(peerStats.String())) + b.statsLogf("[v1] v%v peers: %v", version.Long(), strings.TrimSpace(peerStats.String())) } return ret } From 1145b9751d26d1008c0123b3604b1ef059db7d45 Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Wed, 26 Apr 2023 15:30:28 -0700 Subject: [PATCH 035/331] VERSION.txt: this is v1.41.0 Signed-off-by: Denton Gentry --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 5edffce6d570b..7d47e599800eb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.39.0 +1.41.0 From 161d1d281a9a229b55489bdde7d3a72e2c487909 Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn <46385858+catzkorn@users.noreply.github.com> Date: Wed, 26 Apr 2023 15:59:37 -0700 Subject: [PATCH 036/331] net/ping,netcheck: add v6 pinging capabilities to pinger (#7971) This change adds a v6conn to the pinger to enable sending pings to v6 addrs. Updates #7826 Signed-off-by: Charlotte Brandhorst-Satzkorn --- cmd/tailscale/depaware.txt | 2 +- net/netcheck/netcheck.go | 5 +- net/ping/ping.go | 167 ++++++++++++++++++++++++++++--------- net/ping/ping_test.go | 130 +++++++++++++++++++++++++---- 4 files changed, 243 insertions(+), 61 deletions(-) diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index da38ff9dbd685..b7ce9c4015a3e 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -152,7 +152,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/net/icmp from tailscale.com/net/ping golang.org/x/net/idna from golang.org/x/net/http/httpguts+ golang.org/x/net/ipv4 from golang.org/x/net/icmp+ - golang.org/x/net/ipv6 from golang.org/x/net/icmp + golang.org/x/net/ipv6 from golang.org/x/net/icmp+ golang.org/x/net/proxy from tailscale.com/net/netns D golang.org/x/net/route from net+ golang.org/x/oauth2 from golang.org/x/oauth2/clientcredentials diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 603fa3a4162c4..ac52a7a415da8 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -1321,10 +1321,7 @@ func (c *Client) measureAllICMPLatency(ctx context.Context, rs *reportState, nee ctx, done := context.WithTimeout(ctx, icmpProbeTimeout) defer done() - p, err := ping.New(ctx, c.logf, c.NetMon) - if err != nil { - return err - } + p := ping.New(ctx, c.logf, netns.Listener(c.logf, c.NetMon)) defer p.Close() c.logf("UDP is blocked, trying ICMP") diff --git a/net/ping/ping.go b/net/ping/ping.go index 9b9618e0ff34c..170d87fb9453b 100644 --- a/net/ping/ping.go +++ b/net/ping/ping.go @@ -11,16 +11,25 @@ import ( "crypto/rand" "encoding/binary" "fmt" + "io" "log" "net" + "net/netip" "sync" + "sync/atomic" "time" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" - "tailscale.com/net/netmon" - "tailscale.com/net/netns" + "golang.org/x/net/ipv6" "tailscale.com/types/logger" + "tailscale.com/util/mak" + "tailscale.com/util/multierr" +) + +const ( + v4Type = "ip4:icmp" + v6Type = "ip6:icmp" ) type response struct { @@ -33,12 +42,21 @@ type outstanding struct { data []byte } +// PacketListener defines the interface required to listen to packages +// on an address. +type ListenPacketer interface { + ListenPacket(ctx context.Context, typ string, addr string) (net.PacketConn, error) +} + // Pinger represents a set of ICMP echo requests to be sent at a single time. // // A new instance should be created for each concurrent set of ping requests; // this type should not be reused. type Pinger struct { - c net.PacketConn + lp ListenPacketer + + // closed guards against send incrementing the waitgroup concurrently with close. + closed atomic.Bool Logf logger.Logf Verbose bool timeNow func() time.Time @@ -46,16 +64,37 @@ type Pinger struct { wg sync.WaitGroup // Following fields protected by mu - mu sync.Mutex + mu sync.Mutex + // conns is a map of "type" to net.PacketConn, type is either + // "ip4:icmp" or "ip6:icmp" + conns map[string]net.PacketConn seq uint16 // uint16 per RFC 792 pings map[uint16]outstanding } // New creates a new Pinger. The Context provided will be used to create // network listeners, and to set an absolute deadline (if any) on the net.Conn -// The netMon parameter is optional; if non-nil it's used to do faster interface lookups. -func New(ctx context.Context, logf logger.Logf, netMon *netmon.Monitor) (*Pinger, error) { - p, err := newUnstarted(ctx, logf, netMon) +func New(ctx context.Context, logf logger.Logf, lp ListenPacketer) *Pinger { + var id [2]byte + if _, err := io.ReadFull(rand.Reader, id[:]); err != nil { + panic("net/ping: New:" + err.Error()) + } + + return &Pinger{ + lp: lp, + Logf: logf, + timeNow: time.Now, + id: binary.LittleEndian.Uint16(id[:]), + pings: make(map[uint16]outstanding), + } +} + +func (p *Pinger) mkconn(ctx context.Context, typ, addr string) (net.PacketConn, error) { + if p.closed.Load() { + return nil, net.ErrClosed + } + + c, err := p.lp.ListenPacket(ctx, typ, addr) if err != nil { return nil, err } @@ -64,35 +103,36 @@ func New(ctx context.Context, logf logger.Logf, netMon *netmon.Monitor) (*Pinger // applies to all future I/O, so we only need to do it once. deadline, ok := ctx.Deadline() if ok { - if err := p.c.SetReadDeadline(deadline); err != nil { + if err := c.SetReadDeadline(deadline); err != nil { return nil, err } } p.wg.Add(1) - go p.run(ctx) - return p, nil + go p.run(ctx, c, typ) + + return c, err } -func newUnstarted(ctx context.Context, logf logger.Logf, netMon *netmon.Monitor) (*Pinger, error) { - var id [2]byte - _, err := rand.Read(id[:]) - if err != nil { - return nil, err +// getConn creates or returns a conn matching typ which is ip4:icmp +// or ip6:icmp. +func (p *Pinger) getConn(ctx context.Context, typ string) (net.PacketConn, error) { + p.mu.Lock() + defer p.mu.Unlock() + if c, ok := p.conns[typ]; ok { + return c, nil } - conn, err := netns.Listener(logf, netMon).ListenPacket(ctx, "ip4:icmp", "0.0.0.0") + var addr = "0.0.0.0" + if typ == v6Type { + addr = "::" + } + c, err := p.mkconn(ctx, typ, addr) if err != nil { return nil, err } - - return &Pinger{ - c: conn, - Logf: logf, - timeNow: time.Now, - id: binary.LittleEndian.Uint16(id[:]), - pings: make(map[uint16]outstanding), - }, nil + mak.Set(&p.conns, typ, c) + return c, nil } func (p *Pinger) logf(format string, a ...any) { @@ -110,13 +150,34 @@ func (p *Pinger) vlogf(format string, a ...any) { } func (p *Pinger) Close() error { - err := p.c.Close() + p.closed.Store(true) + + p.mu.Lock() + conns := p.conns + p.conns = nil + p.mu.Unlock() + + var errors []error + for _, c := range conns { + if err := c.Close(); err != nil { + errors = append(errors, err) + } + } + p.wg.Wait() - return err + p.cleanupOutstanding() + + return multierr.New(errors...) } -func (p *Pinger) run(ctx context.Context) { +func (p *Pinger) run(ctx context.Context, conn net.PacketConn, typ string) { defer p.wg.Done() + defer func() { + conn.Close() + p.mu.Lock() + delete(p.conns, typ) + p.mu.Unlock() + }() buf := make([]byte, 1500) loop: @@ -127,7 +188,7 @@ loop: default: } - n, addr, err := p.c.ReadFrom(buf) + n, _, err := conn.ReadFrom(buf) if err != nil { // Ignore temporary errors; everything else is fatal if netErr, ok := err.(net.Error); !ok || !netErr.Temporary() { @@ -136,10 +197,8 @@ loop: continue } - p.handleResponse(buf[:n], addr, p.timeNow()) + p.handleResponse(buf[:n], p.timeNow(), typ) } - - p.cleanupOutstanding() } func (p *Pinger) cleanupOutstanding() { @@ -151,16 +210,28 @@ func (p *Pinger) cleanupOutstanding() { } } -func (p *Pinger) handleResponse(buf []byte, addr net.Addr, now time.Time) { - const ProtocolICMP = 1 - m, err := icmp.ParseMessage(ProtocolICMP, buf) +func (p *Pinger) handleResponse(buf []byte, now time.Time, typ string) { + // We need to handle responding to both IPv4 + // and IPv6. + var icmpType icmp.Type + switch typ { + case v4Type: + icmpType = ipv4.ICMPTypeEchoReply + case v6Type: + icmpType = ipv6.ICMPTypeEchoReply + default: + p.vlogf("handleResponse: unknown icmp.Type") + return + } + + m, err := icmp.ParseMessage(icmpType.Protocol(), buf) if err != nil { p.vlogf("handleResponse: invalid packet: %v", err) return } - if m.Type != ipv4.ICMPTypeEchoReply { - p.vlogf("handleResponse: wanted m.Type=%d; got %d", ipv4.ICMPTypeEchoReply, m.Type) + if m.Type != icmpType { + p.vlogf("handleResponse: wanted m.Type=%d; got %d", icmpType, m.Type) return } @@ -212,9 +283,27 @@ func (p *Pinger) Send(ctx context.Context, dest net.Addr, data []byte) (time.Dur seq := p.seq p.mu.Unlock() + // Check whether the address is IPv4 or IPv6 to + // determine the icmp.Type and conn to use. + var conn net.PacketConn + var icmpType icmp.Type = ipv4.ICMPTypeEcho + ap, err := netip.ParseAddr(dest.String()) + if err != nil { + return 0, err + } + if ap.Is6() { + icmpType = ipv6.ICMPTypeEchoRequest + conn, err = p.getConn(ctx, v6Type) + } else { + conn, err = p.getConn(ctx, v4Type) + } + if err != nil { + return 0, err + } + m := icmp.Message{ - Type: ipv4.ICMPTypeEcho, - Code: 0, + Type: icmpType, + Code: icmpType.Protocol(), Body: &icmp.Echo{ ID: int(p.id), Seq: int(seq), @@ -234,7 +323,7 @@ func (p *Pinger) Send(ctx context.Context, dest net.Addr, data []byte) (time.Dur p.mu.Unlock() start := p.timeNow() - n, err := p.c.WriteTo(b, dest) + n, err := conn.WriteTo(b, dest) if err != nil { return 0, err } else if n != len(b) { diff --git a/net/ping/ping_test.go b/net/ping/ping_test.go index 1fdefc6e7f979..bbedbcad80e44 100644 --- a/net/ping/ping_test.go +++ b/net/ping/ping_test.go @@ -6,18 +6,20 @@ package ping import ( "context" "errors" + "fmt" "net" "testing" "time" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" "tailscale.com/tstest" + "tailscale.com/util/mak" ) var ( - localhost = &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} - localhostUDP = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 12345} + localhost = &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} ) func TestPinger(t *testing.T) { @@ -35,7 +37,7 @@ func TestPinger(t *testing.T) { // Start a ping in the background r := make(chan time.Duration, 1) go func() { - dur, err := p.Send(ctx, localhostUDP, bodyData) + dur, err := p.Send(ctx, localhost, bodyData) if err != nil { t.Errorf("p.Send: %v", err) r <- 0 @@ -49,7 +51,7 @@ func TestPinger(t *testing.T) { // Fake a response from ourself fakeResponse := mustMarshal(t, &icmp.Message{ Type: ipv4.ICMPTypeEchoReply, - Code: 0, + Code: ipv4.ICMPTypeEchoReply.Protocol(), Body: &icmp.Echo{ ID: 1234, Seq: 1, @@ -58,7 +60,65 @@ func TestPinger(t *testing.T) { }) const fakeDuration = 100 * time.Millisecond - p.handleResponse(fakeResponse, localhost, clock.Now().Add(fakeDuration)) + p.handleResponse(fakeResponse, clock.Now().Add(fakeDuration), v4Type) + + select { + case dur := <-r: + want := fakeDuration + if dur != want { + t.Errorf("wanted ping response time = %d; got %d", want, dur) + } + case <-ctx.Done(): + t.Fatal("did not get response by timeout") + } +} + +func TestV6Pinger(t *testing.T) { + if c, err := net.ListenPacket("udp6", "::1"); err != nil { + // skip test if we can't use IPv6. + t.Skipf("IPv6 not supported: %s", err) + } else { + c.Close() + } + + clock := &tstest.Clock{} + + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + p, closeP := mockPinger(t, clock) + defer closeP() + + bodyData := []byte("data goes here") + + // Start a ping in the background + r := make(chan time.Duration, 1) + go func() { + dur, err := p.Send(ctx, &net.IPAddr{IP: net.ParseIP("::")}, bodyData) + if err != nil { + t.Errorf("p.Send: %v", err) + r <- 0 + } else { + r <- dur + } + }() + + p.waitOutstanding(t, ctx, 1) + + // Fake a response from ourself + fakeResponse := mustMarshal(t, &icmp.Message{ + Type: ipv6.ICMPTypeEchoReply, + Code: ipv6.ICMPTypeEchoReply.Protocol(), + Body: &icmp.Echo{ + ID: 1234, + Seq: 1, + Data: bodyData, + }, + }) + + const fakeDuration = 100 * time.Millisecond + p.handleResponse(fakeResponse, clock.Now().Add(fakeDuration), v6Type) select { case dur := <-r: @@ -83,7 +143,7 @@ func TestPingerTimeout(t *testing.T) { // Send a ping in the background r := make(chan error, 1) go func() { - _, err := p.Send(ctx, localhostUDP, []byte("data goes here")) + _, err := p.Send(ctx, localhost, []byte("data goes here")) r <- err }() @@ -115,7 +175,7 @@ func TestPingerMismatch(t *testing.T) { // Start a ping in the background r := make(chan time.Duration, 1) go func() { - dur, err := p.Send(ctx, localhostUDP, bodyData) + dur, err := p.Send(ctx, localhost, bodyData) if err != nil && !errors.Is(err, context.DeadlineExceeded) { t.Errorf("p.Send: %v", err) r <- 0 @@ -185,11 +245,11 @@ func TestPingerMismatch(t *testing.T) { for _, tt := range badPackets { fakeResponse := mustMarshal(t, tt.pkt) - p.handleResponse(fakeResponse, localhost, tm) + p.handleResponse(fakeResponse, tm, v4Type) } // Also "receive" a packet that does not unmarshal as an ICMP packet - p.handleResponse([]byte("foo"), localhost, tm) + p.handleResponse([]byte("foo"), tm, v4Type) select { case <-r: @@ -199,23 +259,59 @@ func TestPingerMismatch(t *testing.T) { } } +// udpingPacketConn will convert potentially ICMP destination addrs to UDP +// destination addrs in WriteTo so that a test that is intending to send ICMP +// traffic will instead send UDP traffic, without the higher level Pinger being +// aware of this difference. +type udpingPacketConn struct { + net.PacketConn + // destPort will be configured by the test to be the peer expected to respond to a ping. + destPort uint16 +} + +func (u *udpingPacketConn) WriteTo(body []byte, dest net.Addr) (int, error) { + switch d := dest.(type) { + case *net.IPAddr: + udpAddr := &net.UDPAddr{ + IP: d.IP, + Port: int(u.destPort), + Zone: d.Zone, + } + return u.PacketConn.WriteTo(body, udpAddr) + } + return 0, fmt.Errorf("unimplemented udpingPacketConn for %T", dest) +} + func mockPinger(t *testing.T, clock *tstest.Clock) (*Pinger, func()) { + p := New(context.Background(), t.Logf, nil) + p.timeNow = clock.Now + p.Verbose = true + p.id = 1234 + // In tests, we use UDP so that we can test without being root; this // doesn't matter because we mock out the ICMP reply below to be a real // ICMP echo reply packet. - conn, err := net.ListenPacket("udp4", "127.0.0.1:0") + conn4, err := net.ListenPacket("udp4", "127.0.0.1:0") if err != nil { t.Fatalf("net.ListenPacket: %v", err) } - p := &Pinger{ - c: conn, - Logf: t.Logf, - Verbose: true, - timeNow: clock.Now, - id: 1234, - pings: make(map[uint16]outstanding), + conn6, err := net.ListenPacket("udp6", "[::]:0") + if err != nil { + t.Fatalf("net.ListenPacket: %v", err) } + + conn4 = &udpingPacketConn{ + destPort: 12345, + PacketConn: conn4, + } + conn6 = &udpingPacketConn{ + PacketConn: conn6, + destPort: 12345, + } + + mak.Set(&p.conns, v4Type, conn4) + mak.Set(&p.conns, v6Type, conn6) done := func() { if err := p.Close(); err != nil { t.Errorf("error on close: %v", err) From d78b3349645423e0f350976f7d1e91adf9101810 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 27 Mar 2023 15:45:42 -0500 Subject: [PATCH 037/331] cmd/derper: disable http2 DERP doesn't support HTTP/2. If an HTTP/2 proxy was placed in front of a DERP server requests would fail because the connection would be initialized with HTTP/2, which the DERP client doesn't support. Signed-off-by: Kyle Carberry --- cmd/derper/cert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/derper/cert.go b/cmd/derper/cert.go index 1fab755a024c5..db84aa515d257 100644 --- a/cmd/derper/cert.go +++ b/cmd/derper/cert.go @@ -81,7 +81,7 @@ func (m *manualCertManager) TLSConfig() *tls.Config { return &tls.Config{ Certificates: nil, NextProtos: []string{ - "h2", "http/1.1", // enable HTTP/2 + "http/1.1", }, GetCertificate: m.getCertificate, } From 8032b966a16b5b843a0e8cca2a7b1e6f1eb2bf12 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 26 Apr 2023 11:02:18 -0700 Subject: [PATCH 038/331] .github/workflows: add recency bias to action cache keys The action cache restore process either matches the restore key pattern exactly, or uses a matching prefix with the most recent date. If the restore key is an exact match, then no updates are uploaded, but if we've just computed tests executions for more recent code then we will likely want to use those results in future runs. Appending run_id to the cache key will give us an always new key, and then we will be restore a recently uploaded cache that is more likely has a higher overlap with the code being tested. Updates #7975 Signed-off-by: James Tucker --- .github/workflows/test.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8e2d9b5b15c20..1116f428d3e9b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -65,8 +65,9 @@ jobs: ~\AppData\Local\go-build # The -2- here should be incremented when the scheme of data to be # cached changes (e.g. path above changes). - key: ${{ github.job }}-${{ runner.os }}-${{ matrix.goarch }}-${{ matrix.buildflags }}-go-2-${{ hashFiles('**/go.sum') }} + key: ${{ github.job }}-${{ runner.os }}-${{ matrix.goarch }}-${{ matrix.buildflags }}-go-2-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} restore-keys: | + ${{ github.job }}-${{ runner.os }}-${{ matrix.goarch }}-${{ matrix.buildflags }}-go-2-${{ hashFiles('**/go.sum') }} ${{ github.job }}-${{ runner.os }}-${{ matrix.goarch }}-${{ matrix.buildflags }}-go-2- - name: build all run: ./tool/go build ${{matrix.buildflags}} ./... @@ -135,8 +136,9 @@ jobs: ~\AppData\Local\go-build # The -2- here should be incremented when the scheme of data to be # cached changes (e.g. path above changes). - key: ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }} + key: ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} restore-keys: | + ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }} ${{ github.job }}-${{ runner.os }}-go-2- - name: test # Don't use -bench=. -benchtime=1x. @@ -210,8 +212,9 @@ jobs: ~\AppData\Local\go-build # The -2- here should be incremented when the scheme of data to be # cached changes (e.g. path above changes). - key: ${{ github.job }}-${{ runner.os }}-${{ matrix.goos }}-${{ matrix.goarch }}-go-2-${{ hashFiles('**/go.sum') }} + key: ${{ github.job }}-${{ runner.os }}-${{ matrix.goos }}-${{ matrix.goarch }}-go-2-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} restore-keys: | + ${{ github.job }}-${{ runner.os }}-${{ matrix.goos }}-${{ matrix.goarch }}-go-2-${{ hashFiles('**/go.sum') }} ${{ github.job }}-${{ runner.os }}-${{ matrix.goos }}-${{ matrix.goarch }}-go-2- - name: build all run: ./tool/go build ./cmd/... @@ -275,8 +278,9 @@ jobs: ~\AppData\Local\go-build # The -2- here should be incremented when the scheme of data to be # cached changes (e.g. path above changes). - key: ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }} + key: ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }}-${{ github.run_id }} restore-keys: | + ${{ github.job }}-${{ runner.os }}-go-2-${{ hashFiles('**/go.sum') }} ${{ github.job }}-${{ runner.os }}-go-2- - name: build tsconnect client run: ./tool/go build ./cmd/tsconnect/wasm ./cmd/tailscale/cli From c3ab36cb9d83e9a08343c5c5ec0c390b2e63363e Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn <46385858+catzkorn@users.noreply.github.com> Date: Thu, 27 Apr 2023 08:58:52 -0700 Subject: [PATCH 039/331] words: charlotte 1 spell-checking-linter 0 (#7993) Can't have a dupe when the dupe is wrong. Clearly we need to up our spell checking game. Did anyone say AI? Signed-off-by: Charlotte Brandhorst-Satzkorn --- words/tails.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/words/tails.txt b/words/tails.txt index a527977bf9e90..00377fc495e94 100644 --- a/words/tails.txt +++ b/words/tails.txt @@ -379,7 +379,6 @@ cusimanse polecat degu coatimundi -stringray diplodocus stegosaurus zuul From d35ce1add95e124ca43c5db8ce7f13972c74877a Mon Sep 17 00:00:00 2001 From: James Tucker Date: Thu, 27 Apr 2023 16:51:47 -0700 Subject: [PATCH 040/331] syncs: add documentation to Map.Range Updates #cleanup Signed-off-by: James Tucker --- syncs/syncs.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/syncs/syncs.go b/syncs/syncs.go index 52fcad220a40c..aa89486a4d118 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -208,6 +208,8 @@ func (m *Map[K, V]) Delete(key K) { delete(m.m, key) } +// Range iterates over the map in undefined order calling f for each entry. +// Iteration stops if f returns false. Map changes are blocked during iteration. func (m *Map[K, V]) Range(f func(key K, value V) bool) { m.mu.RLock() defer m.mu.RUnlock() From 633d08bd7b0f9fcc5d30d151a0a3df130e058f19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:57:24 +0000 Subject: [PATCH 041/331] .github: Bump actions/setup-go from 3 to 4 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/golangci-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 571588660489c..8e6c7ec605ffe 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version-file: go.mod cache: false From 042f82ea3228bbe0edb0496ba09e0f44e161fab2 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Thu, 27 Apr 2023 15:58:57 +0800 Subject: [PATCH 042/331] build_dist.sh: make cross-compilation friendly for env CC specified Signed-off-by: ayanamist --- build_dist.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_dist.sh b/build_dist.sh index 8a77bf8a74b38..b55b7f0532ba0 100755 --- a/build_dist.sh +++ b/build_dist.sh @@ -16,7 +16,7 @@ if [ -n "${TS_USE_TOOLCHAIN:-}" ]; then go="./tool/go" fi -eval `GOOS=$($go env GOHOSTOS) GOARCH=$($go env GOHOSTARCH) $go run ./cmd/mkversion` +eval `CGO_ENABLED=0 GOOS=$($go env GOHOSTOS) GOARCH=$($go env GOHOSTARCH) $go run ./cmd/mkversion` if [ "$1" = "shellvars" ]; then cat < Date: Thu, 27 Apr 2023 17:09:30 -0700 Subject: [PATCH 043/331] syncs: add Map.Len to get the length of the Map I need this for a corp change where I have a set as a queue, and make a different decisison if the set is empty. Updates tailscale/corp#10344 Signed-off-by: James Tucker --- syncs/syncs.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/syncs/syncs.go b/syncs/syncs.go index aa89486a4d118..79acd8654ca3d 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -220,6 +220,13 @@ func (m *Map[K, V]) Range(f func(key K, value V) bool) { } } +// Len returns the length of the map. +func (m *Map[K, V]) Len() int { + m.mu.RLock() + defer m.mu.RUnlock() + return len(m.m) +} + // WaitGroup is identical to [sync.WaitGroup], // but provides a Go method to start a goroutine. type WaitGroup struct{ sync.WaitGroup } From a82f2756193f80caa82f10b5531f9edeb5251217 Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Fri, 28 Apr 2023 21:28:52 -0700 Subject: [PATCH 044/331] cmd/sniproxy: Set App name in tsnet hostinfo Updates #1748 Signed-off-by: Denton Gentry --- cmd/sniproxy/{snipproxy.go => sniproxy.go} | 3 +++ 1 file changed, 3 insertions(+) rename cmd/sniproxy/{snipproxy.go => sniproxy.go} (98%) diff --git a/cmd/sniproxy/snipproxy.go b/cmd/sniproxy/sniproxy.go similarity index 98% rename from cmd/sniproxy/snipproxy.go rename to cmd/sniproxy/sniproxy.go index 068c107c9626d..49ab764a3977e 100644 --- a/cmd/sniproxy/snipproxy.go +++ b/cmd/sniproxy/sniproxy.go @@ -18,6 +18,7 @@ import ( "golang.org/x/net/dns/dnsmessage" "inet.af/tcpproxy" "tailscale.com/client/tailscale" + "tailscale.com/hostinfo" "tailscale.com/net/netutil" "tailscale.com/tsnet" "tailscale.com/types/nettype" @@ -36,6 +37,8 @@ func main() { log.Fatal("no ports") } + hostinfo.SetApp("sniproxy") + var s server defer s.ts.Close() From 1f4a34588be4b0da4838667f11fe4fef6c285d1f Mon Sep 17 00:00:00 2001 From: Anton Tolchanov Date: Fri, 28 Apr 2023 13:44:54 +0100 Subject: [PATCH 045/331] .github: test installer script in CI in docker Every time we change `installer.sh`, run it in a few docker containers based on different Linux distros, just as a simple test. Also includes a few changes to the installer script itself to make installation work in docker: - install dnf config-manager command before running it - run zypper in non-interactive mode - update pacman indexes before installing packages Updates https://github.com/tailscale/corp/issues/8952 Signed-off-by: Anton Tolchanov --- .github/workflows/installer.yml | 102 ++++++++++++++++++++++++++++++++ scripts/installer.sh | 14 +++-- 2 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/installer.yml diff --git a/.github/workflows/installer.yml b/.github/workflows/installer.yml new file mode 100644 index 0000000000000..bcd70381cd156 --- /dev/null +++ b/.github/workflows/installer.yml @@ -0,0 +1,102 @@ +name: test installer.sh + +on: + push: + branches: + - "main" + paths: + - scripts/installer.sh + pull_request: + branches: + - "*" + paths: + - scripts/installer.sh + +jobs: + test: + strategy: + # Don't abort the entire matrix if one element fails. + fail-fast: false + # Don't start all of these at once, which could saturate Github workers. + max-parallel: 4 + matrix: + image: + # This is a list of Docker images against which we test our installer. + # If you find that some of these no longer exist, please feel free + # to remove them from the list. + # When adding new images, please only use official ones. + - "debian:oldstable-slim" + - "debian:stable-slim" + - "debian:testing-slim" + - "debian:sid-slim" + - "ubuntu:18.04" + - "ubuntu:20.04" + - "ubuntu:22.04" + - "ubuntu:22.10" + - "ubuntu:23.04" + - "elementary/docker:stable" + - "elementary/docker:unstable" + - "parrotsec/core:lts-amd64" + - "parrotsec/core:latest" + - "kalilinux/kali-rolling" + - "kalilinux/kali-dev" + - "oraclelinux:9" + - "oraclelinux:8" + - "fedora:latest" + - "rockylinux:8.7" + - "rockylinux:9" + - "amazonlinux:latest" + - "opensuse/leap:latest" + - "opensuse/tumbleweed:latest" + - "archlinux:latest" + - "alpine:3.14" + - "alpine:latest" + - "alpine:edge" + deps: + # Run all images installing curl as a dependency. + - curl + include: + # Check a few images with wget rather than curl. + - { image: "debian:oldstable-slim", deps: "wget" } + - { image: "debian:sid-slim", deps: "wget" } + - { image: "ubuntu:23.04", deps: "wget" } + # Ubuntu 16.04 also needs apt-transport-https installed. + - { image: "ubuntu:16.04", deps: "curl apt-transport-https" } + - { image: "ubuntu:16.04", deps: "wget apt-transport-https" } + runs-on: ubuntu-latest + container: + image: ${{ matrix.image }} + options: --user root + steps: + - name: install dependencies (yum) + # tar and gzip are needed by the actions/checkout below. + run: yum install -y --allowerasing tar gzip ${{ matrix.deps }} + if: | + contains(matrix.image, 'centos') + || contains(matrix.image, 'oraclelinux') + || contains(matrix.image, 'fedora') + || contains(matrix.image, 'amazonlinux') + - name: install dependencies (zypper) + # tar and gzip are needed by the actions/checkout below. + run: zypper --non-interactive install tar gzip + if: contains(matrix.image, 'opensuse') + - name: install dependencies (apt-get) + run: | + apt-get update + apt-get install -y ${{ matrix.deps }} + if: | + contains(matrix.image, 'debian') + || contains(matrix.image, 'ubuntu') + || contains(matrix.image, 'elementary') + || contains(matrix.image, 'parrotsec') + || contains(matrix.image, 'kalilinux') + - name: checkout + uses: actions/checkout@v3 + - name: run installer + run: scripts/installer.sh + # Package installation can fail in docker because systemd is not running + # as PID 1, so ignore errors at this step. The real check is the + # `tailscale --version` command below. + continue-on-error: true + - name: check tailscale version + run: tailscale --version diff --git a/scripts/installer.sh b/scripts/installer.sh index 5ae0a2f695cb3..7f4ff7e9b4898 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -430,7 +430,9 @@ main() { # Step 4: run the installation. - echo "Installing Tailscale for $OS $VERSION, using method $PACKAGETYPE" + OSVERSION="$OS" + [ "$VERSION" != "" ] && OSVERSION="$OSVERSION $VERSION" + echo "Installing Tailscale for $OSVERSION, using method $PACKAGETYPE" case "$PACKAGETYPE" in apt) export DEBIAN_FRONTEND=noninteractive @@ -469,6 +471,7 @@ main() { ;; dnf) set -x + $SUDO dnf install -y 'dnf-command(config-manager)' $SUDO dnf config-manager --add-repo "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" $SUDO dnf install -y tailscale $SUDO systemctl enable --now tailscaled @@ -483,14 +486,15 @@ main() { ;; zypper) set -x - $SUDO zypper ar -g -r "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" - $SUDO zypper ref - $SUDO zypper in tailscale + $SUDO zypper --non-interactive ar -g -r "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" + $SUDO zypper --non-interactive --gpg-auto-import-keys refresh + $SUDO zypper --non-interactive install tailscale $SUDO systemctl enable --now tailscaled set +x ;; pacman) set -x + $SUDO pacman -Sy $SUDO pacman -S tailscale --noconfirm $SUDO systemctl enable --now tailscaled set +x @@ -510,7 +514,7 @@ main() { ;; xbps) set -x - $SUDO xbps-install tailscale -y + $SUDO xbps-install tailscale -y set +x ;; emerge) From 979d29b5f59fcf67d96d2dfd3bcc91c6fd912dc7 Mon Sep 17 00:00:00 2001 From: License Updater Date: Mon, 1 May 2023 15:26:52 +0000 Subject: [PATCH 046/331] licenses: update win/apple licenses Signed-off-by: License Updater --- licenses/apple.md | 8 ++++---- licenses/windows.md | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/licenses/apple.md b/licenses/apple.md index 93585566c87a0..6359b727d9f90 100644 --- a/licenses/apple.md +++ b/licenses/apple.md @@ -59,11 +59,11 @@ and [iOS][]. See also the dependencies in the [Tailscale CLI][]. - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) diff --git a/licenses/windows.md b/licenses/windows.md index ef7784806099b..dc5b17e650139 100644 --- a/licenses/windows.md +++ b/licenses/windows.md @@ -32,8 +32,8 @@ Windows][]. See also the dependencies in the [Tailscale CLI][]. - [github.com/nfnt/resize](https://pkg.go.dev/github.com/nfnt/resize) ([ISC](https://github.com/nfnt/resize/blob/83c6a9932646/LICENSE)) - [github.com/peterbourgon/diskv](https://pkg.go.dev/github.com/peterbourgon/diskv) ([MIT](https://github.com/peterbourgon/diskv/blob/v2.0.1/LICENSE)) - [github.com/skip2/go-qrcode](https://pkg.go.dev/github.com/skip2/go-qrcode) ([MIT](https://github.com/skip2/go-qrcode/blob/da1b6568686e/LICENSE)) - - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/188cb8eef03f/LICENSE)) - - [github.com/tailscale/win](https://pkg.go.dev/github.com/tailscale/win) ([BSD-3-Clause](https://github.com/tailscale/win/blob/ad93eed16885/LICENSE)) + - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/f374e3278cd0/LICENSE)) + - [github.com/tailscale/win](https://pkg.go.dev/github.com/tailscale/win) ([BSD-3-Clause](https://github.com/tailscale/win/blob/59dfb47dfef1/LICENSE)) - [github.com/tc-hib/winres](https://pkg.go.dev/github.com/tc-hib/winres) ([0BSD](https://github.com/tc-hib/winres/blob/v0.1.6/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/4f986261bf13/LICENSE)) @@ -41,12 +41,12 @@ Windows][]. See also the dependencies in the [Tailscale CLI][]. - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) - [golang.org/x/image/bmp](https://pkg.go.dev/golang.org/x/image/bmp) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.5.0:LICENSE)) - - [golang.org/x/mod](https://pkg.go.dev/golang.org/x/mod) ([BSD-3-Clause](https://cs.opensource.google/go/x/mod/+/v0.9.0:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) + - [golang.org/x/mod](https://pkg.go.dev/golang.org/x/mod) ([BSD-3-Clause](https://cs.opensource.google/go/x/mod/+/v0.10.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) - [golang.zx2c4.com/wireguard/windows/tunnel/winipcfg](https://pkg.go.dev/golang.zx2c4.com/wireguard/windows/tunnel/winipcfg) ([MIT](https://git.zx2c4.com/wireguard-windows/tree/COPYING?h=v0.5.3)) - [gopkg.in/Knetic/govaluate.v3](https://pkg.go.dev/gopkg.in/Knetic/govaluate.v3) ([MIT](https://github.com/Knetic/govaluate/blob/v3.0.0/LICENSE)) From 42fd96409023f2d2d8ec0111c18e6be0c4791bad Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Sat, 29 Apr 2023 20:25:37 -0700 Subject: [PATCH 047/331] control/controlclient: use dnscache.Resolver for Noise client This passes the *dnscache.Resolver down from the Direct client into the Noise client and from there into the controlhttp client. This retains the Resolver so that it can share state across calls instead of creating a new resolver. Updates #4845 Updates #6110 Signed-off-by: Andrew Dunham Change-Id: Ia5d6af1870f3b5b5d7dd5685d775dcf300aec7af --- control/controlclient/direct.go | 28 ++++++++++++----- control/controlclient/noise.go | 47 ++++++++++++++++++++++++----- control/controlclient/noise_test.go | 7 ++++- control/controlhttp/client.go | 24 ++++++++++----- control/controlhttp/constants.go | 5 +++ 5 files changed, 87 insertions(+), 24 deletions(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index cf6fd998762cb..006f2614a3a82 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -61,6 +61,7 @@ import ( type Direct struct { httpc *http.Client // HTTP client used to talk to tailcontrol dialer *tsdial.Dialer + dnsCache *dnscache.Resolver serverURL string // URL of the tailcontrol server timeNow func() time.Time lastPrintMap time.Time @@ -199,6 +200,14 @@ func NewDirect(opts Options) (*Direct, error) { opts.Logf = log.Printf } + dnsCache := &dnscache.Resolver{ + Forward: dnscache.Get().Forward, // use default cache's forwarder + UseLastGood: true, + LookupIPFallback: dnsfallback.MakeLookupFunc(opts.Logf, opts.NetMon), + Logf: opts.Logf, + NetMon: opts.NetMon, + } + httpc := opts.HTTPTestClient if httpc == nil && runtime.GOOS == "js" { // In js/wasm, net/http.Transport (as of Go 1.18) will @@ -208,13 +217,6 @@ func NewDirect(opts Options) (*Direct, error) { httpc = http.DefaultClient } if httpc == nil { - dnsCache := &dnscache.Resolver{ - Forward: dnscache.Get().Forward, // use default cache's forwarder - UseLastGood: true, - LookupIPFallback: dnsfallback.MakeLookupFunc(opts.Logf, opts.NetMon), - Logf: opts.Logf, - NetMon: opts.NetMon, - } tr := http.DefaultTransport.(*http.Transport).Clone() tr.Proxy = tshttpproxy.ProxyFromEnvironment tshttpproxy.SetTransportGetProxyConnectHeader(tr) @@ -250,6 +252,7 @@ func NewDirect(opts Options) (*Direct, error) { onControlTime: opts.OnControlTime, c2nHandler: opts.C2NHandler, dialer: opts.Dialer, + dnsCache: dnsCache, dialPlan: opts.DialPlan, } if opts.Hostinfo == nil { @@ -1509,7 +1512,16 @@ func (c *Direct) getNoiseClient() (*NoiseClient, error) { return nil, err } c.logf("creating new noise client") - nc, err := NewNoiseClient(k, serverNoiseKey, c.serverURL, c.dialer, c.logf, c.netMon, dp) + nc, err := NewNoiseClient(NoiseOpts{ + PrivKey: k, + ServerPubKey: serverNoiseKey, + ServerURL: c.serverURL, + Dialer: c.dialer, + DNSCache: c.dnsCache, + Logf: c.logf, + NetMon: c.netMon, + DialPlan: dp, + }) if err != nil { return nil, err } diff --git a/control/controlclient/noise.go b/control/controlclient/noise.go index 61c472a356dc3..cad81b82ce09c 100644 --- a/control/controlclient/noise.go +++ b/control/controlclient/noise.go @@ -19,6 +19,7 @@ import ( "golang.org/x/net/http2" "tailscale.com/control/controlbase" "tailscale.com/control/controlhttp" + "tailscale.com/net/dnscache" "tailscale.com/net/netmon" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" @@ -158,6 +159,7 @@ type NoiseClient struct { sfDial singleflight.Group[struct{}, *noiseConn] dialer *tsdial.Dialer + dnsCache *dnscache.Resolver privKey key.MachinePrivate serverPubKey key.MachinePublic host string // the host part of serverURL @@ -179,13 +181,39 @@ type NoiseClient struct { connPool map[int]*noiseConn // active connections not yet closed; see noiseConn.Close } +// NoiseOpts contains options for the NewNoiseClient function. All fields are +// required unless otherwise specified. +type NoiseOpts struct { + // PrivKey is this node's private key. + PrivKey key.MachinePrivate + // ServerPubKey is the public key of the server. + ServerPubKey key.MachinePublic + // ServerURL is the URL of the server to connect to. + ServerURL string + // Dialer's SystemDial function is used to connect to the server. + Dialer *tsdial.Dialer + // DNSCache is the caching Resolver to use to connect to the server. + // + // This field can be nil. + DNSCache *dnscache.Resolver + // Logf is the log function to use. This field can be nil. + Logf logger.Logf + // NetMon is the network monitor that, if set, will be used to get the + // network interface state. This field can be nil; if so, the current + // state will be looked up dynamically. + NetMon *netmon.Monitor + // DialPlan, if set, is a function that should return an explicit plan + // on how to connect to the server. + DialPlan func() *tailcfg.ControlDialPlan +} + // NewNoiseClient returns a new noiseClient for the provided server and machine key. // serverURL is of the form https://: (no trailing slash). // // netMon may be nil, if non-nil it's used to do faster interface lookups. // dialPlan may be nil -func NewNoiseClient(privKey key.MachinePrivate, serverPubKey key.MachinePublic, serverURL string, dialer *tsdial.Dialer, logf logger.Logf, netMon *netmon.Monitor, dialPlan func() *tailcfg.ControlDialPlan) (*NoiseClient, error) { - u, err := url.Parse(serverURL) +func NewNoiseClient(opts NoiseOpts) (*NoiseClient, error) { + u, err := url.Parse(opts.ServerURL) if err != nil { return nil, err } @@ -205,16 +233,18 @@ func NewNoiseClient(privKey key.MachinePrivate, serverPubKey key.MachinePublic, httpPort = "80" httpsPort = "443" } + np := &NoiseClient{ - serverPubKey: serverPubKey, - privKey: privKey, + serverPubKey: opts.ServerPubKey, + privKey: opts.PrivKey, host: u.Hostname(), httpPort: httpPort, httpsPort: httpsPort, - dialer: dialer, - dialPlan: dialPlan, - logf: logf, - netMon: netMon, + dialer: opts.Dialer, + dnsCache: opts.DNSCache, + dialPlan: opts.DialPlan, + logf: opts.Logf, + netMon: opts.NetMon, } // Create the HTTP/2 Transport using a net/http.Transport @@ -373,6 +403,7 @@ func (nc *NoiseClient) dial() (*noiseConn, error) { ControlKey: nc.serverPubKey, ProtocolVersion: uint16(tailcfg.CurrentCapabilityVersion), Dialer: nc.dialer.SystemDial, + DNSCache: nc.dnsCache, DialPlan: dialPlan, Logf: nc.logf, NetMon: nc.netMon, diff --git a/control/controlclient/noise_test.go b/control/controlclient/noise_test.go index 11e35f0af8879..9961e3318de45 100644 --- a/control/controlclient/noise_test.go +++ b/control/controlclient/noise_test.go @@ -74,7 +74,12 @@ func (tt noiseClientTest) run(t *testing.T) { defer hs.Close() dialer := new(tsdial.Dialer) - nc, err := NewNoiseClient(clientPrivate, serverPrivate.Public(), hs.URL, dialer, nil, nil, nil) + nc, err := NewNoiseClient(NoiseOpts{ + PrivKey: clientPrivate, + ServerPubKey: serverPrivate.Public(), + ServerURL: hs.URL, + Dialer: dialer, + }) if err != nil { t.Fatal(err) } diff --git a/control/controlhttp/client.go b/control/controlhttp/client.go index d04aac5188650..b0d91bada8747 100644 --- a/control/controlhttp/client.go +++ b/control/controlhttp/client.go @@ -374,6 +374,22 @@ func (a *Dialer) dialURL(ctx context.Context, u *url.URL, addr netip.Addr) (*Cli }, nil } +// resolver returns a.DNSCache if non-nil or a new *dnscache.Resolver +// otherwise. +func (a *Dialer) resolver() *dnscache.Resolver { + if a.DNSCache != nil { + return a.DNSCache + } + + return &dnscache.Resolver{ + Forward: dnscache.Get().Forward, + LookupIPFallback: dnsfallback.MakeLookupFunc(a.logf, a.NetMon), + UseLastGood: true, + Logf: a.Logf, // not a.logf method; we want to propagate nil-ness + NetMon: a.NetMon, + } +} + // tryURLUpgrade connects to u, and tries to upgrade it to a net.Conn. If addr // is valid, then no DNS is used and the connection will be made to the // provided address. @@ -392,13 +408,7 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr, NetMon: a.NetMon, } } else { - dns = &dnscache.Resolver{ - Forward: dnscache.Get().Forward, - LookupIPFallback: dnsfallback.MakeLookupFunc(a.logf, a.NetMon), - UseLastGood: true, - Logf: a.Logf, // not a.logf method; we want to propagate nil-ness - NetMon: a.NetMon, - } + dns = a.resolver() } var dialer dnscache.DialContextFunc diff --git a/control/controlhttp/constants.go b/control/controlhttp/constants.go index a58ee5374a7d4..b838f84c435bd 100644 --- a/control/controlhttp/constants.go +++ b/control/controlhttp/constants.go @@ -67,6 +67,11 @@ type Dialer struct { // If not specified, this defaults to net.Dialer.DialContext. Dialer dnscache.DialContextFunc + // DNSCache is the caching Resolver used by this Dialer. + // + // If not specified, a new Resolver is created per attempt. + DNSCache *dnscache.Resolver + // Logf, if set, is a logging function to use; if unset, logs are // dropped. Logf logger.Logf From c5bf868940d89315f403e2e1dcab67b0c1aa0a46 Mon Sep 17 00:00:00 2001 From: Tom DNetto Date: Mon, 1 May 2023 13:17:16 -0700 Subject: [PATCH 048/331] ssh/tailssh: improve debug logging around revoked sessions Updates https://github.com/tailscale/corp/issues/10943 Signed-off-by: Tom DNetto --- ssh/tailssh/tailssh.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 37e73e1401217..2ba20e00c7e72 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -236,6 +236,12 @@ func (c *conn) logf(format string, args ...any) { c.srv.logf(format, args...) } +func (c *conn) vlogf(format string, args ...any) { + if sshVerboseLogging() { + c.logf(format, args...) + } +} + // isAuthorized walks through the action chain and returns nil if the connection // is authorized. If the connection is not authorized, it returns // gossh.ErrDenied. If the action chain resolution fails, it returns the @@ -841,6 +847,7 @@ func (c *conn) newSSHSession(s ssh.Session) *sshSession { // isStillValid reports whether the conn is still valid. func (c *conn) isStillValid() bool { a, localUser, err := c.evaluatePolicy(c.pubKey) + c.vlogf("stillValid: %+v %v %v", a, localUser, err) if err != nil { return false } @@ -1211,6 +1218,10 @@ var ( ) func (c *conn) matchRule(r *tailcfg.SSHRule, pubKey gossh.PublicKey) (a *tailcfg.SSHAction, localUser string, err error) { + defer func() { + c.vlogf("matchRule(%+v): %v", r, err) + }() + if c == nil { return nil, "", errInvalidConn } From bcf7b63d7e8cd104e61c984dcc7047cc23ca697e Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Fri, 21 Apr 2023 11:35:16 -0400 Subject: [PATCH 049/331] wgengine/magicsock: add hysteresis to endpoint selection Avoid selecting an endpoint as "better" than the current endpoint if the total latency improvement is less than 1%. This adds some hysteresis to avoid flapping between endpoints for a minimal improvement in latency. Signed-off-by: Andrew Dunham Change-Id: If8312e1768ea65c4b4d4e13d8de284b3825d7a73 --- wgengine/magicsock/magicsock.go | 22 ++++++++++++++++++++++ wgengine/magicsock/magicsock_test.go | 6 +++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 123b2e70b91e3..95af2589144af 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -4921,6 +4921,28 @@ func betterAddr(a, b addrLatency) bool { return false } } + + // If we get here, then both addresses are the same IP type (i.e. both + // IPv4 or both IPv6). All decisions below are made solely on latency. + // + // Determine how much the latencies differ; we ensure the larger + // latency is the denominator, so this fraction will always be <= 1.0. + var latencyFraction float64 + if a.latency >= b.latency { + latencyFraction = float64(b.latency) / float64(a.latency) + } else { + latencyFraction = float64(a.latency) / float64(b.latency) + } + + // Don't change anything if the latency improvement is less than 1%; we + // want a bit of "stickiness" (a.k.a. hysteresis) to avoid flapping if + // there's two roughly-equivalent endpoints. + if latencyFraction >= 0.99 { + return false + } + + // The total difference is >1%, so a is better than b if it's + // lower-latency. return a.latency < b.latency } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index c050cfc2011e4..9115a3eeac7e3 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -1633,9 +1633,13 @@ func TestBetterAddr(t *testing.T) { {a: zero, b: zero, want: false}, {a: al("10.0.0.2:123", 5*ms), b: zero, want: true}, {a: zero, b: al("10.0.0.2:123", 5*ms), want: false}, - {a: al("10.0.0.2:123", 5*ms), b: al("1.2.3.4:555", 6*ms), want: true}, + {a: al("10.0.0.2:123", 5*ms), b: al("1.2.3.4:555", 10*ms), want: true}, {a: al("10.0.0.2:123", 5*ms), b: al("10.0.0.2:123", 10*ms), want: false}, // same IPPort + // Don't prefer b to a if it's not substantially better. + {a: al("10.0.0.2:123", 100*ms), b: al("1.2.3.4:555", 101*ms), want: false}, + {a: al("10.0.0.2:123", 100*ms), b: al("1.2.3.4:555", 103*ms), want: true}, + // Prefer IPv6 if roughly equivalent: { a: al("[2001::5]:123", 100*ms), From 3ae7140690cee3d3454f977957f209a4b00b14a0 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Tue, 2 May 2023 12:12:44 -0700 Subject: [PATCH 050/331] net/tstun: handle exit nodes in NAT configs In the case where the exit node requires SNAT, we would SNAT all traffic not just the traffic meant to go through the exit node. This was a result of the default route being added to the routing table which would match basically everything. In this case, we need to account for all peers in the routing table not just the ones that require NAT. Fix and add a test. Updates tailscale/corp#8020 Signed-off-by: Maisem Ali --- net/tstun/wrap.go | 26 +++++++++++--- net/tstun/wrap_test.go | 81 +++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 33 deletions(-) diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index 450885fbf5eb1..74bf54134c23b 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -20,6 +20,7 @@ import ( "github.com/tailscale/wireguard-go/device" "github.com/tailscale/wireguard-go/tun" "go4.org/mem" + "golang.org/x/exp/slices" "gvisor.dev/gvisor/pkg/tcpip/stack" "tailscale.com/disco" "tailscale.com/net/connstats" @@ -590,16 +591,33 @@ func natConfigFromWGConfig(wcfg *wgcfg.Config) *natV4Config { dstMasqAddrs map[key.NodePublic]netip.Addr listenAddrs map[netip.Addr]struct{} ) + + // When using an exit node that requires masquerading, we need to + // fill out the routing table with all peers not just the ones that + // require masquerading. + exitNodeRequiresMasq := false // true if using an exit node and it requires masquerading + for _, p := range wcfg.Peers { + isExitNode := slices.Contains(p.AllowedIPs, tsaddr.AllIPv4()) || slices.Contains(p.AllowedIPs, tsaddr.AllIPv6()) + if isExitNode && p.V4MasqAddr != nil && p.V4MasqAddr.IsValid() { + exitNodeRequiresMasq = true + break + } + } for i := range wcfg.Peers { p := &wcfg.Peers[i] - if p.V4MasqAddr == nil || !p.V4MasqAddr.IsValid() { + var addrToUse netip.Addr + if p.V4MasqAddr != nil && p.V4MasqAddr.IsValid() { + addrToUse = *p.V4MasqAddr + mak.Set(&listenAddrs, addrToUse, struct{}{}) + } else if exitNodeRequiresMasq { + addrToUse = nativeAddr + } else { continue } rt.InsertOrReplace(p.PublicKey, p.AllowedIPs...) - mak.Set(&dstMasqAddrs, p.PublicKey, *p.V4MasqAddr) - mak.Set(&listenAddrs, *p.V4MasqAddr, struct{}{}) + mak.Set(&dstMasqAddrs, p.PublicKey, addrToUse) } - if len(listenAddrs) == 0 || len(dstMasqAddrs) == 0 { + if len(listenAddrs) == 0 && len(dstMasqAddrs) == 0 { return nil } return &natV4Config{ diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index f2ae0a6145a7c..f9e35beecd72e 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -602,13 +602,13 @@ func TestFilterDiscoLoop(t *testing.T) { } func TestNATCfg(t *testing.T) { - node := func(ip, eip netip.Addr, otherAllowedIPs ...netip.Prefix) wgcfg.Peer { + node := func(ip, masqIP netip.Addr, otherAllowedIPs ...netip.Prefix) wgcfg.Peer { p := wgcfg.Peer{ PublicKey: key.NewNode().Public(), AllowedIPs: []netip.Prefix{ netip.PrefixFrom(ip, ip.BitLen()), }, - V4MasqAddr: ptr.To(eip), + V4MasqAddr: ptr.To(masqIP), } p.AllowedIPs = append(p.AllowedIPs, otherAllowedIPs...) return p @@ -619,13 +619,16 @@ func TestNATCfg(t *testing.T) { selfNativeIP = netip.MustParseAddr("100.64.0.1") selfEIP1 = netip.MustParseAddr("100.64.1.1") selfEIP2 = netip.MustParseAddr("100.64.1.2") + selfAddrs = []netip.Prefix{netip.PrefixFrom(selfNativeIP, selfNativeIP.BitLen())} peer1IP = netip.MustParseAddr("100.64.0.2") peer2IP = netip.MustParseAddr("100.64.0.3") - subnet = netip.MustParseAddr("192.168.0.1") + subnet = netip.MustParsePrefix("192.168.0.0/24") + subnetIP = netip.MustParseAddr("192.168.0.1") - selfAddrs = []netip.Prefix{netip.PrefixFrom(selfNativeIP, selfNativeIP.BitLen())} + exitRoute = netip.MustParsePrefix("0.0.0.0/0") + publicIP = netip.MustParseAddr("8.8.8.8") ) tests := []struct { @@ -638,9 +641,9 @@ func TestNATCfg(t *testing.T) { name: "no-cfg", wcfg: nil, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfNativeIP, - peer2IP: selfNativeIP, - subnet: selfNativeIP, + peer1IP: selfNativeIP, + peer2IP: selfNativeIP, + subnetIP: selfNativeIP, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, @@ -658,15 +661,15 @@ func TestNATCfg(t *testing.T) { }, }, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfNativeIP, - peer2IP: selfEIP1, - subnet: selfNativeIP, + peer1IP: selfNativeIP, + peer2IP: selfEIP1, + subnetIP: selfNativeIP, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, selfEIP1: selfNativeIP, selfEIP2: selfEIP2, - subnet: subnet, + subnetIP: subnetIP, }, }, { @@ -679,15 +682,15 @@ func TestNATCfg(t *testing.T) { }, }, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfEIP1, - peer2IP: selfEIP2, - subnet: selfNativeIP, + peer1IP: selfEIP1, + peer2IP: selfEIP2, + subnetIP: selfNativeIP, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, selfEIP1: selfNativeIP, selfEIP2: selfNativeIP, - subnet: subnet, + subnetIP: subnetIP, }, }, { @@ -696,19 +699,19 @@ func TestNATCfg(t *testing.T) { Addresses: selfAddrs, Peers: []wgcfg.Peer{ node(peer1IP, selfEIP1), - node(peer2IP, selfEIP2, netip.MustParsePrefix("192.168.0.0/24")), + node(peer2IP, selfEIP2, subnet), }, }, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfEIP1, - peer2IP: selfEIP2, - subnet: selfEIP2, + peer1IP: selfEIP1, + peer2IP: selfEIP2, + subnetIP: selfEIP2, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, selfEIP1: selfNativeIP, selfEIP2: selfNativeIP, - subnet: subnet, + subnetIP: subnetIP, }, }, { @@ -717,19 +720,19 @@ func TestNATCfg(t *testing.T) { Addresses: selfAddrs, Peers: []wgcfg.Peer{ node(peer1IP, selfEIP1), - node(peer2IP, selfEIP2, netip.MustParsePrefix("0.0.0.0/0")), + node(peer2IP, selfEIP2, exitRoute), }, }, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfEIP1, - peer2IP: selfEIP2, - netip.MustParseAddr("8.8.8.8"): selfEIP2, + peer1IP: selfEIP1, + peer2IP: selfEIP2, + publicIP: selfEIP2, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, selfEIP1: selfNativeIP, selfEIP2: selfNativeIP, - subnet: subnet, + subnetIP: subnetIP, }, }, { @@ -742,15 +745,35 @@ func TestNATCfg(t *testing.T) { }, }, snatMap: map[netip.Addr]netip.Addr{ - peer1IP: selfNativeIP, - peer2IP: selfNativeIP, - subnet: selfNativeIP, + peer1IP: selfNativeIP, + peer2IP: selfNativeIP, + subnetIP: selfNativeIP, }, dnatMap: map[netip.Addr]netip.Addr{ selfNativeIP: selfNativeIP, selfEIP1: selfEIP1, selfEIP2: selfEIP2, - subnet: subnet, + subnetIP: subnetIP, + }, + }, + { + name: "exit-node-require-nat-peer-doesnt", + wcfg: &wgcfg.Config{ + Addresses: selfAddrs, + Peers: []wgcfg.Peer{ + node(peer1IP, noIP), + node(peer2IP, selfEIP2, exitRoute), + }, + }, + snatMap: map[netip.Addr]netip.Addr{ + peer1IP: selfNativeIP, + peer2IP: selfEIP2, + publicIP: selfEIP2, + }, + dnatMap: map[netip.Addr]netip.Addr{ + selfNativeIP: selfNativeIP, + selfEIP2: selfNativeIP, + subnetIP: subnetIP, }, }, } From c1e6888fc77e7f525bf676113aecaf725211ff77 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 2 May 2023 09:50:39 -0700 Subject: [PATCH 051/331] derp: add a README.md with some docs Updates #docs Signed-off-by: Brad Fitzpatrick --- derp/README.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 derp/README.md diff --git a/derp/README.md b/derp/README.md new file mode 100644 index 0000000000000..16877020d465e --- /dev/null +++ b/derp/README.md @@ -0,0 +1,61 @@ +# DERP + +This directory (and subdirectories) contain the DERP code. The server itself is +in `../cmd/derper`. + +DERP is a packet relay system (client and servers) where peers are addressed +using WireGuard public keys instead of IP addresses. + +It relays two types of packets: + +* "Disco" discovery messages (see `../disco`) as the a side channel during [NAT + traversal](https://tailscale.com/blog/how-nat-traversal-works/). + +* Encrypted WireGuard packets as the fallback of last resort when UDP is blocked + or NAT traversal fails. + +## DERP Map + +Each client receives a "[DERP +Map](https://pkg.go.dev/tailscale.com/tailcfg#DERPMap)" from the coordination +server describing the DERP servers the client should try to use. + +The client picks its home "DERP home" based on latency. This is done to keep +costs low by avoid using cloud load balancers (pricey) or anycast, which would +necessarily require server-side routing between DERP regions. + +Clients pick their DERP home and report it to the coordination server which +shares it to all the peers in the tailnet. When a peer wants to send a packet +and it doesn't already have a WireGuard session open, it sends disco messages +(some direct, and some over DERP), trying to do the NAT traversal. The client +will make connections to multiple DERP regions as needed. Only the DERP home +region connection needs to be alive forever. + +## DERP Regions + +Tailscale runs 1 or more DERP nodes (instances of `cmd/derper`) in various +geographic regions to make sure users have low latency to their DERP home. + +Regions generally have multiple nodes per region "meshed" (routing to each +other) together for redundancy: it allows for cloud failures or upgrades without +kicking users out to a higher latency region. Instead, clients will reconnect to +the next node in the region. Each node in the region is required to to be meshed +with every other node in the region and forward packets to the other nodes in +the region. Packets are forwarded only one hop within the region. There is no +routing between regions. The assumption is that the mesh TCP connections are +over a VPC that's very fast, low latency, and not charged per byte. The +coordination server assigns the list of nodes in a region as a function of the +tailnet, so all nodes within a tailnet should generally be on the same node and +not require forwarding. Only after a failure do clients of a particular tailnet +get split between nodes in a region and require inter-node forwarding. But over +time it balances back out. There's also an admin-only DERP frame type to force +close the TCP connection of a particular client to force them to reconnect to +their primary if the operator wants to force things to balance out sooner. +(Using the `(*derphttp.Client).ClosePeer` method, as used by Tailscale's +internal rarely-used `cmd/derpprune` maintenance tool) + +We generally run a minimum of three nodes in a region not for quorum reasons +(there's no voting) but just because two is too uncomfortably few for cascading +failure reasons: if you're running two nodes at 51% load (CPU, memory, etc) and +then one fails, that makes the second one fail. With three or more nodes, you +can run each node a bit hotter. \ No newline at end of file From ddb4040aa0cd7cdb2eef064658d18e3e75de1c5d Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn <46385858+catzkorn@users.noreply.github.com> Date: Tue, 2 May 2023 17:49:56 -0700 Subject: [PATCH 052/331] wgengine/magicsock: add address selection for wireguard only endpoints (#7979) This change introduces address selection for wireguard only endpoints. If a endpoint has not been used before, an address is randomly selected to be used based on information we know about, such as if they are able to use IPv4 or IPv6. When an address is initially selected, we also initiate a new ICMP ping to the endpoints addresses to determine which endpoint offers the best latency. This information is then used to update which endpoint we should be using based on the best possible route. If the latency is the same for a IPv4 and an IPv6 address, IPv6 will be used. Updates #7826 Signed-off-by: Charlotte Brandhorst-Satzkorn --- cmd/tailscaled/depaware.txt | 2 +- wgengine/magicsock/magicsock.go | 298 ++++++++++++---- wgengine/magicsock/magicsock_test.go | 488 ++++++++++++++++++++++++++- 3 files changed, 714 insertions(+), 74 deletions(-) diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index b51b3a3de0790..16c8c6bba73c9 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -245,7 +245,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnauth+ tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+ tailscale.com/net/packet from tailscale.com/net/tstun+ - tailscale.com/net/ping from tailscale.com/net/netcheck + tailscale.com/net/ping from tailscale.com/net/netcheck+ tailscale.com/net/portmapper from tailscale.com/net/netcheck+ tailscale.com/net/proxymux from tailscale.com/cmd/tailscaled tailscale.com/net/routetable from tailscale.com/doctor/routetable diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 95af2589144af..3223441c461e1 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -50,6 +50,7 @@ import ( "tailscale.com/net/netmon" "tailscale.com/net/netns" "tailscale.com/net/packet" + "tailscale.com/net/ping" "tailscale.com/net/portmapper" "tailscale.com/net/sockstats" "tailscale.com/net/stun" @@ -59,6 +60,7 @@ import ( "tailscale.com/tstime" "tailscale.com/tstime/mono" "tailscale.com/types/key" + "tailscale.com/types/lazy" "tailscale.com/types/logger" "tailscale.com/types/netmap" "tailscale.com/types/nettype" @@ -209,11 +211,16 @@ func (m *peerMap) upsertEndpoint(ep *endpoint, oldDiscoKey key.DiscoPublic) { if epDisco == nil || oldDiscoKey != epDisco.key { delete(m.nodesOfDisco[oldDiscoKey], ep.publicKey) } - if epDisco == nil { - // If the peer does not support Disco, but it does have an endpoint address, - // attempt to use that (e.g. WireGuardOnly peers). - if ep.bestAddr.AddrPort.IsValid() { - m.setNodeKeyForIPPort(ep.bestAddr.AddrPort, ep.publicKey) + if ep.isWireguardOnly { + // If the peer is a WireGuard only peer, add all of its endpoints. + + // TODO(raggi,catzkorn): this could mean that if a "isWireguardOnly" + // peer has, say, 192.168.0.2 and so does a tailscale peer, the + // wireguard one will win. That may not be the outcome that we want - + // perhaps we should prefer bestAddr.AddrPort if it is set? + // see tailscale/tailscale#7994 + for ipp := range ep.endpointState { + m.setNodeKeyForIPPort(ipp, ep.publicKey) } return @@ -473,6 +480,9 @@ type Conn struct { // peerLastDerp tracks which DERP node we last used to speak with a // peer. It's only used to quiet logging, so we only log on change. peerLastDerp map[key.NodePublic]int + + // wgPinger is the WireGuard only pinger used for latency measurements. + wgPinger lazy.SyncValue[*ping.Pinger] } // SetDebugLoggingEnabled controls whether spammy debug logging is enabled. @@ -2766,6 +2776,7 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) { sentPing: map[stun.TxID]sentPing{}, endpointState: map[netip.AddrPort]*endpointState{}, heartbeatDisabled: heartbeatDisabled, + isWireguardOnly: n.IsWireGuardOnly, } if len(n.Addresses) > 0 { ep.nodeAddr = n.Addresses[0].Addr() @@ -3143,6 +3154,11 @@ func (c *Conn) Close() error { for c.goroutinesRunningLocked() { c.muCond.Wait() } + + if pinger := c.getPinger(); pinger != nil { + pinger.Close() + } + return nil } @@ -4084,9 +4100,14 @@ type endpointDisco struct { short string // ShortString of discoKey. } -// endpoint is a wireguard/conn.Endpoint that picks the best -// available path to communicate with a peer, based on network -// conditions and what the peer supports. +// endpoint is a wireguard/conn.Endpoint. In wireguard-go and kernel WireGuard +// there is only one endpoint for a peer, but in Tailscale we distribute a +// number of possible endpoints for a peer which would include the all the +// likely addresses at which a peer may be reachable. This endpoint type holds +// the information required that when WiregGuard-Go wants to send to a +// particular peer (essentally represented by this endpoint type), the send +// function can use the currnetly best known Tailscale endpoint to send packets +// to the peer. type endpoint struct { // atomically accessed; declared first for alignment reasons lastRecv mono.Time @@ -4108,7 +4129,7 @@ type endpoint struct { heartBeatTimer *time.Timer // nil when idle lastSend mono.Time // last time there was outgoing packets sent to this peer (from wireguard-go) - lastFullPing mono.Time // last time we pinged all endpoints + lastFullPing mono.Time // last time we pinged all disco endpoints derpAddr netip.AddrPort // fallback/bootstrap path, if non-zero (non-zero for well-behaved clients) bestAddr addrLatency // best non-DERP path; zero if none @@ -4126,7 +4147,8 @@ type endpoint struct { heartbeatDisabled bool pathFinderRunning bool - expired bool // whether the node has expired + expired bool // whether the node has expired + isWireguardOnly bool // whether the endpoint is WireGuard only } type pendingCLIPing struct { @@ -4238,6 +4260,15 @@ func (st *endpointState) shouldDeleteLocked() bool { } } +// latencyLocked returns the most recent latency measurement, if any. +// endpoint.mu must be held. +func (st *endpointState) latencyLocked() (lat time.Duration, ok bool) { + if len(st.recentPongs) == 0 { + return 0, false + } + return st.recentPongs[st.recentPong].latency, true +} + func (de *endpoint) deleteEndpointLocked(why string, ep netip.AddrPort) { de.debugUpdates.Add(EndpointChange{ When: time.Now(), @@ -4321,17 +4352,87 @@ func (de *endpoint) DstToBytes() []byte { return packIPPort(de.fakeWGAddr) } // addrForSendLocked returns the address(es) that should be used for // sending the next packet. Zero, one, or both of UDP address and DERP -// addr may be non-zero. +// addr may be non-zero. If the endpoint is WireGuard only and does not have +// latency information, a bool is returned to indiciate that the +// WireGuard latency discovery pings should be sent. // // de.mu must be held. -func (de *endpoint) addrForSendLocked(now mono.Time) (udpAddr, derpAddr netip.AddrPort) { +func (de *endpoint) addrForSendLocked(now mono.Time) (udpAddr, derpAddr netip.AddrPort, sendWGPing bool) { udpAddr = de.bestAddr.AddrPort - if !udpAddr.IsValid() || now.After(de.trustBestAddrUntil) { - // We had a bestAddr but it expired so send both to it - // and DERP. - derpAddr = de.derpAddr + + if udpAddr.IsValid() && !now.After(de.trustBestAddrUntil) { + return udpAddr, netip.AddrPort{}, false } - return + + if de.isWireguardOnly { + // If the endpoint is wireguard-only, we don't have a DERP + // address to send to, so we have to send to the UDP address. + udpAddr, shouldPing := de.addrForWireGuardSendLocked(now) + return udpAddr, netip.AddrPort{}, shouldPing + } + + // We had a bestAddr but it expired so send both to it + // and DERP. + return udpAddr, de.derpAddr, false +} + +// addrForWireGuardSendLocked returns the address that should be used for +// sending the next packet. If a packet has never or not recently been sent to +// the endpoint, then a randomly selected address for the endpoint is returned, +// as well as a bool indiciating that WireGuard discovery pings should be started. +// If the addresses have latency information available, then the address with the +// best latency is used. +// +// de.mu must be held. +func (de *endpoint) addrForWireGuardSendLocked(now mono.Time) (udpAddr netip.AddrPort, shouldPing bool) { + // lowestLatency is a high duration initially, so we + // can be sure we're going to have a duration lower than this + // for the first latency retrieved. + lowestLatency := time.Hour + for ipp, state := range de.endpointState { + if latency, ok := state.latencyLocked(); ok { + if latency < lowestLatency || latency == lowestLatency && ipp.Addr().Is6() { + // If we have the same latency,IPv6 is prioritized. + // TODO(catzkorn): Consider a small increase in latency to use + // IPv6 in comparison to IPv4, when possible. + lowestLatency = latency + udpAddr = ipp + } + } + } + + if udpAddr.IsValid() { + // Set trustBestAddrUntil to an hour, so we will + // continue to use this address for a long period of time. + de.bestAddr.AddrPort = udpAddr + de.trustBestAddrUntil = now.Add(1 * time.Hour) + return udpAddr, false + } + + candidates := make([]netip.AddrPort, 0, len(de.endpointState)) + for ipp := range de.endpointState { + if ipp.Addr().Is4() && de.c.noV4.Load() { + continue + } + if ipp.Addr().Is6() && de.c.noV6.Load() { + continue + } + candidates = append(candidates, ipp) + } + // Randomly select an address to use until we retrieve latency information + // and give it a short trustBestAddrUntil time so we avoid flapping between + // addresses while waiting on latency information to be populated. + udpAddr = candidates[rand.Intn(len(candidates))] + de.bestAddr.AddrPort = udpAddr + if len(candidates) == 1 { + // if we only have one address that we can send data too, + // we should trust it for a longer period of time. + de.trustBestAddrUntil = now.Add(1 * time.Hour) + } else { + de.trustBestAddrUntil = now.Add(15 * time.Second) + } + + return udpAddr, len(candidates) > 1 } // heartbeat is called every heartbeatInterval to keep the best UDP path alive, @@ -4359,14 +4460,14 @@ func (de *endpoint) heartbeat() { } now := mono.Now() - udpAddr, _ := de.addrForSendLocked(now) + udpAddr, _, _ := de.addrForSendLocked(now) if udpAddr.IsValid() { // We have a preferred path. Ping that every 2 seconds. - de.startPingLocked(udpAddr, now, pingHeartbeat) + de.startDiscoPingLocked(udpAddr, now, pingHeartbeat) } if de.wantFullPingLocked(now) { - de.sendPingsLocked(now, true) + de.sendDiscoPingsLocked(now, true) } de.heartBeatTimer = time.AfterFunc(heartbeatInterval, de.heartbeat) @@ -4417,19 +4518,19 @@ func (de *endpoint) cliPing(res *ipnstate.PingResult, cb func(*ipnstate.PingResu de.pendingCLIPings = append(de.pendingCLIPings, pendingCLIPing{res, cb}) now := mono.Now() - udpAddr, derpAddr := de.addrForSendLocked(now) + udpAddr, derpAddr, _ := de.addrForSendLocked(now) if derpAddr.IsValid() { - de.startPingLocked(derpAddr, now, pingCLI) + de.startDiscoPingLocked(derpAddr, now, pingCLI) } if udpAddr.IsValid() && now.Before(de.trustBestAddrUntil) { // Already have an active session, so just ping the address we're using. // Otherwise "tailscale ping" results to a node on the local network // can look like they're bouncing between, say 10.0.0.0/9 and the peer's // IPv6 address, both 1ms away, and it's random who replies first. - de.startPingLocked(udpAddr, now, pingCLI) + de.startDiscoPingLocked(udpAddr, now, pingCLI) } else { for ep := range de.endpointState { - de.startPingLocked(ep, now, pingCLI) + de.startDiscoPingLocked(ep, now, pingCLI) } } de.noteActiveLocked() @@ -4459,9 +4560,14 @@ func (de *endpoint) send(buffs [][]byte) error { } now := mono.Now() - udpAddr, derpAddr := de.addrForSendLocked(now) - if !udpAddr.IsValid() || now.After(de.trustBestAddrUntil) { - de.sendPingsLocked(now, true) + udpAddr, derpAddr, startWGPing := de.addrForSendLocked(now) + + if de.isWireguardOnly { + if startWGPing { + de.sendWireGuardOnlyPingsLocked(now) + } + } else if !udpAddr.IsValid() || now.After(de.trustBestAddrUntil) { + de.sendDiscoPingsLocked(now, true) } de.noteActiveLocked() de.mu.Unlock() @@ -4499,7 +4605,7 @@ func (de *endpoint) send(buffs [][]byte) error { return err } -func (de *endpoint) pingTimeout(txid stun.TxID) { +func (de *endpoint) discoPingTimeout(txid stun.TxID) { de.mu.Lock() defer de.mu.Unlock() sp, ok := de.sentPing[txid] @@ -4509,20 +4615,20 @@ func (de *endpoint) pingTimeout(txid stun.TxID) { if debugDisco() || !de.bestAddr.IsValid() || mono.Now().After(de.trustBestAddrUntil) { de.c.dlogf("[v1] magicsock: disco: timeout waiting for pong %x from %v (%v, %v)", txid[:6], sp.to, de.publicKey.ShortString(), de.discoShort()) } - de.removeSentPingLocked(txid, sp) + de.removeSentDiscoPingLocked(txid, sp) } -// forgetPing is called by a timer when a ping either fails to send or +// forgetDiscoPing is called by a timer when a ping either fails to send or // has taken too long to get a pong reply. -func (de *endpoint) forgetPing(txid stun.TxID) { +func (de *endpoint) forgetDiscoPing(txid stun.TxID) { de.mu.Lock() defer de.mu.Unlock() if sp, ok := de.sentPing[txid]; ok { - de.removeSentPingLocked(txid, sp) + de.removeSentDiscoPingLocked(txid, sp) } } -func (de *endpoint) removeSentPingLocked(txid stun.TxID, sp sentPing) { +func (de *endpoint) removeSentDiscoPingLocked(txid stun.TxID, sp sentPing) { // Stop the timer for the case where sendPing failed to write to UDP. // In the case of a timer already having fired, this is a no-op: sp.timer.Stop() @@ -4542,7 +4648,7 @@ func (de *endpoint) sendDiscoPing(ep netip.AddrPort, discoKey key.DiscoPublic, t NodeKey: de.c.publicKeyAtomic.Load(), }, logLevel) if !sent { - de.forgetPing(txid) + de.forgetDiscoPing(txid) } } @@ -4564,7 +4670,7 @@ const ( pingCLI ) -func (de *endpoint) startPingLocked(ep netip.AddrPort, now mono.Time, purpose discoPingPurpose) { +func (de *endpoint) startDiscoPingLocked(ep netip.AddrPort, now mono.Time, purpose discoPingPurpose) { if runtime.GOOS == "js" { return } @@ -4587,7 +4693,7 @@ func (de *endpoint) startPingLocked(ep netip.AddrPort, now mono.Time, purpose di de.sentPing[txid] = sentPing{ to: ep, at: now, - timer: time.AfterFunc(pingTimeoutDuration, func() { de.pingTimeout(txid) }), + timer: time.AfterFunc(pingTimeoutDuration, func() { de.discoPingTimeout(txid) }), purpose: purpose, } logLevel := discoLog @@ -4597,7 +4703,7 @@ func (de *endpoint) startPingLocked(ep netip.AddrPort, now mono.Time, purpose di go de.sendDiscoPing(ep, epDisco.key, txid, logLevel) } -func (de *endpoint) sendPingsLocked(now mono.Time, sendCallMeMaybe bool) { +func (de *endpoint) sendDiscoPingsLocked(now mono.Time, sendCallMeMaybe bool) { de.lastFullPing = now var sentAny bool for ep, st := range de.endpointState { @@ -4619,7 +4725,7 @@ func (de *endpoint) sendPingsLocked(now mono.Time, sendCallMeMaybe bool) { de.c.dlogf("[v1] magicsock: disco: send, starting discovery for %v (%v)", de.publicKey.ShortString(), de.discoShort()) } - de.startPingLocked(ep, now, pingDiscovery) + de.startDiscoPingLocked(ep, now, pingDiscovery) } derpAddr := de.derpAddr if sentAny && sendCallMeMaybe && derpAddr.IsValid() { @@ -4632,9 +4738,99 @@ func (de *endpoint) sendPingsLocked(now mono.Time, sendCallMeMaybe bool) { } } +// sendWireGuardOnlyPingsLocked evaluates all available addresses for +// a WireGuard only endpoint and initates an ICMP ping for useable +// addresses. +func (de *endpoint) sendWireGuardOnlyPingsLocked(now mono.Time) { + if runtime.GOOS == "js" { + return + } + + // Normally the we only send pings at a low rate as the decision to start + // sending a ping sets bestAddrAtUntil with a reasonable time to keep trying + // that address, however, if that code changed we may want to be sure that + // we don't ever send excessive pings to avoid impact to the client/user. + if !now.After(de.lastFullPing.Add(10 * time.Second)) { + return + } + de.lastFullPing = now + + for ipp := range de.endpointState { + if ipp.Addr().Is4() && de.c.noV4.Load() { + continue + } + if ipp.Addr().Is6() && de.c.noV6.Load() { + continue + } + + go de.sendWireGuardOnlyPing(ipp, now) + } +} + +// getPinger lazily instantiates a pinger and returns it, if it was +// already instantiated it returns the existing one. +func (c *Conn) getPinger() *ping.Pinger { + return c.wgPinger.Get(func() *ping.Pinger { + return ping.New(c.connCtx, c.dlogf, netns.Listener(c.logf, c.netMon)) + }) +} + +// sendWireGuardOnlyPing sends a ICMP ping to a WireGuard only address to +// discover the latency. +func (de *endpoint) sendWireGuardOnlyPing(ipp netip.AddrPort, now mono.Time) { + ctx, cancel := context.WithTimeout(de.c.connCtx, 5*time.Second) + defer cancel() + + de.setLastPing(ipp, now) + + addr := &net.IPAddr{ + IP: net.IP(ipp.Addr().AsSlice()), + Zone: ipp.Addr().Zone(), + } + + p := de.c.getPinger() + if p == nil { + de.c.logf("[v2] magicsock: sendWireGuardOnlyPingLocked: pinger is nil") + return + } + + latency, err := p.Send(ctx, addr, nil) + if err != nil { + de.c.logf("[v2] magicsock: sendWireGuardOnlyPingLocked: %s", err) + return + } + + de.mu.Lock() + defer de.mu.Unlock() + + state, ok := de.endpointState[ipp] + if !ok { + return + } + state.addPongReplyLocked(pongReply{ + latency: latency, + pongAt: now, + from: ipp, + pongSrc: netip.AddrPort{}, // We don't know this. + }) +} + +// setLastPing sets lastPing on the endpointState to now. +func (de *endpoint) setLastPing(ipp netip.AddrPort, now mono.Time) { + de.mu.Lock() + defer de.mu.Unlock() + state, ok := de.endpointState[ipp] + if !ok { + return + } + state.lastPing = now +} + +// updateFromNode updates the endpoint based on a tailcfg.Node from a NetMap +// update. func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) { if n == nil { - panic("nil node when updating disco ep") + panic("nil node when updating endpoint") } de.mu.Lock() defer de.mu.Unlock() @@ -4642,22 +4838,6 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) { de.heartbeatDisabled = heartbeatDisabled de.expired = n.Expired - // TODO(#7826): add support for more than one endpoint for pure WireGuard - // peers, and/or support for probing "bestness" for endpoints. - if n.IsWireGuardOnly { - for _, ep := range n.Endpoints { - ipp, err := netip.ParseAddrPort(ep) - if err != nil { - de.c.logf("magicsock: invalid endpoint: %s %s", ep, err) - continue - } - de.bestAddr = addrLatency{ - AddrPort: ipp, - } - break - } - } - epDisco := de.disco.Load() var discoKey key.DiscoPublic if epDisco != nil { @@ -4810,7 +4990,7 @@ func (de *endpoint) handlePongConnLocked(m *disco.Pong, di *discoInfo, src netip return false } knownTxID = true // for naked returns below - de.removeSentPingLocked(m.TxID, sp) + de.removeSentDiscoPingLocked(m.TxID, sp) now := mono.Now() latency := now.Sub(sp.at) @@ -5026,7 +5206,7 @@ func (de *endpoint) handleCallMeMaybe(m *disco.CallMeMaybe) { for _, st := range de.endpointState { st.lastPing = 0 } - de.sendPingsLocked(mono.Now(), false) + de.sendDiscoPingsLocked(mono.Now(), false) } func (de *endpoint) populatePeerStatus(ps *ipnstate.PeerStatus) { @@ -5043,7 +5223,7 @@ func (de *endpoint) populatePeerStatus(ps *ipnstate.PeerStatus) { ps.LastWrite = de.lastSend.WallTime() ps.Active = now.Sub(de.lastSend) < sessionActiveTimeout - if udpAddr, derpAddr := de.addrForSendLocked(now); udpAddr.IsValid() && !derpAddr.IsValid() { + if udpAddr, derpAddr, _ := de.addrForSendLocked(now); udpAddr.IsValid() && !derpAddr.IsValid() { ps.CurAddr = udpAddr.String() } } @@ -5086,7 +5266,7 @@ func (de *endpoint) resetLocked() { es.lastPing = 0 } for txid, sp := range de.sentPing { - de.removeSentPingLocked(txid, sp) + de.removeSentDiscoPingLocked(txid, sp) } } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 9115a3eeac7e3..dee6c8d472162 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "testing" "time" "unsafe" @@ -33,6 +34,8 @@ import ( "go4.org/mem" "golang.org/x/exp/maps" "golang.org/x/exp/slices" + "golang.org/x/net/icmp" + "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" "tailscale.com/cmd/testwrapper/flakytest" "tailscale.com/derp" @@ -42,11 +45,13 @@ import ( "tailscale.com/net/connstats" "tailscale.com/net/netaddr" "tailscale.com/net/packet" + "tailscale.com/net/ping" "tailscale.com/net/stun/stuntest" "tailscale.com/net/tstun" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/tstest/natlab" + "tailscale.com/tstime/mono" "tailscale.com/types/key" "tailscale.com/types/logger" "tailscale.com/types/netlogtype" @@ -2117,9 +2122,8 @@ func Test_batchingUDPConn_coalesceMessages(t *testing.T) { } // newWireguard starts up a new wireguard-go device attached to a test tun, and -// returns the device, tun and netpoint address. To add peers call device.IpcSet -// with UAPI instructions. -func newWireguard(t *testing.T, uapi string, aips []netip.Prefix) (*device.Device, *tuntest.ChannelTUN, netip.AddrPort) { +// returns the device, tun and endpoint port. To add peers call device.IpcSet with UAPI instructions. +func newWireguard(t *testing.T, uapi string, aips []netip.Prefix) (*device.Device, *tuntest.ChannelTUN, uint16) { wgtun := tuntest.NewChannelTUN() wglogf := func(f string, args ...any) { t.Logf("wg-go: "+f, args...) @@ -2138,8 +2142,7 @@ func newWireguard(t *testing.T, uapi string, aips []netip.Prefix) (*device.Devic t.Fatal(err) } - var wgEp netip.AddrPort - + var port uint16 s, err := wgdev.IpcGet() if err != nil { t.Fatal(err) @@ -2151,17 +2154,16 @@ func newWireguard(t *testing.T, uapi string, aips []netip.Prefix) (*device.Devic } k, v, _ := strings.Cut(line, "=") if k == "listen_port" { - wgEp = netip.MustParseAddrPort("127.0.0.1:" + v) + p, err := strconv.ParseUint(v, 10, 16) + if err != nil { + panic(err) + } + port = uint16(p) break } } - if !wgEp.IsValid() { - t.Fatalf("failed to get endpoint out of wg-go") - } - t.Logf("wg-go endpoint: %s", wgEp) - - return wgdev, wgtun, wgEp + return wgdev, wgtun, port } func TestIsWireGuardOnlyPeer(t *testing.T) { @@ -2176,8 +2178,9 @@ func TestIsWireGuardOnlyPeer(t *testing.T) { uapi := fmt.Sprintf("private_key=%s\npublic_key=%s\nallowed_ip=%s\n\n", wgkey.UntypedHexString(), tskey.Public().UntypedHexString(), tsaip.String()) - wgdev, wgtun, wgEp := newWireguard(t, uapi, []netip.Prefix{wgaip}) + wgdev, wgtun, port := newWireguard(t, uapi, []netip.Prefix{wgaip}) defer wgdev.Close() + wgEp := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), port) m := newMagicStackWithKey(t, t.Logf, localhostListener{}, derpMap, tskey) defer m.Close() @@ -2233,8 +2236,9 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) { uapi := fmt.Sprintf("private_key=%s\npublic_key=%s\nallowed_ip=%s\n\n", wgkey.UntypedHexString(), tskey.Public().UntypedHexString(), masqip.String()) - wgdev, wgtun, wgEp := newWireguard(t, uapi, []netip.Prefix{wgaip}) + wgdev, wgtun, port := newWireguard(t, uapi, []netip.Prefix{wgaip}) defer wgdev.Close() + wgEp := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), port) m := newMagicStackWithKey(t, t.Logf, localhostListener{}, derpMap, tskey) defer m.Close() @@ -2397,3 +2401,459 @@ func TestEndpointTracker(t *testing.T) { } } } + +// applyNetworkMap is a test helper that sets the network map and +// configures WG. +func applyNetworkMap(t *testing.T, m *magicStack, nm *netmap.NetworkMap) { + t.Helper() + m.conn.SetNetworkMap(nm) + // Make sure we can't use v6 to avoid test failures. + m.conn.noV6.Store(true) + + // Turn the network map into a wireguard config (for the tailscale internal wireguard device). + cfg, err := nmcfg.WGCfg(nm, t.Logf, netmap.AllowSingleHosts|netmap.AllowSubnetRoutes, "") + if err != nil { + t.Fatal(err) + } + // Apply the wireguard config to the tailscale internal wireguard device. + if err := m.Reconfig(cfg); err != nil { + t.Fatal(err) + } +} + +func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) { + clock := &tstest.Clock{} + derpMap, cleanup := runDERPAndStun(t, t.Logf, localhostListener{}, netaddr.IPv4(127, 0, 0, 1)) + defer cleanup() + + // Create a TS client. + tskey := key.NewNode() + tsaip := netip.MustParsePrefix("100.111.222.111/32") + + // Create a WireGuard only client. + wgkey := key.NewNode() + wgaip := netip.MustParsePrefix("100.222.111.222/32") + + uapi := fmt.Sprintf("private_key=%s\npublic_key=%s\nallowed_ip=%s\n\n", + wgkey.UntypedHexString(), tskey.Public().UntypedHexString(), tsaip.String()) + + wgdev, wgtun, port := newWireguard(t, uapi, []netip.Prefix{wgaip}) + defer wgdev.Close() + wgEp := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), port) + wgEp2 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.2"), port) + + m := newMagicStackWithKey(t, t.Logf, localhostListener{}, derpMap, tskey) + defer m.Close() + + pr := newPingResponder(t) + // Get a destination address which includes a port, so that UDP packets flow + // to the correct place, the mockPinger will use this to direct port-less + // pings to this place. + pingDest := pr.LocalAddr() + + // Create and start the pinger that is used for the + // wireguard only endpoint pings + p, closeP := mockPinger(t, clock, pingDest) + defer closeP() + m.conn.wgPinger.Set(p) + + // Create an IPv6 endpoint which should not receive any traffic. + v6, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.ParseIP("::"), Port: 0}) + if err != nil { + t.Fatal(err) + } + badEpRecv := make(chan []byte) + go func() { + defer v6.Close() + for { + b := make([]byte, 1500) + n, _, err := v6.ReadFrom(b) + if err != nil { + close(badEpRecv) + return + } + badEpRecv <- b[:n] + } + }() + wgEpV6 := netip.MustParseAddrPort(v6.LocalAddr().String()) + + nm := &netmap.NetworkMap{ + Name: "ts", + PrivateKey: m.privateKey, + NodeKey: m.privateKey.Public(), + Addresses: []netip.Prefix{tsaip}, + Peers: []*tailcfg.Node{ + { + Key: wgkey.Public(), + Endpoints: []string{wgEp.String(), wgEp2.String(), wgEpV6.String()}, + IsWireGuardOnly: true, + Addresses: []netip.Prefix{wgaip}, + AllowedIPs: []netip.Prefix{wgaip}, + }, + }, + } + + applyNetworkMap(t, m, nm) + + buf := tuntest.Ping(wgaip.Addr(), tsaip.Addr()) + m.tun.Outbound <- buf + + select { + case p := <-wgtun.Inbound: + if !bytes.Equal(p, buf) { + t.Errorf("got unexpected packet: %x", p) + } + case <-badEpRecv: + t.Fatal("got packet on bad endpoint") + case <-time.After(5 * time.Second): + t.Fatal("no packet after 1s") + } + + pi, ok := m.conn.peerMap.byNodeKey[wgkey.Public()] + if !ok { + t.Fatal("wgkey doesn't exist in peer map") + } + + // Check that we got a valid address set on the first send - this + // will be randomly selected, but because we have noV6 set to true, + // it will be the IPv4 address. + if !pi.ep.bestAddr.Addr().IsValid() { + t.Fatal("bestaddr was nil") + } + + if pi.ep.trustBestAddrUntil.Before(mono.Now().Add(14 * time.Second)) { + t.Errorf("trustBestAddrUntil time wasn't set to 15 seconds in the future: got %v", pi.ep.trustBestAddrUntil) + } + + for ipp, state := range pi.ep.endpointState { + if ipp == wgEp { + if len(state.recentPongs) != 1 { + t.Errorf("IPv4 address did not have a recentPong entry: got %v, want %v", len(state.recentPongs), 1) + } + // Set the latency extremely low so we choose this endpoint during the next + // addrForSendLocked call. + state.recentPongs[state.recentPong].latency = time.Nanosecond + } + + if ipp == wgEp2 { + if len(state.recentPongs) != 1 { + t.Errorf("IPv4 address did not have a recentPong entry: got %v, want %v", len(state.recentPongs), 1) + } + // Set the latency extremely high so we dont choose endpoint during the next + // addrForSendLocked call. + state.recentPongs[state.recentPong].latency = time.Second + } + + if ipp == wgEpV6 && len(state.recentPongs) != 0 { + t.Fatal("IPv6 should not have recentPong: IPv6 is not useable") + } + } + + // Set trustBestAddrUnitl to now, so addrForSendLocked goes through the + // latency selection flow. + pi.ep.trustBestAddrUntil = mono.Now().Add(-time.Second) + + buf = tuntest.Ping(wgaip.Addr(), tsaip.Addr()) + m.tun.Outbound <- buf + + select { + case p := <-wgtun.Inbound: + if !bytes.Equal(p, buf) { + t.Errorf("got unexpected packet: %x", p) + } + case <-badEpRecv: + t.Fatal("got packet on bad endpoint") + case <-time.After(5 * time.Second): + t.Fatal("no packet after 1s") + } + + // Check that we have responded to a WireGuard only ping twice. + if pr.responseCount != 2 { + t.Fatal("pingresponder response count was not 2", pr.responseCount) + } + + pi, ok = m.conn.peerMap.byNodeKey[wgkey.Public()] + if !ok { + t.Fatal("wgkey doesn't exist in peer map") + } + + if !pi.ep.bestAddr.Addr().IsValid() { + t.Error("no bestAddr address was set") + } + + if pi.ep.bestAddr.Addr() != wgEp.Addr() { + t.Errorf("bestAddr was not set to the expected IPv4 address: got %v, want %v", pi.ep.bestAddr.Addr().String(), wgEp.Addr()) + } + + if pi.ep.trustBestAddrUntil.IsZero() { + t.Fatal("trustBestAddrUntil was not set") + } + + if pi.ep.trustBestAddrUntil.Before(mono.Now().Add(55 * time.Minute)) { + // Set to 55 minutes incase of sloooow tests. + t.Errorf("trustBestAddrUntil time wasn't set to an hour in the future: got %v", pi.ep.trustBestAddrUntil) + } +} + +// udpingPacketConn will convert potentially ICMP destination addrs to UDP +// destination addrs in WriteTo so that a test that is intending to send ICMP +// traffic will instead send UDP traffic, without the higher level Pinger being +// aware of this difference. +type udpingPacketConn struct { + net.PacketConn + // destPort will be configured by the test to be the peer expected to respond to a ping. + destPort uint16 +} + +func (u *udpingPacketConn) WriteTo(body []byte, dest net.Addr) (int, error) { + switch d := dest.(type) { + case *net.IPAddr: + udpAddr := &net.UDPAddr{ + IP: d.IP, + Port: int(u.destPort), + Zone: d.Zone, + } + return u.PacketConn.WriteTo(body, udpAddr) + } + return 0, fmt.Errorf("unimplemented udpingPacketConn for %T", dest) +} + +type mockListenPacketer struct { + conn4 net.PacketConn + conn6 net.PacketConn +} + +func (mlp *mockListenPacketer) ListenPacket(ctx context.Context, typ string, addr string) (net.PacketConn, error) { + switch typ { + case "ip4:icmp": + return mlp.conn4, nil + case "ip6:icmp": + return mlp.conn6, nil + } + return nil, fmt.Errorf("unimplemented ListenPacketForTesting for %s", typ) +} + +func mockPinger(t *testing.T, clock *tstest.Clock, dest net.Addr) (*ping.Pinger, func()) { + ctx := context.Background() + + dIPP := netip.MustParseAddrPort(dest.String()) + // In tests, we use UDP so that we can test without being root; this + // doesn't matter because we mock out the ICMP reply below to be a real + // ICMP echo reply packet. + conn4, err := net.ListenPacket("udp4", "127.0.0.1:0") + if err != nil { + t.Fatalf("net.ListenPacket: %v", err) + } + conn6, err := net.ListenPacket("udp6", "[::]:0") + if err != nil { + t.Fatalf("net.ListenPacket: %v", err) + } + + conn4 = &udpingPacketConn{ + PacketConn: conn4, + destPort: dIPP.Port(), + } + + conn6 = &udpingPacketConn{ + PacketConn: conn6, + destPort: dIPP.Port(), + } + + p := ping.New(ctx, t.Logf, &mockListenPacketer{conn4: conn4, conn6: conn6}) + + done := func() { + if err := p.Close(); err != nil { + t.Errorf("error on close: %v", err) + } + } + + return p, done +} + +type pingResponder struct { + net.PacketConn + running atomic.Bool + responseCount int +} + +func (p *pingResponder) start() { + buf := make([]byte, 1500) + for p.running.Load() { + n, addr, err := p.PacketConn.ReadFrom(buf) + if err != nil { + return + } + + m, err := icmp.ParseMessage(1, buf[:n]) + if err != nil { + panic("got a non-ICMP message:" + fmt.Sprintf("%x", m)) + } + + r := icmp.Message{ + Type: ipv4.ICMPTypeEchoReply, + Code: m.Code, + Body: m.Body, + } + + b, err := r.Marshal(nil) + if err != nil { + panic(err) + } + + if _, err := p.PacketConn.WriteTo(b, addr); err != nil { + panic(err) + } + p.responseCount++ + } +} + +func (p *pingResponder) stop() { + p.running.Store(false) + p.Close() +} + +func newPingResponder(t *testing.T) *pingResponder { + t.Helper() + // global binds should be both IPv4 and IPv6 (if our test platforms don't, + // we might need to bind two sockets instead) + conn, err := net.ListenPacket("udp", ":") + if err != nil { + t.Fatal(err) + } + pr := &pingResponder{PacketConn: conn} + pr.running.Store(true) + go pr.start() + t.Cleanup(pr.stop) + return pr +} + +func TestAddrForSendLockedForWireGuardOnly(t *testing.T) { + testTime := mono.Now() + + type endpointDetails struct { + addrPort netip.AddrPort + latency time.Duration + } + + wgTests := []struct { + name string + noV4 bool + noV6 bool + sendWGPing bool + ep []endpointDetails + want netip.AddrPort + }{ + { + name: "choose lowest latency for useable IPv4 and IPv6", + sendWGPing: true, + ep: []endpointDetails{ + { + addrPort: netip.MustParseAddrPort("1.1.1.1:111"), + latency: 100 * time.Millisecond, + }, + { + addrPort: netip.MustParseAddrPort("[2345:0425:2CA1:0000:0000:0567:5673:23b5]:222"), + latency: 10 * time.Millisecond, + }, + }, + want: netip.MustParseAddrPort("[2345:0425:2CA1:0000:0000:0567:5673:23b5]:222"), + }, + { + name: "choose IPv4 when IPv6 is not useable", + sendWGPing: false, + noV6: true, + ep: []endpointDetails{ + { + addrPort: netip.MustParseAddrPort("1.1.1.1:111"), + latency: 100 * time.Millisecond, + }, + { + addrPort: netip.MustParseAddrPort("[1::1]:567"), + }, + }, + want: netip.MustParseAddrPort("1.1.1.1:111"), + }, + { + name: "choose IPv6 when IPv4 is not useable", + sendWGPing: false, + noV4: true, + ep: []endpointDetails{ + { + addrPort: netip.MustParseAddrPort("1.1.1.1:111"), + }, + { + addrPort: netip.MustParseAddrPort("[1::1]:567"), + latency: 100 * time.Millisecond, + }, + }, + want: netip.MustParseAddrPort("[1::1]:567"), + }, + { + name: "choose IPv6 address when latency is the same for v4 and v6", + sendWGPing: true, + ep: []endpointDetails{ + { + addrPort: netip.MustParseAddrPort("1.1.1.1:111"), + latency: 100 * time.Millisecond, + }, + { + addrPort: netip.MustParseAddrPort("[1::1]:567"), + latency: 100 * time.Millisecond, + }, + }, + want: netip.MustParseAddrPort("[1::1]:567"), + }, + } + + for _, test := range wgTests { + endpoint := &endpoint{ + isWireguardOnly: true, + endpointState: map[netip.AddrPort]*endpointState{}, + c: &Conn{ + noV4: atomic.Bool{}, + noV6: atomic.Bool{}, + }, + } + endpoint.c.noV4.Store(test.noV4) + endpoint.c.noV6.Store(test.noV6) + + for _, epd := range test.ep { + endpoint.endpointState[epd.addrPort] = &endpointState{} + } + + udpAddr, _, shouldPing := endpoint.addrForSendLocked(testTime) + if !udpAddr.IsValid() { + t.Error("udpAddr returned is not valid") + } + if shouldPing != test.sendWGPing { + t.Errorf("addrForSendLocked did not indiciate correct ping state; got %v, want %v", shouldPing, test.sendWGPing) + } + + for _, epd := range test.ep { + state, ok := endpoint.endpointState[epd.addrPort] + if !ok { + t.Errorf("addr does not exist in endpoint state map") + } + + latency, ok := state.latencyLocked() + if ok { + t.Errorf("latency was set for %v: %v", epd.addrPort, latency) + } + state.recentPongs = append(state.recentPongs, pongReply{ + latency: epd.latency, + }) + state.recentPong = 0 + } + + udpAddr, _, shouldPing = endpoint.addrForSendLocked(testTime.Add(2 * time.Minute)) + if udpAddr != test.want { + t.Errorf("udpAddr returned is not expected: got %v, want %v", udpAddr, test.want) + } + if shouldPing { + t.Error("addrForSendLocked should not indicate ping is required") + } + if endpoint.bestAddr.AddrPort != test.want { + t.Errorf("bestAddr.AddrPort is not as expected: got %v, want %v", endpoint.bestAddr.AddrPort, test.want) + } + } +} From 4d7927047c1883b88cf822e5cb6037cc3c002f54 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 3 May 2023 14:56:51 -0700 Subject: [PATCH 053/331] wgengine/magicsock: annotate, skip flaky TestIsWireGuardOnlyPickEndpointByPing Updates #8037 Updates #7826 Signed-off-by: Brad Fitzpatrick --- wgengine/magicsock/magicsock_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index dee6c8d472162..f2f4a76adcb2e 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -2422,6 +2422,8 @@ func applyNetworkMap(t *testing.T, m *magicStack, nm *netmap.NetworkMap) { } func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) { + t.Skip("This test is flaky; see https://github.com/tailscale/tailscale/issues/8037") + clock := &tstest.Clock{} derpMap, cleanup := runDERPAndStun(t, t.Logf, localhostListener{}, netaddr.IPv4(127, 0, 0, 1)) defer cleanup() From be190e990faf9faeb7e347b9681cff3e6b4c5e52 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Tue, 2 May 2023 12:48:51 -0700 Subject: [PATCH 054/331] ssh/tailssh: restore support for recording locally We removed it earlier in 916aa782af5d43ccfa92f6245201796df212fb8a, but we still want to support it for some time longer. Updates tailscale/corp#9967 Signed-off-by: Maisem Ali --- ssh/tailssh/tailssh.go | 96 ++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 32 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 2ba20e00c7e72..27437901cc453 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -67,6 +67,7 @@ type ipnLocalBackend interface { WhoIs(ipp netip.AddrPort) (n *tailcfg.Node, u tailcfg.UserProfile, ok bool) DoNoiseRequest(req *http.Request) (*http.Response, error) Dialer() *tsdial.Dialer + TailscaleVarRoot() string } type server struct { @@ -1154,6 +1155,11 @@ func (ss *sshSession) run() { return } +// recordSSHToLocalDisk is a deprecated dev knob to allow recording SSH sessions +// to local storage. It is only used if there is no recording configured by the +// coordination server. This will be removed in the future. +var recordSSHToLocalDisk = envknob.RegisterBool("TS_DEBUG_LOG_SSH") + // recorders returns the list of recorders to use for this session. // If the final action has a non-empty list of recorders, that list is // returned. Otherwise, the list of recorders from the initial action @@ -1167,7 +1173,7 @@ func (ss *sshSession) recorders() ([]netip.AddrPort, *tailcfg.SSHRecorderFailure func (ss *sshSession) shouldRecord() bool { recs, _ := ss.recorders() - return len(recs) > 0 + return len(recs) > 0 || recordSSHToLocalDisk() } type sshConnInfo struct { @@ -1510,12 +1516,33 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo return nil, nil, multierr.New(errs...) } +func (ss *sshSession) openFileForRecording(now time.Time) (_ io.WriteCloser, err error) { + varRoot := ss.conn.srv.lb.TailscaleVarRoot() + if varRoot == "" { + return nil, errors.New("no var root for recording storage") + } + dir := filepath.Join(varRoot, "ssh-sessions") + if err := os.MkdirAll(dir, 0700); err != nil { + return nil, err + } + f, err := os.CreateTemp(dir, fmt.Sprintf("ssh-session-%v-*.cast", now.UnixNano())) + if err != nil { + return nil, err + } + return f, nil +} + // startNewRecording starts a new SSH session recording. // It may return a nil recording if recording is not available. func (ss *sshSession) startNewRecording() (_ *recording, err error) { recorders, onFailure := ss.recorders() + var localRecording bool if len(recorders) == 0 { - return nil, errors.New("no recorders configured") + if recordSSHToLocalDisk() { + localRecording = true + } else { + return nil, errors.New("no recorders configured") + } } var w ssh.Window @@ -1539,40 +1566,45 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { // ss.ctx is closed when the session closes, but we don't want to break the upload at that time. // Instead we want to wait for the session to close the writer when it finishes. ctx := context.Background() - wc, errChan, err := ss.connectToRecorder(ctx, recorders) - if err != nil { - // TODO(catzkorn): notify control here. - if onFailure != nil && onFailure.RejectSessionWithMessage != "" { - ss.logf("recording: error starting recording (rejecting session): %v", err) - return nil, userVisibleError{ - error: err, - msg: onFailure.RejectSessionWithMessage, + if localRecording { + rec.out, err = ss.openFileForRecording(now) + if err != nil { + return nil, err + } + } else { + var errChan <-chan error + rec.out, errChan, err = ss.connectToRecorder(ctx, recorders) + if err != nil { + // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.RejectSessionWithMessage != "" { + ss.logf("recording: error starting recording (rejecting session): %v", err) + return nil, userVisibleError{ + error: err, + msg: onFailure.RejectSessionWithMessage, + } } + ss.logf("recording: error starting recording (failing open): %v", err) + return nil, nil } - ss.logf("recording: error starting recording (failing open): %v", err) - return nil, nil + go func() { + err := <-errChan + if err == nil { + // Success. + return + } + // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.TerminateSessionWithMessage != "" { + ss.logf("recording: error uploading recording (closing session): %v", err) + ss.cancelCtx(userVisibleError{ + error: err, + msg: onFailure.TerminateSessionWithMessage, + }) + return + } + ss.logf("recording: error uploading recording (failing open): %v", err) + }() } - go func() { - err := <-errChan - if err == nil { - // Success. - return - } - // TODO(catzkorn): notify control here. - if onFailure != nil && onFailure.TerminateSessionWithMessage != "" { - ss.logf("recording: error uploading recording (closing session): %v", err) - ss.cancelCtx(userVisibleError{ - error: err, - msg: onFailure.TerminateSessionWithMessage, - }) - return - } - ss.logf("recording: error uploading recording (failing open): %v", err) - }() - - rec.out = wc - ch := CastHeader{ Version: 2, Width: w.Width, From 270942094f7f6ec94a88894022695044c79dfc91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 22:39:42 +0000 Subject: [PATCH 055/331] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.16+incompatible to 20.10.24+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v20.10.16...v20.10.24) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cb14d881719f2..7d128815ae926 100644 --- a/go.mod +++ b/go.mod @@ -154,7 +154,7 @@ require ( github.com/denis-tingaikin/go-header v0.4.3 // indirect github.com/docker/cli v20.10.16+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.16+incompatible // indirect + github.com/docker/docker v20.10.24+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/emirpasic/gods v1.12.0 // indirect diff --git a/go.sum b/go.sum index 78a7afd4a4a18..7c2a3cb6a74ac 100644 --- a/go.sum +++ b/go.sum @@ -300,8 +300,8 @@ github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61 github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= -github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= From 7675d323fa7560bd402134482f17632f4719fc60 Mon Sep 17 00:00:00 2001 From: License Updater Date: Wed, 3 May 2023 22:42:00 +0000 Subject: [PATCH 056/331] licenses: update tailscale{,d} licenses Signed-off-by: License Updater --- licenses/tailscale.md | 1 + 1 file changed, 1 insertion(+) diff --git a/licenses/tailscale.md b/licenses/tailscale.md index 38a55a0b56083..8ab16f946b557 100644 --- a/licenses/tailscale.md +++ b/licenses/tailscale.md @@ -80,6 +80,7 @@ Some packages may only be included on certain architectures or operating systems - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47842c84:LICENSE)) - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) + - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.5.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) From 459744c9ea96b5ea4e63e0ca0c07182108867ed7 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Wed, 3 May 2023 18:36:19 -0700 Subject: [PATCH 057/331] .github: mark bots for exemption by issuebot (#8041) #cleanup Change-Id: I13757ee20240166af72606d166e840ae3ee797d7 Signed-off-by: M. J. Fromberger --- .github/workflows/go-licenses.yml | 4 ++-- .github/workflows/update-flake.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-licenses.yml b/.github/workflows/go-licenses.yml index c1bd05ec1dd8e..2912aa61620b6 100644 --- a/.github/workflows/go-licenses.yml +++ b/.github/workflows/go-licenses.yml @@ -53,8 +53,8 @@ jobs: uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 #v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} - author: License Updater - committer: License Updater + author: License Updater + committer: License Updater branch: licenses/cli commit-message: "licenses: update tailscale{,d} licenses" title: "licenses: update tailscale{,d} licenses" diff --git a/.github/workflows/update-flake.yml b/.github/workflows/update-flake.yml index 6d6dee2b72772..0c63cf4f588d7 100644 --- a/.github/workflows/update-flake.yml +++ b/.github/workflows/update-flake.yml @@ -38,8 +38,8 @@ jobs: uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5 #v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} - author: Flakes Updater - committer: Flakes Updater + author: Flakes Updater + committer: Flakes Updater branch: flakes commit-message: "go.mod.sri: update SRI hash for go.mod changes" title: "go.mod.sri: update SRI hash for go.mod changes" From 9e9ea6e974dd8acae827d22f46f4c1e8045ba501 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 3 May 2023 19:14:12 -0700 Subject: [PATCH 058/331] go.mod: bump all deps possible that don't break the build This holds back gvisor, kubernetes, goreleaser, and esbuild, which all had breaking API changes. Updates #8043 Updates #7381 Updates #8042 (updates u-root which adds deps) Change-Id: I889759bea057cd3963037d41f608c99eb7466a5b Signed-off-by: Brad Fitzpatrick --- cmd/derper/depaware.txt | 5 +- cmd/tailscale/depaware.txt | 2 + cmd/tailscaled/depaware.txt | 22 +- go.mod | 257 +++++----- go.sum | 972 +++++++++++------------------------- 5 files changed, 446 insertions(+), 812 deletions(-) diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index b40ca360a95bc..d6562fb759f24 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -3,7 +3,9 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa filippo.io/edwards25519 from github.com/hdevalence/ed25519consensus filippo.io/edwards25519/field from filippo.io/edwards25519 W 💣 github.com/Microsoft/go-winio from tailscale.com/safesocket + W 💣 github.com/Microsoft/go-winio/internal/fs from github.com/Microsoft/go-winio W 💣 github.com/Microsoft/go-winio/internal/socket from github.com/Microsoft/go-winio + W github.com/Microsoft/go-winio/internal/stringbuffer from github.com/Microsoft/go-winio/internal/fs W github.com/Microsoft/go-winio/pkg/guid from github.com/Microsoft/go-winio+ W 💣 github.com/alexbrainman/sspi from github.com/alexbrainman/sspi/internal/common+ W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate @@ -13,7 +15,6 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa github.com/fxamacker/cbor/v2 from tailscale.com/tka github.com/golang/groupcache/lru from tailscale.com/net/dnscache github.com/golang/protobuf/proto from github.com/matttproud/golang_protobuf_extensions/pbutil+ - github.com/golang/protobuf/ptypes/timestamp from github.com/prometheus/client_model/go github.com/hdevalence/ed25519consensus from tailscale.com/tka L github.com/josharian/native from github.com/mdlayher/netlink+ L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces+ @@ -64,7 +65,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa google.golang.org/protobuf/runtime/protoiface from github.com/golang/protobuf/proto+ google.golang.org/protobuf/runtime/protoimpl from github.com/golang/protobuf/proto+ google.golang.org/protobuf/types/descriptorpb from google.golang.org/protobuf/reflect/protodesc - google.golang.org/protobuf/types/known/timestamppb from github.com/golang/protobuf/ptypes/timestamp+ + google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+ nhooyr.io/websocket from tailscale.com/cmd/derper+ nhooyr.io/websocket/internal/errd from nhooyr.io/websocket nhooyr.io/websocket/internal/xsync from nhooyr.io/websocket diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index b7ce9c4015a3e..72444a2a24d1f 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -3,7 +3,9 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep filippo.io/edwards25519 from github.com/hdevalence/ed25519consensus filippo.io/edwards25519/field from filippo.io/edwards25519 W 💣 github.com/Microsoft/go-winio from tailscale.com/safesocket + W 💣 github.com/Microsoft/go-winio/internal/fs from github.com/Microsoft/go-winio W 💣 github.com/Microsoft/go-winio/internal/socket from github.com/Microsoft/go-winio + W github.com/Microsoft/go-winio/internal/stringbuffer from github.com/Microsoft/go-winio/internal/fs W github.com/Microsoft/go-winio/pkg/guid from github.com/Microsoft/go-winio+ W 💣 github.com/alexbrainman/sspi from github.com/alexbrainman/sspi/negotiate+ W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 16c8c6bba73c9..58f61e60ed60b 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -3,7 +3,9 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de filippo.io/edwards25519 from github.com/hdevalence/ed25519consensus filippo.io/edwards25519/field from filippo.io/edwards25519 W 💣 github.com/Microsoft/go-winio from tailscale.com/safesocket + W 💣 github.com/Microsoft/go-winio/internal/fs from github.com/Microsoft/go-winio W 💣 github.com/Microsoft/go-winio/internal/socket from github.com/Microsoft/go-winio + W github.com/Microsoft/go-winio/internal/stringbuffer from github.com/Microsoft/go-winio/internal/fs W github.com/Microsoft/go-winio/pkg/guid from github.com/Microsoft/go-winio+ W 💣 github.com/alexbrainman/sspi from github.com/alexbrainman/sspi/internal/common+ W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate @@ -12,7 +14,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2 from github.com/aws/aws-sdk-go-v2/internal/ini L github.com/aws/aws-sdk-go-v2/aws from github.com/aws/aws-sdk-go-v2/aws/middleware+ L github.com/aws/aws-sdk-go-v2/aws/arn from tailscale.com/ipn/store/awsstore - L github.com/aws/aws-sdk-go-v2/aws/defaults from github.com/aws/aws-sdk-go-v2/service/ssm + L github.com/aws/aws-sdk-go-v2/aws/defaults from github.com/aws/aws-sdk-go-v2/service/ssm+ L github.com/aws/aws-sdk-go-v2/aws/middleware from github.com/aws/aws-sdk-go-v2/aws/retry+ L github.com/aws/aws-sdk-go-v2/aws/protocol/query from github.com/aws/aws-sdk-go-v2/service/sts L github.com/aws/aws-sdk-go-v2/aws/protocol/restjson from github.com/aws/aws-sdk-go-v2/service/ssm+ @@ -38,6 +40,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2/internal/rand from github.com/aws/aws-sdk-go-v2/aws+ L github.com/aws/aws-sdk-go-v2/internal/sdk from github.com/aws/aws-sdk-go-v2/aws+ L github.com/aws/aws-sdk-go-v2/internal/sdkio from github.com/aws/aws-sdk-go-v2/credentials/processcreds + L github.com/aws/aws-sdk-go-v2/internal/shareddefaults from github.com/aws/aws-sdk-go-v2/config+ L github.com/aws/aws-sdk-go-v2/internal/strings from github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4 L github.com/aws/aws-sdk-go-v2/internal/sync/singleflight from github.com/aws/aws-sdk-go-v2/aws L github.com/aws/aws-sdk-go-v2/internal/timeconv from github.com/aws/aws-sdk-go-v2/aws/retry @@ -48,16 +51,19 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/aws/aws-sdk-go-v2/service/sso from github.com/aws/aws-sdk-go-v2/config+ L github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sso L github.com/aws/aws-sdk-go-v2/service/sso/types from github.com/aws/aws-sdk-go-v2/service/sso + L github.com/aws/aws-sdk-go-v2/service/ssooidc from github.com/aws/aws-sdk-go-v2/config+ + L github.com/aws/aws-sdk-go-v2/service/ssooidc/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/ssooidc + L github.com/aws/aws-sdk-go-v2/service/ssooidc/types from github.com/aws/aws-sdk-go-v2/service/ssooidc L github.com/aws/aws-sdk-go-v2/service/sts from github.com/aws/aws-sdk-go-v2/config+ L github.com/aws/aws-sdk-go-v2/service/sts/internal/endpoints from github.com/aws/aws-sdk-go-v2/service/sts L github.com/aws/aws-sdk-go-v2/service/sts/types from github.com/aws/aws-sdk-go-v2/credentials/stscreds+ L github.com/aws/smithy-go from github.com/aws/aws-sdk-go-v2/aws/protocol/restjson+ - L github.com/aws/smithy-go/auth/bearer from github.com/aws/aws-sdk-go-v2/aws + L github.com/aws/smithy-go/auth/bearer from github.com/aws/aws-sdk-go-v2/aws+ L github.com/aws/smithy-go/context from github.com/aws/smithy-go/auth/bearer L github.com/aws/smithy-go/document from github.com/aws/aws-sdk-go-v2/service/ssm+ L github.com/aws/smithy-go/encoding from github.com/aws/smithy-go/encoding/json+ L github.com/aws/smithy-go/encoding/httpbinding from github.com/aws/aws-sdk-go-v2/aws/protocol/query+ - L github.com/aws/smithy-go/encoding/json from github.com/aws/aws-sdk-go-v2/service/ssm + L github.com/aws/smithy-go/encoding/json from github.com/aws/aws-sdk-go-v2/service/ssm+ L github.com/aws/smithy-go/encoding/xml from github.com/aws/aws-sdk-go-v2/service/sts L github.com/aws/smithy-go/internal/sync/singleflight from github.com/aws/smithy-go/auth/bearer L github.com/aws/smithy-go/io from github.com/aws/aws-sdk-go-v2/feature/ec2/imds+ @@ -73,6 +79,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de LD 💣 github.com/creack/pty from tailscale.com/ssh/tailssh W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com W 💣 github.com/dblohm7/wingoes/com from tailscale.com/cmd/tailscaled + W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com github.com/fxamacker/cbor/v2 from tailscale.com/tka W 💣 github.com/go-ole/go-ole from github.com/go-ole/go-ole/oleutil+ W 💣 github.com/go-ole/go-ole/oleutil from tailscale.com/wgengine/winnet @@ -93,7 +100,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de github.com/klauspost/compress/flate from nhooyr.io/websocket github.com/klauspost/compress/fse from github.com/klauspost/compress/huff0 github.com/klauspost/compress/huff0 from github.com/klauspost/compress/zstd - github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/zstd + github.com/klauspost/compress/internal/cpuinfo from github.com/klauspost/compress/zstd+ github.com/klauspost/compress/internal/snapref from github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd from tailscale.com/smallzstd github.com/klauspost/compress/zstd/internal/xxhash from github.com/klauspost/compress/zstd @@ -105,12 +112,17 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/mdlayher/sdnotify from tailscale.com/util/systemd L 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink 💣 github.com/mitchellh/go-ps from tailscale.com/safesocket + L github.com/pierrec/lz4/v4 from github.com/u-root/uio/uio + L github.com/pierrec/lz4/v4/internal/lz4block from github.com/pierrec/lz4/v4+ + L github.com/pierrec/lz4/v4/internal/lz4errors from github.com/pierrec/lz4/v4+ + L github.com/pierrec/lz4/v4/internal/lz4stream from github.com/pierrec/lz4/v4 + L github.com/pierrec/lz4/v4/internal/xxh32 from github.com/pierrec/lz4/v4/internal/lz4stream W github.com/pkg/errors from github.com/tailscale/certstore LD github.com/pkg/sftp from tailscale.com/ssh/tailssh LD github.com/pkg/sftp/internal/encoding/ssh/filexfer from github.com/pkg/sftp W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient LD github.com/tailscale/golang-x-crypto/chacha20 from github.com/tailscale/golang-x-crypto/ssh - LD 💣 github.com/tailscale/golang-x-crypto/internal/subtle from github.com/tailscale/golang-x-crypto/chacha20 + LD 💣 github.com/tailscale/golang-x-crypto/internal/alias from github.com/tailscale/golang-x-crypto/chacha20 LD github.com/tailscale/golang-x-crypto/ssh from tailscale.com/ipn/ipnlocal+ LD github.com/tailscale/golang-x-crypto/ssh/internal/bcrypt_pbkdf from github.com/tailscale/golang-x-crypto/ssh github.com/tailscale/goupnp from github.com/tailscale/goupnp/dcps/internetgateway2+ diff --git a/go.mod b/go.mod index 7d128815ae926..240da148459c0 100644 --- a/go.mod +++ b/go.mod @@ -3,93 +3,93 @@ module tailscale.com go 1.20 require ( - filippo.io/mkcert v1.4.3 - github.com/Microsoft/go-winio v0.6.0 + filippo.io/mkcert v1.4.4 + github.com/Microsoft/go-winio v0.6.1 github.com/akutz/memconn v0.1.0 github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 - github.com/andybalholm/brotli v1.0.3 + github.com/andybalholm/brotli v1.0.5 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be - github.com/aws/aws-sdk-go-v2 v1.17.3 - github.com/aws/aws-sdk-go-v2/config v1.11.0 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0 - github.com/aws/aws-sdk-go-v2/service/ssm v1.35.0 + github.com/aws/aws-sdk-go-v2 v1.18.0 + github.com/aws/aws-sdk-go-v2/config v1.18.22 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 + github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0 + github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 github.com/coreos/go-iptables v0.6.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf - github.com/creack/pty v1.1.17 - github.com/dave/jennifer v1.4.1 - github.com/dblohm7/wingoes v0.0.0-20221124203957-6ac47ab19aa5 + github.com/creack/pty v1.1.18 + github.com/dave/jennifer v1.6.1 + github.com/dblohm7/wingoes v0.0.0-20230426155039-111c8c3b57c8 github.com/dsnet/try v0.0.3 github.com/evanw/esbuild v0.14.53 - github.com/frankban/quicktest v1.14.3 + github.com/frankban/quicktest v1.14.5 github.com/fxamacker/cbor/v2 v2.4.0 - github.com/go-json-experiment/json v0.0.0-20221017203807-c5ed296b8c92 + github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929 github.com/go-logr/zapr v1.2.3 github.com/go-ole/go-ole v1.2.6 - github.com/godbus/dbus/v5 v5.0.6 + github.com/godbus/dbus/v5 v5.1.0 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/golangci/golangci-lint v1.52.2 github.com/google/go-cmp v0.5.9 - github.com/google/go-containerregistry v0.9.0 + github.com/google/go-containerregistry v0.14.0 github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c github.com/google/uuid v1.3.0 github.com/goreleaser/nfpm v1.10.3 - github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 + github.com/hdevalence/ed25519consensus v0.1.0 github.com/iancoleman/strcase v0.2.0 github.com/illarion/gonotify v1.0.1 - github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8 + github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 - github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b + github.com/jsimonetti/rtnetlink v1.3.2 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/klauspost/compress v1.15.4 + github.com/klauspost/compress v1.16.5 github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a github.com/mattn/go-colorable v0.1.13 - github.com/mattn/go-isatty v0.0.17 - github.com/mdlayher/genetlink v1.2.0 - github.com/mdlayher/netlink v1.7.1 + github.com/mattn/go-isatty v0.0.18 + github.com/mdlayher/genetlink v1.3.2 + github.com/mdlayher/netlink v1.7.2 github.com/mdlayher/sdnotify v1.0.0 - github.com/miekg/dns v1.1.43 + github.com/miekg/dns v1.1.54 github.com/mitchellh/go-ps v1.0.0 - github.com/peterbourgon/ff/v3 v3.1.2 + github.com/peterbourgon/ff/v3 v3.3.0 github.com/pkg/errors v0.9.1 - github.com/pkg/sftp v1.13.4 - github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/common v0.41.0 + github.com/pkg/sftp v1.13.5 + github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/common v0.42.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41 - github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17 + github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 - github.com/tailscale/hujson v0.0.0-20220630195928-54599719472f + github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a github.com/tailscale/mkctr v0.0.0-20220601142259-c0b937af2e89 github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd - github.com/tc-hib/winres v0.1.6 + github.com/tc-hib/winres v0.2.0 github.com/tcnksm/go-httpstat v0.2.0 github.com/toqueteos/webbrowser v1.2.0 - github.com/u-root/u-root v0.9.1-0.20230109201855-948a78c969ad - github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 + github.com/u-root/u-root v0.11.0 + github.com/vishvananda/netlink v1.2.1-beta.2 go.uber.org/zap v1.24.0 - go4.org/mem v0.0.0-20210711025021-927187094b94 - go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf - golang.org/x/crypto v0.6.0 - golang.org/x/exp v0.0.0-20221205204356-47842c84f3db - golang.org/x/mod v0.9.0 - golang.org/x/net v0.8.0 - golang.org/x/oauth2 v0.5.0 + go4.org/mem v0.0.0-20220726221520-4f986261bf13 + go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 + golang.org/x/crypto v0.8.0 + golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 + golang.org/x/mod v0.10.0 + golang.org/x/net v0.9.0 + golang.org/x/oauth2 v0.7.0 golang.org/x/sync v0.1.0 - golang.org/x/sys v0.6.0 - golang.org/x/term v0.6.0 - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 - golang.org/x/tools v0.7.0 + golang.org/x/sys v0.7.0 + golang.org/x/term v0.7.0 + golang.org/x/time v0.3.0 + golang.org/x/tools v0.8.0 golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 golang.zx2c4.com/wireguard/windows v0.5.3 gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d honnef.co/go/tools v0.4.3 inet.af/peercred v0.0.0-20210906144145-0893ea02156a inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 - inet.af/wf v0.0.0-20220728202103-50d96caab2f6 + inet.af/wf v0.0.0-20221017222439-36129f591884 k8s.io/api v0.25.0 k8s.io/apimachinery v0.25.0 k8s.io/client-go v0.25.0 @@ -102,37 +102,38 @@ require ( require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.1 // indirect - filippo.io/edwards25519 v1.0.0-rc.1 // indirect + filippo.io/edwards25519 v1.0.0 // indirect github.com/Abirdcfly/dupword v0.0.11 // indirect github.com/Antonboom/errname v0.1.9 // indirect - github.com/Antonboom/nilnil v0.1.3 // indirect + github.com/Antonboom/nilnil v0.1.4 // indirect github.com/BurntSushi/toml v1.2.1 // indirect github.com/Djarvur/go-err113 v0.1.0 // indirect github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/OpenPeeDeeP/depguard v1.1.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/ashanbrown/forbidigo v1.5.1 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.6.4 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.0 // indirect @@ -141,41 +142,40 @@ require ( github.com/bombsimon/wsl/v3 v3.4.0 // indirect github.com/breml/bidichk v0.2.4 // indirect github.com/breml/errchkjson v0.3.1 // indirect - github.com/butuzov/ireturn v0.1.1 // indirect - github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e // indirect + github.com/butuzov/ireturn v0.2.0 // indirect + github.com/cavaliergopher/cpio v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect - github.com/cloudflare/circl v1.1.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.11.4 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect github.com/daixiang0/gci v0.10.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect - github.com/docker/cli v20.10.16+incompatible // indirect + github.com/docker/cli v23.0.5+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.24+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.4 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/emirpasic/gods v1.12.0 // indirect + github.com/docker/docker v23.0.5+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/esimonov/ifshort v1.0.4 // indirect github.com/ettle/strcase v0.1.1 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/gliderlabs/ssh v0.3.3 // indirect - github.com/go-critic/go-critic v0.7.0 // indirect + github.com/go-critic/go-critic v0.8.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.3.1 // indirect - github.com/go-git/go-git/v5 v5.4.2 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-git/go-billy/v5 v5.4.1 // indirect + github.com/go-git/go-git/v5 v5.6.1 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.1.0 // indirect @@ -187,7 +187,7 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect @@ -197,11 +197,11 @@ require ( github.com/golangci/misspell v0.4.0 // indirect github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/btree v1.0.1 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 // indirect - github.com/google/rpmpack v0.0.0-20201206194719-59e495f2b7e1 // indirect + github.com/google/rpmpack v0.0.0-20221120200012-98b63d62fd77 // indirect github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect github.com/goreleaser/chglog v0.1.2 // indirect github.com/goreleaser/fileglob v0.3.1 // indirect @@ -214,9 +214,9 @@ require ( github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/huandu/xstrings v1.4.0 // indirect + github.com/imdario/mergo v0.3.15 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jgautheron/goconst v1.5.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect @@ -226,10 +226,11 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julz/importas v0.1.0 // indirect github.com/junk1tm/musttag v0.5.0 // indirect - github.com/kevinburke/ssh_config v1.1.0 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kisielk/errcheck v1.6.3 // indirect github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/fs v0.1.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -237,18 +238,18 @@ require ( github.com/kunwardeep/paralleltest v1.0.6 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.4.0 // indirect + github.com/ldez/tagliatelle v0.5.0 // indirect github.com/leonklingele/grouper v1.1.1 // indirect github.com/lufeee/execinquery v1.2.1 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mdlayher/socket v0.4.0 // indirect + github.com/mdlayher/socket v0.4.1 // indirect github.com/mgechev/revive v1.3.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -261,75 +262,77 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/nishanths/exhaustive v0.9.5 // indirect + github.com/nishanths/exhaustive v0.10.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.9.0 // indirect + github.com/nunnatsa/ginkgolinter v0.11.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/pelletier/go-toml/v2 v2.0.7 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.4.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect + github.com/polyfloyd/go-errorlint v1.4.1 // indirect + github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/quasilyte/go-ruleguard v0.3.19 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/rivo/uniseg v0.2.0 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect - github.com/sassoftware/go-rpmutils v0.1.0 // indirect + github.com/sassoftware/go-rpmutils v0.2.0 // indirect github.com/securego/gosec/v2 v2.15.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect + github.com/sergi/go-diff v1.3.1 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.0 // indirect - github.com/sivchari/containedctx v1.0.2 // indirect + github.com/sivchari/containedctx v1.0.3 // indirect github.com/sivchari/nosnakecase v1.7.0 // indirect github.com/sivchari/tenv v1.7.1 // indirect + github.com/skeema/knownhosts v1.1.0 // indirect github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.6.1 // indirect + github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.12.0 // indirect + github.com/spf13/viper v1.15.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/testify v1.8.2 // indirect - github.com/subosito/gotenv v1.4.1 // indirect + github.com/subosito/gotenv v1.4.2 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect github.com/tetafro/godot v1.4.11 // indirect - github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e // indirect + github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect - github.com/u-root/uio v0.0.0-20221213070652-c3537552635f // indirect - github.com/ulikunitz/xz v0.5.10 // indirect + github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect github.com/uudashr/gocognit v1.0.6 // indirect github.com/vbatts/tar-split v0.11.2 // indirect - github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect + github.com/vishvananda/netns v0.0.4 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/ssh-agent v0.3.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect gitlab.com/bosi/decorder v0.2.3 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 // indirect - golang.org/x/image v0.5.0 // indirect - golang.org/x/text v0.8.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 // indirect + golang.org/x/image v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect @@ -341,13 +344,13 @@ require ( howett.net/plist v1.0.0 // indirect k8s.io/apiextensions-apiserver v0.25.0 // indirect k8s.io/component-base v0.25.0 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - mvdan.cc/gofumpt v0.4.0 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + mvdan.cc/gofumpt v0.5.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/go.sum b/go.sum index 7c2a3cb6a74ac..c8cdd290da4aa 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,8 @@ 4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= 4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= -4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= 4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= 4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= -bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -19,20 +17,11 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -42,40 +31,34 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= -cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= -filippo.io/mkcert v1.4.3 h1:axpnmtrZMM8u5Hf4N3UXxboGemMOV+Tn+e+pkHM6E3o= -filippo.io/mkcert v1.4.3/go.mod h1:64ke566uBwAQcdK3vRDABgsgVHqrfORPTw6YytZCTxk= +filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= +filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc= +filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA= github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= -github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCqWCLp6Cifo= github.com/Antonboom/errname v0.1.9 h1:BZDX4r3l4TBZxZ2o2LNrlGxSHran4d1u4veZdoORTT4= github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= -github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= -github.com/Antonboom/nilnil v0.1.3 h1:6RTbx3d2mcEu3Zwq9TowQpQMVpP75zugwOtqY1RTtcE= -github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= +github.com/Antonboom/nilnil v0.1.4 h1:yWIfwbCRDpJiJvs7Quz55dzeXCgORQyAG29N9/J5H2Q= +github.com/Antonboom/nilnil v0.1.4/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Djarvur/go-err113 v0.1.0 h1:uCRZZOdMQ0TZPHYTdYpoC0bLYJKPEHPUJ8MeAa51lNU= github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= @@ -83,36 +66,30 @@ github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmc github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= -github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 h1:L6S7kR7SlhQKplIBpkra3s6yhcZV51lhRnXmYc4HohI= +github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= @@ -129,68 +106,60 @@ github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cv github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= -github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= -github.com/aws/aws-sdk-go-v2 v1.17.3 h1:shN7NlnVzvDUgPQ+1rLMSxY8OWRNDRYtiqe0p/PgrhY= -github.com/aws/aws-sdk-go-v2 v1.17.3/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= -github.com/aws/aws-sdk-go-v2/config v1.11.0 h1:Czlld5zBB61A3/aoegA9/buZulwL9mHHfizh/Oq+Kqs= -github.com/aws/aws-sdk-go-v2/config v1.11.0/go.mod h1:VrQDJGFBM5yZe+IOeenNZ/DWoErdny+k2MHEIpwDsEY= -github.com/aws/aws-sdk-go-v2/credentials v1.6.4 h1:2hvbUoHufns0lDIsaK8FVCMukT1WngtZPavN+W2FkSw= -github.com/aws/aws-sdk-go-v2/credentials v1.6.4/go.mod h1:tTrhvBPHyPde4pdIPSba4Nv7RYr4wP9jxXEDa1bKn/8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 h1:KiN5TPOLrEjbGCvdTQR4t0U4T87vVwALZ5Bg3jpMqPY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2/go.mod h1:dF2F6tXEOgmW5X1ZFO/EPtWrcm7XkW07KNcJUGNtt4s= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4 h1:P8dY1eHwdKQtMLTSn4Lg0A+vEHTqBnTkYxgy5kzK4Y0= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4/go.mod h1:FqSlw++zBunV8Kt5rPETKxIPGO8axbW4L8v25oql7ok= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27 h1:I3cakv2Uy1vNmmhRQmFptYDxOvBnwCdNwyw63N0RaRU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.27/go.mod h1:a1/UpzeyBBerajpnP5nGZa9mGzsBn5cOKxm6NWQsvoI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21 h1:5NbbMrIzmUn/TXFqAle6mgrH5m9cOvMLRGL7pnG8tRE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.21/go.mod h1:+Gxn8jYn5k9ebfHEqlhrMirFjSW0v0C9fI+KN5vk2kE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 h1:IQup8Q6lorXeiA/rK72PeToWoWK8h7VAPgHNWdSrtgE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2/go.mod h1:VITe/MdW6EMXPb0o0txu/fsonXbMHUU2OC2Qp7ivU4o= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 h1:lPLbw4Gn59uoKqvOfSnkJr54XWk5Ak1NK20ZEiSWb3U= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 h1:CKdUNKmuilw/KNmO2Q53Av8u+ZyXMC2M9aX8Z+c/gzg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2/go.mod h1:FgR1tCsn8C6+Hf+N5qkfrE4IXvUL1RgW87sunJ+5J4I= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2 h1:GnPGH1FGc4fkn0Jbm/8r2+nPOwSJjYPyHSqFSvY1ii8= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2/go.mod h1:eDUYjOYt4Uio7xfHi5jOsO393ZG8TSfZB92a3ZNadWM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0 h1:vUM2P60BI755i35Gyik4s/lXKcnpEbnvw2Vud+soqpI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0/go.mod h1:lQ5AeEW2XWzu8hwQ3dCqZFWORQ3RntO0Kq135Xd9VCo= -github.com/aws/aws-sdk-go-v2/service/ssm v1.35.0 h1:QWCcOeLTrjvf7UdYIadzrhNH3PI6T9jXOV64Ez5YUgg= -github.com/aws/aws-sdk-go-v2/service/ssm v1.35.0/go.mod h1:Hf7wSogKP1XCJ9GgW8erZDL6IZ1NLwLN7bYdV/Gn/LI= -github.com/aws/aws-sdk-go-v2/service/sso v1.6.2 h1:2IDmvSb86KT44lSg1uU4ONpzgWLOuApRl6Tg54mZ6Dk= -github.com/aws/aws-sdk-go-v2/service/sso v1.6.2/go.mod h1:KnIpszaIdwI33tmc/W/GGXyn22c1USYxA/2KyvoeDY0= -github.com/aws/aws-sdk-go-v2/service/sts v1.11.1 h1:QKR7wy5e650q70PFKMfGF9sTo0rZgUevSSJ4wxmyWXk= -github.com/aws/aws-sdk-go-v2/service/sts v1.11.1/go.mod h1:UV2N5HaPfdbDpkgkz4sRzWCvQswZjdO1FfqCWl0t7RA= -github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/aws-sdk-go-v2 v1.18.0 h1:882kkTpSFhdgYRKVZ/VCgf7sd0ru57p2JCxz4/oN5RY= +github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= +github.com/aws/aws-sdk-go-v2/config v1.18.22 h1:7vkUEmjjv+giht4wIROqLs+49VWmiQMMHSduxmoNKLU= +github.com/aws/aws-sdk-go-v2/config v1.18.22/go.mod h1:mN7Li1wxaPxSSy4Xkr6stFuinJGf3VZW3ZSNvO0q6sI= +github.com/aws/aws-sdk-go-v2/credentials v1.13.21 h1:VRiXnPEaaPeGeoFcXvMZOB5K/yfIXOYE3q97Kgb0zbU= +github.com/aws/aws-sdk-go-v2/credentials v1.13.21/go.mod h1:90Dk1lJoMyspa/EDUrldTxsPns0wn6+KpRKpdAWc0uA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3 h1:jJPgroehGvjrde3XufFIJUZVK5A2L9a3KwSFgKy9n8w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 h1:9QJQs36z61YB8nxGwRDfWXEDYbU6H7jdI6zFiAX1vag= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64/go.mod h1:4Q7R9MFpXRdjO3YnAfUTdnuENs32WzBkASt6VxSYDYQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33 h1:kG5eQilShqmJbv11XL1VpyDbaEJzWxd4zRiCG30GSn4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27 h1:vFQlirhuM8lLlpI7imKOMsjdQLuN9CPi+k44F/OFVsk= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34 h1:gGLG7yKaXG02/jBlg210R7VgQIotiQntNhsCFejawx8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.34/go.mod h1:Etz2dj6UHYuw+Xw830KfzCfWGMzqvUTCjUj5b76GVDc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25 h1:AzwRi5OKKwo4QNqPf7TjeO+tK8AyOK3GVSwmRPo7/Cs= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.25/go.mod h1:SUbB4wcbSEyCvqBxv/O/IBf93RbEze7U7OnoTlpPB+g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28 h1:vGWm5vTpMr39tEZfQeDiDAMgk+5qsnvRny3FjLpnH5w= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.28/go.mod h1:spfrICMD6wCAhjhzHuy6DOZZ+LAIY10UxhUmLzpJTTs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27 h1:0iKliEXAcCa2qVtRs7Ot5hItA2MsufrphbRFlz1Owxo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.27/go.mod h1:EOwBD4J4S5qYszS5/3DpkejfuK+Z5/1uzICfPaZLtqw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2 h1:NbWkRxEEIRSCqxhsHQuMiTH7yo+JZW1gp8v3elSVMTQ= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.2/go.mod h1:4tfW5l4IAB32VWCDEBxCRtR9T4BWy4I4kr1spr8NgZM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0 h1:L5h2fymEdVJYvn6hYO8Jx48YmC6xVmjmgHJV3oGKgmc= +github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0/go.mod h1:J9kLNzEiHSeGMyN7238EjJmBpCniVzFda75Gxl/NqB8= +github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 h1:TQZH0Djie8VVgTBDOQ02M4zVHJFrNzLMsYMbNfRitVM= +github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3/go.mod h1:p6MaesK9061w6NTiFmZpUzEkKUY5blKlwD2zYyErxKA= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.9 h1:GAiaQWuQhQQui76KjuXeShmyXqECwQ0mGRMc/rwsL+c= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.9/go.mod h1:ouy2P4z6sJN70fR3ka3wD3Ro3KezSxU6eKGQI2+2fjI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9 h1:TraLwncRJkWqtIBVKI/UqBymq4+hL+3MzUOtUATuzkA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.9/go.mod h1:AFvkxc8xfBe8XA+5St5XIHHrQQtkxqrRincx4hmMHOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.10 h1:6UbNM/KJhMBfOI5+lpVcJ/8OA7cBSz0O6OX37SRKlSw= +github.com/aws/aws-sdk-go-v2/service/sts v1.18.10/go.mod h1:BgQOMsg8av8jset59jelyPW7NoZcZXLVpDsXunGDrk8= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -201,163 +170,136 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= -github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= -github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= -github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4= +github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e h1:hHg27A0RSSp2Om9lubZpiMgVbvn39bsUmW9U5h0twqc= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= +github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= +github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.8.1/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk= -github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc= +github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk= -github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= +github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= +github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= -github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/daixiang0/gci v0.2.4/go.mod h1:+AV8KmHTGxxwp/pY84TLQfFKp2vuKXXJVzF3kD/hfR4= github.com/daixiang0/gci v0.2.7/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= -github.com/daixiang0/gci v0.2.9/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= -github.com/dave/jennifer v1.4.1 h1:XyqG6cn5RQsTj3qlWQTKlRGAyrTcsk1kUmWdZBzRjDw= -github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= -github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dave/jennifer v1.6.1 h1:T4T/67t6RAA5AIV6+NP8Uk/BIsXgDoqEowgycdQQLuk= +github.com/dave/jennifer v1.6.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dblohm7/wingoes v0.0.0-20221124203957-6ac47ab19aa5 h1:84SSlQpWqllOmtng34NorWGJbzX00SI2J4MQjXNYUuU= -github.com/dblohm7/wingoes v0.0.0-20221124203957-6ac47ab19aa5/go.mod h1:LPBSRY0diEb4/R1gqa4OaBexvmklv7XdPv7m6cudDR8= +github.com/dblohm7/wingoes v0.0.0-20230426155039-111c8c3b57c8 h1:vtIE3GO4hKplR58aTRx3yLPqAbfWyoyYrE8PXUv0Prw= +github.com/dblohm7/wingoes v0.0.0-20230426155039-111c8c3b57c8/go.mod h1:6NCrWM5jRefaG7iN0iMShPalLsljHWBh9v1zxM2f8Xs= github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/denis-tingajkin/go-header v0.3.1/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0= -github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= -github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v23.0.5+incompatible h1:ufWmAOuD3Vmr7JP2G5K3cyuNC4YZWiAsuDEvFVVDafE= +github.com/docker/cli v23.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= -github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k= +github.com/docker/docker v23.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI= github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/evanw/esbuild v0.14.53 h1:9uU73SZUmP1jRQhaC6hPm9aoqFGYlPwfk7OrhG6AhpQ= github.com/evanw/esbuild v0.14.53/go.mod h1:iINY06rn799hi48UqEnaQvVfZWe6W9bET78LbvN8VWk= -github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -368,54 +310,49 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I= github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/gliderlabs/ssh v0.3.3 h1:mBQ8NiOgDkINJrZtoizkC3nDNYgSaWtxyem6S2XHBtA= -github.com/gliderlabs/ssh v0.3.3/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-critic/go-critic v0.5.2/go.mod h1:cc0+HvdE3lFpqLecgqMaJcvWWH77sLdBp+wLGPM1Yyo= -github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= -github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ= -github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= +github.com/go-critic/go-critic v0.8.0 h1:4zOcpvDoKvBOl+R1W81IBznr78f8YaE4zKXkfDVxGGA= +github.com/go-critic/go-critic v0.8.0/go.mod h1:5TjdkPI9cu/yKbYS96BTsslihjKd6zg6vd8O9RZXj2s= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ= +github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= +github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-json-experiment/json v0.0.0-20221017203807-c5ed296b8c92 h1:eoE7yxLELqDQVlHGoYYxXLFZqF8NcdOnrukTm4ObJaY= -github.com/go-json-experiment/json v0.0.0-20221017203807-c5ed296b8c92/go.mod h1:I+I5/LT2lLP0eZsBNaVDrOrYASx9h7o7mRHmy+535/A= +github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929 h1:GdbUZo0+623j+pKRhwwdf1q28IUgRc7asx3TjF9b7VQ= +github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929/go.mod h1:AHV+bpNGVGD0DCHMBhhTYtT7yeBYD9Yk92XAjB7vOgo= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -423,11 +360,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= @@ -435,7 +369,6 @@ github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjj github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= @@ -466,20 +399,16 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -493,9 +422,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -511,10 +437,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= @@ -528,7 +453,6 @@ github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= github.com/golangci/golangci-lint v1.33.0/go.mod h1:zMnMLSCaDlrXExYsuq2LOweE9CHVqYk5jexk23UsjYM= -github.com/golangci/golangci-lint v1.43.0/go.mod h1:VIFlUqidx5ggxDfQagdvd9E67UjMXtTHBkBQ7sHoC5Q= github.com/golangci/golangci-lint v1.52.2 h1:FrPElUUI5rrHXg1mQ7KxI1MXPAw5lBVskiz7U7a8a1A= github.com/golangci/golangci-lint v1.52.2/go.mod h1:S5fhC5sHM5kE22/HcATKd1XLWQxX+y7mHj8B5H91Q/0= github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= @@ -543,19 +467,16 @@ github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkj github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= -github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -568,21 +489,19 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.9.0 h1:5Ths7RjxyFV0huKChQTgY6fLzvHhZMpLTFNja8U0/0w= -github.com/google/go-containerregistry v0.9.0/go.mod h1:9eq4BnSufyT1kHNffX+vSXVonaJ7yaIOulrKZejMxnQ= +github.com/google/go-containerregistry v0.14.0 h1:z58vMqHxuwvAsVwvKEkmVBz2TlgBgH5k6koEXBtlYkw= +github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 h1:CVuJwN34x4xM2aT4sIKhmeib40NeBPhRihNjQmpJsA4= github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c h1:06RMfw+TMMHtRuUOroMeatRCCgSMWXCJQeABvHU69YQ= github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c/go.mod h1:BVIYo3cdnT4qSylnYqcd5YtmXhr51cJPGtnLBe/uLBU= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -591,35 +510,23 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/rpmpack v0.0.0-20201206194719-59e495f2b7e1 h1:BRIy5qQZKSC/nthA5ueW547F73BV5hMoIoxhPfhxa3k= github.com/google/rpmpack v0.0.0-20201206194719-59e495f2b7e1/go.mod h1:+y9lKiqDhR4zkLl+V9h4q0rdyrYVsWWm6LLCQP33DIk= -github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= -github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/rpmpack v0.0.0-20221120200012-98b63d62fd77 h1:+C0+foB1Bm0WYdbaDIuUGEVG1Eqx9WWcGUoJBSLdZo0= +github.com/google/rpmpack v0.0.0-20221120200012-98b63d62fd77/go.mod h1:Ys71Xf3d5OC4Ww06S5YJcbk+Eh/1CsB+rZibR7NDEA4= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ= -github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= -github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/goreleaser/chglog v0.1.2 h1:tdzAb/ILeMnphzI9zQ7Nkq+T8R9qyXli8GydD8plFRY= @@ -628,16 +535,12 @@ github.com/goreleaser/fileglob v0.3.1 h1:OTFDWqUUHjQazk2N5GdUqEbqT/grBnRARaAXsV0 github.com/goreleaser/fileglob v0.3.1/go.mod h1:kNcPrPzjCp+Ox3jmXLU5QEsjhqrtLBm6OnXAif8KRl8= github.com/goreleaser/nfpm v1.10.3 h1:NzpWKKzSFr7JOn55XN0SskyFOjP6BkvRt3JujoX8fws= github.com/goreleaser/nfpm v1.10.3/go.mod h1:EEC7YD5wi+ol0MiAshpgPANBOkjXDl7wqTLVk68OBsk= -github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= -github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= github.com/gostaticanalysis/analysisutil v0.6.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= @@ -645,40 +548,28 @@ github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnq github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -689,43 +580,36 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= -github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= +github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= +github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= -github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/illarion/gonotify v1.0.1 h1:F1d+0Fgbq/sDWjj/r66ekjDG+IDeecQKUFH4wNwsoio= github.com/illarion/gonotify v1.0.1/go.mod h1:zt5pmDofZpU1f8aqlK0+95eQhoEAn/d4G4B/FjVW4jE= -github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8 h1:Z72DOke2yOK0Ms4Z2LK1E1OrRJXOxSj5DllTz2FYTRg= -github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8/go.mod h1:m5WMe03WCvWcXjRnhvaAbAAXdCnu20J5P+mmH44ZzpE= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 h1:+aAGyK41KRn8jbF2Q7PLL0Sxwg6dShGcQSeCC7nZQ8E= +github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16/go.mod h1:IKrnDWs3/Mqq5n0lI+RxA2sB7MvN/vbMBP3ehXg65UI= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -733,14 +617,12 @@ github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -748,23 +630,15 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk= github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86/go.mod h1:aFAMtuldEgx/4q7iSGazk22+IcgvtiC+HIimFO9XlS8= -github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= -github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= -github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= -github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b h1:Yws7RV6kZr2O7PPdT+RkbSmmOponA8i/1DuGHe8BRsM= -github.com/jsimonetti/rtnetlink v1.1.2-0.20220408201609-d380b505068b/go.mod h1:TzDCVOZKUa79z6iXbbXqhtAflVgUKaFkZ21M5tK5tzY= +github.com/jsimonetti/rtnetlink v1.3.2 h1:dcn0uWkfxycEEyNy0IGfx3GrhQ38LH7odjxAghimsVI= +github.com/jsimonetti/rtnetlink v1.3.2/go.mod h1:BBu4jZCpTjP6Gk0/wfrO8qcqymnN3g0hoFqObRmUo6U= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -773,25 +647,20 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v1.1.0 h1:pH/t1WS9NzT8go394IqZeJTMHVm6Cr6ZJ6AQ+mdNo/o= -github.com/kevinburke/ssh_config v1.1.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= @@ -801,13 +670,13 @@ github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ= -github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= +github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ= github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk= @@ -817,53 +686,38 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30= -github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= -github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= -github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= +github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= @@ -871,7 +725,6 @@ github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1r github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matoous/godox v0.0.0-20200801072554-4fb83dc2941e/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= @@ -879,28 +732,19 @@ github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -909,36 +753,20 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr github.com/mbilski/exhaustivestruct v1.1.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= -github.com/mdlayher/genetlink v1.2.0 h1:4yrIkRV5Wfk1WfpWTcoOlGmsWgQj3OtQN9ZsbrE+XtU= -github.com/mdlayher/genetlink v1.2.0/go.mod h1:ra5LDov2KrUCZJiAtEvXXZBxGMInICMXIwshlJ+qRxQ= -github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= -github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= -github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= -github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= -github.com/mdlayher/netlink v1.7.1 h1:FdUaT/e33HjEXagwELR8R3/KL1Fq5x3G5jgHLp/BTmg= -github.com/mdlayher/netlink v1.7.1/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ= -github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= -github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= +github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw= +github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c= github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE= -github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= -github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= -github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= -github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= -github.com/mgechev/revive v1.1.2/go.mod h1:bnXsMr+ZTH09V5rssEI+jHAZ4z+ZdyhgO/zsy3EhK+0= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mgechev/revive v1.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= +github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -954,14 +782,13 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -969,19 +796,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= -github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= -github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= @@ -992,42 +814,31 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ= -github.com/nishanths/exhaustive v0.2.3/go.mod h1:bhIX678Nx8inLM9PbpvK1yv6oGtoP8BfaIeMzgBNKvc= -github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= -github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= -github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= -github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE= +github.com/nishanths/exhaustive v0.10.0 h1:BMznKAcVa9WOoLq/kTGp4NJOJSMwEpcpjFNAVRfPlSo= +github.com/nishanths/exhaustive v0.10.0/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= -github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= +github.com/nunnatsa/ginkgolinter v0.11.2 h1:xzQpAsEyZe5F1RMy2Z5kn8UFCGiWfKqJOUd2ZzBXA4M= +github.com/nunnatsa/ginkgolinter v0.11.2/go.mod h1:dJIGXYXbkBswqa/pIzG0QlVTTDSBMxDoCFwhsl4Uras= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 h1:+czc/J8SlhPKLOtVLMQc+xDCFBT73ZStMsRhSsUhsSg= -github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= +github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -1037,18 +848,17 @@ github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM= -github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= +github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= +github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/peterbourgon/ff/v3 v3.3.0 h1:PaKe7GW8orVFh8Unb5jNHS+JZBwWUMa2se0HM6/BI24= +github.com/peterbourgon/ff/v3 v3.3.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -1058,40 +868,37 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pkg/sftp v1.13.4 h1:Lb0RYJCmgUcBgZosfoi9Y9sbl6+LJgOIgk/2Y4YjMFg= -github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= +github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v0.0.0-20201006195004-351e25ade6e3/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/polyfloyd/go-errorlint v0.0.0-20201127212506-19bd8db6546f/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= -github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= -github.com/polyfloyd/go-errorlint v1.4.0 h1:b+sQ5HibPIAjEZwtuwU8Wz/u0dMZ7YL+bk+9yWyHVJk= -github.com/polyfloyd/go-errorlint v1.4.0/go.mod h1:qJCkPeBn+0EXkdKTrUCcuFStM2xrDKfxI3MGLXPexUs= +github.com/polyfloyd/go-errorlint v1.4.1 h1:r8ru5FhXSn34YU1GJDOuoJv2LdsQkPmK325EOpPMJlM= +github.com/polyfloyd/go-errorlint v1.4.1/go.mod h1:k6fU/+fQe38ednoZS51T7gSIGQW1y94d6TkSr35OzH8= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= -github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1101,19 +908,11 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= -github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/quasilyte/go-ruleguard v0.2.0/go.mod h1:2RT/tf0Ce0UDj5y243iWKosQogJd8+1G3Rs2fxmlYnw= github.com/quasilyte/go-ruleguard v0.2.1/go.mod h1:hN2rVc/uS4bQhQKTio2XaSJSafJwqBUWWwtssT3cQmc= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.13/go.mod h1:Ul8wwdqR6kBVOCt2dipDBkE+T6vAV/iixkrKuRTN1oQ= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.10/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= @@ -1122,31 +921,27 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM= -github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= -github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= @@ -1154,21 +949,19 @@ github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84d github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= -github.com/sassoftware/go-rpmutils v0.1.0 h1:VLrna+tV+77Tclr956QkY/pTyyKomQlq2Xw6PuE8tsc= -github.com/sassoftware/go-rpmutils v0.1.0/go.mod h1:euhXULoBpvAxqrBHEyJS4Tsu3hHxUmQWNymxoJbzgUY= +github.com/sassoftware/go-rpmutils v0.2.0 h1:pKW0HDYMFWQ5b4JQPiI3WI12hGsVoW0V8+GMoZiI/JE= +github.com/sassoftware/go-rpmutils v0.2.0/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/securego/gosec/v2 v2.5.0/go.mod h1:L/CDXVntIff5ypVHIkqPXbtRpJiNCh6c6Amn68jXDjo= -github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc= github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= -github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= @@ -1178,16 +971,16 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= -github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= +github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= +github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= +github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1201,37 +994,27 @@ github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCp github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= @@ -1244,7 +1027,6 @@ github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1254,12 +1036,12 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8= @@ -1268,20 +1050,20 @@ github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 h1:34icjjmqJ2HP github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41 h1:/V2rCMMWcsjYaYO2MeovLw+ClP63OtXgCF2Y1eb8+Ns= github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41/go.mod h1:/roCdA6gg6lQyw/Oz6gIIGu3ggJKYhF+WC/AQReE5XQ= -github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17 h1:cSm67hIDABvL13S0n9TNoVhzYwjb24M46znbABLll18= -github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17/go.mod h1:95n9fbUCixVSI4QXLEvdKJjnYK2eUlkTx9+QwLPXFKU= +github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 h1:pBpqbsyX9H8c26oPYC2H+232HOdp1gDnCztoKmKWKDA= +github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2/go.mod h1:V2G8jyemEGZWKQ+3xNn4+bOx+FuoXU9Zc5GUsZMthBg= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8= -github.com/tailscale/hujson v0.0.0-20220630195928-54599719472f h1:n4r/sJ92cBSBHK8n9lR1XLFr0OiTVeGfN5TR+9LaN7E= -github.com/tailscale/hujson v0.0.0-20220630195928-54599719472f/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8= +github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw= +github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8= github.com/tailscale/mkctr v0.0.0-20220601142259-c0b937af2e89 h1:7xU7AFQE83h0wz/dIMvD0t77g0FxFfZIQjghDQxyG2U= github.com/tailscale/mkctr v0.0.0-20220601142259-c0b937af2e89/go.mod h1:OGMqrTzDqmJkGumUTtOv44Rp3/4xS+QFbE8Rn0AGlaU= github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk= github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0= github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd h1:+fBevMGmDRNi0oWD4SJXmPKLWvIBYX1NroMjo9czjcY= github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd/go.mod h1:QRIcq2+DbdIC5sKh/gcAZhuqu6WT6L6G8/ALPN5wqYw= -github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= -github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= +github.com/tc-hib/winres v0.2.0 h1:gly/ivDWGvlhl7ENtEmA7wPQ6dWab1LlLq/DgcZECKE= +github.com/tc-hib/winres v0.2.0/go.mod h1:uG6S5M2Q0/kThoqsCSYvGJODUQP9O9R0SNxUPmFIegw= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= @@ -1298,169 +1080,132 @@ github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= -github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= +github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= +github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= -github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= -github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tomarrell/wrapcheck v0.0.0-20200807122107-df9e8bcb914d/go.mod h1:yiFB6fFoV7saXirUGfuK+cPtUh4NX/Hf5y2WC2lehu0= github.com/tomarrell/wrapcheck v0.0.0-20201130113247-1683564d9756/go.mod h1:yiFB6fFoV7saXirUGfuK+cPtUh4NX/Hf5y2WC2lehu0= -github.com/tomarrell/wrapcheck/v2 v2.4.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2OgfoG8bLp9ZyoBfyY= github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= -github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= -github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/u-root/gobusybox/src v0.0.0-20221229083637-46b2883a7f90 h1:zTk5683I9K62wtZ6eUa6vu6IWwVHXPnoKK5n2unAwv0= -github.com/u-root/u-root v0.9.1-0.20230109201855-948a78c969ad h1:0lEUXaz1vhlAtoMpu18vhb16s5rGRpNCl2trxc2/Qbg= -github.com/u-root/u-root v0.9.1-0.20230109201855-948a78c969ad/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY= -github.com/u-root/uio v0.0.0-20221213070652-c3537552635f h1:dpx1PHxYqAnXzbryJrWP1NQLzEjwcVgFLhkknuFQ7ww= -github.com/u-root/uio v0.0.0-20221213070652-c3537552635f/go.mod h1:IogEAUBXDEwX7oR/BMmCctShYs80ql4hF0ySdzGxf7E= +github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8= +github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY= +github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= +github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= -github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= -github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY= -github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= -github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= -github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So= -github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= +github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= -github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= -go4.org/mem v0.0.0-20210711025021-927187094b94 h1:OAAkygi2Js191AJP1Ds42MhJRgeofeKGjuoUqNp1QC4= -go4.org/mem v0.0.0-20210711025021-927187094b94/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= -go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf h1:IdwJUzqoIo5lkr2EOyKoe5qipUaEjbOKKY5+fzPBZ3A= -go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf/go.mod h1:+QXzaoURFd0rGDIjDNpyIkv+F9R7EmeKorvlKRnhqgA= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4= -golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H9rmp5nkDTAst8= +go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= +go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo= +go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y= +golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1471,18 +1216,17 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= -golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 h1:w/MOPdQ1IoYoDou3L55ZbTx2Nhn7JAhX1BBZor8qChU= +golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= -golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= +golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= +golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw= +golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1494,7 +1238,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1506,15 +1249,14 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1526,7 +1268,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -1534,11 +1275,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1546,7 +1282,6 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -1556,34 +1291,27 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1593,20 +1321,13 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1624,29 +1345,21 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1655,7 +1368,6 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1663,7 +1375,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1677,75 +1388,57 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201109165425-215b40eba54c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1759,19 +1452,17 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1791,13 +1482,9 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1806,7 +1493,6 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1835,9 +1521,6 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -1853,19 +1536,12 @@ golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124202034-299f270db459/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1873,12 +1549,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= @@ -1888,8 +1559,8 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1904,7 +1575,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1920,27 +1590,15 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1948,7 +1606,6 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1962,56 +1619,32 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -2021,14 +1654,7 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -2051,16 +1677,12 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -2075,7 +1697,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -2083,6 +1704,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= @@ -2096,18 +1718,16 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= -honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= -howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= inet.af/peercred v0.0.0-20210906144145-0893ea02156a h1:qdkS8Q5/i10xU2ArJMKYhVa1DORzBfYS/qA2UK2jheg= inet.af/peercred v0.0.0-20210906144145-0893ea02156a/go.mod h1:FjawnflS/udxX+SvpsMgZfdqx2aykOlkISeAsADi5IU= inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 h1:2dMP3Ox/Wh5BiItwOt4jxRsfzkgyBrHzx2nW28Yg6nc= inet.af/tcpproxy v0.0.0-20221017015627-91f861402626/go.mod h1:Tojt5kmHpDIR2jMojxzZK2w2ZR7OILODmUo2gaSwjrk= -inet.af/wf v0.0.0-20220728202103-50d96caab2f6 h1:BfgDtKnWJTeu+xI1aOEweXdPwqOhB3IbQUDj1XuftcY= -inet.af/wf v0.0.0-20220728202103-50d96caab2f6/go.mod h1:bSAQ38BYbY68uwpasXOTZo22dKGy9SNvI6PZFeKomZE= +inet.af/wf v0.0.0-20221017222439-36129f591884 h1:zg9snq3Cpy50lWuVqDYM7AIRVTtU50y5WXETMFohW/Q= +inet.af/wf v0.0.0-20221017222439-36129f591884/go.mod h1:bSAQ38BYbY68uwpasXOTZo22dKGy9SNvI6PZFeKomZE= k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= @@ -2118,40 +1738,36 @@ k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.0.0-20200802201014-ab5a8192947d/go.mod h1:bzrjFmaD6+xqohD3KYP0H2FEuxknnBmyyOxdhLdaIws= mvdan.cc/gofumpt v0.0.0-20201129102820-5c11c50e9475/go.mod h1:E4LOcu9JQEtnYXtB1Y51drqh2Qr2Ngk9J3YrRCwcbd0= -mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= -mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= -mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= +mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= +mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc= -mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= +mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 h1:VuJo4Mt0EVPychre4fNlDWDuE5AjXtPJpRUWqZDQhaI= +mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8/go.mod h1:Oh/d7dEtzsNHGOq1Cdv8aMm3KdKhVvPbRQcM8WFpBR8= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg= sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -software.sslmate.com/src/go-pkcs12 v0.0.0-20180114231543-2291e8f0f237/go.mod h1:/xvNRWUqm0+/ZMiF4EX00vrSCMsE4/NHb+Pt3freEeQ= software.sslmate.com/src/go-pkcs12 v0.2.0 h1:nlFkj7bTysH6VkC4fGphtjXRbezREPgrHuJG20hBGPE= software.sslmate.com/src/go-pkcs12 v0.2.0/go.mod h1:23rNcYsMabIc1otwLpTkCCPwUq6kQsTyowttG/as0kQ= From 503b6dd8be55c5e3a744e77b81b3b9bf04d4a28e Mon Sep 17 00:00:00 2001 From: License Updater Date: Thu, 4 May 2023 02:54:28 +0000 Subject: [PATCH 059/331] licenses: update tailscale{,d} licenses Signed-off-by: License Updater --- licenses/tailscale.md | 94 ++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/licenses/tailscale.md b/licenses/tailscale.md index 8ab16f946b557..e9e93908385f8 100644 --- a/licenses/tailscale.md +++ b/licenses/tailscale.md @@ -13,85 +13,87 @@ well as an [option for macOS][]. Some packages may only be included on certain architectures or operating systems. - - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0-rc.1/LICENSE)) - - [github.com/Microsoft/go-winio](https://pkg.go.dev/github.com/Microsoft/go-winio) ([MIT](https://github.com/Microsoft/go-winio/blob/v0.6.0/LICENSE)) + - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0/LICENSE)) + - [github.com/Microsoft/go-winio](https://pkg.go.dev/github.com/Microsoft/go-winio) ([MIT](https://github.com/Microsoft/go-winio/blob/v0.6.1/LICENSE)) - [github.com/akutz/memconn](https://pkg.go.dev/github.com/akutz/memconn) ([Apache-2.0](https://github.com/akutz/memconn/blob/v0.1.0/LICENSE)) - [github.com/alexbrainman/sspi](https://pkg.go.dev/github.com/alexbrainman/sspi) ([BSD-3-Clause](https://github.com/alexbrainman/sspi/blob/909beea2cc74/LICENSE)) - [github.com/anmitsu/go-shlex](https://pkg.go.dev/github.com/anmitsu/go-shlex) ([MIT](https://github.com/anmitsu/go-shlex/blob/38f4b401e2be/LICENSE)) - - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.11.0/config/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.6.4/credentials/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.8.2/feature/ec2/imds/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.27/internal/configsources/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.21/internal/endpoints/v2/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.2/internal/ini/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/internal/sync/singleflight/LICENSE)) - - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.5.2/service/internal/presigned-url/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.35.0/service/ssm/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.6.2/service/sso/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.11.1/service/sts/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.18.22/config/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.13.21/credentials/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.13.3/feature/ec2/imds/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.33/internal/configsources/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.27/internal/endpoints/v2/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.34/internal/ini/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/internal/sync/singleflight/LICENSE)) + - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.9.27/service/internal/presigned-url/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.36.3/service/ssm/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.12.9/service/sso/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssooidc](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssooidc) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.14.9/service/ssooidc/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.18.10/service/sts/LICENSE.txt)) - [github.com/aws/smithy-go](https://pkg.go.dev/github.com/aws/smithy-go) ([Apache-2.0](https://github.com/aws/smithy-go/blob/v1.13.5/LICENSE)) - [github.com/aws/smithy-go/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/smithy-go/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/smithy-go/blob/v1.13.5/internal/sync/singleflight/LICENSE)) - [github.com/coreos/go-iptables/iptables](https://pkg.go.dev/github.com/coreos/go-iptables/iptables) ([Apache-2.0](https://github.com/coreos/go-iptables/blob/v0.6.0/LICENSE)) - - [github.com/creack/pty](https://pkg.go.dev/github.com/creack/pty) ([MIT](https://github.com/creack/pty/blob/v1.1.17/LICENSE)) - - [github.com/dblohm7/wingoes](https://pkg.go.dev/github.com/dblohm7/wingoes) ([BSD-3-Clause](https://github.com/dblohm7/wingoes/blob/6ac47ab19aa5/LICENSE)) + - [github.com/creack/pty](https://pkg.go.dev/github.com/creack/pty) ([MIT](https://github.com/creack/pty/blob/v1.1.18/LICENSE)) + - [github.com/dblohm7/wingoes](https://pkg.go.dev/github.com/dblohm7/wingoes) ([BSD-3-Clause](https://github.com/dblohm7/wingoes/blob/111c8c3b57c8/LICENSE)) - [github.com/fxamacker/cbor/v2](https://pkg.go.dev/github.com/fxamacker/cbor/v2) ([MIT](https://github.com/fxamacker/cbor/blob/v2.4.0/LICENSE)) - [github.com/go-ole/go-ole](https://pkg.go.dev/github.com/go-ole/go-ole) ([MIT](https://github.com/go-ole/go-ole/blob/v1.2.6/LICENSE)) - - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.0.6/LICENSE)) + - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.1.0/LICENSE)) - [github.com/golang/groupcache/lru](https://pkg.go.dev/github.com/golang/groupcache/lru) ([Apache-2.0](https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE)) - - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.0.1/LICENSE)) + - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.1.2/LICENSE)) - [github.com/google/uuid](https://pkg.go.dev/github.com/google/uuid) ([BSD-3-Clause](https://github.com/google/uuid/blob/v1.3.0/LICENSE)) - - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/c00d1f31bab3/LICENSE)) + - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/v0.1.0/LICENSE)) - [github.com/illarion/gonotify](https://pkg.go.dev/github.com/illarion/gonotify) ([MIT](https://github.com/illarion/gonotify/blob/v1.0.1/LICENSE)) - - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/de60144f33f8/LICENSE)) + - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/974c6f05fe16/LICENSE)) - [github.com/jmespath/go-jmespath](https://pkg.go.dev/github.com/jmespath/go-jmespath) ([Apache-2.0](https://github.com/jmespath/go-jmespath/blob/v0.4.0/LICENSE)) - [github.com/josharian/native](https://pkg.go.dev/github.com/josharian/native) ([MIT](https://github.com/josharian/native/blob/5c7d0dd6ab86/license)) - - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/d380b505068b/LICENSE.md)) + - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/v1.3.2/LICENSE.md)) - [github.com/kballard/go-shellquote](https://pkg.go.dev/github.com/kballard/go-shellquote) ([MIT](https://github.com/kballard/go-shellquote/blob/95032a82bc51/LICENSE)) - - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.15.4/LICENSE)) - - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.15.4/internal/snapref/LICENSE)) - - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.15.4/zstd/internal/xxhash/LICENSE.txt)) + - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.16.5/LICENSE)) + - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.16.5/internal/snapref/LICENSE)) + - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.16.5/zstd/internal/xxhash/LICENSE.txt)) - [github.com/kortschak/wol](https://pkg.go.dev/github.com/kortschak/wol) ([BSD-3-Clause](https://github.com/kortschak/wol/blob/da482cc4850a/LICENSE)) - [github.com/kr/fs](https://pkg.go.dev/github.com/kr/fs) ([BSD-3-Clause](https://github.com/kr/fs/blob/v0.1.0/LICENSE)) - [github.com/mattn/go-colorable](https://pkg.go.dev/github.com/mattn/go-colorable) ([MIT](https://github.com/mattn/go-colorable/blob/v0.1.13/LICENSE)) - - [github.com/mattn/go-isatty](https://pkg.go.dev/github.com/mattn/go-isatty) ([MIT](https://github.com/mattn/go-isatty/blob/v0.0.17/LICENSE)) - - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.2.0/LICENSE.md)) - - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.1/LICENSE.md)) + - [github.com/mattn/go-isatty](https://pkg.go.dev/github.com/mattn/go-isatty) ([MIT](https://github.com/mattn/go-isatty/blob/v0.0.18/LICENSE)) + - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.2/LICENSE.md)) - [github.com/mdlayher/sdnotify](https://pkg.go.dev/github.com/mdlayher/sdnotify) ([MIT](https://github.com/mdlayher/sdnotify/blob/v1.0.0/LICENSE.md)) - - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.0/LICENSE.md)) + - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.1/LICENSE.md)) - [github.com/mitchellh/go-ps](https://pkg.go.dev/github.com/mitchellh/go-ps) ([MIT](https://github.com/mitchellh/go-ps/blob/v1.0.0/LICENSE.md)) - - [github.com/peterbourgon/ff/v3](https://pkg.go.dev/github.com/peterbourgon/ff/v3) ([Apache-2.0](https://github.com/peterbourgon/ff/blob/v3.1.2/LICENSE)) + - [github.com/peterbourgon/ff/v3](https://pkg.go.dev/github.com/peterbourgon/ff/v3) ([Apache-2.0](https://github.com/peterbourgon/ff/blob/v3.3.0/LICENSE)) + - [github.com/pierrec/lz4/v4](https://pkg.go.dev/github.com/pierrec/lz4/v4) ([BSD-3-Clause](https://github.com/pierrec/lz4/blob/v4.1.17/LICENSE)) - [github.com/pkg/errors](https://pkg.go.dev/github.com/pkg/errors) ([BSD-2-Clause](https://github.com/pkg/errors/blob/v0.9.1/LICENSE)) - - [github.com/pkg/sftp](https://pkg.go.dev/github.com/pkg/sftp) ([BSD-2-Clause](https://github.com/pkg/sftp/blob/v1.13.4/LICENSE)) + - [github.com/pkg/sftp](https://pkg.go.dev/github.com/pkg/sftp) ([BSD-2-Clause](https://github.com/pkg/sftp/blob/v1.13.5/LICENSE)) - [github.com/skip2/go-qrcode](https://pkg.go.dev/github.com/skip2/go-qrcode) ([MIT](https://github.com/skip2/go-qrcode/blob/da1b6568686e/LICENSE)) - [github.com/tailscale/certstore](https://pkg.go.dev/github.com/tailscale/certstore) ([MIT](https://github.com/tailscale/certstore/blob/78d6e1c49d8d/LICENSE.md)) - - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/bc99ab8c2d17/LICENSE)) + - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/17a3db2c30d2/LICENSE)) - [github.com/tailscale/netlink](https://pkg.go.dev/github.com/tailscale/netlink) ([Apache-2.0](https://github.com/tailscale/netlink/blob/cabfb018fe85/LICENSE)) - [github.com/tailscale/wireguard-go](https://pkg.go.dev/github.com/tailscale/wireguard-go) ([MIT](https://github.com/tailscale/wireguard-go/blob/af172621b4dd/LICENSE)) - [github.com/tcnksm/go-httpstat](https://pkg.go.dev/github.com/tcnksm/go-httpstat) ([MIT](https://github.com/tcnksm/go-httpstat/blob/v0.2.0/LICENSE)) - [github.com/toqueteos/webbrowser](https://pkg.go.dev/github.com/toqueteos/webbrowser) ([MIT](https://github.com/toqueteos/webbrowser/blob/v1.2.0/LICENSE.md)) - - [github.com/u-root/u-root/pkg/termios](https://pkg.go.dev/github.com/u-root/u-root/pkg/termios) ([BSD-3-Clause](https://github.com/u-root/u-root/blob/948a78c969ad/LICENSE)) - - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/c3537552635f/LICENSE)) - - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/650dca95af54/LICENSE)) - - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/50045581ed74/LICENSE)) + - [github.com/u-root/u-root/pkg/termios](https://pkg.go.dev/github.com/u-root/u-root/pkg/termios) ([BSD-3-Clause](https://github.com/u-root/u-root/blob/v0.11.0/LICENSE)) + - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/3e8cd9d6bf63/LICENSE)) + - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/v1.2.1-beta.2/LICENSE)) + - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/v0.0.4/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) - - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/927187094b94/LICENSE)) - - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47842c84:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.5.0:LICENSE)) + - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/4f986261bf13/LICENSE)) + - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/f1b76eb4bb35/LICENSE)) + - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.8.0:LICENSE)) + - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47ecfdc1:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) + - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.7.0:LICENSE)) - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) + - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/v0.3.0:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) - [golang.zx2c4.com/wireguard/windows/tunnel/winipcfg](https://pkg.go.dev/golang.zx2c4.com/wireguard/windows/tunnel/winipcfg) ([MIT](https://git.zx2c4.com/wireguard-windows/tree/COPYING?h=v0.5.3)) - [gopkg.in/yaml.v2](https://pkg.go.dev/gopkg.in/yaml.v2) ([Apache-2.0](https://github.com/go-yaml/yaml/blob/v2.4.0/LICENSE)) - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) - - [inet.af/wf](https://pkg.go.dev/inet.af/wf) ([BSD-3-Clause](https://github.com/inetaf/wf/blob/50d96caab2f6/LICENSE)) + - [inet.af/wf](https://pkg.go.dev/inet.af/wf) ([BSD-3-Clause](https://github.com/inetaf/wf/blob/36129f591884/LICENSE)) - [k8s.io/client-go/util/homedir](https://pkg.go.dev/k8s.io/client-go/util/homedir) ([Apache-2.0](https://github.com/kubernetes/client-go/blob/v0.25.0/LICENSE)) - [nhooyr.io/websocket](https://pkg.go.dev/nhooyr.io/websocket) ([MIT](https://github.com/nhooyr/websocket/blob/v1.8.7/LICENSE.txt)) - [sigs.k8s.io/yaml](https://pkg.go.dev/sigs.k8s.io/yaml) ([MIT](https://github.com/kubernetes-sigs/yaml/blob/v1.3.0/LICENSE)) From 5783adcc6fc469c0791ca339876d6847cfcc1b01 Mon Sep 17 00:00:00 2001 From: Flakes Updater Date: Thu, 4 May 2023 02:54:00 +0000 Subject: [PATCH 060/331] go.mod.sri: update SRI hash for go.mod changes Signed-off-by: Flakes Updater --- flake.nix | 2 +- go.mod.sri | 2 +- shell.nix | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index 70d9da2058713..f16aea708ab6e 100644 --- a/flake.nix +++ b/flake.nix @@ -115,4 +115,4 @@ in flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system); } -# nix-direnv cache busting line: sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= +# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= diff --git a/go.mod.sri b/go.mod.sri index 5bb984a0378f8..fb898c112801b 100644 --- a/go.mod.sri +++ b/go.mod.sri @@ -1 +1 @@ -sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= +sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= diff --git a/shell.nix b/shell.nix index 73a3e9d20cf4e..2a58cdb076358 100644 --- a/shell.nix +++ b/shell.nix @@ -16,4 +16,4 @@ ) { src = ./.; }).shellNix -# nix-direnv cache busting line: sha256-lirn07XE3JOS6oiwZBMwxzywkbXHowOJUMWWLrZtccY= +# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= From 787fc41fa48d7c944c16ae7dff6a2f70aca6474c Mon Sep 17 00:00:00 2001 From: Anton Tolchanov Date: Fri, 28 Apr 2023 13:47:03 +0100 Subject: [PATCH 061/331] scripts/installer.sh: check connectivity with pkgs.tailscale.com Installer script relies on pkgs.tailscale.com being reachable, both for checking what Linux distros are supported, but also for actually downloading repo configuration files, gpg keys and packages themselves. This change adds a simple reachability check which will print an error message when pkgs.tailscale.com is not reachable. Fixes https://github.com/tailscale/corp/issues/8952 Signed-off-by: Anton Tolchanov --- scripts/installer.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/installer.sh b/scripts/installer.sh index 7f4ff7e9b4898..86649bfdb36be 100755 --- a/scripts/installer.sh +++ b/scripts/installer.sh @@ -321,6 +321,17 @@ main() { exit 1 fi + TEST_URL="https://pkgs.tailscale.com/" + RC=0 + TEST_OUT=$($CURL "$TEST_URL" 2>&1) || RC=$? + if [ $RC != 0 ]; then + echo "The installer cannot reach $TEST_URL" + echo "Please make sure that your machine has internet access." + echo "Test output:" + echo $TEST_OUT + exit 1 + fi + # Step 2: having detected an OS we support, is it one of the # versions we support? OS_UNSUPPORTED= From 73d128238e123c92af985fee6e1d7c78c09e4d99 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 4 May 2023 10:17:54 -0700 Subject: [PATCH 062/331] envknob: support tailscaled-env.txt on macOS too Updates #3707 Co-authored-by: Marwan Sulaiman Signed-off-by: Brad Fitzpatrick --- envknob/envknob.go | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/envknob/envknob.go b/envknob/envknob.go index cd7440f9444c9..654131e2a34ab 100644 --- a/envknob/envknob.go +++ b/envknob/envknob.go @@ -457,13 +457,24 @@ var applyDiskConfigErr error // ApplyDiskConfigError returns the most recent result of ApplyDiskConfig. func ApplyDiskConfigError() error { return applyDiskConfigErr } -// ApplyDiskConfig returns a platform-specific config file of environment keys/values and -// applies them. On Linux and Unix operating systems, it's a no-op and always returns nil. -// If no platform-specific config file is found, it also returns nil. +// ApplyDiskConfig returns a platform-specific config file of environment +// keys/values and applies them. On Linux and Unix operating systems, it's a +// no-op and always returns nil. If no platform-specific config file is found, +// it also returns nil. +// +// It exists primarily for Windows and macOS to make it easy to apply +// environment variables to a running service in a way similar to modifying +// /etc/default/tailscaled on Linux. // -// It exists primarily for Windows to make it easy to apply environment variables to -// a running service in a way similar to modifying /etc/default/tailscaled on Linux. // On Windows, you use %ProgramData%\Tailscale\tailscaled-env.txt instead. +// +// On macOS, use one of: +// +// - ~/Library/Containers/io.tailscale.ipn.macsys/Data/tailscaled-env.txt +// for standalone macOS GUI builds +// - ~/Library/Containers/io.tailscale.ipn.macos.network-extension/Data/tailscaled-env.txt +// for App Store builds +// - /etc/tailscale/tailscaled-env.txt for tailscaled-on-macOS (homebrew, etc) func ApplyDiskConfig() (err error) { var f *os.File defer func() { @@ -512,9 +523,15 @@ func getPlatformEnvFile() string { return "/etc/tailscale/tailscaled-env.txt" } case "darwin": - // TODO(bradfitz): figure this out. There are three ways to run - // Tailscale on macOS (tailscaled, GUI App Store, GUI System Extension) - // and we should deal with all three. + if version.IsSandboxedMacOS() { // the two GUI variants (App Store or separate download) + // This will be user-visible as ~/Library/Containers/$VARIANT/Data/tailscaled-env.txt + // where $VARIANT is "io.tailscale.ipn.macsys" for macsys (downloadable mac GUI builds) + // or "io.tailscale.ipn.macos.network-extension" for App Store builds. + return filepath.Join(os.Getenv("HOME"), "tailscaled-env.txt") + } else { + // Open source / homebrew variable, running tailscaled-on-macOS. + return "/etc/tailscale/tailscaled-env.txt" + } } return "" } From f46c1aede0472b6a71f1382169f6f19578c76610 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Thu, 4 May 2023 11:33:00 -0700 Subject: [PATCH 063/331] go.mod: bump k8s libs The key is to update sigs.k8s.io/controller-runtime and let it update others. Updates #8043 Signed-off-by: Maisem Ali --- go.mod | 12 ++++++------ go.sum | 30 ++++++++++++++---------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 240da148459c0..eeafdd24cadf8 100644 --- a/go.mod +++ b/go.mod @@ -90,11 +90,11 @@ require ( inet.af/peercred v0.0.0-20210906144145-0893ea02156a inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 inet.af/wf v0.0.0-20221017222439-36129f591884 - k8s.io/api v0.25.0 - k8s.io/apimachinery v0.25.0 - k8s.io/client-go v0.25.0 + k8s.io/api v0.26.1 + k8s.io/apimachinery v0.26.1 + k8s.io/client-go v0.26.1 nhooyr.io/websocket v1.8.7 - sigs.k8s.io/controller-runtime v0.13.1 + sigs.k8s.io/controller-runtime v0.14.6 sigs.k8s.io/yaml v1.3.0 software.sslmate.com/src/go-pkcs12 v0.2.0 ) @@ -342,8 +342,8 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect howett.net/plist v1.0.0 // indirect - k8s.io/apiextensions-apiserver v0.25.0 // indirect - k8s.io/component-base v0.25.0 // indirect + k8s.io/apiextensions-apiserver v0.26.1 // indirect + k8s.io/component-base v0.26.1 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect diff --git a/go.sum b/go.sum index c8cdd290da4aa..8611600c82a45 100644 --- a/go.sum +++ b/go.sum @@ -821,14 +821,13 @@ github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3L github.com/nunnatsa/ginkgolinter v0.11.2 h1:xzQpAsEyZe5F1RMy2Z5kn8UFCGiWfKqJOUd2ZzBXA4M= github.com/nunnatsa/ginkgolinter v0.11.2/go.mod h1:dJIGXYXbkBswqa/pIzG0QlVTTDSBMxDoCFwhsl4Uras= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -1166,7 +1165,7 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -1686,7 +1685,6 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -1728,16 +1726,16 @@ inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 h1:2dMP3Ox/Wh5BiItwOt4jxRsfz inet.af/tcpproxy v0.0.0-20221017015627-91f861402626/go.mod h1:Tojt5kmHpDIR2jMojxzZK2w2ZR7OILODmUo2gaSwjrk= inet.af/wf v0.0.0-20221017222439-36129f591884 h1:zg9snq3Cpy50lWuVqDYM7AIRVTtU50y5WXETMFohW/Q= inet.af/wf v0.0.0-20221017222439-36129f591884/go.mod h1:bSAQ38BYbY68uwpasXOTZo22dKGy9SNvI6PZFeKomZE= -k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= -k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= -k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= -k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= -k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= -k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= -k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= -k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= -k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= -k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= +k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= +k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= +k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= +k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= +k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= +k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= +k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= @@ -1761,8 +1759,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg= -sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= +sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= From 48605226dd98ff12d854fb03bc32ee65922693f2 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Thu, 4 May 2023 11:10:19 -0700 Subject: [PATCH 064/331] go.mod: bump gvisor Periodic update for start of cycle. Updates #8043 Signed-off-by: James Tucker --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eeafdd24cadf8..baeab9328ea01 100644 --- a/go.mod +++ b/go.mod @@ -85,7 +85,7 @@ require ( golang.org/x/tools v0.8.0 golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 golang.zx2c4.com/wireguard/windows v0.5.3 - gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d + gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f honnef.co/go/tools v0.4.3 inet.af/peercred v0.0.0-20210906144145-0893ea02156a inet.af/tcpproxy v0.0.0-20221017015627-91f861402626 diff --git a/go.sum b/go.sum index 8611600c82a45..39d029aec3457 100644 --- a/go.sum +++ b/go.sum @@ -1706,8 +1706,8 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d h1:pzPNKWBCLdzu7KGiFnFGuvKsLf+pNkOzHSK6zJ9tMKY= -gvisor.dev/gvisor v0.0.0-20230328175328-162ed5ef888d/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q= +gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f h1:8GE2MRjGiFmfpon8dekPI08jEuNMQzSffVHgdupcO4E= +gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 1c6ff310ae311190b474e59d06a4a7124eeaa508 Mon Sep 17 00:00:00 2001 From: Flakes Updater Date: Thu, 4 May 2023 19:01:17 +0000 Subject: [PATCH 065/331] go.mod.sri: update SRI hash for go.mod changes Signed-off-by: Flakes Updater --- flake.nix | 2 +- go.mod.sri | 2 +- shell.nix | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index f16aea708ab6e..fff97101d9321 100644 --- a/flake.nix +++ b/flake.nix @@ -115,4 +115,4 @@ in flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system); } -# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= +# nix-direnv cache busting line: sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= diff --git a/go.mod.sri b/go.mod.sri index fb898c112801b..c9aec662dc1b2 100644 --- a/go.mod.sri +++ b/go.mod.sri @@ -1 +1 @@ -sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= +sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= diff --git a/shell.nix b/shell.nix index 2a58cdb076358..5a17c16f8d35e 100644 --- a/shell.nix +++ b/shell.nix @@ -16,4 +16,4 @@ ) { src = ./.; }).shellNix -# nix-direnv cache busting line: sha256-ZQ6aE+9PfAxfeNQeDzwcOCXpztLORVriHkEw51lbeHM= +# nix-direnv cache busting line: sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= From 5def4f4a1c09f08aedf4c4052f79f42fd2def8c9 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Thu, 4 May 2023 11:27:31 -0700 Subject: [PATCH 066/331] go.mod: bump goreleaser deps Periodic update for start of cycle. goreleaser is not updated to v2 yet, but indirects updated. Updates #8043 Signed-off-by: James Tucker --- go.mod | 7 ++++--- go.sum | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index baeab9328ea01..7ea5a142c944f 100644 --- a/go.mod +++ b/go.mod @@ -78,8 +78,8 @@ require ( golang.org/x/mod v0.10.0 golang.org/x/net v0.9.0 golang.org/x/oauth2 v0.7.0 - golang.org/x/sync v0.1.0 - golang.org/x/sys v0.7.0 + golang.org/x/sync v0.2.0 + golang.org/x/sys v0.8.0 golang.org/x/term v0.7.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.8.0 @@ -203,7 +203,7 @@ require ( github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2 // indirect github.com/google/rpmpack v0.0.0-20221120200012-98b63d62fd77 // indirect github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect - github.com/goreleaser/chglog v0.1.2 // indirect + github.com/goreleaser/chglog v0.4.2 // indirect github.com/goreleaser/fileglob v0.3.1 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect @@ -328,6 +328,7 @@ require ( github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect gitlab.com/bosi/decorder v0.2.3 // indirect + gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 // indirect diff --git a/go.sum b/go.sum index 39d029aec3457..aa6a8a2a19aff 100644 --- a/go.sum +++ b/go.sum @@ -526,11 +526,13 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/goreleaser/chglog v0.1.2 h1:tdzAb/ILeMnphzI9zQ7Nkq+T8R9qyXli8GydD8plFRY= github.com/goreleaser/chglog v0.1.2/go.mod h1:tTZsFuSZK4epDXfjMkxzcGbrIOXprf0JFp47BjIr3B8= +github.com/goreleaser/chglog v0.4.2 h1:afmbT1d7lX/q+GF8wv3a1Dofs2j/Y9YkiCpGemWR6mI= +github.com/goreleaser/chglog v0.4.2/go.mod h1:u/F03un4hMCQrp65qSWCkkC6T+G7YLKZ+AM2mITE47s= github.com/goreleaser/fileglob v0.3.1 h1:OTFDWqUUHjQazk2N5GdUqEbqT/grBnRARaAXsV07q1Y= github.com/goreleaser/fileglob v0.3.1/go.mod h1:kNcPrPzjCp+Ox3jmXLU5QEsjhqrtLBm6OnXAif8KRl8= github.com/goreleaser/nfpm v1.10.3 h1:NzpWKKzSFr7JOn55XN0SskyFOjP6BkvRt3JujoX8fws= @@ -646,6 +648,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -983,7 +986,9 @@ github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXi github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= @@ -1152,6 +1157,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= +gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= +gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -1335,8 +1342,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1424,8 +1432,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= From d1ce7a9b5ebb8c9acac6358ecc9b50f03bf09ca6 Mon Sep 17 00:00:00 2001 From: Flakes Updater Date: Thu, 4 May 2023 19:34:39 +0000 Subject: [PATCH 067/331] go.mod.sri: update SRI hash for go.mod changes Signed-off-by: Flakes Updater --- flake.nix | 2 +- go.mod.sri | 2 +- shell.nix | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index fff97101d9321..8d262428225f8 100644 --- a/flake.nix +++ b/flake.nix @@ -115,4 +115,4 @@ in flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system); } -# nix-direnv cache busting line: sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= +# nix-direnv cache busting line: sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs= diff --git a/go.mod.sri b/go.mod.sri index c9aec662dc1b2..f4faeb3f2e422 100644 --- a/go.mod.sri +++ b/go.mod.sri @@ -1 +1 @@ -sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= +sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs= diff --git a/shell.nix b/shell.nix index 5a17c16f8d35e..4bc2435e3499d 100644 --- a/shell.nix +++ b/shell.nix @@ -16,4 +16,4 @@ ) { src = ./.; }).shellNix -# nix-direnv cache busting line: sha256-fLAIAxWNvQm95YcEryrKFlv6WgBIo/IAo9sXfluL+bU= +# nix-direnv cache busting line: sha256-7L+dvS++UNfMVcPUCbK/xuBPwtrzW4RpZTtcl7VCwQs= From 0d7303b798e85da6a2c9cd6d86f0d9f165ceb4c4 Mon Sep 17 00:00:00 2001 From: Derek Kaser Date: Tue, 2 May 2023 23:57:52 -0400 Subject: [PATCH 068/331] various: add detection and Taildrop for Unraid Updates tailscale/tailscale#8025 Signed-off-by: Derek Kaser --- cmd/tailscale/cli/diag.go | 2 +- cmd/tailscaled/taildrop.go | 26 +++++++++++++++++++++++++- hostinfo/hostinfo_linux.go | 4 ++++ ipn/ipnlocal/peerapi.go | 5 +++++ version/distro/distro.go | 3 +++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/cmd/tailscale/cli/diag.go b/cmd/tailscale/cli/diag.go index 5ed6ba92b63b1..ebf26985fe0bd 100644 --- a/cmd/tailscale/cli/diag.go +++ b/cmd/tailscale/cli/diag.go @@ -66,7 +66,7 @@ func isSystemdSystem() bool { return false } switch distro.Get() { - case distro.QNAP, distro.Gokrazy, distro.Synology: + case distro.QNAP, distro.Gokrazy, distro.Synology, distro.Unraid: return false } _, err := exec.LookPath("systemctl") diff --git a/cmd/tailscaled/taildrop.go b/cmd/tailscaled/taildrop.go index 71be089db0c23..11f026e27312f 100644 --- a/cmd/tailscaled/taildrop.go +++ b/cmd/tailscaled/taildrop.go @@ -18,7 +18,7 @@ import ( func configureTaildrop(logf logger.Logf, lb *ipnlocal.LocalBackend) { dg := distro.Get() switch dg { - case distro.Synology, distro.TrueNAS, distro.QNAP: + case distro.Synology, distro.TrueNAS, distro.QNAP, distro.Unraid: // See if they have a "Taildrop" share. // See https://github.com/tailscale/tailscale/issues/2179#issuecomment-982821319 path, err := findTaildropDir(dg) @@ -42,6 +42,8 @@ func findTaildropDir(dg distro.Distro) (string, error) { return findTrueNASTaildropDir(name) case distro.QNAP: return findQnapTaildropDir(name) + case distro.Unraid: + return findUnraidTaildropDir(name) } return "", fmt.Errorf("%s is an unsupported distro for Taildrop dir", dg) } @@ -103,3 +105,25 @@ func findQnapTaildropDir(name string) (string, error) { } return "", fmt.Errorf("shared folder %q not found", name) } + +// findUnraidTaildropDir looks for a directory linked at +// /var/lib/tailscale/Taildrop. This is a symlink to the +// path specified by the user in the Unraid Web UI +func findUnraidTaildropDir(name string) (string, error) { + dir := fmt.Sprintf("/var/lib/tailscale/%s", name) + _, err := os.Stat(dir) + if err != nil { + return "", fmt.Errorf("symlink %q not found", name) + } + + fullpath, err := filepath.EvalSymlinks(dir) + if err != nil { + return "", fmt.Errorf("symlink %q to shared folder not valid", name) + } + + fi, err := os.Stat(fullpath) + if err == nil && fi.IsDir() { + return dir, nil // return the symlink + } + return "", fmt.Errorf("shared folder %q not found", name) +} diff --git a/hostinfo/hostinfo_linux.go b/hostinfo/hostinfo_linux.go index 6c2ab8ff85ebf..d52c084b8966a 100644 --- a/hostinfo/hostinfo_linux.go +++ b/hostinfo/hostinfo_linux.go @@ -95,6 +95,8 @@ func linuxVersionMeta() (meta versionMeta) { propFile = "/etc.defaults/VERSION" case distro.OpenWrt: propFile = "/etc/openwrt_release" + case distro.Unraid: + propFile = "/etc/unraid-version" case distro.WDMyCloud: slurp, _ := os.ReadFile("/etc/version") meta.DistroVersion = string(bytes.TrimSpace(slurp)) @@ -153,6 +155,8 @@ func linuxVersionMeta() (meta versionMeta) { meta.DistroVersion = m["productversion"] case distro.OpenWrt: meta.DistroVersion = m["DISTRIB_RELEASE"] + case distro.Unraid: + meta.DistroVersion = m["version"] } return } diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index fa749d995f53b..e8e06b6eed135 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -49,6 +49,7 @@ import ( "tailscale.com/tailcfg" "tailscale.com/util/clientmetric" "tailscale.com/util/multierr" + "tailscale.com/version/distro" "tailscale.com/wgengine" "tailscale.com/wgengine/filter" ) @@ -1090,6 +1091,10 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) { http.Error(w, errNoTaildrop.Error(), http.StatusInternalServerError) return } + if distro.Get() == distro.Unraid && !h.ps.directFileMode { + http.Error(w, "Taildrop folder not configured or accessible", http.StatusInternalServerError) + return + } rawPath := r.URL.EscapedPath() suffix, ok := strings.CutPrefix(rawPath, "/v0/put/") if !ok { diff --git a/version/distro/distro.go b/version/distro/distro.go index 0724265a4630e..e319d1ba72645 100644 --- a/version/distro/distro.go +++ b/version/distro/distro.go @@ -29,6 +29,7 @@ const ( TrueNAS = Distro("truenas") Gokrazy = Distro("gokrazy") WDMyCloud = Distro("wdmycloud") + Unraid = Distro("unraid") ) var distro lazy.SyncValue[Distro] @@ -90,6 +91,8 @@ func linuxDistro() Distro { return WDMyCloud case have("/usr/sbin/wd_crontab.sh"): // Western Digital MyCloud OS5 return WDMyCloud + case have("/etc/unraid-version"): + return Unraid } return "" } From 6e967446e412a5f54d9a5888d6514520ff4e40ae Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 3 May 2023 13:57:17 -0700 Subject: [PATCH 069/331] tsd: add package with System type to unify subsystem init, discovery This is part of an effort to clean up tailscaled initialization between tailscaled, tailscaled Windows service, tsnet, and the mac GUI. Updates #8036 Signed-off-by: Brad Fitzpatrick --- cmd/tailscaled/depaware.txt | 1 + cmd/tailscaled/tailscaled.go | 97 +++++++------ cmd/tailscaled/tailscaled_windows.go | 9 +- cmd/tsconnect/wasm/wasm_js.go | 13 +- ipn/ipnlocal/local.go | 67 ++++----- ipn/ipnlocal/local_test.go | 15 +- ipn/ipnlocal/loglines_test.go | 8 +- ipn/ipnlocal/peerapi.go | 12 +- ipn/ipnlocal/serve.go | 2 +- ipn/ipnlocal/state_test.go | 23 ++- ipn/ipnserver/server.go | 7 +- net/tstun/fake.go | 5 +- ssh/tailssh/tailssh_test.go | 11 +- tsd/tsd.go | 135 ++++++++++++++++++ tsnet/tsnet.go | 20 +-- .../tailscaled_deps_test_darwin.go | 1 + .../tailscaled_deps_test_freebsd.go | 1 + .../integration/tailscaled_deps_test_linux.go | 1 + .../tailscaled_deps_test_openbsd.go | 1 + .../tailscaled_deps_test_windows.go | 1 + wgengine/netstack/netstack_test.go | 42 +++--- wgengine/netstack/subnet_router_wrapper.go | 7 - wgengine/userspace.go | 101 +++++-------- wgengine/userspace_ext_test.go | 30 ++-- wgengine/watchdog.go | 19 --- wgengine/wgengine.go | 4 - 26 files changed, 373 insertions(+), 260 deletions(-) create mode 100644 tsd/tsd.go diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 58f61e60ed60b..7e51976fc8f55 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -282,6 +282,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de LD tailscale.com/tempfork/gliderlabs/ssh from tailscale.com/ssh/tailssh tailscale.com/tka from tailscale.com/ipn/ipnlocal+ W tailscale.com/tsconst from tailscale.com/net/interfaces + tailscale.com/tsd from tailscale.com/cmd/tailscaled+ tailscale.com/tstime from tailscale.com/wgengine/magicsock 💣 tailscale.com/tstime/mono from tailscale.com/net/tstun+ tailscale.com/tstime/rate from tailscale.com/wgengine/filter+ diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index d2c28de99ee3d..0d46cdb0f13e8 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -50,6 +50,7 @@ import ( "tailscale.com/safesocket" "tailscale.com/smallzstd" "tailscale.com/syncs" + "tailscale.com/tsd" "tailscale.com/tsweb/varz" "tailscale.com/types/flagtype" "tailscale.com/types/logger" @@ -330,12 +331,16 @@ var debugMux *http.ServeMux func run() error { var logf logger.Logf = log.Printf + + sys := new(tsd.System) + netMon, err := netmon.New(func(format string, args ...any) { logf(format, args...) }) if err != nil { return fmt.Errorf("netmon.New: %w", err) } + sys.Set(netMon) pol := logpolicy.New(logtail.CollectionNode, netMon) pol.SetVerbosityLevel(args.verbose) @@ -386,10 +391,10 @@ func run() error { debugMux = newDebugMux() } - return startIPNServer(context.Background(), logf, pol.PublicID, netMon) + return startIPNServer(context.Background(), logf, pol.PublicID, sys) } -func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) error { +func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, sys *tsd.System) error { ln, err := safesocket.Listen(args.socketpath) if err != nil { return fmt.Errorf("safesocket.Listen: %v", err) @@ -415,7 +420,7 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, } }() - srv := ipnserver.New(logf, logID, netMon) + srv := ipnserver.New(logf, logID, sys.NetMon.Get()) if debugMux != nil { debugMux.HandleFunc("/debug/ipn", srv.ServeHTMLStatus) } @@ -433,7 +438,7 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, return } } - lb, err := getLocalBackend(ctx, logf, logID, netMon) + lb, err := getLocalBackend(ctx, logf, logID, sys) if err == nil { logf("got LocalBackend in %v", time.Since(t0).Round(time.Millisecond)) srv.SetLocalBackend(lb) @@ -457,31 +462,28 @@ func startIPNServer(ctx context.Context, logf logger.Logf, logID logid.PublicID, return nil } -func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) (_ *ipnlocal.LocalBackend, retErr error) { +func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID, sys *tsd.System) (_ *ipnlocal.LocalBackend, retErr error) { if logPol != nil { - logPol.Logtail.SetNetMon(netMon) + logPol.Logtail.SetNetMon(sys.NetMon.Get()) } socksListener, httpProxyListener := mustStartProxyListeners(args.socksAddr, args.httpProxyAddr) dialer := &tsdial.Dialer{Logf: logf} // mutated below (before used) - e, onlyNetstack, err := createEngine(logf, netMon, dialer) + sys.Set(dialer) + + onlyNetstack, err := createEngine(logf, sys) if err != nil { return nil, fmt.Errorf("createEngine: %w", err) } - if _, ok := e.(wgengine.ResolvingEngine).GetResolver(); !ok { - panic("internal error: exit node resolver not wired up") - } if debugMux != nil { - if ig, ok := e.(wgengine.InternalsGetter); ok { - if _, mc, _, ok := ig.GetInternals(); ok { - debugMux.HandleFunc("/debug/magicsock", mc.ServeHTTPDebug) - } + if ms, ok := sys.MagicSock.GetOK(); ok { + debugMux.HandleFunc("/debug/magicsock", ms.ServeHTTPDebug) } go runDebugServer(debugMux, args.debug) } - ns, err := newNetstack(logf, dialer, e) + ns, err := newNetstack(logf, sys) if err != nil { return nil, fmt.Errorf("newNetstack: %w", err) } @@ -489,6 +491,7 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID ns.ProcessSubnets = onlyNetstack || handleSubnetsInNetstack() if onlyNetstack { + e := sys.Engine.Get() dialer.UseNetstackForIP = func(ip netip.Addr) bool { _, ok := e.PeerForIP(ip) return ok @@ -519,16 +522,15 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID tshttpproxy.SetSelfProxy(addrs...) } - e = wgengine.NewWatchdog(e) - opts := ipnServerOpts() store, err := store.New(logf, statePathOrDefault()) if err != nil { return nil, fmt.Errorf("store.New: %w", err) } + sys.Set(store) - lb, err := ipnlocal.NewLocalBackend(logf, logID, store, dialer, e, opts.LoginFlags) + lb, err := ipnlocal.NewLocalBackend(logf, logID, sys, opts.LoginFlags) if err != nil { return nil, fmt.Errorf("ipnlocal.NewLocalBackend: %w", err) } @@ -554,21 +556,21 @@ func getLocalBackend(ctx context.Context, logf logger.Logf, logID logid.PublicID // // onlyNetstack is true if the user has explicitly requested that we use netstack // for all networking. -func createEngine(logf logger.Logf, netMon *netmon.Monitor, dialer *tsdial.Dialer) (e wgengine.Engine, onlyNetstack bool, err error) { +func createEngine(logf logger.Logf, sys *tsd.System) (onlyNetstack bool, err error) { if args.tunname == "" { - return nil, false, errors.New("no --tun value specified") + return false, errors.New("no --tun value specified") } var errs []error for _, name := range strings.Split(args.tunname, ",") { logf("wgengine.NewUserspaceEngine(tun %q) ...", name) - e, onlyNetstack, err = tryEngine(logf, netMon, dialer, name) + onlyNetstack, err = tryEngine(logf, sys, name) if err == nil { - return e, onlyNetstack, nil + return onlyNetstack, nil } logf("wgengine.NewUserspaceEngine(tun %q) error: %v", name, err) errs = append(errs, err) } - return nil, false, multierr.New(errs...) + return false, multierr.New(errs...) } // handleSubnetsInNetstack reports whether netstack should handle subnet routers @@ -593,21 +595,23 @@ func handleSubnetsInNetstack() bool { var tstunNew = tstun.New -func tryEngine(logf logger.Logf, netMon *netmon.Monitor, dialer *tsdial.Dialer, name string) (e wgengine.Engine, onlyNetstack bool, err error) { +func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack bool, err error) { conf := wgengine.Config{ - ListenPort: args.port, - NetMon: netMon, - Dialer: dialer, + ListenPort: args.port, + NetMon: sys.NetMon.Get(), + Dialer: sys.Dialer.Get(), + SetSubsystem: sys.Set, } onlyNetstack = name == "userspace-networking" + netstackSubnetRouter := onlyNetstack // but mutated later on some platforms netns.SetEnabled(!onlyNetstack) if args.birdSocketPath != "" && createBIRDClient != nil { log.Printf("Connecting to BIRD at %s ...", args.birdSocketPath) conf.BIRDClient, err = createBIRDClient(args.birdSocketPath) if err != nil { - return nil, false, fmt.Errorf("createBIRDClient: %w", err) + return false, fmt.Errorf("createBIRDClient: %w", err) } } if onlyNetstack { @@ -620,44 +624,55 @@ func tryEngine(logf logger.Logf, netMon *netmon.Monitor, dialer *tsdial.Dialer, // TODO(bradfitz): add a Synology-specific DNS manager. conf.DNS, err = dns.NewOSConfigurator(logf, "") // empty interface name if err != nil { - return nil, false, fmt.Errorf("dns.NewOSConfigurator: %w", err) + return false, fmt.Errorf("dns.NewOSConfigurator: %w", err) } } } else { dev, devName, err := tstunNew(logf, name) if err != nil { tstun.Diagnose(logf, name, err) - return nil, false, fmt.Errorf("tstun.New(%q): %w", name, err) + return false, fmt.Errorf("tstun.New(%q): %w", name, err) } conf.Tun = dev if strings.HasPrefix(name, "tap:") { conf.IsTAP = true e, err := wgengine.NewUserspaceEngine(logf, conf) - return e, false, err + if err != nil { + return false, err + } + sys.Set(e) + return false, err } - r, err := router.New(logf, dev, netMon) + r, err := router.New(logf, dev, sys.NetMon.Get()) if err != nil { dev.Close() - return nil, false, fmt.Errorf("creating router: %w", err) + return false, fmt.Errorf("creating router: %w", err) } + sys.Set(r) + d, err := dns.NewOSConfigurator(logf, devName) if err != nil { dev.Close() r.Close() - return nil, false, fmt.Errorf("dns.NewOSConfigurator: %w", err) + return false, fmt.Errorf("dns.NewOSConfigurator: %w", err) } conf.DNS = d conf.Router = r if handleSubnetsInNetstack() { conf.Router = netstack.NewSubnetRouterWrapper(conf.Router) + netstackSubnetRouter = true } } - e, err = wgengine.NewUserspaceEngine(logf, conf) + e, err := wgengine.NewUserspaceEngine(logf, conf) if err != nil { - return nil, onlyNetstack, err + return onlyNetstack, err } - return e, onlyNetstack, nil + e = wgengine.NewWatchdog(e) + sys.Set(e) + sys.NetstackRouter.Set(netstackSubnetRouter) + + return onlyNetstack, nil } func newDebugMux() *http.ServeMux { @@ -687,12 +702,8 @@ func runDebugServer(mux *http.ServeMux, addr string) { } } -func newNetstack(logf logger.Logf, dialer *tsdial.Dialer, e wgengine.Engine) (*netstack.Impl, error) { - tunDev, magicConn, dns, ok := e.(wgengine.InternalsGetter).GetInternals() - if !ok { - return nil, fmt.Errorf("%T is not a wgengine.InternalsGetter", e) - } - return netstack.Create(logf, tunDev, e, magicConn, dialer, dns) +func newNetstack(logf logger.Logf, sys *tsd.System) (*netstack.Impl, error) { + return netstack.Create(logf, sys.Tun.Get(), sys.Engine.Get(), sys.MagicSock.Get(), sys.Dialer.Get(), sys.DNSManager.Get()) } // mustStartProxyListeners creates listeners for local SOCKS and HTTP diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go index 077d3f99f2c7f..ae538bed6ac4f 100644 --- a/cmd/tailscaled/tailscaled_windows.go +++ b/cmd/tailscaled/tailscaled_windows.go @@ -47,6 +47,7 @@ import ( "tailscale.com/net/dns" "tailscale.com/net/netmon" "tailscale.com/net/tstun" + "tailscale.com/tsd" "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/util/winutil" @@ -292,13 +293,15 @@ func beWindowsSubprocess() bool { } }() + sys := new(tsd.System) netMon, err := netmon.New(log.Printf) if err != nil { - log.Printf("Could not create netMon: %v", err) - netMon = nil + log.Fatalf("Could not create netMon: %v", err) } + sys.Set(netMon) + publicLogID, _ := logid.ParsePublicID(logID) - err = startIPNServer(ctx, log.Printf, publicLogID, netMon) + err = startIPNServer(ctx, log.Printf, publicLogID, sys) if err != nil { log.Fatalf("ipnserver: %v", err) } diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index a1b0fd95e0a15..153941b29b3de 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -37,6 +37,7 @@ import ( "tailscale.com/safesocket" "tailscale.com/smallzstd" "tailscale.com/tailcfg" + "tailscale.com/tsd" "tailscale.com/wgengine" "tailscale.com/wgengine/netstack" "tailscale.com/words" @@ -96,6 +97,8 @@ func newIPN(jsConfig js.Value) map[string]any { logtail := logtail.NewLogger(c, log.Printf) logf := logtail.Logf + sys := new(tsd.System) + sys.Set(store) dialer := &tsdial.Dialer{Logf: logf} eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ Dialer: dialer, @@ -103,12 +106,9 @@ func newIPN(jsConfig js.Value) map[string]any { if err != nil { log.Fatal(err) } + sys.Set(eng) - tunDev, magicConn, dnsManager, ok := eng.(wgengine.InternalsGetter).GetInternals() - if !ok { - log.Fatalf("%T is not a wgengine.InternalsGetter", eng) - } - ns, err := netstack.Create(logf, tunDev, eng, magicConn, dialer, dnsManager) + ns, err := netstack.Create(logf, sys.Tun.Get(), eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get()) if err != nil { log.Fatalf("netstack.Create: %v", err) } @@ -121,10 +121,11 @@ func newIPN(jsConfig js.Value) map[string]any { dialer.NetstackDialTCP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { return ns.DialContextTCP(ctx, dst) } + sys.NetstackRouter.Set(true) logid := lpc.PublicID srv := ipnserver.New(logf, logid, nil /* no netMon */) - lb, err := ipnlocal.NewLocalBackend(logf, logid, store, dialer, eng, controlclient.LoginEphemeral) + lb, err := ipnlocal.NewLocalBackend(logf, logid, sys, controlclient.LoginEphemeral) if err != nil { log.Fatalf("ipnlocal.NewLocalBackend: %v", err) } diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index e2894e6633ca4..15202b0fd06a8 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -60,6 +60,7 @@ import ( "tailscale.com/syncs" "tailscale.com/tailcfg" "tailscale.com/tka" + "tailscale.com/tsd" "tailscale.com/types/dnstype" "tailscale.com/types/empty" "tailscale.com/types/key" @@ -137,10 +138,11 @@ type LocalBackend struct { logf logger.Logf // general logging keyLogf logger.Logf // for printing list of peers on change statsLogf logger.Logf // for printing peers stats on change - e wgengine.Engine + sys *tsd.System + e wgengine.Engine // non-nil; TODO(bradfitz): remove; use sys pm *profileManager - store ipn.StateStore - dialer *tsdial.Dialer // non-nil + store ipn.StateStore // non-nil; TODO(bradfitz): remove; use sys + dialer *tsdial.Dialer // non-nil; TODO(bradfitz): remove; use sys backendLogID logid.PublicID unregisterNetMon func() unregisterHealthWatch func() @@ -267,10 +269,10 @@ type clientGen func(controlclient.Options) (controlclient.Client, error) // but is not actually running. // // If dialer is nil, a new one is made. -func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStore, dialer *tsdial.Dialer, e wgengine.Engine, loginFlags controlclient.LoginFlags) (*LocalBackend, error) { - if e == nil { - panic("ipn.NewLocalBackend: engine must not be nil") - } +func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, loginFlags controlclient.LoginFlags) (*LocalBackend, error) { + e := sys.Engine.Get() + store := sys.StateStore.Get() + dialer := sys.Dialer.Get() pm, err := newProfileManager(store, logf) if err != nil { @@ -301,10 +303,11 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor logf: logf, keyLogf: logger.LogOnChange(logf, 5*time.Minute, time.Now), statsLogf: logger.LogOnChange(logf, 5*time.Minute, time.Now), + sys: sys, e: e, - pm: pm, - store: store, dialer: dialer, + store: store, + pm: pm, backendLogID: logID, state: ipn.NoState, portpoll: portpoll, @@ -313,7 +316,8 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor loginFlags: loginFlags, } - b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID, e.GetNetMon()) + netMon := sys.NetMon.Get() + b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID, netMon) if err != nil { log.Printf("error setting up sockstat logger: %v", err) } @@ -330,7 +334,6 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor b.statusChanged = sync.NewCond(&b.statusLock) b.e.SetStatusCallback(b.setWgengineStatus) - netMon := e.GetNetMon() b.prevIfState = netMon.InterfaceState() // Call our linkChange code once with the current state, and // then also whenever it changes: @@ -339,14 +342,9 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor b.unregisterHealthWatch = health.RegisterWatcher(b.onHealthChange) - wiredPeerAPIPort := false - if ig, ok := e.(wgengine.InternalsGetter); ok { - if tunWrap, _, _, ok := ig.GetInternals(); ok { - tunWrap.PeerAPIPort = b.GetPeerAPIPort - wiredPeerAPIPort = true - } - } - if !wiredPeerAPIPort { + if tunWrap, ok := b.sys.Tun.GetOK(); ok { + tunWrap.PeerAPIPort = b.GetPeerAPIPort + } else { b.logf("[unexpected] failed to wire up PeerAPI port for engine %T", e) } @@ -464,6 +462,7 @@ func (b *LocalBackend) GetComponentDebugLogging(component string) time.Time { } // Dialer returns the backend's dialer. +// It is always non-nil. func (b *LocalBackend) Dialer() *tsdial.Dialer { return b.dialer } @@ -644,7 +643,7 @@ func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func defer b.mu.Unlock() sb.MutateStatus(func(s *ipnstate.Status) { s.Version = version.Long() - s.TUN = !wgengine.IsNetstack(b.e) + s.TUN = !b.sys.IsNetstack() s.BackendState = b.state.String() s.AuthURL = b.authURLSticky if err := health.OverallError(); err != nil { @@ -1315,8 +1314,8 @@ func (b *LocalBackend) Start(opts ipn.Options) error { hostinfo := hostinfo.New() hostinfo.BackendLogID = b.backendLogID.String() hostinfo.FrontendLogID = opts.FrontendLogID - hostinfo.Userspace.Set(wgengine.IsNetstack(b.e)) - hostinfo.UserspaceRouter.Set(wgengine.IsNetstackRouter(b.e)) + hostinfo.Userspace.Set(b.sys.IsNetstack()) + hostinfo.UserspaceRouter.Set(b.sys.IsNetstackRouter()) if b.cc != nil { // TODO(apenwarr): avoid the need to reinit controlclient. @@ -1401,7 +1400,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { var err error - isNetstack := wgengine.IsNetstackRouter(b.e) + isNetstack := b.sys.IsNetstackRouter() debugFlags := controlDebugFlags if isNetstack { debugFlags = append([]string{"netstack"}, debugFlags...) @@ -1423,7 +1422,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { HTTPTestClient: httpTestClient, DiscoPublicKey: discoPublic, DebugFlags: debugFlags, - NetMon: b.e.GetNetMon(), + NetMon: b.sys.NetMon.Get(), Pinger: b, PopBrowserURL: b.tellClientToBrowseToURL, OnClientVersion: b.onClientVersion, @@ -3317,14 +3316,12 @@ func (b *LocalBackend) initPeerAPIListener() { directFileMode: b.directFileRoot != "", directFileDoFinalRename: b.directFileDoFinalRename, } - if re, ok := b.e.(wgengine.ResolvingEngine); ok { - if r, ok := re.GetResolver(); ok { - ps.resolver = r - } + if dm, ok := b.sys.DNSManager.GetOK(); ok { + ps.resolver = dm.Resolver() } b.peerAPIServer = ps - isNetstack := wgengine.IsNetstack(b.e) + isNetstack := b.sys.IsNetstack() for i, a := range b.netMap.Addresses { var ln net.Listener var err error @@ -4040,7 +4037,7 @@ func (b *LocalBackend) setTCPPortsInterceptedFromNetmapAndPrefsLocked(prefs ipn. b.setServeProxyHandlersLocked() // don't listen on netmap addresses if we're in userspace mode - if !wgengine.IsNetstack(b.e) { + if !b.sys.IsNetstack() { b.updateServeTCPPortNetMapAddrListenersLocked(servePorts) } } @@ -4391,7 +4388,7 @@ func nodeIP(n *tailcfg.Node, pred func(netip.Addr) bool) netip.Addr { } func (b *LocalBackend) CheckIPForwarding() error { - if wgengine.IsNetstackRouter(b.e) { + if b.sys.IsNetstackRouter() { return nil } @@ -4537,13 +4534,9 @@ func (b *LocalBackend) DebugReSTUN() error { } func (b *LocalBackend) magicConn() (*magicsock.Conn, error) { - ig, ok := b.e.(wgengine.InternalsGetter) - if !ok { - return nil, errors.New("engine isn't InternalsGetter") - } - _, mc, _, ok := ig.GetInternals() + mc, ok := b.sys.MagicSock.GetOK() if !ok { - return nil, errors.New("failed to get internals") + return nil, errors.New("failed to get magicsock from sys") } return mc, nil } diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 2a474e46d672b..9fd44def8f4d0 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -20,6 +20,7 @@ import ( "tailscale.com/net/interfaces" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" + "tailscale.com/tsd" "tailscale.com/tstest" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -501,13 +502,16 @@ func TestLazyMachineKeyGeneration(t *testing.T) { tstest.Replace(t, &panicOnMachineKeyGeneration, func() bool { return true }) var logf logger.Logf = logger.Discard + sys := new(tsd.System) store := new(mem.Store) - eng, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys.Set(store) + eng, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatalf("NewFakeUserspaceEngine: %v", err) } t.Cleanup(eng.Close) - lb, err := NewLocalBackend(logf, logid.PublicID{}, store, nil, eng, 0) + sys.Set(eng) + lb, err := NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatalf("NewLocalBackend: %v", err) } @@ -765,13 +769,16 @@ func TestPacketFilterPermitsUnlockedNodes(t *testing.T) { func TestStatusWithoutPeers(t *testing.T) { logf := tstest.WhileTestRunningLogger(t) store := new(testStateStorage) - e, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys := new(tsd.System) + sys.Set(store) + e, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatalf("NewFakeUserspaceEngine: %v", err) } + sys.Set(e) t.Cleanup(e.Close) - b, err := NewLocalBackend(logf, logid.PublicID{}, store, nil, e, 0) + b, err := NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatalf("NewLocalBackend: %v", err) } diff --git a/ipn/ipnlocal/loglines_test.go b/ipn/ipnlocal/loglines_test.go index cde3f9198dc0d..361791858a65e 100644 --- a/ipn/ipnlocal/loglines_test.go +++ b/ipn/ipnlocal/loglines_test.go @@ -12,6 +12,7 @@ import ( "tailscale.com/ipn/ipnstate" "tailscale.com/ipn/store/mem" "tailscale.com/tailcfg" + "tailscale.com/tsd" "tailscale.com/tstest" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -47,14 +48,17 @@ func TestLocalLogLines(t *testing.T) { idA := logid(0xaa) // set up a LocalBackend, super bare bones. No functional data. + sys := new(tsd.System) store := new(mem.Store) - e, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys.Set(store) + e, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatal(err) } t.Cleanup(e.Close) + sys.Set(e) - lb, err := NewLocalBackend(logf, idA, store, nil, e, 0) + lb, err := NewLocalBackend(logf, idA, sys, 0) if err != nil { t.Fatal(err) } diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index e8e06b6eed135..e4e69727f6529 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -50,7 +50,6 @@ import ( "tailscale.com/util/clientmetric" "tailscale.com/util/multierr" "tailscale.com/version/distro" - "tailscale.com/wgengine" "tailscale.com/wgengine/filter" ) @@ -469,7 +468,7 @@ func (s *peerAPIServer) listen(ip netip.Addr, ifState *interfaces.State) (ln net } } - if wgengine.IsNetstack(s.b.e) { + if s.b.sys.IsNetstack() { ipStr = "" } @@ -1239,12 +1238,9 @@ func (h *peerAPIHandler) handleServeMagicsock(w http.ResponseWriter, r *http.Req http.Error(w, "denied; no debug access", http.StatusForbidden) return } - eng := h.ps.b.e - if ig, ok := eng.(wgengine.InternalsGetter); ok { - if _, mc, _, ok := ig.GetInternals(); ok { - mc.ServeHTTPDebug(w, r) - return - } + if mc, ok := h.ps.b.sys.MagicSock.GetOK(); ok { + mc.ServeHTTPDebug(w, r) + return } http.Error(w, "miswired", 500) } diff --git a/ipn/ipnlocal/serve.go b/ipn/ipnlocal/serve.go index e6d1d010455a4..7bf4604ddc635 100644 --- a/ipn/ipnlocal/serve.go +++ b/ipn/ipnlocal/serve.go @@ -143,7 +143,7 @@ func (s *serveListener) Run() { } func (s *serveListener) shouldWarnAboutListenError(err error) bool { - if !s.b.e.GetNetMon().InterfaceState().HasIP(s.ap.Addr()) { + if !s.b.sys.NetMon.Get().InterfaceState().HasIP(s.ap.Addr()) { // Machine likely doesn't have IPv6 enabled (or the IP is still being // assigned). No need to warn. Notably, WSL2 (Issue 6303). return false diff --git a/ipn/ipnlocal/state_test.go b/ipn/ipnlocal/state_test.go index 7a2c7132e2525..22e4ada826611 100644 --- a/ipn/ipnlocal/state_test.go +++ b/ipn/ipnlocal/state_test.go @@ -17,6 +17,7 @@ import ( "tailscale.com/ipn" "tailscale.com/ipn/store/mem" "tailscale.com/tailcfg" + "tailscale.com/tsd" "tailscale.com/tstest" "tailscale.com/types/empty" "tailscale.com/types/key" @@ -297,14 +298,17 @@ func TestStateMachine(t *testing.T) { c := qt.New(t) logf := tstest.WhileTestRunningLogger(t) + sys := new(tsd.System) store := new(testStateStorage) - e, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys.Set(store) + e, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatalf("NewFakeUserspaceEngine: %v", err) } t.Cleanup(e.Close) + sys.Set(e) - b, err := NewLocalBackend(logf, logid.PublicID{}, store, nil, e, 0) + b, err := NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatalf("NewLocalBackend: %v", err) } @@ -941,13 +945,16 @@ func TestStateMachine(t *testing.T) { func TestEditPrefsHasNoKeys(t *testing.T) { logf := tstest.WhileTestRunningLogger(t) - e, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys := new(tsd.System) + sys.Set(new(mem.Store)) + e, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatalf("NewFakeUserspaceEngine: %v", err) } t.Cleanup(e.Close) + sys.Set(e) - b, err := NewLocalBackend(logf, logid.PublicID{}, new(mem.Store), nil, e, 0) + b, err := NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatalf("NewLocalBackend: %v", err) } @@ -1023,10 +1030,14 @@ func TestWGEngineStatusRace(t *testing.T) { t.Skip("test fails") c := qt.New(t) logf := tstest.WhileTestRunningLogger(t) - eng, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys := new(tsd.System) + sys.Set(new(mem.Store)) + + eng, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) c.Assert(err, qt.IsNil) t.Cleanup(eng.Close) - b, err := NewLocalBackend(logf, logid.PublicID{}, new(mem.Store), nil, eng, 0) + sys.Set(eng) + b, err := NewLocalBackend(logf, logid.PublicID{}, sys, 0) c.Assert(err, qt.IsNil) var cc *mockControl diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 3abfa93646f91..705c01016092d 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -37,7 +37,7 @@ import ( type Server struct { lb atomic.Pointer[ipnlocal.LocalBackend] logf logger.Logf - netMon *netmon.Monitor // optional; nil means interfaces will be looked up on-demand + netMon *netmon.Monitor // must be non-nil backendLogID logid.PublicID // resetOnZero is whether to call bs.Reset on transition from // 1->0 active HTTP requests. That is, this is whether the backend is @@ -410,14 +410,15 @@ func (s *Server) addActiveHTTPRequest(req *http.Request, ci *ipnauth.ConnIdentit } // New returns a new Server. -// The netMon parameter is optional; if non-nil it's used to do faster interface -// lookups. // // To start it, use the Server.Run method. // // At some point, either before or after Run, the Server's SetLocalBackend // method must also be called before Server can do anything useful. func New(logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) *Server { + if netMon == nil { + panic("nil netMon") + } return &Server{ backendLogID: logID, logf: logf, diff --git a/net/tstun/fake.go b/net/tstun/fake.go index 4bf29d0935aed..d1ae467faa376 100644 --- a/net/tstun/fake.go +++ b/net/tstun/fake.go @@ -47,8 +47,11 @@ func (t *fakeTUN) Write(b [][]byte, n int) (int, error) { return 1, nil } +// FakeTUNName is the name of the fake TUN device. +const FakeTUNName = "FakeTUN" + func (t *fakeTUN) Flush() error { return nil } func (t *fakeTUN) MTU() (int, error) { return 1500, nil } -func (t *fakeTUN) Name() (string, error) { return "FakeTUN", nil } +func (t *fakeTUN) Name() (string, error) { return FakeTUNName, nil } func (t *fakeTUN) Events() <-chan tun.Event { return t.evchan } func (t *fakeTUN) BatchSize() int { return 1 } diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index c0935d24bc01f..607b4eeaa4238 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -38,6 +38,7 @@ import ( "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/tempfork/gliderlabs/ssh" + "tailscale.com/tsd" "tailscale.com/tstest" "tailscale.com/types/logger" "tailscale.com/types/logid" @@ -815,14 +816,14 @@ func TestSSHAuthFlow(t *testing.T) { func TestSSH(t *testing.T) { var logf logger.Logf = t.Logf - eng, err := wgengine.NewFakeUserspaceEngine(logf, 0) + sys := &tsd.System{} + eng, err := wgengine.NewFakeUserspaceEngine(logf, sys.Set) if err != nil { t.Fatal(err) } - lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, - new(mem.Store), - new(tsdial.Dialer), - eng, 0) + sys.Set(eng) + sys.Set(new(mem.Store)) + lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatal(err) } diff --git a/tsd/tsd.go b/tsd/tsd.go new file mode 100644 index 0000000000000..ffa245bc9c5f7 --- /dev/null +++ b/tsd/tsd.go @@ -0,0 +1,135 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// Package tsd (short for "Tailscale Daemon") contains a System type that +// containing all the subsystems a Tailscale node (tailscaled or platform +// equivalent) uses. +// +// The goal of this package (as of 2023-05-03) is to eventually unify +// initialization across tailscaled, tailscaled as a Windows services, the mac +// GUI, tsnet, wasm, tests, and other places that wire up all the subsystems. +// And doing so without weird optional interface accessors on some subsystems +// that return other subsystems. It's all a work in progress. +// +// This package depends on nearly all parts of Tailscale, so it should not be +// imported by (or thus passed to) any package that does not want to depend on +// the world. In practice this means that only things like cmd/tailscaled, +// ipn/ipnlocal, and ipn/ipnserver should import this package. +package tsd + +import ( + "fmt" + "reflect" + + "tailscale.com/ipn" + "tailscale.com/net/dns" + "tailscale.com/net/netmon" + "tailscale.com/net/tsdial" + "tailscale.com/net/tstun" + "tailscale.com/wgengine" + "tailscale.com/wgengine/magicsock" + "tailscale.com/wgengine/router" +) + +// System contains all the subsystems of a Tailscale node (tailscaled, etc.) +type System struct { + Dialer SubSystem[*tsdial.Dialer] + DNSManager SubSystem[*dns.Manager] // can get its *resolver.Resolver from DNSManager.Resolver + Engine SubSystem[wgengine.Engine] + NetMon SubSystem[*netmon.Monitor] + MagicSock SubSystem[*magicsock.Conn] + NetstackRouter SubSystem[bool] // using Netstack at all (either entirely or at least for subnets) + Router SubSystem[router.Router] + Tun SubSystem[*tstun.Wrapper] + StateStore SubSystem[ipn.StateStore] +} + +// Set is a convenience method to set a subsystem value. +// It panics if the type is unknown or has that type +// has already been set. +func (s *System) Set(v any) { + switch v := v.(type) { + case *netmon.Monitor: + s.NetMon.Set(v) + case *dns.Manager: + s.DNSManager.Set(v) + case *tsdial.Dialer: + s.Dialer.Set(v) + case wgengine.Engine: + s.Engine.Set(v) + case router.Router: + s.Router.Set(v) + case *tstun.Wrapper: + s.Tun.Set(v) + case *magicsock.Conn: + s.MagicSock.Set(v) + case ipn.StateStore: + s.StateStore.Set(v) + default: + panic(fmt.Sprintf("unknown type %T", v)) + } +} + +// IsNetstackRouter reports whether Tailscale is either fully netstack based +// (without TUN) or is at least using netstack for routing. +func (s *System) IsNetstackRouter() bool { + if v, ok := s.NetstackRouter.GetOK(); ok && v { + return true + } + return s.IsNetstack() +} + +// IsNetstack reports whether Tailscale is running as a netstack-based TUN-free engine. +func (s *System) IsNetstack() bool { + name, _ := s.Tun.Get().Name() + return name == tstun.FakeTUNName +} + +// SubSystem represents some subsystem of the Tailscale node daemon. +// +// A subsystem can be set to a value, and then later retrieved. A subsystem +// value tracks whether it's been set and, once set, doesn't allow the value to +// change. +type SubSystem[T any] struct { + set bool + v T +} + +// Set sets p to v. +// +// It panics if p is already set to a different value. +// +// Set must not be called concurrently with other Sets or Gets. +func (p *SubSystem[T]) Set(v T) { + if p.set { + var oldVal any = p.v + var newVal any = v + if oldVal == newVal { + // Allow setting to the same value. + // Note we had to box them through "any" to force them to be comparable. + // We can't set the type constraint T to be "comparable" because the interfaces + // aren't comparable. (See https://github.com/golang/go/issues/52531 and + // https://github.com/golang/go/issues/52614 for some background) + return + } + + var z *T + panic(fmt.Sprintf("%v is already set", reflect.TypeOf(z).Elem().String())) + } + p.v = v + p.set = true +} + +// Get returns the value of p, panicking if it hasn't been set. +func (p *SubSystem[T]) Get() T { + if !p.set { + var z *T + panic(fmt.Sprintf("%v is not set", reflect.TypeOf(z).Elem().String())) + } + return p.v +} + +// GetOK returns the value of p (if any) and whether it's been set. +func (p *SubSystem[T]) GetOK() (_ T, ok bool) { + return p.v, p.set +} diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 2bea9026b6462..1b0ae7bb61995 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -47,6 +47,7 @@ import ( "tailscale.com/net/socks5" "tailscale.com/net/tsdial" "tailscale.com/smallzstd" + "tailscale.com/tsd" "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/types/nettype" @@ -482,23 +483,21 @@ func (s *Server) start() (reterr error) { } closePool.add(s.netMon) + sys := new(tsd.System) s.dialer = &tsdial.Dialer{Logf: logf} // mutated below (before used) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - ListenPort: 0, - NetMon: s.netMon, - Dialer: s.dialer, + ListenPort: 0, + NetMon: s.netMon, + Dialer: s.dialer, + SetSubsystem: sys.Set, }) if err != nil { return err } closePool.add(s.dialer) + sys.Set(eng) - tunDev, magicConn, dns, ok := eng.(wgengine.InternalsGetter).GetInternals() - if !ok { - return fmt.Errorf("%T is not a wgengine.InternalsGetter", eng) - } - - ns, err := netstack.Create(logf, tunDev, eng, magicConn, s.dialer, dns) + ns, err := netstack.Create(logf, sys.Tun.Get(), eng, sys.MagicSock.Get(), s.dialer, sys.DNSManager.Get()) if err != nil { return fmt.Errorf("netstack.Create: %w", err) } @@ -522,12 +521,13 @@ func (s *Server) start() (reterr error) { return err } } + sys.Set(s.Store) loginFlags := controlclient.LoginDefault if s.Ephemeral { loginFlags = controlclient.LoginEphemeral } - lb, err := ipnlocal.NewLocalBackend(logf, s.logid, s.Store, s.dialer, eng, loginFlags) + lb, err := ipnlocal.NewLocalBackend(logf, s.logid, sys, loginFlags) if err != nil { return fmt.Errorf("NewLocalBackend: %v", err) } diff --git a/tstest/integration/tailscaled_deps_test_darwin.go b/tstest/integration/tailscaled_deps_test_darwin.go index ed2e6e5ffce6b..75ef83af0435f 100644 --- a/tstest/integration/tailscaled_deps_test_darwin.go +++ b/tstest/integration/tailscaled_deps_test_darwin.go @@ -37,6 +37,7 @@ import ( _ "tailscale.com/ssh/tailssh" _ "tailscale.com/syncs" _ "tailscale.com/tailcfg" + _ "tailscale.com/tsd" _ "tailscale.com/tsweb/varz" _ "tailscale.com/types/flagtype" _ "tailscale.com/types/key" diff --git a/tstest/integration/tailscaled_deps_test_freebsd.go b/tstest/integration/tailscaled_deps_test_freebsd.go index ed2e6e5ffce6b..75ef83af0435f 100644 --- a/tstest/integration/tailscaled_deps_test_freebsd.go +++ b/tstest/integration/tailscaled_deps_test_freebsd.go @@ -37,6 +37,7 @@ import ( _ "tailscale.com/ssh/tailssh" _ "tailscale.com/syncs" _ "tailscale.com/tailcfg" + _ "tailscale.com/tsd" _ "tailscale.com/tsweb/varz" _ "tailscale.com/types/flagtype" _ "tailscale.com/types/key" diff --git a/tstest/integration/tailscaled_deps_test_linux.go b/tstest/integration/tailscaled_deps_test_linux.go index ed2e6e5ffce6b..75ef83af0435f 100644 --- a/tstest/integration/tailscaled_deps_test_linux.go +++ b/tstest/integration/tailscaled_deps_test_linux.go @@ -37,6 +37,7 @@ import ( _ "tailscale.com/ssh/tailssh" _ "tailscale.com/syncs" _ "tailscale.com/tailcfg" + _ "tailscale.com/tsd" _ "tailscale.com/tsweb/varz" _ "tailscale.com/types/flagtype" _ "tailscale.com/types/key" diff --git a/tstest/integration/tailscaled_deps_test_openbsd.go b/tstest/integration/tailscaled_deps_test_openbsd.go index ed2e6e5ffce6b..75ef83af0435f 100644 --- a/tstest/integration/tailscaled_deps_test_openbsd.go +++ b/tstest/integration/tailscaled_deps_test_openbsd.go @@ -37,6 +37,7 @@ import ( _ "tailscale.com/ssh/tailssh" _ "tailscale.com/syncs" _ "tailscale.com/tailcfg" + _ "tailscale.com/tsd" _ "tailscale.com/tsweb/varz" _ "tailscale.com/types/flagtype" _ "tailscale.com/types/key" diff --git a/tstest/integration/tailscaled_deps_test_windows.go b/tstest/integration/tailscaled_deps_test_windows.go index 33620c9d9260e..6eb00eff40939 100644 --- a/tstest/integration/tailscaled_deps_test_windows.go +++ b/tstest/integration/tailscaled_deps_test_windows.go @@ -44,6 +44,7 @@ import ( _ "tailscale.com/smallzstd" _ "tailscale.com/syncs" _ "tailscale.com/tailcfg" + _ "tailscale.com/tsd" _ "tailscale.com/tsweb/varz" _ "tailscale.com/types/flagtype" _ "tailscale.com/types/key" diff --git a/wgengine/netstack/netstack_test.go b/wgengine/netstack/netstack_test.go index 7a30fd84aa3c0..f08308e2dad69 100644 --- a/wgengine/netstack/netstack_test.go +++ b/wgengine/netstack/netstack_test.go @@ -16,6 +16,7 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" "tailscale.com/net/tstun" + "tailscale.com/tsd" "tailscale.com/tstest" "tailscale.com/types/ipproto" "tailscale.com/types/logid" @@ -33,29 +34,26 @@ func TestInjectInboundLeak(t *testing.T) { t.Logf(format, args...) } } + sys := new(tsd.System) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - Tun: tunDev, - Dialer: dialer, + Tun: tunDev, + Dialer: dialer, + SetSubsystem: sys.Set, }) if err != nil { t.Fatal(err) } defer eng.Close() - ig, ok := eng.(wgengine.InternalsGetter) - if !ok { - t.Fatal("not an InternalsGetter") - } - tunWrap, magicSock, dns, ok := ig.GetInternals() - if !ok { - t.Fatal("failed to get internals") - } + sys.Set(eng) + sys.Set(new(mem.Store)) - lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, new(mem.Store), dialer, eng, 0) + tunWrap := sys.Tun.Get() + lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatal(err) } - ns, err := Create(logf, tunWrap, eng, magicSock, dialer, dns) + ns, err := Create(logf, tunWrap, eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get()) if err != nil { t.Fatal(err) } @@ -89,32 +87,28 @@ func getMemStats() (ms runtime.MemStats) { func makeNetstack(t *testing.T, config func(*Impl)) *Impl { tunDev := tstun.NewFake() + sys := &tsd.System{} + sys.Set(new(mem.Store)) dialer := new(tsdial.Dialer) logf := tstest.WhileTestRunningLogger(t) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - Tun: tunDev, - Dialer: dialer, + Tun: tunDev, + Dialer: dialer, + SetSubsystem: sys.Set, }) if err != nil { t.Fatal(err) } t.Cleanup(func() { eng.Close() }) - ig, ok := eng.(wgengine.InternalsGetter) - if !ok { - t.Fatal("not an InternalsGetter") - } - tunWrap, magicSock, dns, ok := ig.GetInternals() - if !ok { - t.Fatal("failed to get internals") - } + sys.Set(eng) - ns, err := Create(logf, tunWrap, eng, magicSock, dialer, dns) + ns, err := Create(logf, sys.Tun.Get(), eng, sys.MagicSock.Get(), dialer, sys.DNSManager.Get()) if err != nil { t.Fatal(err) } t.Cleanup(func() { ns.Close() }) - lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, new(mem.Store), dialer, eng, 0) + lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, sys, 0) if err != nil { t.Fatalf("NewLocalBackend: %v", err) } diff --git a/wgengine/netstack/subnet_router_wrapper.go b/wgengine/netstack/subnet_router_wrapper.go index dd9c96ec6b0fa..97eb6406fd6a6 100644 --- a/wgengine/netstack/subnet_router_wrapper.go +++ b/wgengine/netstack/subnet_router_wrapper.go @@ -4,16 +4,9 @@ package netstack import ( - "reflect" - - "tailscale.com/wgengine" "tailscale.com/wgengine/router" ) -func init() { - wgengine.NetstackRouterType = reflect.TypeOf(&subnetRouter{}) -} - type subnetRouter struct { router.Router } diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 1356b36dfdf8e..e29e20daec6b8 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -10,8 +10,8 @@ import ( "errors" "fmt" "io" + "math" "net/netip" - "reflect" "runtime" "strings" "sync" @@ -25,7 +25,6 @@ import ( "tailscale.com/health" "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" - "tailscale.com/net/dns/resolver" "tailscale.com/net/flowtrack" "tailscale.com/net/interfaces" "tailscale.com/net/netmon" @@ -150,29 +149,6 @@ type userspaceEngine struct { // Lock ordering: magicsock.Conn.mu, wgLock, then mu. } -// InternalsGetter is implemented by Engines that can export their internals. -type InternalsGetter interface { - GetInternals() (_ *tstun.Wrapper, _ *magicsock.Conn, _ *dns.Manager, ok bool) -} - -func (e *userspaceEngine) GetInternals() (_ *tstun.Wrapper, _ *magicsock.Conn, _ *dns.Manager, ok bool) { - return e.tundev, e.magicConn, e.dns, true -} - -// ResolvingEngine is implemented by Engines that have DNS resolvers. -type ResolvingEngine interface { - GetResolver() (_ *resolver.Resolver, ok bool) -} - -var ( - _ ResolvingEngine = (*userspaceEngine)(nil) - _ ResolvingEngine = (*watchdogEngine)(nil) -) - -func (e *userspaceEngine) GetResolver() (r *resolver.Resolver, ok bool) { - return e.dns.Resolver(), true -} - // BIRDClient handles communication with the BIRD Internet Routing Daemon. type BIRDClient interface { EnableProtocol(proto string) error @@ -219,47 +195,37 @@ type Config struct { // BIRDClient, if non-nil, will be used to configure BIRD whenever // this node is a primary subnet router. BIRDClient BIRDClient -} - -func NewFakeUserspaceEngine(logf logger.Logf, listenPort uint16) (Engine, error) { - logf("Starting userspace WireGuard engine (with fake TUN device)") - return NewUserspaceEngine(logf, Config{ - ListenPort: listenPort, - RespondToPing: true, - }) -} -// NetstackRouterType is a gross cross-package init-time registration -// from netstack to here, informing this package of netstack's router -// type. -var NetstackRouterType reflect.Type - -// IsNetstackRouter reports whether e is either fully netstack based -// (without TUN) or is at least using netstack for routing. -func IsNetstackRouter(e Engine) bool { - switch e := e.(type) { - case *userspaceEngine: - if reflect.TypeOf(e.router) == NetstackRouterType { - return true - } - case *watchdogEngine: - return IsNetstackRouter(e.wrap) - } - return IsNetstack(e) + // SetSubsystem, if non-nil, is called for each new subsystem created, just before a successful return. + SetSubsystem func(any) } -// IsNetstack reports whether e is a netstack-based TUN-free engine. -func IsNetstack(e Engine) bool { - ig, ok := e.(InternalsGetter) - if !ok { - return false +// NewFakeUserspaceEngine returns a new userspace engine for testing. +// +// The opts may contain the following types: +// +// - int or uint16: to set the ListenPort. +func NewFakeUserspaceEngine(logf logger.Logf, opts ...any) (Engine, error) { + conf := Config{ + RespondToPing: true, } - tw, _, _, ok := ig.GetInternals() - if !ok { - return false + for _, o := range opts { + switch v := o.(type) { + case uint16: + conf.ListenPort = v + case int: + if v < 0 || v > math.MaxUint16 { + return nil, fmt.Errorf("invalid ListenPort: %d", v) + } + conf.ListenPort = uint16(v) + case func(any): + conf.SetSubsystem = v + default: + return nil, fmt.Errorf("unknown option type %T", v) + } } - name, err := tw.Name() - return err == nil && name == "FakeTUN" + logf("Starting userspace WireGuard engine (with fake TUN device)") + return NewUserspaceEngine(logf, conf) } // NewUserspaceEngine creates the named tun device and returns a @@ -458,6 +424,15 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) e.logf("Starting network monitor...") e.netMon.Start() + if conf.SetSubsystem != nil { + conf.SetSubsystem(e.tundev) + conf.SetSubsystem(e.magicConn) + conf.SetSubsystem(e.dns) + conf.SetSubsystem(conf.Router) + conf.SetSubsystem(conf.Dialer) + conf.SetSubsystem(e.netMon) + } + e.logf("Engine created.") return e, nil } @@ -1119,10 +1094,6 @@ func (e *userspaceEngine) Wait() { <-e.waitCh } -func (e *userspaceEngine) GetNetMon() *netmon.Monitor { - return e.netMon -} - // LinkChange signals a network change event. It's currently // (2021-03-03) only called on Android. On other platforms, netMon // generates link change events for us. diff --git a/wgengine/userspace_ext_test.go b/wgengine/userspace_ext_test.go index b2235c9c9b27a..67b33705144dc 100644 --- a/wgengine/userspace_ext_test.go +++ b/wgengine/userspace_ext_test.go @@ -8,6 +8,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "tailscale.com/net/tstun" + "tailscale.com/tsd" "tailscale.com/types/logger" "tailscale.com/wgengine" "tailscale.com/wgengine/netstack" @@ -15,21 +16,23 @@ import ( ) func TestIsNetstack(t *testing.T) { - e, err := wgengine.NewUserspaceEngine(t.Logf, wgengine.Config{}) + sys := new(tsd.System) + e, err := wgengine.NewUserspaceEngine(t.Logf, wgengine.Config{SetSubsystem: sys.Set}) if err != nil { t.Fatal(err) } defer e.Close() - if !wgengine.IsNetstack(e) { + if !sys.IsNetstack() { t.Errorf("IsNetstack = false; want true") } } func TestIsNetstackRouter(t *testing.T) { tests := []struct { - name string - conf wgengine.Config - want bool + name string + conf wgengine.Config + setNetstackRouter bool + want bool }{ { name: "no_netstack", @@ -50,23 +53,26 @@ func TestIsNetstackRouter(t *testing.T) { Tun: newFakeOSTUN(), Router: netstack.NewSubnetRouterWrapper(newFakeOSRouter()), }, - want: true, + setNetstackRouter: true, + want: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - e, err := wgengine.NewUserspaceEngine(logger.Discard, tt.conf) + sys := &tsd.System{} + if tt.setNetstackRouter { + sys.NetstackRouter.Set(true) + } + conf := tt.conf + conf.SetSubsystem = sys.Set + e, err := wgengine.NewUserspaceEngine(logger.Discard, conf) if err != nil { t.Fatal(err) } defer e.Close() - if got := wgengine.IsNetstackRouter(e); got != tt.want { + if got := sys.IsNetstackRouter(); got != tt.want { t.Errorf("IsNetstackRouter = %v; want %v", got, tt.want) } - - if got := wgengine.IsNetstackRouter(wgengine.NewWatchdog(e)); got != tt.want { - t.Errorf("IsNetstackRouter(watchdog-wrapped) = %v; want %v", got, tt.want) - } }) } } diff --git a/wgengine/watchdog.go b/wgengine/watchdog.go index 76abfa8cc0914..19505be896989 100644 --- a/wgengine/watchdog.go +++ b/wgengine/watchdog.go @@ -17,15 +17,11 @@ import ( "tailscale.com/envknob" "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" - "tailscale.com/net/dns/resolver" - "tailscale.com/net/netmon" - "tailscale.com/net/tstun" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/netmap" "tailscale.com/wgengine/capture" "tailscale.com/wgengine/filter" - "tailscale.com/wgengine/magicsock" "tailscale.com/wgengine/router" "tailscale.com/wgengine/wgcfg" ) @@ -126,9 +122,6 @@ func (e *watchdogEngine) watchdog(name string, fn func()) { func (e *watchdogEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *dns.Config, debug *tailcfg.Debug) error { return e.watchdogErr("Reconfig", func() error { return e.wrap.Reconfig(cfg, routerCfg, dnsCfg, debug) }) } -func (e *watchdogEngine) GetNetMon() *netmon.Monitor { - return e.wrap.GetNetMon() -} func (e *watchdogEngine) GetFilter() *filter.Filter { return e.wrap.GetFilter() } @@ -181,18 +174,6 @@ func (e *watchdogEngine) WhoIsIPPort(ipp netip.AddrPort) (tsIP netip.Addr, ok bo func (e *watchdogEngine) Close() { e.watchdog("Close", e.wrap.Close) } -func (e *watchdogEngine) GetInternals() (tw *tstun.Wrapper, c *magicsock.Conn, d *dns.Manager, ok bool) { - if ig, ok := e.wrap.(InternalsGetter); ok { - return ig.GetInternals() - } - return -} -func (e *watchdogEngine) GetResolver() (r *resolver.Resolver, ok bool) { - if re, ok := e.wrap.(ResolvingEngine); ok { - return re.GetResolver() - } - return nil, false -} func (e *watchdogEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) { e.watchdog("PeerForIP", func() { ret, ok = e.wrap.PeerForIP(ip) }) return ret, ok diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go index 4d4e240c1ec49..df591c9e039cb 100644 --- a/wgengine/wgengine.go +++ b/wgengine/wgengine.go @@ -10,7 +10,6 @@ import ( "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" - "tailscale.com/net/netmon" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/netmap" @@ -92,9 +91,6 @@ type Engine interface { // WireGuard status changes. SetStatusCallback(StatusCallback) - // GetNetMon returns the network monitor. - GetNetMon() *netmon.Monitor - // RequestStatus requests a WireGuard status update right // away, sent to the callback registered via SetStatusCallback. RequestStatus() From 9ed3a061c303b10666073f91e76a898bf2de08fc Mon Sep 17 00:00:00 2001 From: James Tucker Date: Fri, 5 May 2023 10:53:10 -0700 Subject: [PATCH 070/331] net/netns: fix segv when no tailscale interface is found `interfaces.Tailscale()` returns all zero values when it finds no Tailscale interface and encounters no errors. The netns package was treating no error as a signal that it would receive a non-zero pointer value leading to nil pointer dereference. Observed in: ``` --- FAIL: TestGetInterfaceIndex (0.00s) --- FAIL: TestGetInterfaceIndex/IP_and_port (0.00s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x1029eb7d8] goroutine 7 [running]: testing.tRunner.func1.2({0x102a691e0, 0x102bc05c0}) /Users/raggi/.cache/tailscale-go/src/testing/testing.go:1526 +0x1c8 testing.tRunner.func1() /Users/raggi/.cache/tailscale-go/src/testing/testing.go:1529 +0x384 panic({0x102a691e0, 0x102bc05c0}) /Users/raggi/.cache/tailscale-go/src/runtime/panic.go:884 +0x204 tailscale.com/net/netns.getInterfaceIndex(0x14000073f28, 0x1028d0284?, {0x1029ef3b7, 0xa}) /Users/raggi/src/github.com/tailscale/tailscale/net/netns/netns_darwin.go:114 +0x228 tailscale.com/net/netns.TestGetInterfaceIndex.func2(0x14000138000) /Users/raggi/src/github.com/tailscale/tailscale/net/netns/netns_darwin_test.go:37 +0x54 testing.tRunner(0x14000138000, 0x140000551b0) /Users/raggi/.cache/tailscale-go/src/testing/testing.go:1576 +0x10c created by testing.(*T).Run /Users/raggi/.cache/tailscale-go/src/testing/testing.go:1629 +0x368 FAIL tailscale.com/net/netns 0.824s ``` Fixes #8064 Signed-off-by: James Tucker --- net/netns/netns_darwin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netns/netns_darwin.go b/net/netns/netns_darwin.go index 7315dff4052af..b32a744b7ee8e 100644 --- a/net/netns/netns_darwin.go +++ b/net/netns/netns_darwin.go @@ -111,7 +111,7 @@ func getInterfaceIndex(logf logger.Logf, netMon *netmon.Monitor, address string) // Verify that we didn't just choose the Tailscale interface; // if so, we fall back to binding from the default. _, tsif, err2 := interfaces.Tailscale() - if err2 == nil && tsif.Index == idx { + if err2 == nil && tsif != nil && tsif.Index == idx { logf("[unexpected] netns: interfaceIndexFor returned Tailscale interface") return defaultIdx() } From 8864112a0cf8434b67e993e9252bed7ebaae786e Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 5 May 2023 12:19:25 -0700 Subject: [PATCH 071/331] ipn/ipnlocal: bound how long cert fetchher checks for existing DNS records It was supposed to be best effort but in some cases (macsys at least, per @marwan-at-work) it hangs and exhausts the whole context.Context deadline so we fail to make the SetDNS call to the server. Updates #8067 Updates #3273 etc Change-Id: Ie1f04abe9689951484748aecdeae312afbafdb0f Signed-off-by: Brad Fitzpatrick --- ipn/ipnlocal/cert.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ipn/ipnlocal/cert.go b/ipn/ipnlocal/cert.go index cabcae1fb5840..ef19a65718cb4 100644 --- a/ipn/ipnlocal/cert.go +++ b/ipn/ipnlocal/cert.go @@ -31,6 +31,7 @@ import ( "time" "golang.org/x/crypto/acme" + "golang.org/x/exp/slices" "tailscale.com/atomicfile" "tailscale.com/envknob" "tailscale.com/hostinfo" @@ -361,17 +362,16 @@ func (b *LocalBackend) getCertPEM(ctx context.Context, cs certStore, logf logger } key := "_acme-challenge." + domain + // Do a best-effort lookup to see if we've already created this DNS name + // in a previous attempt. Don't burn too much time on it, though. Worst + // case we ask the server to create something that already exists. var resolver net.Resolver - var ok bool - txts, _ := resolver.LookupTXT(ctx, key) - for _, txt := range txts { - if txt == rec { - ok = true - logf("TXT record already existed") - break - } - } - if !ok { + lookupCtx, lookupCancel := context.WithTimeout(ctx, 500*time.Millisecond) + txts, _ := resolver.LookupTXT(lookupCtx, key) + lookupCancel() + if slices.Contains(txts, rec) { + logf("TXT record already existed") + } else { logf("starting SetDNS call...") err = b.SetDNS(ctx, key, rec) if err != nil { From 8d3d48e000f1aea1e349ad3f3f209d29248024d7 Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Thu, 4 May 2023 17:34:44 -0700 Subject: [PATCH 072/331] ipn/ipnlocal: add NodeKey func to return the public node NodeKey This change introduces a NodeKey func on localbackend that returns the public node key. Updates tailscale/corp#9967 Signed-off-by: Charlotte Brandhorst-Satzkorn --- ipn/ipnlocal/local.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 15202b0fd06a8..8c8f342e1c7d3 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -3627,6 +3627,19 @@ func (b *LocalBackend) hasNodeKey() bool { return p.Valid() && p.Persist().Valid() && !p.Persist().PrivateNodeKey().IsZero() } +// NodeKey returns the public node key. +func (b *LocalBackend) NodeKey() key.NodePublic { + b.mu.Lock() + defer b.mu.Unlock() + + p := b.pm.CurrentPrefs() + if !p.Valid() || !p.Persist().Valid() || p.Persist().PrivateNodeKey().IsZero() { + return key.NodePublic{} + } + + return p.Persist().PublicNodeKey() +} + // nextState returns the state the backend seems to be in, based on // its internal state. func (b *LocalBackend) nextState() ipn.State { From 280432707439921bc4de56d55a63c4886cdb0cbf Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Thu, 4 May 2023 18:08:11 -0700 Subject: [PATCH 073/331] tailcfg: update rename SSHFailureNotifyRequest and add EventType This change renames SSHFailureNotifyRequest to SSHEventNotifyRequest to better reflect the additional events we could add in the future. This change also adds an EventType used to catagories the events. Updates tailscale/corp#9967 Signed-off-by: Charlotte Brandhorst-Satzkorn --- tailcfg/tailcfg.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index b77193f2b9902..6e4b20b383189 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2075,9 +2075,11 @@ type SSHRecorderFailureAction struct { NotifyURL string `json:",omitempty"` } -// SSHRecordingFailureNotifyRequest is the JSON payload sent to the NotifyURL -// when a recording fails. -type SSHRecordingFailureNotifyRequest struct { +// SSHEventNotifyRequest is the JSON payload sent to the NotifyURL +// for an SSH event. +type SSHEventNotifyRequest struct { + // EventType is the type of notify request being sent. + EventType SSHEventType // CapVersion is the client's current CapabilityVersion. CapVersion CapabilityVersion @@ -2093,10 +2095,19 @@ type SSHRecordingFailureNotifyRequest struct { // LocalUser is the user that was resolved from the SSHUser for the local machine. LocalUser string - // Attempts is the list of recorders that were attempted, in order. - Attempts []SSHRecordingAttempt + // RecordingAttempts is the list of recorders that were attempted, in order. + RecordingAttempts []*SSHRecordingAttempt } +// SSHEventType defines the event type linked to a SSH action or state. +type SSHEventType int + +const ( + UnspecifiedSSHEventType SSHEventType = 0 + SSHSessionRecordingRejected SSHEventType = 1 + SSHSessionRecordingTerminated SSHEventType = 2 +) + // SSHRecordingAttempt is a single attempt to start a recording. type SSHRecordingAttempt struct { // Recorder is the address of the recorder that was attempted. From 68307c1411381809ac28c5677a0ddef90d556480 Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Thu, 4 May 2023 19:49:32 -0700 Subject: [PATCH 074/331] ssh/tailssh: send ssh event notifications on recording failures This change sends an SSHEventNotificationRequest over noise when a SSH session is set to fail closed and the session is unable to start because a recorder is not available or a session is terminated because connection to the recorder is ended. Each of these scenarios have their own event type. Updates tailscale/corp#9967 Signed-off-by: Charlotte Brandhorst-Satzkorn --- ssh/tailssh/tailssh.go | 96 +++++++++++++++++++++++++++++++++---- ssh/tailssh/tailssh_test.go | 5 ++ 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 27437901cc453..623a8695af7bc 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -39,6 +39,7 @@ import ( "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/tempfork/gliderlabs/ssh" + "tailscale.com/types/key" "tailscale.com/types/logger" "tailscale.com/types/netmap" "tailscale.com/util/clientmetric" @@ -68,6 +69,7 @@ type ipnLocalBackend interface { DoNoiseRequest(req *http.Request) (*http.Response, error) Dialer() *tsdial.Dialer TailscaleVarRoot() string + NodeKey() key.NodePublic } type server struct { @@ -105,6 +107,7 @@ func init() { logf: logf, tailscaledPath: tsd, } + return srv, nil }) } @@ -1445,11 +1448,17 @@ func (ss *sshSession) sessionRecordingClient(dialCtx context.Context) (*http.Cli // On success, it returns a WriteCloser that can be used to upload the // recording, and a channel that will be sent an error (or nil) when the upload // fails or completes. -func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPort) (io.WriteCloser, <-chan error, error) { +// +// In both cases, a slice of SSHRecordingAttempts is returned which detail the +// attempted recorder IP and the error message, if the attempt failed. The +// attempts are in order the recorder(s) was attempted. If successful a +// successful connection is made, the last attempt in the slice is the +// attempt for connected recorder. +func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPort) (io.WriteCloser, []*tailcfg.SSHRecordingAttempt, <-chan error, error) { if len(recs) == 0 { - return nil, nil, errors.New("no recorders configured") + return nil, nil, nil, errors.New("no recorders configured") } - + var attempts []*tailcfg.SSHRecordingAttempt // We use a special context for dialing the recorder, so that we can // limit the time we spend dialing to 30 seconds and still have an // unbounded context for the upload. @@ -1457,10 +1466,18 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo defer dialCancel() hc, err := ss.sessionRecordingClient(dialCtx) if err != nil { - return nil, nil, err + attempts = append(attempts, &tailcfg.SSHRecordingAttempt{ + FailureMessage: err.Error(), + }) + return nil, attempts, nil, err } var errs []error for _, ap := range recs { + attempt := &tailcfg.SSHRecordingAttempt{ + Recorder: ap, + } + attempts = append(attempts, attempt) + // We dial the recorder and wait for it to send a 100-continue // response before returning from this function. This ensures that // the recorder is ready to accept the recording. @@ -1476,7 +1493,9 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo pr, pw := io.Pipe() req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("http://%s:%d/record", ap.Addr(), ap.Port()), pr) if err != nil { - errs = append(errs, fmt.Errorf("recording: error starting recording: %w", err)) + err = fmt.Errorf("recording: error starting recording: %w", err) + attempt.FailureMessage = err.Error() + errs = append(errs, err) continue } // We set the Expect header to 100-continue, so that the recorder @@ -1508,12 +1527,13 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo // is unexpected as we haven't sent any data yet. err = errors.New("recording: unexpected EOF") } + attempt.FailureMessage = err.Error() errs = append(errs, err) continue } - return pw, errChan, nil + return pw, attempts, errChan, nil } - return nil, nil, multierr.New(errs...) + return nil, attempts, nil, multierr.New(errs...) } func (ss *sshSession) openFileForRecording(now time.Time) (_ io.WriteCloser, err error) { @@ -1535,6 +1555,15 @@ func (ss *sshSession) openFileForRecording(now time.Time) (_ io.WriteCloser, err // startNewRecording starts a new SSH session recording. // It may return a nil recording if recording is not available. func (ss *sshSession) startNewRecording() (_ *recording, err error) { + // We store the node key as soon as possible when creating + // a new recording incase of FUS. + var nodeKey key.NodePublic + if nk := ss.conn.srv.lb.NodeKey(); nk.IsZero() { + return nil, errors.New("ssh server is unavailable: no node key") + } else { + nodeKey = nk + } + recorders, onFailure := ss.recorders() var localRecording bool if len(recorders) == 0 { @@ -1573,9 +1602,13 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { } } else { var errChan <-chan error - rec.out, errChan, err = ss.connectToRecorder(ctx, recorders) + var attempts []*tailcfg.SSHRecordingAttempt + rec.out, attempts, errChan, err = ss.connectToRecorder(ctx, recorders) if err != nil { - // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.NotifyURL != "" && len(attempts) > 0 { + ss.notifyControl(ctx, nodeKey, tailcfg.SSHSessionRecordingRejected, attempts, onFailure.NotifyURL) + } + if onFailure != nil && onFailure.RejectSessionWithMessage != "" { ss.logf("recording: error starting recording (rejecting session): %v", err) return nil, userVisibleError{ @@ -1592,7 +1625,12 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { // Success. return } - // TODO(catzkorn): notify control here. + if onFailure != nil && onFailure.NotifyURL != "" && len(attempts) > 0 { + lastAttempt := attempts[len(attempts)-1] + lastAttempt.FailureMessage = err.Error() + + ss.notifyControl(ctx, nodeKey, tailcfg.SSHSessionRecordingTerminated, attempts, onFailure.NotifyURL) + } if onFailure != nil && onFailure.TerminateSessionWithMessage != "" { ss.logf("recording: error uploading recording (closing session): %v", err) ss.cancelCtx(userVisibleError{ @@ -1650,6 +1688,44 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { return rec, nil } +// notifyControl sends a SSHEventNotifyRequest to control over noise. +// A SSHEventNotifyRequest is sent when an action or state reached during +// an SSH session is a defined EventType. +func (ss *sshSession) notifyControl(ctx context.Context, nodeKey key.NodePublic, notifyType tailcfg.SSHEventType, attempts []*tailcfg.SSHRecordingAttempt, url string) { + re := tailcfg.SSHEventNotifyRequest{ + EventType: notifyType, + CapVersion: tailcfg.CurrentCapabilityVersion, + NodeKey: nodeKey, + SrcNode: ss.conn.info.node.ID, + SSHUser: ss.conn.info.sshUser, + LocalUser: ss.conn.localUser.Username, + RecordingAttempts: attempts, + } + + body, err := json.Marshal(re) + if err != nil { + ss.logf("notifyControl: unable to marshal SSHNotifyRequest:", err) + return + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(body)) + if err != nil { + ss.logf("notifyControl: unable to create request:", err) + return + } + + resp, err := ss.conn.srv.lb.DoNoiseRequest(req) + if err != nil { + ss.logf("notifyControl: unable to send noise request:", err) + return + } + + if resp.StatusCode != http.StatusCreated { + ss.logf("notifyControl: noise request returned status code %v", resp.StatusCode) + return + } +} + // recording is the state for an SSH session recording. type recording struct { ss *sshSession diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index 607b4eeaa4238..5eb1a3f62e502 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -40,6 +40,7 @@ import ( "tailscale.com/tempfork/gliderlabs/ssh" "tailscale.com/tsd" "tailscale.com/tstest" + "tailscale.com/types/key" "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/types/netmap" @@ -313,6 +314,10 @@ func (ts *localState) TailscaleVarRoot() string { return "" } +func (ts *localState) NodeKey() key.NodePublic { + return key.NewNode().Public() +} + func newSSHRule(action *tailcfg.SSHAction) *tailcfg.SSHRule { return &tailcfg.SSHRule{ SSHUsers: map[string]string{ From 29ded8f9f986645f8add236821c48c0a0479dccf Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Fri, 5 May 2023 11:03:15 -0700 Subject: [PATCH 075/331] ssh/tailssh,tailcfg: add connID to ssheventnotifyrequest and castheader This change adds a ConnectionID field to both SSHEventNotifyRequest and CastHeader that identifies the ID of a connection to the SSH server. Updates tailscale/corp#9967 Signed-off-by: Charlotte Brandhorst-Satzkorn --- ssh/tailssh/tailssh.go | 29 ++++++++++++++++------------- tailcfg/tailcfg.go | 6 ++++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 623a8695af7bc..63e14b86dcd1c 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -1410,6 +1410,11 @@ type CastHeader struct { // LocalUser is the effective username on the server. LocalUser string `json:"localUser"` + + // ConnectionID uniquely identifies a connection made to the SSH server. + // It may be shared across multiple sessions over the same connection in + // case of SSH multiplexing. + ConnectionID string `json:"connectionID"` } // sessionRecordingClient returns an http.Client that uses srv.lb.Dialer() to @@ -1458,7 +1463,6 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo if len(recs) == 0 { return nil, nil, nil, errors.New("no recorders configured") } - var attempts []*tailcfg.SSHRecordingAttempt // We use a special context for dialing the recorder, so that we can // limit the time we spend dialing to 30 seconds and still have an // unbounded context for the upload. @@ -1466,12 +1470,11 @@ func (ss *sshSession) connectToRecorder(ctx context.Context, recs []netip.AddrPo defer dialCancel() hc, err := ss.sessionRecordingClient(dialCtx) if err != nil { - attempts = append(attempts, &tailcfg.SSHRecordingAttempt{ - FailureMessage: err.Error(), - }) - return nil, attempts, nil, err + return nil, nil, nil, err } + var errs []error + var attempts []*tailcfg.SSHRecordingAttempt for _, ap := range recs { attempt := &tailcfg.SSHRecordingAttempt{ Recorder: ap, @@ -1557,11 +1560,9 @@ func (ss *sshSession) openFileForRecording(now time.Time) (_ io.WriteCloser, err func (ss *sshSession) startNewRecording() (_ *recording, err error) { // We store the node key as soon as possible when creating // a new recording incase of FUS. - var nodeKey key.NodePublic - if nk := ss.conn.srv.lb.NodeKey(); nk.IsZero() { + nodeKey := ss.conn.srv.lb.NodeKey() + if nodeKey.IsZero() { return nil, errors.New("ssh server is unavailable: no node key") - } else { - nodeKey = nk } recorders, onFailure := ss.recorders() @@ -1660,10 +1661,11 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { // it. Then we can (1) make the cmd, (2) start the // recording, (3) start the process. }, - SSHUser: ss.conn.info.sshUser, - LocalUser: ss.conn.localUser.Username, - SrcNode: strings.TrimSuffix(ss.conn.info.node.Name, "."), - SrcNodeID: ss.conn.info.node.StableID, + SSHUser: ss.conn.info.sshUser, + LocalUser: ss.conn.localUser.Username, + SrcNode: strings.TrimSuffix(ss.conn.info.node.Name, "."), + SrcNodeID: ss.conn.info.node.StableID, + ConnectionID: ss.conn.connID, } if !ss.conn.info.node.IsTagged() { ch.SrcNodeUser = ss.conn.info.uprof.LoginName @@ -1694,6 +1696,7 @@ func (ss *sshSession) startNewRecording() (_ *recording, err error) { func (ss *sshSession) notifyControl(ctx context.Context, nodeKey key.NodePublic, notifyType tailcfg.SSHEventType, attempts []*tailcfg.SSHRecordingAttempt, url string) { re := tailcfg.SSHEventNotifyRequest{ EventType: notifyType, + ConnectionID: ss.conn.connID, CapVersion: tailcfg.CurrentCapabilityVersion, NodeKey: nodeKey, SrcNode: ss.conn.info.node.ID, diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 6e4b20b383189..d2df24fc07cb3 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2080,6 +2080,12 @@ type SSHRecorderFailureAction struct { type SSHEventNotifyRequest struct { // EventType is the type of notify request being sent. EventType SSHEventType + + // ConnectionID uniquely identifies a connection made to the SSH server. + // It may be shared across multiple sessions over the same connection in + // case a single connection creates multiple sessions. + ConnectionID string + // CapVersion is the client's current CapabilityVersion. CapVersion CapabilityVersion From 024d48d9c1d81e6c4a9225aef1a436be823e5ee9 Mon Sep 17 00:00:00 2001 From: Charlotte Brandhorst-Satzkorn Date: Fri, 5 May 2023 14:06:23 -0700 Subject: [PATCH 076/331] tailcfg: bump capability version This change bumps the capability version to 62, after support for sending SSHEventNotificationRequests to control via noise for failure events was introduced. Updates tailscale/corp#9967 Signed-off-by: Charlotte Brandhorst-Satzkorn --- tailcfg/tailcfg.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index d2df24fc07cb3..d9a38eda0e528 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -98,7 +98,8 @@ type CapabilityVersion int // - 59: 2023-03-16: Client understands Peers[].SelfNodeV4MasqAddrForThisPeer // - 60: 2023-04-06: Client understands IsWireGuardOnly // - 61: 2023-04-18: Client understand SSHAction.SSHRecorderFailureAction -const CurrentCapabilityVersion CapabilityVersion = 61 +// - 62: 2023-05-05: Client can notify control over noise for SSHEventNotificationRequest recording failure events +const CurrentCapabilityVersion CapabilityVersion = 62 type StableID string From 5c38f0979e5f6c599d665b4c0b53e0d09799e81b Mon Sep 17 00:00:00 2001 From: James Tucker Date: Fri, 5 May 2023 11:37:24 -0700 Subject: [PATCH 077/331] tsweb/promvarz: fix repeated expvar definition in test expvar can only be defined once, so running tests with a repeat counter will fail if the variables are defined inside of the test function. Observed failure: ``` --- FAIL: TestHandler (0.00s) panic: Reuse of exported var name: gauge_promvarz_test_expvar [recovered] panic: Reuse of exported var name: gauge_promvarz_test_expvar goroutine 9 [running]: testing.tRunner.func1.2({0x100f267e0, 0x1400026e770}) /usr/local/go/src/testing/testing.go:1526 +0x1c8 testing.tRunner.func1() /usr/local/go/src/testing/testing.go:1529 +0x364 panic({0x100f267e0, 0x1400026e770}) /usr/local/go/src/runtime/panic.go:884 +0x1f4 log.Panicln({0x140000b8e20?, 0x1a?, 0x1400026e750?}) /usr/local/go/src/log/log.go:398 +0x60 expvar.Publish({0x100e2b21d, 0x1a}, {0x100fd7a08?, 0x140000232c0}) /usr/local/go/src/expvar/expvar.go:284 +0xc0 expvar.NewInt(...) /usr/local/go/src/expvar/expvar.go:304 tailscale.com/tsweb/promvarz.TestHandler(0x14000082b60) /Users/charlotte/ts-src/tailscale/tsweb/promvarz/promvarz_test.go:18 +0x5c testing.tRunner(0x14000082b60, 0x100fd5858) /usr/local/go/src/testing/testing.go:1576 +0x104 created by testing.(*T).Run /usr/local/go/src/testing/testing.go:1629 +0x370 FAIL tailscale.com/tsweb/promvarz 0.149s ``` Fixes #8065 Signed-off-by: James Tucker --- tsweb/promvarz/promvarz_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tsweb/promvarz/promvarz_test.go b/tsweb/promvarz/promvarz_test.go index 28c906c57376f..a3f4e66f11a42 100644 --- a/tsweb/promvarz/promvarz_test.go +++ b/tsweb/promvarz/promvarz_test.go @@ -14,11 +14,14 @@ import ( "github.com/prometheus/client_golang/prometheus/testutil" ) +var ( + testVar1 = expvar.NewInt("gauge_promvarz_test_expvar") + testVar2 = promauto.NewGauge(prometheus.GaugeOpts{Name: "promvarz_test_native"}) +) + func TestHandler(t *testing.T) { - test1 := expvar.NewInt("gauge_promvarz_test_expvar") - test1.Set(42) - test2 := promauto.NewGauge(prometheus.GaugeOpts{Name: "promvarz_test_native"}) - test2.Set(4242) + testVar1.Set(42) + testVar2.Set(4242) svr := httptest.NewServer(http.HandlerFunc(Handler)) defer svr.Close() From b9fb8ac70244f6b391118a9b180699e65533e7b0 Mon Sep 17 00:00:00 2001 From: Chenyang Gao Date: Sat, 6 May 2023 14:04:37 +0800 Subject: [PATCH 078/331] fix sys.Set(router) issue will crash the daemon in some OSs Signed-off-by: Chenyang Gao in commit 6e96744, the tsd system type has been added. Which will cause the daemon will crash on some OSs (Windows, darwin and so on). The root cause is that on those OSs, handleSubnetsInNetstack() will return true and set the conf.Router with a wrapper. Later in NewUserspaceEngine() it will do subsystem set and found that early set router mismatch to current value, then panic. --- cmd/tailscaled/tailscaled.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 0d46cdb0f13e8..95193f1e7b36a 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -649,7 +649,6 @@ func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack boo dev.Close() return false, fmt.Errorf("creating router: %w", err) } - sys.Set(r) d, err := dns.NewOSConfigurator(logf, devName) if err != nil { @@ -663,6 +662,7 @@ func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack boo conf.Router = netstack.NewSubnetRouterWrapper(conf.Router) netstackSubnetRouter = true } + sys.Set(conf.Router) } e, err := wgengine.NewUserspaceEngine(logf, conf) if err != nil { From 4d730e154c19f54faac23a6f050efd19af06e43b Mon Sep 17 00:00:00 2001 From: License Updater Date: Sat, 6 May 2023 21:42:20 +0000 Subject: [PATCH 079/331] licenses: update android licenses Signed-off-by: License Updater --- licenses/android.md | 82 +++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/licenses/android.md b/licenses/android.md index 87d88b08de486..c1cfc84acd359 100644 --- a/licenses/android.md +++ b/licenses/android.md @@ -9,22 +9,23 @@ Client][]. See also the dependencies in the [Tailscale CLI][]. - [eliasnaur.com/font/roboto](https://pkg.go.dev/eliasnaur.com/font/roboto) ([BSD-3-Clause](https://git.sr.ht/~eliasnaur/font/tree/832bb8fc08c3/LICENSE)) - - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0-rc.1/LICENSE)) + - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0/LICENSE)) - [gioui.org](https://pkg.go.dev/gioui.org) ([MIT](https://git.sr.ht/~eliasnaur/gio/tree/32c6a9b10d0b/LICENSE)) - [gioui.org/cpu](https://pkg.go.dev/gioui.org/cpu) ([MIT](https://git.sr.ht/~eliasnaur/gio-cpu/tree/8d6a761490d2/LICENSE)) - [gioui.org/shader](https://pkg.go.dev/gioui.org/shader) ([MIT](https://git.sr.ht/~eliasnaur/gio-shader/tree/v1.0.6/LICENSE)) - - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.11.0/config/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.6.4/credentials/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.8.2/feature/ec2/imds/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.27/internal/configsources/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.21/internal/endpoints/v2/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.2/internal/ini/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/internal/sync/singleflight/LICENSE)) - - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.5.2/service/internal/presigned-url/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.35.0/service/ssm/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.6.2/service/sso/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.11.1/service/sts/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.18.22/config/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.13.21/credentials/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.13.3/feature/ec2/imds/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.33/internal/configsources/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.27/internal/endpoints/v2/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.34/internal/ini/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/internal/sync/singleflight/LICENSE)) + - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.9.27/service/internal/presigned-url/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.36.3/service/ssm/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.12.9/service/sso/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssooidc](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssooidc) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.14.9/service/ssooidc/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.18.10/service/sts/LICENSE.txt)) - [github.com/aws/smithy-go](https://pkg.go.dev/github.com/aws/smithy-go) ([Apache-2.0](https://github.com/aws/smithy-go/blob/v1.13.5/LICENSE)) - [github.com/aws/smithy-go/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/smithy-go/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/smithy-go/blob/v1.13.5/internal/sync/singleflight/LICENSE)) - [github.com/benoitkugler/textlayout](https://pkg.go.dev/github.com/benoitkugler/textlayout) ([MIT](https://github.com/benoitkugler/textlayout/blob/v0.3.0/LICENSE)) @@ -34,50 +35,51 @@ Client][]. See also the dependencies in the [Tailscale CLI][]. - [github.com/coreos/go-iptables/iptables](https://pkg.go.dev/github.com/coreos/go-iptables/iptables) ([Apache-2.0](https://github.com/coreos/go-iptables/blob/v0.6.0/LICENSE)) - [github.com/fxamacker/cbor/v2](https://pkg.go.dev/github.com/fxamacker/cbor/v2) ([MIT](https://github.com/fxamacker/cbor/blob/v2.4.0/LICENSE)) - [github.com/go-text/typesetting](https://pkg.go.dev/github.com/go-text/typesetting) ([BSD-3-Clause](https://github.com/go-text/typesetting/blob/0399769901d5/LICENSE)) - - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.0.6/LICENSE)) + - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.1.0/LICENSE)) - [github.com/golang/groupcache/lru](https://pkg.go.dev/github.com/golang/groupcache/lru) ([Apache-2.0](https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE)) - - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.0.1/LICENSE)) - - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/c00d1f31bab3/LICENSE)) + - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.1.2/LICENSE)) + - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/v0.1.0/LICENSE)) - [github.com/illarion/gonotify](https://pkg.go.dev/github.com/illarion/gonotify) ([MIT](https://github.com/illarion/gonotify/blob/v1.0.1/LICENSE)) - - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/de60144f33f8/LICENSE)) + - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/974c6f05fe16/LICENSE)) - [github.com/jmespath/go-jmespath](https://pkg.go.dev/github.com/jmespath/go-jmespath) ([Apache-2.0](https://github.com/jmespath/go-jmespath/blob/v0.4.0/LICENSE)) - [github.com/josharian/native](https://pkg.go.dev/github.com/josharian/native) ([MIT](https://github.com/josharian/native/blob/5c7d0dd6ab86/license)) - - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/d380b505068b/LICENSE.md)) - - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.15.4/LICENSE)) - - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.15.4/internal/snapref/LICENSE)) - - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.15.4/zstd/internal/xxhash/LICENSE.txt)) + - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.16.5/LICENSE)) + - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.16.5/internal/snapref/LICENSE)) + - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.16.5/zstd/internal/xxhash/LICENSE.txt)) - [github.com/kortschak/wol](https://pkg.go.dev/github.com/kortschak/wol) ([BSD-3-Clause](https://github.com/kortschak/wol/blob/da482cc4850a/LICENSE)) - - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.2.0/LICENSE.md)) - - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.1/LICENSE.md)) + - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.2/LICENSE.md)) - [github.com/mdlayher/sdnotify](https://pkg.go.dev/github.com/mdlayher/sdnotify) ([MIT](https://github.com/mdlayher/sdnotify/blob/v1.0.0/LICENSE.md)) - - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.0/LICENSE.md)) + - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.1/LICENSE.md)) - [github.com/mitchellh/go-ps](https://pkg.go.dev/github.com/mitchellh/go-ps) ([MIT](https://github.com/mitchellh/go-ps/blob/v1.0.0/LICENSE.md)) + - [github.com/pierrec/lz4/v4](https://pkg.go.dev/github.com/pierrec/lz4/v4) ([BSD-3-Clause](https://github.com/pierrec/lz4/blob/v4.1.17/LICENSE)) - [github.com/skip2/go-qrcode](https://pkg.go.dev/github.com/skip2/go-qrcode) ([MIT](https://github.com/skip2/go-qrcode/blob/da1b6568686e/LICENSE)) - - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/bc99ab8c2d17/LICENSE)) + - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/17a3db2c30d2/LICENSE)) - [github.com/tailscale/goupnp](https://pkg.go.dev/github.com/tailscale/goupnp) ([BSD-2-Clause](https://github.com/tailscale/goupnp/blob/c64d0f06ea05/LICENSE)) - [github.com/tailscale/netlink](https://pkg.go.dev/github.com/tailscale/netlink) ([Apache-2.0](https://github.com/tailscale/netlink/blob/cabfb018fe85/LICENSE)) - [github.com/tailscale/tailscale-android](https://pkg.go.dev/github.com/tailscale/tailscale-android) ([BSD-3-Clause](https://github.com/tailscale/tailscale-android/blob/HEAD/LICENSE)) - [github.com/tailscale/wireguard-go](https://pkg.go.dev/github.com/tailscale/wireguard-go) ([MIT](https://github.com/tailscale/wireguard-go/blob/af172621b4dd/LICENSE)) - [github.com/tcnksm/go-httpstat](https://pkg.go.dev/github.com/tcnksm/go-httpstat) ([MIT](https://github.com/tcnksm/go-httpstat/blob/v0.2.0/LICENSE)) - - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/c3537552635f/LICENSE)) - - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/650dca95af54/LICENSE)) - - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/50045581ed74/LICENSE)) + - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/3e8cd9d6bf63/LICENSE)) + - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/v1.2.1-beta.2/LICENSE)) + - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/v0.0.4/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) - [go4.org/intern](https://pkg.go.dev/go4.org/intern) ([BSD-3-Clause](https://github.com/go4org/intern/blob/ae77deb06f29/LICENSE)) - - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/927187094b94/LICENSE)) - - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) + - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/4f986261bf13/LICENSE)) + - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/f1b76eb4bb35/LICENSE)) - [go4.org/unsafe/assume-no-moving-gc](https://pkg.go.dev/go4.org/unsafe/assume-no-moving-gc) ([BSD-3-Clause](https://github.com/go4org/unsafe-assume-no-moving-gc/blob/ee73d164e760/LICENSE)) - - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47842c84:LICENSE)) + - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.8.0:LICENSE)) + - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47ecfdc1:LICENSE)) - [golang.org/x/exp/shiny](https://pkg.go.dev/golang.org/x/exp/shiny) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/334a2380:shiny/LICENSE)) - - [golang.org/x/image](https://pkg.go.dev/golang.org/x/image) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.5.0:LICENSE)) - - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.8.0:LICENSE)) - - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.6.0:LICENSE)) - - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.6.0:LICENSE)) - - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.8.0:LICENSE)) - - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) + - [golang.org/x/image](https://pkg.go.dev/golang.org/x/image) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.7.0:LICENSE)) + - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) + - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.2.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.8.0:LICENSE)) + - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) + - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) + - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/v0.3.0:LICENSE)) + - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/7b0a1988a28f/LICENSE)) - [inet.af/netaddr](https://pkg.go.dev/inet.af/netaddr) ([BSD-3-Clause](https://github.com/inetaf/netaddr/blob/097006376321/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) - [nhooyr.io/websocket](https://pkg.go.dev/nhooyr.io/websocket) ([MIT](https://github.com/nhooyr/websocket/blob/v1.8.7/LICENSE.txt)) From df8b1b2179302a9e30efb4bc91b77d14737eda46 Mon Sep 17 00:00:00 2001 From: License Updater Date: Thu, 4 May 2023 19:34:48 +0000 Subject: [PATCH 080/331] licenses: update tailscale{,d} licenses Signed-off-by: License Updater --- licenses/tailscale.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/licenses/tailscale.md b/licenses/tailscale.md index e9e93908385f8..1d2eeb7bb32b1 100644 --- a/licenses/tailscale.md +++ b/licenses/tailscale.md @@ -83,18 +83,18 @@ Some packages may only be included on certain architectures or operating systems - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47ecfdc1:LICENSE)) - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.7.0:LICENSE)) - - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.2.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.8.0:LICENSE)) - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/v0.3.0:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) - [golang.zx2c4.com/wireguard/windows/tunnel/winipcfg](https://pkg.go.dev/golang.zx2c4.com/wireguard/windows/tunnel/winipcfg) ([MIT](https://git.zx2c4.com/wireguard-windows/tree/COPYING?h=v0.5.3)) - [gopkg.in/yaml.v2](https://pkg.go.dev/gopkg.in/yaml.v2) ([Apache-2.0](https://github.com/go-yaml/yaml/blob/v2.4.0/LICENSE)) - - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) + - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/7b0a1988a28f/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) - [inet.af/wf](https://pkg.go.dev/inet.af/wf) ([BSD-3-Clause](https://github.com/inetaf/wf/blob/36129f591884/LICENSE)) - - [k8s.io/client-go/util/homedir](https://pkg.go.dev/k8s.io/client-go/util/homedir) ([Apache-2.0](https://github.com/kubernetes/client-go/blob/v0.25.0/LICENSE)) + - [k8s.io/client-go/util/homedir](https://pkg.go.dev/k8s.io/client-go/util/homedir) ([Apache-2.0](https://github.com/kubernetes/client-go/blob/v0.26.1/LICENSE)) - [nhooyr.io/websocket](https://pkg.go.dev/nhooyr.io/websocket) ([MIT](https://github.com/nhooyr/websocket/blob/v1.8.7/LICENSE.txt)) - [sigs.k8s.io/yaml](https://pkg.go.dev/sigs.k8s.io/yaml) ([MIT](https://github.com/kubernetes-sigs/yaml/blob/v1.3.0/LICENSE)) - [software.sslmate.com/src/go-pkcs12](https://pkg.go.dev/software.sslmate.com/src/go-pkcs12) ([BSD-3-Clause](https://github.com/SSLMate/go-pkcs12/blob/v0.2.0/LICENSE)) From e8b06b22323668b28ac4f950b8b8963922d4f8bf Mon Sep 17 00:00:00 2001 From: Chenyang Gao Date: Sun, 7 May 2023 15:20:29 +0800 Subject: [PATCH 081/331] version: properly handle vcs.modified when it's "false" Current code will set the "dirty" field of VersionInfo always "true" if vcs.modified flag is there. No matter whether the flag is "true" or "false". It will make sense to set this field due to vcs.modified value, not only the existence of the key. Signed-off-by: Chenyang Gao --- version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.go b/version/version.go index 98e3892e60656..424ac47db6229 100644 --- a/version/version.go +++ b/version/version.go @@ -131,7 +131,7 @@ var getEmbeddedInfo = lazy.SyncFunc(func() embeddedInfo { ret.commitDate = strings.ReplaceAll(ret.commitDate, "-", "") } case "vcs.modified": - ret.dirty = true + ret.dirty = s.Value == "true" } } if ret.commit == "" || ret.commitDate == "" { From 58ab66ec51f1963fbee302c75ad0017d81d37884 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 8 May 2023 09:42:31 -0700 Subject: [PATCH 082/331] ssh/tailssh: support LDAP users for Tailscale SSH Fixes #4945 Change-Id: Ie013cb47684cb87928a44f92c66352310bfe53f1 Signed-off-by: Brad Fitzpatrick --- ssh/tailssh/incubator.go | 22 +++---- ssh/tailssh/tailssh.go | 17 +----- ssh/tailssh/tailssh_test.go | 13 +++- ssh/tailssh/user.go | 116 ++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 28 deletions(-) create mode 100644 ssh/tailssh/user.go diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go index d4815213d107b..8171eb40921b4 100644 --- a/ssh/tailssh/incubator.go +++ b/ssh/tailssh/incubator.go @@ -688,18 +688,14 @@ func (ss *sshSession) startWithStdPipes() (err error) { return nil } -func loginShell(u *user.User) string { +func loginShell(u *userMeta) string { + if u.LoginShell != "" { + // This field should be populated on Linux, at least, because + // func userLookup on Linux uses "getent" to look up the user + // and that populates it. + return u.LoginShell + } switch runtime.GOOS { - case "linux": - if distro.Get() == distro.Gokrazy { - return "/tmp/serial-busybox/ash" - } - out, _ := exec.Command("getent", "passwd", u.Uid).Output() - // out is "root:x:0:0:root:/root:/bin/bash" - f := strings.SplitN(string(out), ":", 10) - if len(f) > 6 { - return strings.TrimSpace(f[6]) // shell - } case "darwin": // Note: /Users/username is key, and not the same as u.HomeDir. out, _ := exec.Command("dscl", ".", "-read", filepath.Join("/Users", u.Username), "UserShell").Output() @@ -715,12 +711,12 @@ func loginShell(u *user.User) string { return "/bin/sh" } -func envForUser(u *user.User) []string { +func envForUser(u *userMeta) []string { return []string{ fmt.Sprintf("SHELL=" + loginShell(u)), fmt.Sprintf("USER=" + u.Username), fmt.Sprintf("HOME=" + u.HomeDir), - fmt.Sprintf("PATH=" + defaultPathForUser(u)), + fmt.Sprintf("PATH=" + defaultPathForUser(&u.User)), } } diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 63e14b86dcd1c..e15d4d991b3e4 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -22,7 +22,6 @@ import ( "net/url" "os" "os/exec" - "os/user" "path/filepath" "runtime" "strconv" @@ -45,7 +44,6 @@ import ( "tailscale.com/util/clientmetric" "tailscale.com/util/mak" "tailscale.com/util/multierr" - "tailscale.com/version/distro" ) var ( @@ -222,7 +220,7 @@ type conn struct { finalActionErr error // set by doPolicyAuth or resolveNextAction info *sshConnInfo // set by setInfo - localUser *user.User // set by doPolicyAuth + localUser *userMeta // set by doPolicyAuth userGroupIDs []string // set by doPolicyAuth pubKey gossh.PublicKey // set by doPolicyAuth @@ -379,16 +377,7 @@ func (c *conn) doPolicyAuth(ctx ssh.Context, pubKey ssh.PublicKey) error { if a.Accept { c.finalAction = a } - if runtime.GOOS == "linux" && distro.Get() == distro.Gokrazy { - // Gokrazy is a single-user appliance with ~no userspace. - // There aren't users to look up (no /etc/passwd, etc) - // so rather than fail below, just hardcode root. - // TODO(bradfitz): fix os/user upstream instead? - c.userGroupIDs = []string{"0"} - c.localUser = &user.User{Uid: "0", Gid: "0", Username: "root"} - return nil - } - lu, err := user.Lookup(localUser) + lu, err := userLookup(localUser) if err != nil { c.logf("failed to look up %v: %v", localUser, err) ctx.SendAuthBanner(fmt.Sprintf("failed to look up %v\r\n", localUser)) @@ -970,7 +959,7 @@ var errSessionDone = errors.New("session is done") // handleSSHAgentForwarding starts a Unix socket listener and in the background // forwards agent connections between the listener and the ssh.Session. // On success, it assigns ss.agentListener. -func (ss *sshSession) handleSSHAgentForwarding(s ssh.Session, lu *user.User) error { +func (ss *sshSession) handleSSHAgentForwarding(s ssh.Session, lu *userMeta) error { if !ssh.AgentRequested(ss) || !ss.conn.finalAction.AllowAgentForwarding { return nil } diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index 5eb1a3f62e502..d124b49df7e38 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -851,7 +851,11 @@ func TestSSH(t *testing.T) { if err != nil { t.Fatal(err) } - sc.localUser = u + um, err := userLookup(u.Uid) + if err != nil { + t.Fatal(err) + } + sc.localUser = um sc.info = &sshConnInfo{ sshUser: "test", src: netip.MustParseAddrPort("1.2.3.4:32342"), @@ -1135,3 +1139,10 @@ func TestPathFromPAMEnvLineOnNixOS(t *testing.T) { } t.Logf("success; got=%q", got) } + +func TestStdOsUserUserAssumptions(t *testing.T) { + v := reflect.TypeOf(user.User{}) + if got, want := v.NumField(), 5; got != want { + t.Errorf("os/user.User has %v fields; this package assumes %v", got, want) + } +} diff --git a/ssh/tailssh/user.go b/ssh/tailssh/user.go new file mode 100644 index 0000000000000..775caa7954c61 --- /dev/null +++ b/ssh/tailssh/user.go @@ -0,0 +1,116 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build linux || (darwin && !ios) || freebsd || openbsd + +package tailssh + +import ( + "context" + "errors" + "log" + "os/exec" + "os/user" + "runtime" + "strings" + "time" + "unicode/utf8" + + "tailscale.com/version/distro" +) + +// userMeta is a wrapper around *user.User with extra fields. +type userMeta struct { + user.User + + // LoginShell is the user's login shell. + LoginShell string +} + +// GroupIds returns the list of group IDs that the user is a member of. +func (u *userMeta) GroupIds() ([]string, error) { + if runtime.GOOS == "linux" && distro.Get() == distro.Gokrazy { + // Gokrazy is a single-user appliance with ~no userspace. + // There aren't users to look up (no /etc/passwd, etc) + // so rather than fail below, just hardcode root. + // TODO(bradfitz): fix os/user upstream instead? + return []string{"0"}, nil + } + return u.User.GroupIds() +} + +// userLookup is like os/user.LookupId but it returns a *userMeta wrapper +// around a *user.User with extra fields. +func userLookup(uid string) (*userMeta, error) { + if runtime.GOOS != "linux" { + return userLookupStd(uid) + } + + // No getent on Gokrazy. So hard-code the login shell. + if distro.Get() == distro.Gokrazy { + um, err := userLookupStd(uid) + if err == nil { + um.LoginShell = "/tmp/serial-busybox/ash" + } + return um, err + } + + // On Linux, default to using "getent" to look up users so that + // even with static tailscaled binaries without cgo (as we distribute), + // we can still look up PAM/NSS users which the standard library's + // os/user without cgo won't get (because of no libc hooks). + // But if "getent" fails, userLookupGetent falls back to the standard + // library anyway. + return userLookupGetent(uid) +} + +func validUsername(uid string) bool { + if len(uid) > 32 || len(uid) == 0 { + return false + } + for _, r := range uid { + if r < ' ' || r == 0x7f || r == utf8.RuneError { // TODO(bradfitz): more? + return false + } + } + return true +} + +func userLookupGetent(uid string) (*userMeta, error) { + // Do some basic validation before passing this string to "getent", even though + // getent should do its own validation. + if !validUsername(uid) { + return nil, errors.New("invalid username") + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + out, err := exec.CommandContext(ctx, "getent", "passwd", uid).Output() + if err != nil { + log.Printf("error calling getent for user %q: %v", uid, err) + return userLookupStd(uid) + } + // output is "alice:x:1001:1001:Alice Smith,,,:/home/alice:/bin/bash" + f := strings.SplitN(strings.TrimSpace(string(out)), ":", 10) + for len(f) < 7 { + f = append(f, "") + } + um := &userMeta{ + User: user.User{ + Username: f[0], + Uid: f[2], + Gid: f[3], + Name: f[4], + HomeDir: f[5], + }, + LoginShell: f[6], + } + return um, nil +} + +func userLookupStd(uid string) (*userMeta, error) { + u, err := user.LookupId(uid) + if err != nil { + return nil, err + } + return &userMeta{User: *u}, nil +} From a743b66f9db4ca5ffac5cea71377237cf9777d72 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 8 May 2023 12:21:37 -0700 Subject: [PATCH 083/331] ssh/tailssh: move some user-related code into new user.go The previous commit 58ab66e added ssh/tailssh/user.go as part of working on #4945. So move some more user-related code over to it. Updates #cleanup Change-Id: I24de66df25ffb8f867e1a0a540d410f9ef16d7b0 Signed-off-by: Brad Fitzpatrick --- ssh/tailssh/incubator.go | 107 +----------------------------------- ssh/tailssh/user.go | 115 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 109 deletions(-) diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go index 8171eb40921b4..1a277d63e4401 100644 --- a/ssh/tailssh/incubator.go +++ b/ssh/tailssh/incubator.go @@ -20,7 +20,6 @@ import ( "log/syslog" "os" "os/exec" - "os/user" "path/filepath" "runtime" "sort" @@ -31,16 +30,12 @@ import ( "github.com/creack/pty" "github.com/pkg/sftp" "github.com/u-root/u-root/pkg/termios" - "go4.org/mem" gossh "golang.org/x/crypto/ssh" "golang.org/x/exp/slices" "golang.org/x/sys/unix" "tailscale.com/cmd/tailscaled/childproc" - "tailscale.com/envknob" - "tailscale.com/hostinfo" "tailscale.com/tempfork/gliderlabs/ssh" "tailscale.com/types/logger" - "tailscale.com/util/lineread" "tailscale.com/version/distro" ) @@ -83,7 +78,7 @@ func (ss *sshSession) newIncubatorCommand() (cmd *exec.Cmd) { case "sftp": isSFTP = true case "": - name = loginShell(ss.conn.localUser) + name = ss.conn.localUser.LoginShell() if rawCmd := ss.RawCommand(); rawCmd != "" { args = append(args, "-c", rawCmd) } else { @@ -688,113 +683,15 @@ func (ss *sshSession) startWithStdPipes() (err error) { return nil } -func loginShell(u *userMeta) string { - if u.LoginShell != "" { - // This field should be populated on Linux, at least, because - // func userLookup on Linux uses "getent" to look up the user - // and that populates it. - return u.LoginShell - } - switch runtime.GOOS { - case "darwin": - // Note: /Users/username is key, and not the same as u.HomeDir. - out, _ := exec.Command("dscl", ".", "-read", filepath.Join("/Users", u.Username), "UserShell").Output() - // out is "UserShell: /bin/bash" - s, ok := strings.CutPrefix(string(out), "UserShell: ") - if ok { - return strings.TrimSpace(s) - } - } - if e := os.Getenv("SHELL"); e != "" { - return e - } - return "/bin/sh" -} - func envForUser(u *userMeta) []string { return []string{ - fmt.Sprintf("SHELL=" + loginShell(u)), + fmt.Sprintf("SHELL=" + u.LoginShell()), fmt.Sprintf("USER=" + u.Username), fmt.Sprintf("HOME=" + u.HomeDir), fmt.Sprintf("PATH=" + defaultPathForUser(&u.User)), } } -// defaultPathTmpl specifies the default PATH template to use for new sessions. -// -// If empty, a default value is used based on the OS & distro to match OpenSSH's -// usually-hardcoded behavior. (see -// https://github.com/tailscale/tailscale/issues/5285 for background). -// -// The template may contain @{HOME} or @{PAM_USER} which expand to the user's -// home directory and username, respectively. (PAM is not used, despite the -// name) -var defaultPathTmpl = envknob.RegisterString("TAILSCALE_SSH_DEFAULT_PATH") - -func defaultPathForUser(u *user.User) string { - if s := defaultPathTmpl(); s != "" { - return expandDefaultPathTmpl(s, u) - } - isRoot := u.Uid == "0" - switch distro.Get() { - case distro.Debian: - hi := hostinfo.New() - if hi.Distro == "ubuntu" { - // distro.Get's Debian includes Ubuntu. But see if it's actually Ubuntu. - // Ubuntu doesn't empirically seem to distinguish between root and non-root for the default. - // And it includes /snap/bin. - return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" - } - if isRoot { - return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - } - return "/usr/local/bin:/usr/bin:/bin:/usr/bn/games" - case distro.NixOS: - return defaultPathForUserOnNixOS(u) - } - if isRoot { - return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - } - return "/usr/local/bin:/usr/bin:/bin" -} - -func defaultPathForUserOnNixOS(u *user.User) string { - var path string - lineread.File("/etc/pam/environment", func(lineb []byte) error { - if v := pathFromPAMEnvLine(lineb, u); v != "" { - path = v - return io.EOF // stop iteration - } - return nil - }) - return path -} - -func pathFromPAMEnvLine(line []byte, u *user.User) (path string) { - if !mem.HasPrefix(mem.B(line), mem.S("PATH")) { - return "" - } - rest := strings.TrimSpace(strings.TrimPrefix(string(line), "PATH")) - if quoted, ok := strings.CutPrefix(rest, "DEFAULT="); ok { - if path, err := strconv.Unquote(quoted); err == nil { - return expandDefaultPathTmpl(path, u) - } - } - return "" -} - -func expandDefaultPathTmpl(t string, u *user.User) string { - p := strings.NewReplacer( - "@{HOME}", u.HomeDir, - "@{PAM_USER}", u.Username, - ).Replace(t) - if strings.Contains(p, "@{") { - // If there are unknown expansions, conservatively fail closed. - return "" - } - return p -} - // updateStringInSlice mutates ss to change the first occurrence of a // to b. func updateStringInSlice(ss []string, a, b string) { diff --git a/ssh/tailssh/user.go b/ssh/tailssh/user.go index 775caa7954c61..89442ed617ad8 100644 --- a/ssh/tailssh/user.go +++ b/ssh/tailssh/user.go @@ -8,14 +8,22 @@ package tailssh import ( "context" "errors" + "io" "log" + "os" "os/exec" "os/user" + "path/filepath" "runtime" + "strconv" "strings" "time" "unicode/utf8" + "go4.org/mem" + "tailscale.com/envknob" + "tailscale.com/hostinfo" + "tailscale.com/util/lineread" "tailscale.com/version/distro" ) @@ -23,8 +31,9 @@ import ( type userMeta struct { user.User - // LoginShell is the user's login shell. - LoginShell string + // loginShellCached is the user's login shell, if known + // at the time of userLookup. + loginShellCached string } // GroupIds returns the list of group IDs that the user is a member of. @@ -50,7 +59,7 @@ func userLookup(uid string) (*userMeta, error) { if distro.Get() == distro.Gokrazy { um, err := userLookupStd(uid) if err == nil { - um.LoginShell = "/tmp/serial-busybox/ash" + um.loginShellCached = "/tmp/serial-busybox/ash" } return um, err } @@ -102,7 +111,7 @@ func userLookupGetent(uid string) (*userMeta, error) { Name: f[4], HomeDir: f[5], }, - LoginShell: f[6], + loginShellCached: f[6], } return um, nil } @@ -114,3 +123,101 @@ func userLookupStd(uid string) (*userMeta, error) { } return &userMeta{User: *u}, nil } + +func (u *userMeta) LoginShell() string { + if u.loginShellCached != "" { + // This field should be populated on Linux, at least, because + // func userLookup on Linux uses "getent" to look up the user + // and that populates it. + return u.loginShellCached + } + switch runtime.GOOS { + case "darwin": + // Note: /Users/username is key, and not the same as u.HomeDir. + out, _ := exec.Command("dscl", ".", "-read", filepath.Join("/Users", u.Username), "UserShell").Output() + // out is "UserShell: /bin/bash" + s, ok := strings.CutPrefix(string(out), "UserShell: ") + if ok { + return strings.TrimSpace(s) + } + } + if e := os.Getenv("SHELL"); e != "" { + return e + } + return "/bin/sh" +} + +// defaultPathTmpl specifies the default PATH template to use for new sessions. +// +// If empty, a default value is used based on the OS & distro to match OpenSSH's +// usually-hardcoded behavior. (see +// https://github.com/tailscale/tailscale/issues/5285 for background). +// +// The template may contain @{HOME} or @{PAM_USER} which expand to the user's +// home directory and username, respectively. (PAM is not used, despite the +// name) +var defaultPathTmpl = envknob.RegisterString("TAILSCALE_SSH_DEFAULT_PATH") + +func defaultPathForUser(u *user.User) string { + if s := defaultPathTmpl(); s != "" { + return expandDefaultPathTmpl(s, u) + } + isRoot := u.Uid == "0" + switch distro.Get() { + case distro.Debian: + hi := hostinfo.New() + if hi.Distro == "ubuntu" { + // distro.Get's Debian includes Ubuntu. But see if it's actually Ubuntu. + // Ubuntu doesn't empirically seem to distinguish between root and non-root for the default. + // And it includes /snap/bin. + return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" + } + if isRoot { + return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + } + return "/usr/local/bin:/usr/bin:/bin:/usr/bn/games" + case distro.NixOS: + return defaultPathForUserOnNixOS(u) + } + if isRoot { + return "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + } + return "/usr/local/bin:/usr/bin:/bin" +} + +func defaultPathForUserOnNixOS(u *user.User) string { + var path string + lineread.File("/etc/pam/environment", func(lineb []byte) error { + if v := pathFromPAMEnvLine(lineb, u); v != "" { + path = v + return io.EOF // stop iteration + } + return nil + }) + return path +} + +func pathFromPAMEnvLine(line []byte, u *user.User) (path string) { + if !mem.HasPrefix(mem.B(line), mem.S("PATH")) { + return "" + } + rest := strings.TrimSpace(strings.TrimPrefix(string(line), "PATH")) + if quoted, ok := strings.CutPrefix(rest, "DEFAULT="); ok { + if path, err := strconv.Unquote(quoted); err == nil { + return expandDefaultPathTmpl(path, u) + } + } + return "" +} + +func expandDefaultPathTmpl(t string, u *user.User) string { + p := strings.NewReplacer( + "@{HOME}", u.HomeDir, + "@{PAM_USER}", u.Username, + ).Replace(t) + if strings.Contains(p, "@{") { + // If there are unknown expansions, conservatively fail closed. + return "" + } + return p +} From d1ecb1f43bee92800c668f6edbd98409c1a76af8 Mon Sep 17 00:00:00 2001 From: License Updater Date: Mon, 8 May 2023 23:45:37 +0000 Subject: [PATCH 084/331] licenses: update win/apple licenses Signed-off-by: License Updater --- licenses/apple.md | 71 +++++++++++++++++++++++---------------------- licenses/windows.md | 36 +++++++++++------------ 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/licenses/apple.md b/licenses/apple.md index 6359b727d9f90..dc24fa28b0b1a 100644 --- a/licenses/apple.md +++ b/licenses/apple.md @@ -10,62 +10,63 @@ and [iOS][]. See also the dependencies in the [Tailscale CLI][]. ## Go Packages - - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0-rc.1/LICENSE)) - - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.17.7/config/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.12.20/credentials/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.12.17/feature/ec2/imds/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.27/internal/configsources/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.21/internal/endpoints/v2/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.24/internal/ini/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.17.3/internal/sync/singleflight/LICENSE)) - - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.9.17/service/internal/presigned-url/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.35.0/service/ssm/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.11.23/service/sso/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/ssooidc](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssooidc) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.13.5/service/ssooidc/LICENSE.txt)) - - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.16.19/service/sts/LICENSE.txt)) + - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0/LICENSE)) + - [github.com/aws/aws-sdk-go-v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/config/v1.18.22/config/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/credentials](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/credentials/v1.13.21/credentials/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/feature/ec2/imds](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/ec2/imds) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/feature/ec2/imds/v1.13.3/feature/ec2/imds/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/configsources](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/configsources) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/configsources/v1.1.33/internal/configsources/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/endpoints/v2](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/endpoints/v2) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/endpoints/v2.4.27/internal/endpoints/v2/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/ini](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/ini) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/internal/ini/v1.3.34/internal/ini/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/aws-sdk-go-v2/blob/v1.18.0/internal/sync/singleflight/LICENSE)) + - [github.com/aws/aws-sdk-go-v2/service/internal/presigned-url](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/internal/presigned-url/v1.9.27/service/internal/presigned-url/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssm](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssm) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssm/v1.36.3/service/ssm/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sso](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sso) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sso/v1.12.9/service/sso/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/ssooidc](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ssooidc) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/ssooidc/v1.14.9/service/ssooidc/LICENSE.txt)) + - [github.com/aws/aws-sdk-go-v2/service/sts](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/sts) ([Apache-2.0](https://github.com/aws/aws-sdk-go-v2/blob/service/sts/v1.18.10/service/sts/LICENSE.txt)) - [github.com/aws/smithy-go](https://pkg.go.dev/github.com/aws/smithy-go) ([Apache-2.0](https://github.com/aws/smithy-go/blob/v1.13.5/LICENSE)) - [github.com/aws/smithy-go/internal/sync/singleflight](https://pkg.go.dev/github.com/aws/smithy-go/internal/sync/singleflight) ([BSD-3-Clause](https://github.com/aws/smithy-go/blob/v1.13.5/internal/sync/singleflight/LICENSE)) - [github.com/coreos/go-iptables/iptables](https://pkg.go.dev/github.com/coreos/go-iptables/iptables) ([Apache-2.0](https://github.com/coreos/go-iptables/blob/v0.6.0/LICENSE)) - [github.com/fxamacker/cbor/v2](https://pkg.go.dev/github.com/fxamacker/cbor/v2) ([MIT](https://github.com/fxamacker/cbor/blob/v2.4.0/LICENSE)) - - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.0.6/LICENSE)) + - [github.com/godbus/dbus/v5](https://pkg.go.dev/github.com/godbus/dbus/v5) ([BSD-2-Clause](https://github.com/godbus/dbus/blob/v5.1.0/LICENSE)) - [github.com/golang/groupcache/lru](https://pkg.go.dev/github.com/golang/groupcache/lru) ([Apache-2.0](https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE)) - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.1.2/LICENSE)) - - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/c00d1f31bab3/LICENSE)) + - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/v0.1.0/LICENSE)) - [github.com/illarion/gonotify](https://pkg.go.dev/github.com/illarion/gonotify) ([MIT](https://github.com/illarion/gonotify/blob/v1.0.1/LICENSE)) - - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/de60144f33f8/LICENSE)) + - [github.com/insomniacslk/dhcp](https://pkg.go.dev/github.com/insomniacslk/dhcp) ([BSD-3-Clause](https://github.com/insomniacslk/dhcp/blob/974c6f05fe16/LICENSE)) - [github.com/jmespath/go-jmespath](https://pkg.go.dev/github.com/jmespath/go-jmespath) ([Apache-2.0](https://github.com/jmespath/go-jmespath/blob/v0.4.0/LICENSE)) - [github.com/josharian/native](https://pkg.go.dev/github.com/josharian/native) ([MIT](https://github.com/josharian/native/blob/5c7d0dd6ab86/license)) - - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/d380b505068b/LICENSE.md)) - - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.15.11/LICENSE)) - - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.15.11/internal/snapref/LICENSE)) - - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.15.11/zstd/internal/xxhash/LICENSE.txt)) + - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.16.5/LICENSE)) + - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.16.5/internal/snapref/LICENSE)) + - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.16.5/zstd/internal/xxhash/LICENSE.txt)) - [github.com/kortschak/wol](https://pkg.go.dev/github.com/kortschak/wol) ([BSD-3-Clause](https://github.com/kortschak/wol/blob/da482cc4850a/LICENSE)) - - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.2.0/LICENSE.md)) - - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.1/LICENSE.md)) + - [github.com/mdlayher/genetlink](https://pkg.go.dev/github.com/mdlayher/genetlink) ([MIT](https://github.com/mdlayher/genetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.2/LICENSE.md)) - [github.com/mdlayher/sdnotify](https://pkg.go.dev/github.com/mdlayher/sdnotify) ([MIT](https://github.com/mdlayher/sdnotify/blob/v1.0.0/LICENSE.md)) - - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.0/LICENSE.md)) + - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.1/LICENSE.md)) - [github.com/mitchellh/go-ps](https://pkg.go.dev/github.com/mitchellh/go-ps) ([MIT](https://github.com/mitchellh/go-ps/blob/v1.0.0/LICENSE.md)) - - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/bc99ab8c2d17/LICENSE)) + - [github.com/pierrec/lz4/v4](https://pkg.go.dev/github.com/pierrec/lz4/v4) ([BSD-3-Clause](https://github.com/pierrec/lz4/blob/v4.1.17/LICENSE)) + - [github.com/tailscale/golang-x-crypto](https://pkg.go.dev/github.com/tailscale/golang-x-crypto) ([BSD-3-Clause](https://github.com/tailscale/golang-x-crypto/blob/17a3db2c30d2/LICENSE)) - [github.com/tailscale/goupnp](https://pkg.go.dev/github.com/tailscale/goupnp) ([BSD-2-Clause](https://github.com/tailscale/goupnp/blob/c64d0f06ea05/LICENSE)) - [github.com/tailscale/netlink](https://pkg.go.dev/github.com/tailscale/netlink) ([Apache-2.0](https://github.com/tailscale/netlink/blob/cabfb018fe85/LICENSE)) - [github.com/tailscale/wireguard-go](https://pkg.go.dev/github.com/tailscale/wireguard-go) ([MIT](https://github.com/tailscale/wireguard-go/blob/af172621b4dd/LICENSE)) - [github.com/tcnksm/go-httpstat](https://pkg.go.dev/github.com/tcnksm/go-httpstat) ([MIT](https://github.com/tcnksm/go-httpstat/blob/v0.2.0/LICENSE)) - - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/c3537552635f/LICENSE)) - - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/650dca95af54/LICENSE)) - - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/50045581ed74/LICENSE)) + - [github.com/u-root/uio](https://pkg.go.dev/github.com/u-root/uio) ([BSD-3-Clause](https://github.com/u-root/uio/blob/3e8cd9d6bf63/LICENSE)) + - [github.com/vishvananda/netlink/nl](https://pkg.go.dev/github.com/vishvananda/netlink/nl) ([Apache-2.0](https://github.com/vishvananda/netlink/blob/v1.2.1-beta.2/LICENSE)) + - [github.com/vishvananda/netns](https://pkg.go.dev/github.com/vishvananda/netns) ([Apache-2.0](https://github.com/vishvananda/netns/blob/v0.0.4/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/4f986261bf13/LICENSE)) - - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) + - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/f1b76eb4bb35/LICENSE)) + - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.8.0:LICENSE)) + - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47ecfdc1:LICENSE)) - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) - - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.2.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.8.0:LICENSE)) - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) - - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/579cf78f:LICENSE)) - - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/162ed5ef888d/LICENSE)) + - [golang.org/x/time/rate](https://pkg.go.dev/golang.org/x/time/rate) ([BSD-3-Clause](https://cs.opensource.google/go/x/time/+/v0.3.0:LICENSE)) + - [gvisor.dev/gvisor/pkg](https://pkg.go.dev/gvisor.dev/gvisor/pkg) ([Apache-2.0](https://github.com/google/gvisor/blob/7b0a1988a28f/LICENSE)) - [inet.af/peercred](https://pkg.go.dev/inet.af/peercred) ([BSD-3-Clause](https://github.com/inetaf/peercred/blob/0893ea02156a/LICENSE)) - [nhooyr.io/websocket](https://pkg.go.dev/nhooyr.io/websocket) ([MIT](https://github.com/nhooyr/websocket/blob/v1.8.7/LICENSE.txt)) - [tailscale.com](https://pkg.go.dev/tailscale.com) ([BSD-3-Clause](https://github.com/tailscale/tailscale/blob/HEAD/LICENSE)) diff --git a/licenses/windows.md b/licenses/windows.md index dc5b17e650139..675fcaaab90de 100644 --- a/licenses/windows.md +++ b/licenses/windows.md @@ -9,42 +9,42 @@ Windows][]. See also the dependencies in the [Tailscale CLI][]. ## Go Packages - - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0-rc.1/LICENSE)) - - [github.com/Microsoft/go-winio](https://pkg.go.dev/github.com/Microsoft/go-winio) ([MIT](https://github.com/Microsoft/go-winio/blob/v0.6.0/LICENSE)) + - [filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519) ([BSD-3-Clause](https://github.com/FiloSottile/edwards25519/blob/v1.0.0/LICENSE)) + - [github.com/Microsoft/go-winio](https://pkg.go.dev/github.com/Microsoft/go-winio) ([MIT](https://github.com/Microsoft/go-winio/blob/v0.6.1/LICENSE)) - [github.com/alexbrainman/sspi](https://pkg.go.dev/github.com/alexbrainman/sspi) ([BSD-3-Clause](https://github.com/alexbrainman/sspi/blob/909beea2cc74/LICENSE)) - [github.com/apenwarr/fixconsole](https://pkg.go.dev/github.com/apenwarr/fixconsole) ([Apache-2.0](https://github.com/apenwarr/fixconsole/blob/5a9f6489cc29/LICENSE)) - [github.com/apenwarr/w32](https://pkg.go.dev/github.com/apenwarr/w32) ([BSD-3-Clause](https://github.com/apenwarr/w32/blob/aa00fece76ab/LICENSE)) - - [github.com/dblohm7/wingoes](https://pkg.go.dev/github.com/dblohm7/wingoes) ([BSD-3-Clause](https://github.com/dblohm7/wingoes/blob/2b26ab7fb5f9/LICENSE)) + - [github.com/dblohm7/wingoes](https://pkg.go.dev/github.com/dblohm7/wingoes) ([BSD-3-Clause](https://github.com/dblohm7/wingoes/blob/111c8c3b57c8/LICENSE)) - [github.com/fxamacker/cbor/v2](https://pkg.go.dev/github.com/fxamacker/cbor/v2) ([MIT](https://github.com/fxamacker/cbor/blob/v2.4.0/LICENSE)) - [github.com/golang/groupcache/lru](https://pkg.go.dev/github.com/golang/groupcache/lru) ([Apache-2.0](https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE)) - [github.com/google/btree](https://pkg.go.dev/github.com/google/btree) ([Apache-2.0](https://github.com/google/btree/blob/v1.1.2/LICENSE)) - [github.com/google/uuid](https://pkg.go.dev/github.com/google/uuid) ([BSD-3-Clause](https://github.com/google/uuid/blob/v1.3.0/LICENSE)) - [github.com/gregjones/httpcache](https://pkg.go.dev/github.com/gregjones/httpcache) ([MIT](https://github.com/gregjones/httpcache/blob/901d90724c79/LICENSE.txt)) - - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/c00d1f31bab3/LICENSE)) + - [github.com/hdevalence/ed25519consensus](https://pkg.go.dev/github.com/hdevalence/ed25519consensus) ([BSD-3-Clause](https://github.com/hdevalence/ed25519consensus/blob/v0.1.0/LICENSE)) - [github.com/josharian/native](https://pkg.go.dev/github.com/josharian/native) ([MIT](https://github.com/josharian/native/blob/5c7d0dd6ab86/license)) - - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/d380b505068b/LICENSE.md)) - - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.15.11/LICENSE)) - - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.15.11/internal/snapref/LICENSE)) - - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.15.11/zstd/internal/xxhash/LICENSE.txt)) - - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.1/LICENSE.md)) - - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.0/LICENSE.md)) + - [github.com/jsimonetti/rtnetlink](https://pkg.go.dev/github.com/jsimonetti/rtnetlink) ([MIT](https://github.com/jsimonetti/rtnetlink/blob/v1.3.2/LICENSE.md)) + - [github.com/klauspost/compress](https://pkg.go.dev/github.com/klauspost/compress) ([Apache-2.0](https://github.com/klauspost/compress/blob/v1.16.5/LICENSE)) + - [github.com/klauspost/compress/internal/snapref](https://pkg.go.dev/github.com/klauspost/compress/internal/snapref) ([BSD-3-Clause](https://github.com/klauspost/compress/blob/v1.16.5/internal/snapref/LICENSE)) + - [github.com/klauspost/compress/zstd/internal/xxhash](https://pkg.go.dev/github.com/klauspost/compress/zstd/internal/xxhash) ([MIT](https://github.com/klauspost/compress/blob/v1.16.5/zstd/internal/xxhash/LICENSE.txt)) + - [github.com/mdlayher/netlink](https://pkg.go.dev/github.com/mdlayher/netlink) ([MIT](https://github.com/mdlayher/netlink/blob/v1.7.2/LICENSE.md)) + - [github.com/mdlayher/socket](https://pkg.go.dev/github.com/mdlayher/socket) ([MIT](https://github.com/mdlayher/socket/blob/v0.4.1/LICENSE.md)) - [github.com/mitchellh/go-ps](https://pkg.go.dev/github.com/mitchellh/go-ps) ([MIT](https://github.com/mitchellh/go-ps/blob/v1.0.0/LICENSE.md)) - [github.com/nfnt/resize](https://pkg.go.dev/github.com/nfnt/resize) ([ISC](https://github.com/nfnt/resize/blob/83c6a9932646/LICENSE)) - [github.com/peterbourgon/diskv](https://pkg.go.dev/github.com/peterbourgon/diskv) ([MIT](https://github.com/peterbourgon/diskv/blob/v2.0.1/LICENSE)) - [github.com/skip2/go-qrcode](https://pkg.go.dev/github.com/skip2/go-qrcode) ([MIT](https://github.com/skip2/go-qrcode/blob/da1b6568686e/LICENSE)) - - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/f374e3278cd0/LICENSE)) + - [github.com/tailscale/walk](https://pkg.go.dev/github.com/tailscale/walk) ([BSD-3-Clause](https://github.com/tailscale/walk/blob/f63dace725d8/LICENSE)) - [github.com/tailscale/win](https://pkg.go.dev/github.com/tailscale/win) ([BSD-3-Clause](https://github.com/tailscale/win/blob/59dfb47dfef1/LICENSE)) - - [github.com/tc-hib/winres](https://pkg.go.dev/github.com/tc-hib/winres) ([0BSD](https://github.com/tc-hib/winres/blob/v0.1.6/LICENSE)) + - [github.com/tc-hib/winres](https://pkg.go.dev/github.com/tc-hib/winres) ([0BSD](https://github.com/tc-hib/winres/blob/v0.2.0/LICENSE)) - [github.com/x448/float16](https://pkg.go.dev/github.com/x448/float16) ([MIT](https://github.com/x448/float16/blob/v0.8.4/LICENSE)) - [go4.org/mem](https://pkg.go.dev/go4.org/mem) ([Apache-2.0](https://github.com/go4org/mem/blob/4f986261bf13/LICENSE)) - - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/7e7bdc8411bf/LICENSE)) - - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.6.0:LICENSE)) - - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/cafedaf6:LICENSE)) - - [golang.org/x/image/bmp](https://pkg.go.dev/golang.org/x/image/bmp) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.5.0:LICENSE)) + - [go4.org/netipx](https://pkg.go.dev/go4.org/netipx) ([BSD-3-Clause](https://github.com/go4org/netipx/blob/f1b76eb4bb35/LICENSE)) + - [golang.org/x/crypto](https://pkg.go.dev/golang.org/x/crypto) ([BSD-3-Clause](https://cs.opensource.google/go/x/crypto/+/v0.8.0:LICENSE)) + - [golang.org/x/exp](https://pkg.go.dev/golang.org/x/exp) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/47ecfdc1:LICENSE)) + - [golang.org/x/image/bmp](https://pkg.go.dev/golang.org/x/image/bmp) ([BSD-3-Clause](https://cs.opensource.google/go/x/image/+/v0.7.0:LICENSE)) - [golang.org/x/mod](https://pkg.go.dev/golang.org/x/mod) ([BSD-3-Clause](https://cs.opensource.google/go/x/mod/+/v0.10.0:LICENSE)) - [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.9.0:LICENSE)) - - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.1.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.7.0:LICENSE)) + - [golang.org/x/sync/errgroup](https://pkg.go.dev/golang.org/x/sync/errgroup) ([BSD-3-Clause](https://cs.opensource.google/go/x/sync/+/v0.2.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.8.0:LICENSE)) - [golang.org/x/term](https://pkg.go.dev/golang.org/x/term) ([BSD-3-Clause](https://cs.opensource.google/go/x/term/+/v0.7.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.9.0:LICENSE)) - [golang.zx2c4.com/wintun](https://pkg.go.dev/golang.zx2c4.com/wintun) ([MIT](https://git.zx2c4.com/wintun-go/tree/LICENSE?id=0fa3db229ce2)) From 827abbeeaaf21388ec0dc7046d61d8350afe98f7 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Thu, 6 Apr 2023 16:01:35 -0700 Subject: [PATCH 085/331] cmd/k8s-operator: print version in startup logs Fixes: #7813 Signed-off-by: Craig Rodrigues --- cmd/k8s-operator/operator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 5155337eeac0b..2d7a8c793e6b8 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -48,6 +48,7 @@ import ( "tailscale.com/types/logger" "tailscale.com/types/opt" "tailscale.com/util/dnsname" + "tailscale.com/version" ) func main() { @@ -235,7 +236,7 @@ waitOnline: startlog.Fatalf("could not create controller: %v", err) } - startlog.Infof("Startup complete, operator running") + startlog.Infof("Startup complete, operator running, version: %s", version.Long()) if shouldRunAuthProxy { cfg, err := restConfig.TransportConfig() if err != nil { From 1ce08256c09cf85e9d2a5dc7324f1ea3169bbd1d Mon Sep 17 00:00:00 2001 From: salman Date: Tue, 9 May 2023 10:09:55 +0100 Subject: [PATCH 086/331] release/dist: add deb/rpm arch mappings for mipses According to https://wiki.debian.org/SupportedArchitectures Debian does not support big-endian mips64, so that one remains disabled. According to https://fedoraproject.org/wiki/Architectures Fedora only supports little-endian mips, so leaving both big-endian ones out too. Updates #8005. Signed-off-by: salman --- release/dist/unixpkgs/pkgs.go | 8 +++++++ release/dist/unixpkgs/targets.go | 38 ++++++++++++++++---------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/release/dist/unixpkgs/pkgs.go b/release/dist/unixpkgs/pkgs.go index b9c36e0b22c07..61a6235df7c1e 100644 --- a/release/dist/unixpkgs/pkgs.go +++ b/release/dist/unixpkgs/pkgs.go @@ -354,6 +354,10 @@ func debArch(arch string) string { // can ship more than 1 ARM deb, so for now match redo's behavior of // shipping armv5 binaries in an armv7 trenchcoat. return "armhf" + case "mipsle": + return "mipsel" + case "mips64le": + return "mips64el" default: return arch } @@ -372,6 +376,10 @@ func rpmArch(arch string) string { return "armv7hl" case "arm64": return "aarch64" + case "mipsle": + return "mipsel" + case "mips64le": + return "mips64el" default: return arch } diff --git a/release/dist/unixpkgs/targets.go b/release/dist/unixpkgs/targets.go index b9f599170951c..aad79d75e620d 100644 --- a/release/dist/unixpkgs/targets.go +++ b/release/dist/unixpkgs/targets.go @@ -82,31 +82,31 @@ var ( } debs = map[string]bool{ - "linux/386": true, - "linux/amd64": true, - "linux/arm": true, - "linux/arm64": true, - "linux/riscv64": true, - // TODO: maybe mipses, we accidentally started building them at some - // point even though they probably don't work right. - // "linux/mips": true, - // "linux/mipsle": true, + "linux/386": true, + "linux/amd64": true, + "linux/arm": true, + "linux/arm64": true, + "linux/riscv64": true, + "linux/mipsle": true, + "linux/mips64le": true, + "linux/mips": true, + // Debian does not support big endian mips64. Leave that out until we know + // we need it. // "linux/mips64": true, - // "linux/mips64le": true, } rpms = map[string]bool{ - "linux/386": true, - "linux/amd64": true, - "linux/arm": true, - "linux/arm64": true, - "linux/riscv64": true, - // TODO: maybe mipses, we accidentally started building them at some - // point even though they probably don't work right. + "linux/386": true, + "linux/amd64": true, + "linux/arm": true, + "linux/arm64": true, + "linux/riscv64": true, + "linux/mipsle": true, + "linux/mips64le": true, + // Fedora only supports little endian mipses. Maybe some other distribution + // supports big-endian? Leave them out for now. // "linux/mips": true, - // "linux/mipsle": true, // "linux/mips64": true, - // "linux/mips64le": true, } ) From ea84fc9ad2532f6a8a43863d5caaa090cdb32833 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Tue, 9 May 2023 09:40:55 -0700 Subject: [PATCH 087/331] net/sockstats: wait before reporting battery usage Wait 2 minutes before we start reporting battery usage. There is always radio activity on initial startup, which gets reported as 100% high power usage. Let that settle before we report usage data. Updates tailscale/corp#9230 Signed-off-by: Will Norris --- net/sockstats/sockstats_tsgo.go | 8 ++++++-- net/sockstats/sockstats_tsgo_test.go | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/net/sockstats/sockstats_tsgo.go b/net/sockstats/sockstats_tsgo.go index 26211958f81aa..37edddddf0d2e 100644 --- a/net/sockstats/sockstats_tsgo.go +++ b/net/sockstats/sockstats_tsgo.go @@ -325,6 +325,10 @@ type radioMonitor struct { // Usage is measured once per second, so this is the number of seconds of history to track. const radioSampleSize = 3600 // 1 hour +// initStallPeriod is the minimum amount of time in seconds to collect data before reporting. +// Otherwise, all clients will report 100% radio usage on startup. +var initStallPeriod int64 = 120 // 2 minutes + var radio = &radioMonitor{ now: time.Now, startTime: time.Now().Unix(), @@ -375,7 +379,7 @@ func (rm *radioMonitor) radioHighPercent() int64 { } }) - if periodLength == 0 { + if periodLength < initStallPeriod { return 0 } @@ -386,7 +390,7 @@ func (rm *radioMonitor) radioHighPercent() int64 { } // forEachSample calls f for each sample in the past hour (or less if less time -// has passed -- the evaluated period is returned) +// has passed -- the evaluated period is returned, measured in seconds) func (rm *radioMonitor) forEachSample(f func(c int, isActive bool)) (periodLength int64) { now := rm.now().Unix() periodLength = radioSampleSize diff --git a/net/sockstats/sockstats_tsgo_test.go b/net/sockstats/sockstats_tsgo_test.go index 9e3a5a86af826..9887d6680bf88 100644 --- a/net/sockstats/sockstats_tsgo_test.go +++ b/net/sockstats/sockstats_tsgo_test.go @@ -33,6 +33,14 @@ func TestRadioMonitor(t *testing.T) { func(_ *testTime, _ *radioMonitor) {}, 0, }, + { + "active less than init stall period", + func(tt *testTime, rm *radioMonitor) { + rm.active() + tt.Add(1 * time.Second) + }, + 0, // radio on, but not long enough to report data + }, { "active, 10 sec idle", func(tt *testTime, rm *radioMonitor) { @@ -42,13 +50,13 @@ func TestRadioMonitor(t *testing.T) { 50, // radio on 5 seconds of 10 seconds }, { - "active, spanning two seconds", + "active, spanning three seconds", func(tt *testTime, rm *radioMonitor) { rm.active() - tt.Add(1100 * time.Millisecond) + tt.Add(2100 * time.Millisecond) rm.active() }, - 100, // radio on for 2 seconds + 100, // radio on for 3 seconds }, { "400 iterations: 2 sec active, 1 min idle", @@ -66,13 +74,17 @@ func TestRadioMonitor(t *testing.T) { { "activity at end of time window", func(tt *testTime, rm *radioMonitor) { - tt.Add(1 * time.Second) + tt.Add(3 * time.Second) rm.active() }, - 50, + 25, }, } + oldStallPeriod := initStallPeriod + initStallPeriod = 3 + t.Cleanup(func() { initStallPeriod = oldStallPeriod }) + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tm := &testTime{time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)} From 4f454f4122f54b79f54ecadc61da781f495be83c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 9 May 2023 15:35:47 -0700 Subject: [PATCH 088/331] util/codegen: support embedded fields I noticed cmd/{cloner,viewer} didn't support structs with embedded fields while working on a change in another repo. This adds support. Signed-off-by: Brad Fitzpatrick --- cmd/viewer/tests/tests.go | 7 +++- cmd/viewer/tests/tests_clone.go | 19 +++++++++++ cmd/viewer/tests/tests_view.go | 58 ++++++++++++++++++++++++++++++++- util/codegen/codegen.go | 9 +++-- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/cmd/viewer/tests/tests.go b/cmd/viewer/tests/tests.go index e281ccb6d5b4f..55413403b999c 100644 --- a/cmd/viewer/tests/tests.go +++ b/cmd/viewer/tests/tests.go @@ -9,7 +9,7 @@ import ( "net/netip" ) -//go:generate go run tailscale.com/cmd/viewer --type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices,OnlyGetClone --clone-only-type=OnlyGetClone +//go:generate go run tailscale.com/cmd/viewer --type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices,OnlyGetClone,StructWithEmbedded --clone-only-type=OnlyGetClone type StructWithoutPtrs struct { Int int @@ -61,3 +61,8 @@ type StructWithSlices struct { type OnlyGetClone struct { SinViewerPorFavor bool } + +type StructWithEmbedded struct { + A *StructWithPtrs + StructWithSlices +} diff --git a/cmd/viewer/tests/tests_clone.go b/cmd/viewer/tests/tests_clone.go index 2558d9ae2752c..3ff9141262e2e 100644 --- a/cmd/viewer/tests/tests_clone.go +++ b/cmd/viewer/tests/tests_clone.go @@ -211,3 +211,22 @@ func (src *OnlyGetClone) Clone() *OnlyGetClone { var _OnlyGetCloneCloneNeedsRegeneration = OnlyGetClone(struct { SinViewerPorFavor bool }{}) + +// Clone makes a deep copy of StructWithEmbedded. +// The result aliases no memory with the original. +func (src *StructWithEmbedded) Clone() *StructWithEmbedded { + if src == nil { + return nil + } + dst := new(StructWithEmbedded) + *dst = *src + dst.A = src.A.Clone() + dst.StructWithSlices = *src.StructWithSlices.Clone() + return dst +} + +// A compilation failure here means this code must be regenerated, with the command at the top of this file. +var _StructWithEmbeddedCloneNeedsRegeneration = StructWithEmbedded(struct { + A *StructWithPtrs + StructWithSlices +}{}) diff --git a/cmd/viewer/tests/tests_view.go b/cmd/viewer/tests/tests_view.go index 7f8d31e010f37..042f10829fe9f 100644 --- a/cmd/viewer/tests/tests_view.go +++ b/cmd/viewer/tests/tests_view.go @@ -14,7 +14,7 @@ import ( "tailscale.com/types/views" ) -//go:generate go run tailscale.com/cmd/cloner -clonefunc=false -type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices,OnlyGetClone +//go:generate go run tailscale.com/cmd/cloner -clonefunc=false -type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices,OnlyGetClone,StructWithEmbedded // View returns a readonly view of StructWithPtrs. func (p *StructWithPtrs) View() StructWithPtrsView { @@ -325,3 +325,59 @@ var _StructWithSlicesViewNeedsRegeneration = StructWithSlices(struct { Prefixes []netip.Prefix Data []byte }{}) + +// View returns a readonly view of StructWithEmbedded. +func (p *StructWithEmbedded) View() StructWithEmbeddedView { + return StructWithEmbeddedView{ж: p} +} + +// StructWithEmbeddedView provides a read-only view over StructWithEmbedded. +// +// Its methods should only be called if `Valid()` returns true. +type StructWithEmbeddedView struct { + // ж is the underlying mutable value, named with a hard-to-type + // character that looks pointy like a pointer. + // It is named distinctively to make you think of how dangerous it is to escape + // to callers. You must not let callers be able to mutate it. + ж *StructWithEmbedded +} + +// Valid reports whether underlying value is non-nil. +func (v StructWithEmbeddedView) Valid() bool { return v.ж != nil } + +// AsStruct returns a clone of the underlying value which aliases no memory with +// the original. +func (v StructWithEmbeddedView) AsStruct() *StructWithEmbedded { + if v.ж == nil { + return nil + } + return v.ж.Clone() +} + +func (v StructWithEmbeddedView) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) } + +func (v *StructWithEmbeddedView) UnmarshalJSON(b []byte) error { + if v.ж != nil { + return errors.New("already initialized") + } + if len(b) == 0 { + return nil + } + var x StructWithEmbedded + if err := json.Unmarshal(b, &x); err != nil { + return err + } + v.ж = &x + return nil +} + +func (v StructWithEmbeddedView) A() StructWithPtrsView { return v.ж.A.View() } +func (v StructWithEmbeddedView) StructWithSlices() StructWithSlicesView { + return v.ж.StructWithSlices.View() +} + +// A compilation failure here means this code must be regenerated, with the command at the top of this file. +var _StructWithEmbeddedViewNeedsRegeneration = StructWithEmbedded(struct { + A *StructWithPtrs + StructWithSlices +}{}) diff --git a/util/codegen/codegen.go b/util/codegen/codegen.go index b1e012fad2e55..cf848b1d25140 100644 --- a/util/codegen/codegen.go +++ b/util/codegen/codegen.go @@ -202,13 +202,18 @@ func AssertStructUnchanged(t *types.Struct, tname, ctx string, it *ImportTracker w("var _%s%sNeedsRegeneration = %s(struct {", tname, ctx, tname) for i := 0; i < t.NumFields(); i++ { - fname := t.Field(i).Name() + st := t.Field(i) + fname := st.Name() ft := t.Field(i).Type() if IsInvalid(ft) { continue } qname := it.QualifiedName(ft) - w("\t%s %s", fname, qname) + if st.Anonymous() { + w("\t%s ", fname) + } else { + w("\t%s %s", fname, qname) + } } w("}{})\n") From d27a6e1c53787621fee4002b9a84606df98a44fd Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 9 May 2023 15:56:41 -0700 Subject: [PATCH 089/331] tool/gocross: fix incorrect relpath usage in bootstrap script The subshell in which gocross gets built cd's to the corp checkout dir near the top, so all future references to corp repository files should be simple relative paths, and not reference $repo_root. When $repo_root is an absolute path, it doesn't matter and everything works out, but on some OSes and shells and invocations, $repo_root is a completely relative path that is invalidated by the "cd". Fixes tailscale/corp#11183 Signed-off-by: David Anderson --- tool/gocross/gocross-wrapper.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tool/gocross/gocross-wrapper.sh b/tool/gocross/gocross-wrapper.sh index 623b7cc796d9c..c14217e9f104b 100755 --- a/tool/gocross/gocross-wrapper.sh +++ b/tool/gocross/gocross-wrapper.sh @@ -31,7 +31,7 @@ toolchain="$HOME/.cache/tailscale-go" if [ -d "$toolchain" ]; then # A toolchain exists, but is it recent enough to compile gocross? If not, # wipe it out so that the next if block fetches a usable one. - want_go_minor=$(grep -E '^go ' "$repo_root/go.mod" | cut -f2 -d'.') + want_go_minor=$(grep -E '^go ' "go.mod" | cut -f2 -d'.') have_go_minor=$(cut -f2 -d'.' <$toolchain/VERSION) if [ -z "$have_go_minor" -o "$have_go_minor" -lt "$want_go_minor" ]; then rm -rf "$toolchain" "$toolchain.extracted" @@ -45,7 +45,7 @@ if [ ! -d "$toolchain" ]; then # build with Go N-1. So, if we have no cached tailscale toolchain at all, # fetch the initial one in shell. Once gocross is built, it'll manage # updates. - read -r REV <$repo_root/go.toolchain.rev + read -r REV Date: Tue, 9 May 2023 21:14:41 -0700 Subject: [PATCH 090/331] cmd/tsconnect: fix forgotten API change for wasm Fix regression from 6e967446e41 Updates #8036 Signed-off-by: Brad Fitzpatrick --- cmd/tsconnect/wasm/wasm_js.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 153941b29b3de..e8d6b665c40eb 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -101,7 +101,8 @@ func newIPN(jsConfig js.Value) map[string]any { sys.Set(store) dialer := &tsdial.Dialer{Logf: logf} eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - Dialer: dialer, + Dialer: dialer, + SetSubsystem: sys.Set, }) if err != nil { log.Fatal(err) From ca49b2958244c323b9e8435fe2a12dd14534e080 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 10 May 2023 14:10:22 -0700 Subject: [PATCH 091/331] tsnet: reenable TestLoopbackSOCKS5 on Windows This test was either fixed in the intermediate time or mis-flagged during the #7876 triage, but is now passing. Updates #7876 Signed-off-by: James Tucker --- tsnet/tsnet_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tsnet/tsnet_test.go b/tsnet/tsnet_test.go index 5ab270994300f..8de7317260e5f 100644 --- a/tsnet/tsnet_test.go +++ b/tsnet/tsnet_test.go @@ -24,7 +24,6 @@ import ( "net/netip" "os" "path/filepath" - "runtime" "strings" "sync" "testing" @@ -357,10 +356,6 @@ func TestLoopbackLocalAPI(t *testing.T) { } func TestLoopbackSOCKS5(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() From da90fab8993c29c8105e97609c697df1e0f6f609 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 10 May 2023 14:06:38 -0700 Subject: [PATCH 092/331] net/netcheck: reenable TestBasic on Windows This test was either fixed by intermediate changes or was mis-flagged as failing during #7876 triage. Updates #7876 Signed-off-by: James Tucker --- net/netcheck/netcheck_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/netcheck/netcheck_test.go b/net/netcheck/netcheck_test.go index 40f84568fba60..1de3693ce9115 100644 --- a/net/netcheck/netcheck_test.go +++ b/net/netcheck/netcheck_test.go @@ -11,7 +11,6 @@ import ( "net/http" "net/netip" "reflect" - "runtime" "sort" "strconv" "strings" @@ -156,9 +155,6 @@ func TestHairpinWait(t *testing.T) { } func TestBasic(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("TODO(#7876): test regressed on windows while CI was broken") - } stunAddr, cleanup := stuntest.Serve(t) defer cleanup() From 84c99fe0d9888c279e2d779040a29a60a2e903f4 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 11 May 2023 12:52:35 -0700 Subject: [PATCH 093/331] logtail: be less aggressive about re-uploads (#8117) The retry logic was pathological in the following ways: * If we restarted the logging service, any pending uploads would be placed in a retry-loop where it depended on backoff.Backoff, which was too aggresive. It would retry failures within milliseconds, taking at least 10 retries to hit a delay of 1 second. * In the event where a logstream was rate limited, the aggressive retry logic would severely exacerbate the problem since each retry would also log an error message. It is by chance that the rate of log error spam does not happen to exceed the rate limit itself. We modify the retry logic in the following ways: * We now respect the "Retry-After" header sent by the logging service. * Lacking a "Retry-After" header, we retry after a hard-coded period of 30 to 60 seconds. This avoids the thundering-herd effect when all nodes try reconnecting to the logging service at the same time after a restart. * We do not treat a status 400 as having been uploaded. This is simply not the behavior of the logging service. Updates #tailscale/corp#11213 Signed-off-by: Joe Tsai --- cmd/tailscaled/depaware.txt | 2 +- logtail/logtail.go | 61 +++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 7e51976fc8f55..24e0896514b44 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -283,7 +283,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/tka from tailscale.com/ipn/ipnlocal+ W tailscale.com/tsconst from tailscale.com/net/interfaces tailscale.com/tsd from tailscale.com/cmd/tailscaled+ - tailscale.com/tstime from tailscale.com/wgengine/magicsock + tailscale.com/tstime from tailscale.com/wgengine/magicsock+ 💣 tailscale.com/tstime/mono from tailscale.com/net/tstun+ tailscale.com/tstime/rate from tailscale.com/wgengine/filter+ tailscale.com/tsweb/varz from tailscale.com/cmd/tailscaled diff --git a/logtail/logtail.go b/logtail/logtail.go index 3c32df3a0e0af..26abe0918551b 100644 --- a/logtail/logtail.go +++ b/logtail/logtail.go @@ -13,19 +13,19 @@ import ( "fmt" "io" "log" + mrand "math/rand" "net/http" "os" "strconv" - "strings" "sync" "sync/atomic" "time" "tailscale.com/envknob" - "tailscale.com/logtail/backoff" "tailscale.com/net/interfaces" "tailscale.com/net/netmon" "tailscale.com/net/sockstats" + "tailscale.com/tstime" tslogger "tailscale.com/types/logger" "tailscale.com/types/logid" "tailscale.com/util/set" @@ -128,9 +128,6 @@ func NewLogger(cfg Config, logf tslogger.Logf) *Logger { cfg.FlushDelayFn = func() time.Duration { return 0 } } - stdLogf := func(f string, a ...any) { - fmt.Fprintf(cfg.Stderr, strings.TrimSuffix(f, "\n")+"\n", a...) - } var urlSuffix string if !cfg.CopyPrivateID.IsZero() { urlSuffix = "?copyId=" + cfg.CopyPrivateID.String() @@ -148,7 +145,6 @@ func NewLogger(cfg Config, logf tslogger.Logf) *Logger { sentinel: make(chan int32, 16), flushDelayFn: cfg.FlushDelayFn, timeNow: cfg.TimeNow, - bo: backoff.NewBackoff("logtail", stdLogf, 30*time.Second), metricsDelta: cfg.MetricsDelta, sockstatsLabel: sockstats.LabelLogtailLogger, @@ -186,7 +182,6 @@ type Logger struct { flushPending atomic.Bool sentinel chan int32 timeNow func() time.Time - bo *backoff.Backoff zstdEncoder Encoder uploadCancel func() explainedRaw bool @@ -373,23 +368,38 @@ func (l *Logger) uploading(ctx context.Context) { } } - for len(body) > 0 { - select { - case <-ctx.Done(): - return - default: - } - uploaded, err := l.upload(ctx, body, origlen) + var lastError string + var numFailures int + var firstFailure time.Time + for len(body) > 0 && ctx.Err() == nil { + retryAfter, err := l.upload(ctx, body, origlen) if err != nil { + numFailures++ + firstFailure = time.Now() + if !l.internetUp() { fmt.Fprintf(l.stderr, "logtail: internet down; waiting\n") l.awaitInternetUp(ctx) continue } - fmt.Fprintf(l.stderr, "logtail: upload: %v\n", err) - } - l.bo.BackOff(ctx, err) - if uploaded { + + // Only print the same message once. + if currError := err.Error(); lastError != currError { + fmt.Fprintf(l.stderr, "logtail: upload: %v\n", err) + lastError = currError + } + + // Sleep for the specified retryAfter period, + // otherwise default to some random value. + if retryAfter <= 0 { + retryAfter = time.Duration(30+mrand.Intn(30)) * time.Second + } + tstime.Sleep(ctx, retryAfter) + } else { + // Only print a success message after recovery. + if numFailures > 0 { + fmt.Fprintf(l.stderr, "logtail: upload succeeded after %d failures and %s\n", numFailures, time.Since(firstFailure).Round(time.Second)) + } break } } @@ -433,7 +443,7 @@ func (l *Logger) awaitInternetUp(ctx context.Context) { // upload uploads body to the log server. // origlen indicates the pre-compression body length. // origlen of -1 indicates that the body is not compressed. -func (l *Logger) upload(ctx context.Context, body []byte, origlen int) (uploaded bool, err error) { +func (l *Logger) upload(ctx context.Context, body []byte, origlen int) (retryAfter time.Duration, err error) { const maxUploadTime = 45 * time.Second ctx = sockstats.WithSockStats(ctx, l.sockstatsLabel, l.Logf) ctx, cancel := context.WithTimeout(ctx, maxUploadTime) @@ -460,17 +470,16 @@ func (l *Logger) upload(ctx context.Context, body []byte, origlen int) (uploaded l.httpDoCalls.Add(1) resp, err := l.httpc.Do(req) if err != nil { - return false, fmt.Errorf("log upload of %d bytes %s failed: %v", len(body), compressedNote, err) + return 0, fmt.Errorf("log upload of %d bytes %s failed: %v", len(body), compressedNote, err) } defer resp.Body.Close() - if resp.StatusCode != 200 { - uploaded = resp.StatusCode == 400 // the server saved the logs anyway - b, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) - return uploaded, fmt.Errorf("log upload of %d bytes %s failed %d: %q", len(body), compressedNote, resp.StatusCode, b) + if resp.StatusCode != http.StatusOK { + n, _ := strconv.Atoi(resp.Header.Get("Retry-After")) + b, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<10)) + return time.Duration(n) * time.Second, fmt.Errorf("log upload of %d bytes %s failed %d: %s", len(body), compressedNote, resp.StatusCode, bytes.TrimSpace(b)) } - - return true, nil + return 0, nil } // Flush uploads all logs to the server. It blocks until complete or there is an From b69059334bbfdfc889208cbc8044a3006e42963c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 11 May 2023 14:59:36 -0700 Subject: [PATCH 094/331] util/set: add a basic map-based Set type We have two other types of Sets here. Add the basic obvious one too. Needed for a change elsewhere. Updates #cleanup Signed-off-by: Brad Fitzpatrick --- util/set/set.go | 15 +++++++++++++++ util/set/set_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 util/set/set_test.go diff --git a/util/set/set.go b/util/set/set.go index e631904a99ad7..6adb5182f52fc 100644 --- a/util/set/set.go +++ b/util/set/set.go @@ -4,6 +4,21 @@ // Package set contains set types. package set +// Set is a set of T. +type Set[T comparable] map[T]struct{} + +// Add adds e to the set. +func (s Set[T]) Add(e T) { s[e] = struct{}{} } + +// Contains reports whether s contains e. +func (s Set[T]) Contains(e T) bool { + _, ok := s[e] + return ok +} + +// Len reports the number of items in s. +func (s Set[T]) Len() int { return len(s) } + // HandleSet is a set of T. // // It is not safe for concurrent use. diff --git a/util/set/set_test.go b/util/set/set_test.go new file mode 100644 index 0000000000000..7a920ed882771 --- /dev/null +++ b/util/set/set_test.go @@ -0,0 +1,24 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package set + +import "testing" + +func TestSet(t *testing.T) { + s := Set[int]{} + s.Add(1) + s.Add(2) + if !s.Contains(1) { + t.Error("missing 1") + } + if !s.Contains(2) { + t.Error("missing 2") + } + if s.Contains(3) { + t.Error("shouldn't have 3") + } + if s.Len() != 2 { + t.Errorf("wrong len %d; want 2", s.Len()) + } +} From 85215ed58aa8c25ca2bdb9a9201a3f84fd85315b Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Thu, 11 May 2023 18:21:23 -0700 Subject: [PATCH 095/331] cmd/k8s-operator: handle NotFound secrets getSingleObject can return `nil, nil`, getDeviceInfo was not handling that case which resulted in panics. Fixes #7303 Signed-off-by: Maisem Ali --- cmd/k8s-operator/operator.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 2d7a8c793e6b8..4398c21ccc89f 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -567,6 +567,9 @@ func (a *ServiceReconciler) getDeviceInfo(ctx context.Context, svc *corev1.Servi if err != nil { return "", "", err } + if sec == nil { + return "", "", nil + } id = string(sec.Data["device_id"]) if id == "" { return "", "", nil From 9b6e48658f36e347f009d819bfa69c85c08aa3cf Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Fri, 12 May 2023 06:05:18 +0100 Subject: [PATCH 096/331] client: allow the expiry time to be specified for new keys Adds a parameter for create key that allows a number of seconds (less than 90) to be specified for new keys. Fixes https://github.com/tailscale/tailscale/issues/7965 Signed-off-by: Matthew Brown --- client/tailscale/keys.go | 14 +++++++++++--- cmd/get-authkey/main.go | 2 +- cmd/k8s-operator/operator.go | 10 +++++++--- cmd/k8s-operator/operator_test.go | 4 ++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/client/tailscale/keys.go b/client/tailscale/keys.go index 05a29be5086c7..38b37e38f8d5a 100644 --- a/client/tailscale/keys.go +++ b/client/tailscale/keys.go @@ -70,10 +70,18 @@ func (c *Client) Keys(ctx context.Context) ([]string, error) { // CreateKey creates a new key for the current user. Currently, only auth keys // can be created. Returns the key itself, which cannot be retrieved again // later, and the key metadata. -func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities) (string, *Key, error) { +func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities, expiry time.Duration) (string, *Key, error) { + + // convert expirySeconds to an int64 (seconds) + expirySeconds := int64(expiry.Seconds()) + if expirySeconds < 0 { + return "", nil, fmt.Errorf("expiry must be positive") + } + keyRequest := struct { - Capabilities KeyCapabilities `json:"capabilities"` - }{caps} + Capabilities KeyCapabilities `json:"capabilities"` + ExpirySeconds int64 `json:"expirySeconds,omitempty"` + }{caps, int64(expirySeconds)} bs, err := json.Marshal(keyRequest) if err != nil { return "", nil, err diff --git a/cmd/get-authkey/main.go b/cmd/get-authkey/main.go index 5f5e85186ee4d..196f45908051d 100644 --- a/cmd/get-authkey/main.go +++ b/cmd/get-authkey/main.go @@ -67,7 +67,7 @@ func main() { }, } - authkey, _, err := tsClient.CreateKey(ctx, caps) + authkey, _, err := tsClient.CreateKey(ctx, caps, 0) if err != nil { log.Fatal(err.Error()) } diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 4398c21ccc89f..fef99e2d5e379 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -153,7 +153,9 @@ waitOnline: }, }, } - authkey, _, err := tsClient.CreateKey(ctx, caps) + // zeroSeconds adopts the default expiration time. + zeroSeconds := time.Duration(0 * time.Second) + authkey, _, err := tsClient.CreateKey(ctx, caps, zeroSeconds) if err != nil { startlog.Fatalf("creating operator authkey: %v", err) } @@ -287,7 +289,7 @@ type ServiceReconciler struct { } type tsClient interface { - CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error) + CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error) DeleteDevice(ctx context.Context, id string) error } @@ -593,7 +595,9 @@ func (a *ServiceReconciler) newAuthKey(ctx context.Context, tags []string) (stri }, }, } - key, _, err := a.tsClient.CreateKey(ctx, caps) + + zeroDuration := time.Duration(0) + key, _, err := a.tsClient.CreateKey(ctx, caps, zeroDuration) if err != nil { return "", err } diff --git a/cmd/k8s-operator/operator_test.go b/cmd/k8s-operator/operator_test.go index 25167961c83e3..001d890f2bf09 100644 --- a/cmd/k8s-operator/operator_test.go +++ b/cmd/k8s-operator/operator_test.go @@ -807,14 +807,14 @@ type fakeTSClient struct { deleted []string } -func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error) { +func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error) { c.Lock() defer c.Unlock() c.keyRequests = append(c.keyRequests, caps) k := &tailscale.Key{ ID: "key", Created: time.Now(), - Expires: time.Now().Add(24 * time.Hour), + Expires: time.Now().Add(expiry), Capabilities: caps, } return "secret-authkey", k, nil From 678bb92bb855290a151f7729d2a66998c4fe5f6d Mon Sep 17 00:00:00 2001 From: shayne Date: Fri, 12 May 2023 02:03:17 -0400 Subject: [PATCH 097/331] cmd/tailscale/cli: [up] fix CreateKey missing argument (#8124) Signed-off-by: Shayne Sweeney --- cmd/tailscale/cli/up.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 06d9b5ff8a5dc..f737fe58829ee 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -1198,7 +1198,8 @@ func resolveAuthKey(ctx context.Context, v, tags string) (string, error) { }, } - authkey, _, err := tsClient.CreateKey(ctx, caps) + const defaultExpiry = 0 + authkey, _, err := tsClient.CreateKey(ctx, caps, defaultExpiry) if err != nil { return "", err } From 4664318be2aad7dbea9a1b16ddf24c7c5efcb395 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 12 May 2023 18:50:30 -0700 Subject: [PATCH 098/331] client/tailscale: revert CreateKey API change, add Client.CreateKeyWithExpiry The client/tailscale is a stable-ish API we try not to break. Revert the Client.CreateKey method as it was and add a new CreateKeyWithExpiry method to do the new thing. And document the expiry field and enforce that the time.Duration can't be between in range greater than 0 and less than a second. Updates #7143 Updates #8124 (reverts it, effectively) Signed-off-by: Brad Fitzpatrick --- client/tailscale/keys.go | 16 ++++++++++++++-- cmd/get-authkey/main.go | 2 +- cmd/k8s-operator/operator.go | 9 +++------ cmd/k8s-operator/operator_test.go | 3 +-- cmd/tailscale/cli/up.go | 3 +-- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/client/tailscale/keys.go b/client/tailscale/keys.go index 38b37e38f8d5a..84bcdfae6aeeb 100644 --- a/client/tailscale/keys.go +++ b/client/tailscale/keys.go @@ -68,15 +68,27 @@ func (c *Client) Keys(ctx context.Context) ([]string, error) { } // CreateKey creates a new key for the current user. Currently, only auth keys -// can be created. Returns the key itself, which cannot be retrieved again +// can be created. It returns the secret key itself, which cannot be retrieved again // later, and the key metadata. -func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities, expiry time.Duration) (string, *Key, error) { +// +// To create a key with a specific expiry, use CreateKeyWithExpiry. +func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities) (keySecret string, keyMeta *Key, _ error) { + return c.CreateKeyWithExpiry(ctx, caps, 0) +} + +// CreateKeyWithExpiry is like CreateKey, but allows specifying a expiration time. +// +// The time is truncated to a whole number of seconds. If zero, that means no expiration. +func (c *Client) CreateKeyWithExpiry(ctx context.Context, caps KeyCapabilities, expiry time.Duration) (keySecret string, keyMeta *Key, _ error) { // convert expirySeconds to an int64 (seconds) expirySeconds := int64(expiry.Seconds()) if expirySeconds < 0 { return "", nil, fmt.Errorf("expiry must be positive") } + if expirySeconds == 0 && expiry != 0 { + return "", nil, fmt.Errorf("non-zero expiry must be at least one second") + } keyRequest := struct { Capabilities KeyCapabilities `json:"capabilities"` diff --git a/cmd/get-authkey/main.go b/cmd/get-authkey/main.go index 196f45908051d..5f5e85186ee4d 100644 --- a/cmd/get-authkey/main.go +++ b/cmd/get-authkey/main.go @@ -67,7 +67,7 @@ func main() { }, } - authkey, _, err := tsClient.CreateKey(ctx, caps, 0) + authkey, _, err := tsClient.CreateKey(ctx, caps) if err != nil { log.Fatal(err.Error()) } diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index fef99e2d5e379..477424bc09060 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -153,9 +153,7 @@ waitOnline: }, }, } - // zeroSeconds adopts the default expiration time. - zeroSeconds := time.Duration(0 * time.Second) - authkey, _, err := tsClient.CreateKey(ctx, caps, zeroSeconds) + authkey, _, err := tsClient.CreateKey(ctx, caps) if err != nil { startlog.Fatalf("creating operator authkey: %v", err) } @@ -289,7 +287,7 @@ type ServiceReconciler struct { } type tsClient interface { - CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error) + CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error) DeleteDevice(ctx context.Context, id string) error } @@ -596,8 +594,7 @@ func (a *ServiceReconciler) newAuthKey(ctx context.Context, tags []string) (stri }, } - zeroDuration := time.Duration(0) - key, _, err := a.tsClient.CreateKey(ctx, caps, zeroDuration) + key, _, err := a.tsClient.CreateKey(ctx, caps) if err != nil { return "", err } diff --git a/cmd/k8s-operator/operator_test.go b/cmd/k8s-operator/operator_test.go index 001d890f2bf09..fff10ce4ee48f 100644 --- a/cmd/k8s-operator/operator_test.go +++ b/cmd/k8s-operator/operator_test.go @@ -807,14 +807,13 @@ type fakeTSClient struct { deleted []string } -func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error) { +func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error) { c.Lock() defer c.Unlock() c.keyRequests = append(c.keyRequests, caps) k := &tailscale.Key{ ID: "key", Created: time.Now(), - Expires: time.Now().Add(expiry), Capabilities: caps, } return "secret-authkey", k, nil diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index f737fe58829ee..06d9b5ff8a5dc 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -1198,8 +1198,7 @@ func resolveAuthKey(ctx context.Context, v, tags string) (string, error) { }, } - const defaultExpiry = 0 - authkey, _, err := tsClient.CreateKey(ctx, caps, defaultExpiry) + authkey, _, err := tsClient.CreateKey(ctx, caps) if err != nil { return "", err } From f0ee03dfafda9c5a8804b25f20ea881090bd4ab5 Mon Sep 17 00:00:00 2001 From: Sonia Appasamy Date: Mon, 15 May 2023 23:34:55 -0400 Subject: [PATCH 099/331] cmd/tailscale/cli: [serve] add reset flag Usage: `tailscale serve reset` Fixes #8139 Signed-off-by: Sonia Appasamy --- cmd/tailscale/cli/serve.go | 20 ++++++++++++++++++++ cmd/tailscale/cli/serve_test.go | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/tailscale/cli/serve.go b/cmd/tailscale/cli/serve.go index 59518feccbfda..3921a57a0b8ac 100644 --- a/cmd/tailscale/cli/serve.go +++ b/cmd/tailscale/cli/serve.go @@ -40,6 +40,7 @@ serve https: [off] serve tcp: tcp://localhost: [off] serve tls-terminated-tcp: tcp://localhost: [off] serve status [--json] + serve reset `), LongHelp: strings.TrimSpace(` *** BETA; all of this is subject to change *** @@ -87,6 +88,13 @@ EXAMPLES }), UsageFunc: usageFunc, }, + { + Name: "reset", + Exec: e.runServeReset, + ShortHelp: "reset current serve/funnel config", + FlagSet: e.newFlags("serve-reset", nil), + UsageFunc: usageFunc, + }, }, } } @@ -705,3 +713,15 @@ func elipticallyTruncate(s string, max int) string { } return s[:max-3] + "..." } + +// runServeReset clears out the current serve config. +// +// Usage: +// - tailscale serve reset +func (e *serveEnv) runServeReset(ctx context.Context, args []string) error { + if len(args) != 0 { + return flag.ErrHelp + } + sc := new(ipn.ServeConfig) + return e.lc.SetServeConfig(ctx, sc) +} diff --git a/cmd/tailscale/cli/serve_test.go b/cmd/tailscale/cli/serve_test.go index 8031b2b024f92..2dec06dd74053 100644 --- a/cmd/tailscale/cli/serve_test.go +++ b/cmd/tailscale/cli/serve_test.go @@ -224,7 +224,10 @@ func TestServeConfigMutations(t *testing.T) { command: cmd("https:443 bar https://127.0.0.1:8443"), want: nil, // nothing to save }) - add(step{reset: true}) + add(step{ // try resetting using reset command + command: cmd("reset"), + want: &ipn.ServeConfig{}, + }) add(step{ command: cmd("https:443 / https+insecure://127.0.0.1:3001"), want: &ipn.ServeConfig{ From 7c88eeba86a575597d15a130cf583b44d801e370 Mon Sep 17 00:00:00 2001 From: Derek Kaser Date: Wed, 17 May 2023 16:26:39 -0400 Subject: [PATCH 100/331] cmd/tailscale: allow Tailscale to work with Unraid web interface (#8062) Updates tailscale/tailscale#8026 Signed-off-by: Derek Kaser --- cmd/tailscale/cli/web.go | 4 ++++ cmd/tailscale/cli/web.html | 30 ++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index 82105a6a3b415..38ee25b96d46e 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -61,6 +61,8 @@ type tmplData struct { TUNMode bool IsSynology bool DSMVersion int // 6 or 7, if IsSynology=true + IsUnraid bool + UnraidToken string IPNVersion string } @@ -441,6 +443,8 @@ func webHandler(w http.ResponseWriter, r *http.Request) { TUNMode: st.TUN, IsSynology: distro.Get() == distro.Synology || envknob.Bool("TS_FAKE_SYNOLOGY"), DSMVersion: distro.DSMVersion(), + IsUnraid: distro.Get() == distro.Unraid, + UnraidToken: os.Getenv("UNRAID_CSRF_TOKEN"), IPNVersion: versionShort, } exitNodeRouteV4 := netip.MustParsePrefix("0.0.0.0/0") diff --git a/cmd/tailscale/cli/web.html b/cmd/tailscale/cli/web.html index b1ad8746be3b4..b990bdd77428d 100644 --- a/cmd/tailscale/cli/web.html +++ b/cmd/tailscale/cli/web.html @@ -116,10 +116,12 @@

Log in

Open Source Licenses