From 266fdcd2edee60c4e48e661f73b1a621ab091be1 Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Mon, 24 Feb 2025 19:12:10 +0100 Subject: [PATCH 01/10] Replace webinar link (#3380) --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7cee2f8dc..5b136eff6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@
- - Webinar: How to Achieve Zero Trust Access to Kubernetes — Effortlessly -

@@ -36,6 +33,10 @@
+
+ + Webinar: Securely Access Kubernetes without Port Forwarding and Jump Hosts +


From 82c12cc8ae1564b05c2e4d71ebee3fad9b012bf0 Mon Sep 17 00:00:00 2001 From: Bethuel Mmbaga Date: Tue, 25 Feb 2025 19:57:04 +0000 Subject: [PATCH 02/10] [management] Handle transaction error on peer deletion (#3387) Signed-off-by: bcmmbaga --- management/server/peer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/management/server/peer.go b/management/server/peer.go index c9b0fcfee..ff898f56c 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -400,6 +400,9 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer eventsToStore, err = deletePeers(ctx, am, transaction, accountID, userID, []*nbpeer.Peer{peer}) return err }) + if err != nil { + return err + } for _, storeEvent := range eventsToStore { storeEvent() From 9d604b7e662cd837a1e3a1dc2e67135884550c74 Mon Sep 17 00:00:00 2001 From: Philippe Vaucher Date: Mon, 3 Mar 2025 17:22:51 +0100 Subject: [PATCH 03/10] [client Fix env var typo (#3415) --- client/iface/netstack/tun.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/iface/netstack/tun.go b/client/iface/netstack/tun.go index 01f19875e..a271a1954 100644 --- a/client/iface/netstack/tun.go +++ b/client/iface/netstack/tun.go @@ -55,7 +55,7 @@ func (t *NetStackTun) Create() (tun.Device, *netstack.Net, error) { skipProxy, err := strconv.ParseBool(os.Getenv(EnvSkipProxy)) if err != nil { - log.Errorf("failed to parse NB_ETSTACK_SKIP_PROXY: %s", err) + log.Errorf("failed to parse %s: %s", EnvSkipProxy, err) } if skipProxy { return nsTunDev, tunNet, nil From af5796de1c25136f23b7289de78b5680e985a4dc Mon Sep 17 00:00:00 2001 From: robertgro <34941707+robertgro@users.noreply.github.com> Date: Mon, 3 Mar 2025 17:32:50 +0100 Subject: [PATCH 04/10] [client] Add Netbird GitHub link to the client ui about sub menu (#3372) --- client/ui/client_ui.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index 51eec59a5..889db70d6 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -154,6 +154,7 @@ type serviceClient struct { mAdminPanel *systray.MenuItem mSettings *systray.MenuItem mAbout *systray.MenuItem + mGitHub *systray.MenuItem mVersionUI *systray.MenuItem mVersionDaemon *systray.MenuItem mUpdate *systray.MenuItem @@ -607,6 +608,9 @@ func (s *serviceClient) onTrayReady() { s.mAbout = systray.AddMenuItem("About", "About") s.mAbout.SetIcon(s.icAbout) + + s.mGitHub = s.mAbout.AddSubMenuItem("GitHub", "GitHub") + versionString := normalizedVersion(version.NetbirdVersion()) s.mVersionUI = s.mAbout.AddSubMenuItem(fmt.Sprintf("GUI: %s", versionString), fmt.Sprintf("GUI Version: %s", versionString)) s.mVersionUI.Disable() @@ -717,6 +721,11 @@ func (s *serviceClient) onTrayReady() { case <-s.mQuit.ClickedCh: systray.Quit() return + case <-s.mGitHub.ClickedCh: + err := openURL("https://github.com/netbirdio/netbird") + if err != nil { + log.Errorf("%s", err) + } case <-s.mUpdate.ClickedCh: err := openURL(version.DownloadUrl()) if err != nil { From bcc5824980c4d510e8bd777325f602dce51518e6 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Tue, 4 Mar 2025 11:19:42 +0100 Subject: [PATCH 05/10] [client] Close userspace firewall properly (#3426) --- client/firewall/iptables/manager_linux.go | 2 +- client/firewall/iptables/manager_linux_test.go | 12 ++++++------ client/firewall/iptables/state_linux.go | 2 +- client/firewall/manager/firewall.go | 4 ++-- client/firewall/nftables/manager_linux.go | 4 ++-- client/firewall/nftables/manager_linux_test.go | 8 ++++---- client/firewall/nftables/router_linux_test.go | 4 ++-- client/firewall/nftables/state_linux.go | 2 +- client/firewall/uspfilter/allow_netbird.go | 8 ++------ .../firewall/uspfilter/allow_netbird_windows.go | 8 ++------ .../firewall/uspfilter/uspfilter_bench_test.go | 16 ++++++++-------- .../firewall/uspfilter/uspfilter_filter_test.go | 4 ++-- client/firewall/uspfilter/uspfilter_test.go | 12 ++++++------ client/internal/acl/manager_test.go | 4 ++-- client/internal/dns/server_test.go | 2 +- client/internal/engine.go | 2 +- 16 files changed, 43 insertions(+), 51 deletions(-) diff --git a/client/firewall/iptables/manager_linux.go b/client/firewall/iptables/manager_linux.go index 929e8a656..144d5a17f 100644 --- a/client/firewall/iptables/manager_linux.go +++ b/client/firewall/iptables/manager_linux.go @@ -166,7 +166,7 @@ func (m *Manager) SetLegacyManagement(isLegacy bool) error { } // Reset firewall to the default state -func (m *Manager) Reset(stateManager *statemanager.Manager) error { +func (m *Manager) Close(stateManager *statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() diff --git a/client/firewall/iptables/manager_linux_test.go b/client/firewall/iptables/manager_linux_test.go index ba578c033..856633409 100644 --- a/client/firewall/iptables/manager_linux_test.go +++ b/client/firewall/iptables/manager_linux_test.go @@ -62,7 +62,7 @@ func TestIptablesManager(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) @@ -100,14 +100,14 @@ func TestIptablesManager(t *testing.T) { _, err = manager.AddPeerFiltering(ip, "udp", nil, port, fw.ActionAccept, "", "accept Fake DNS traffic") require.NoError(t, err, "failed to add rule") - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") ok, err := ipv4Client.ChainExists("filter", chainNameInputRules) require.NoError(t, err, "failed check chain exists") if ok { - require.NoErrorf(t, err, "chain '%v' still exists after Reset", chainNameInputRules) + require.NoErrorf(t, err, "chain '%v' still exists after Close", chainNameInputRules) } }) } @@ -136,7 +136,7 @@ func TestIptablesManagerIPSet(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) @@ -166,7 +166,7 @@ func TestIptablesManagerIPSet(t *testing.T) { }) t.Run("reset check", func(t *testing.T) { - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") }) } @@ -204,7 +204,7 @@ func TestIptablesCreatePerformance(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) diff --git a/client/firewall/iptables/state_linux.go b/client/firewall/iptables/state_linux.go index 44b8340ba..2a7120bbf 100644 --- a/client/firewall/iptables/state_linux.go +++ b/client/firewall/iptables/state_linux.go @@ -62,7 +62,7 @@ func (s *ShutdownState) Cleanup() error { ipt.aclMgr.ipsetStore = s.ACLIPsetStore } - if err := ipt.Reset(nil); err != nil { + if err := ipt.Close(nil); err != nil { return fmt.Errorf("reset iptables manager: %w", err) } diff --git a/client/firewall/manager/firewall.go b/client/firewall/manager/firewall.go index d007e20a5..e71328a44 100644 --- a/client/firewall/manager/firewall.go +++ b/client/firewall/manager/firewall.go @@ -94,8 +94,8 @@ type Manager interface { // SetLegacyManagement sets the legacy management mode SetLegacyManagement(legacy bool) error - // Reset firewall to the default state - Reset(stateManager *statemanager.Manager) error + // Close closes the firewall manager + Close(stateManager *statemanager.Manager) error // Flush the changes to firewall controller Flush() error diff --git a/client/firewall/nftables/manager_linux.go b/client/firewall/nftables/manager_linux.go index de68f3291..3df9b378d 100644 --- a/client/firewall/nftables/manager_linux.go +++ b/client/firewall/nftables/manager_linux.go @@ -87,7 +87,7 @@ func (m *Manager) Init(stateManager *statemanager.Manager) error { // We only need to record minimal interface state for potential recreation. // Unlike iptables, which requires tracking individual rules, nftables maintains // a known state (our netbird table plus a few static rules). This allows for easy - // cleanup using Reset() without needing to store specific rules. + // cleanup using Close() without needing to store specific rules. if err := stateManager.UpdateState(&ShutdownState{ InterfaceState: &InterfaceState{ NameStr: m.wgIface.Name(), @@ -242,7 +242,7 @@ func (m *Manager) SetLegacyManagement(isLegacy bool) error { } // Reset firewall to the default state -func (m *Manager) Reset(stateManager *statemanager.Manager) error { +func (m *Manager) Close(stateManager *statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() diff --git a/client/firewall/nftables/manager_linux_test.go b/client/firewall/nftables/manager_linux_test.go index eaa8ef1f5..9ca20889b 100644 --- a/client/firewall/nftables/manager_linux_test.go +++ b/client/firewall/nftables/manager_linux_test.go @@ -65,7 +65,7 @@ func TestNftablesManager(t *testing.T) { time.Sleep(time.Second * 3) defer func() { - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") time.Sleep(time.Second) }() @@ -162,7 +162,7 @@ func TestNftablesManager(t *testing.T) { // established rule remains require.Len(t, rules, 1, "expected 1 rules after deletion") - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") } @@ -191,7 +191,7 @@ func TestNFtablesCreatePerformance(t *testing.T) { time.Sleep(time.Second * 3) defer func() { - if err := manager.Reset(nil); err != nil { + if err := manager.Close(nil); err != nil { t.Errorf("clear the manager state: %v", err) } time.Sleep(time.Second) @@ -274,7 +274,7 @@ func TestNftablesManagerCompatibilityWithIptables(t *testing.T) { require.NoError(t, manager.Init(nil)) t.Cleanup(func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "failed to reset manager state") // Verify iptables output after reset diff --git a/client/firewall/nftables/router_linux_test.go b/client/firewall/nftables/router_linux_test.go index 2a5d7168d..9081a8349 100644 --- a/client/firewall/nftables/router_linux_test.go +++ b/client/firewall/nftables/router_linux_test.go @@ -38,7 +38,7 @@ func TestNftablesManager_AddNatRule(t *testing.T) { // need fw manager to init both acl mgr and router for all chains to be present manager, err := Create(ifaceMock) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) require.NoError(t, err) require.NoError(t, manager.Init(nil)) @@ -127,7 +127,7 @@ func TestNftablesManager_RemoveNatRule(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { manager, err := Create(ifaceMock) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) require.NoError(t, err) require.NoError(t, manager.Init(nil)) diff --git a/client/firewall/nftables/state_linux.go b/client/firewall/nftables/state_linux.go index a68c8b8b8..facca1cec 100644 --- a/client/firewall/nftables/state_linux.go +++ b/client/firewall/nftables/state_linux.go @@ -39,7 +39,7 @@ func (s *ShutdownState) Cleanup() error { return fmt.Errorf("create nftables manager: %w", err) } - if err := nft.Reset(nil); err != nil { + if err := nft.Close(nil); err != nil { return fmt.Errorf("reset nftables manager: %w", err) } diff --git a/client/firewall/uspfilter/allow_netbird.go b/client/firewall/uspfilter/allow_netbird.go index 03f23f5e6..aba79bc21 100644 --- a/client/firewall/uspfilter/allow_netbird.go +++ b/client/firewall/uspfilter/allow_netbird.go @@ -8,12 +8,11 @@ import ( log "github.com/sirupsen/logrus" - "github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack" "github.com/netbirdio/netbird/client/internal/statemanager" ) // Reset firewall to the default state -func (m *Manager) Reset(stateManager *statemanager.Manager) error { +func (m *Manager) Close(stateManager *statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() @@ -22,17 +21,14 @@ func (m *Manager) Reset(stateManager *statemanager.Manager) error { if m.udpTracker != nil { m.udpTracker.Close() - m.udpTracker = conntrack.NewUDPTracker(conntrack.DefaultUDPTimeout, m.logger) } if m.icmpTracker != nil { m.icmpTracker.Close() - m.icmpTracker = conntrack.NewICMPTracker(conntrack.DefaultICMPTimeout, m.logger) } if m.tcpTracker != nil { m.tcpTracker.Close() - m.tcpTracker = conntrack.NewTCPTracker(conntrack.DefaultTCPTimeout, m.logger) } if m.forwarder != nil { @@ -48,7 +44,7 @@ func (m *Manager) Reset(stateManager *statemanager.Manager) error { } if m.nativeFirewall != nil { - return m.nativeFirewall.Reset(stateManager) + return m.nativeFirewall.Close(stateManager) } return nil } diff --git a/client/firewall/uspfilter/allow_netbird_windows.go b/client/firewall/uspfilter/allow_netbird_windows.go index 379585978..ee540cb1d 100644 --- a/client/firewall/uspfilter/allow_netbird_windows.go +++ b/client/firewall/uspfilter/allow_netbird_windows.go @@ -9,7 +9,6 @@ import ( log "github.com/sirupsen/logrus" - "github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack" "github.com/netbirdio/netbird/client/internal/statemanager" ) @@ -21,8 +20,8 @@ const ( firewallRuleName = "Netbird" ) -// Reset firewall to the default state -func (m *Manager) Reset(*statemanager.Manager) error { +// Close closes the firewall manager +func (m *Manager) Close(*statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() @@ -31,17 +30,14 @@ func (m *Manager) Reset(*statemanager.Manager) error { if m.udpTracker != nil { m.udpTracker.Close() - m.udpTracker = conntrack.NewUDPTracker(conntrack.DefaultUDPTimeout, m.logger) } if m.icmpTracker != nil { m.icmpTracker.Close() - m.icmpTracker = conntrack.NewICMPTracker(conntrack.DefaultICMPTimeout, m.logger) } if m.tcpTracker != nil { m.tcpTracker.Close() - m.tcpTracker = conntrack.NewTCPTracker(conntrack.DefaultTCPTimeout, m.logger) } if m.forwarder != nil { diff --git a/client/firewall/uspfilter/uspfilter_bench_test.go b/client/firewall/uspfilter/uspfilter_bench_test.go index 875bb2425..bb42a8052 100644 --- a/client/firewall/uspfilter/uspfilter_bench_test.go +++ b/client/firewall/uspfilter/uspfilter_bench_test.go @@ -160,7 +160,7 @@ func BenchmarkCoreFiltering(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -205,7 +205,7 @@ func BenchmarkStateScaling(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -253,7 +253,7 @@ func BenchmarkEstablishmentOverhead(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -452,7 +452,7 @@ func BenchmarkRoutedNetworkReturn(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) // Setup scenario @@ -579,7 +579,7 @@ func BenchmarkLongLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -670,7 +670,7 @@ func BenchmarkShortLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -789,7 +789,7 @@ func BenchmarkParallelLongLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -877,7 +877,7 @@ func BenchmarkParallelShortLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ diff --git a/client/firewall/uspfilter/uspfilter_filter_test.go b/client/firewall/uspfilter/uspfilter_filter_test.go index 9a1456d00..9a5ec9c66 100644 --- a/client/firewall/uspfilter/uspfilter_filter_test.go +++ b/client/firewall/uspfilter/uspfilter_filter_test.go @@ -39,7 +39,7 @@ func TestPeerACLFiltering(t *testing.T) { require.NotNil(t, manager) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) manager.wgNetwork = wgNet @@ -310,7 +310,7 @@ func setupRoutedManager(tb testing.TB, network string) *Manager { require.False(tb, manager.nativeRouter) tb.Cleanup(func() { - require.NoError(tb, manager.Reset(nil)) + require.NoError(tb, manager.Close(nil)) }) return manager diff --git a/client/firewall/uspfilter/uspfilter_test.go b/client/firewall/uspfilter/uspfilter_test.go index 089bf8f55..c03762984 100644 --- a/client/firewall/uspfilter/uspfilter_test.go +++ b/client/firewall/uspfilter/uspfilter_test.go @@ -254,7 +254,7 @@ func TestManagerReset(t *testing.T) { return } - err = m.Reset(nil) + err = m.Close(nil) if err != nil { t.Errorf("failed to reset Manager: %v", err) return @@ -333,7 +333,7 @@ func TestNotMatchByIP(t *testing.T) { return } - if err = m.Reset(nil); err != nil { + if err = m.Close(nil); err != nil { t.Errorf("failed to reset Manager: %v", err) return } @@ -352,7 +352,7 @@ func TestRemovePacketHook(t *testing.T) { t.Fatalf("Failed to create Manager: %s", err) } defer func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }() // Add a UDP packet hook @@ -403,7 +403,7 @@ func TestProcessOutgoingHooks(t *testing.T) { manager.udpTracker.Close() manager.udpTracker = conntrack.NewUDPTracker(100*time.Millisecond, logger) defer func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }() manager.decoders = sync.Pool{ @@ -484,7 +484,7 @@ func TestUSPFilterCreatePerformance(t *testing.T) { time.Sleep(time.Second) defer func() { - if err := manager.Reset(nil); err != nil { + if err := manager.Close(nil); err != nil { t.Errorf("clear the manager state: %v", err) } time.Sleep(time.Second) @@ -530,7 +530,7 @@ func TestStatefulFirewall_UDPTracking(t *testing.T) { }, } defer func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }() // Set up packet parameters diff --git a/client/internal/acl/manager_test.go b/client/internal/acl/manager_test.go index 217dbce9f..0327d62ef 100644 --- a/client/internal/acl/manager_test.go +++ b/client/internal/acl/manager_test.go @@ -58,7 +58,7 @@ func TestDefaultManager(t *testing.T) { return } defer func(fw manager.Manager) { - _ = fw.Reset(nil) + _ = fw.Close(nil) }(fw) acl := NewDefaultManager(fw) @@ -352,7 +352,7 @@ func TestDefaultManagerEnableSSHRules(t *testing.T) { return } defer func(fw manager.Manager) { - _ = fw.Reset(nil) + _ = fw.Close(nil) }(fw) acl := NewDefaultManager(fw) diff --git a/client/internal/dns/server_test.go b/client/internal/dns/server_test.go index 94b87124b..d9886fcd8 100644 --- a/client/internal/dns/server_test.go +++ b/client/internal/dns/server_test.go @@ -1015,7 +1015,7 @@ func TestHandlerChain_DomainPriorities(t *testing.T) { mh.AssertExpectations(t) } - // Reset mocks + // Close mocks if mh, ok := tc.expectedHandler.(*MockHandler); ok { mh.ExpectedCalls = nil mh.Calls = nil diff --git a/client/internal/engine.go b/client/internal/engine.go index 10c4fb970..943b7cd0b 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -1362,7 +1362,7 @@ func (e *Engine) close() { } if e.firewall != nil { - err := e.firewall.Reset(e.stateManager) + err := e.firewall.Close(e.stateManager) if err != nil { log.Warnf("failed to reset firewall: %s", err) } From 60ffe0dc872b23595cdd0f6f69f3fa56ed56cf2f Mon Sep 17 00:00:00 2001 From: hakansa <43675540+hakansa@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:29:29 +0300 Subject: [PATCH 06/10] [client] UI Refactor Icon Paths (#3420) [client] UI Refactor Icon Paths (#3420) --- .github/workflows/release.yml | 4 +- .goreleaser_ui.yaml | 8 +- client/installer.nsis | 4 +- client/netbird.wxs | 2 +- client/resources.rc | 2 +- .../netbird-systemtray-connected-dark.ico | Bin .../netbird-systemtray-connected-dark.png | Bin .../netbird-systemtray-connected-macos.png | Bin .../netbird-systemtray-connected.ico | Bin .../netbird-systemtray-connected.png | Bin .../netbird-systemtray-connecting-dark.ico | Bin .../netbird-systemtray-connecting-dark.png | Bin .../netbird-systemtray-connecting-macos.png | Bin .../netbird-systemtray-connecting.ico | Bin .../netbird-systemtray-connecting.png | Bin .../netbird-systemtray-disconnected-macos.png | Bin .../netbird-systemtray-disconnected.ico | Bin .../netbird-systemtray-disconnected.png | Bin .../netbird-systemtray-error-dark.ico | Bin .../netbird-systemtray-error-dark.png | Bin .../netbird-systemtray-error-macos.png | Bin .../{ => assets}/netbird-systemtray-error.ico | Bin .../{ => assets}/netbird-systemtray-error.png | Bin ...tbird-systemtray-update-connected-dark.ico | Bin ...tbird-systemtray-update-connected-dark.png | Bin ...bird-systemtray-update-connected-macos.png | Bin .../netbird-systemtray-update-connected.ico | Bin .../netbird-systemtray-update-connected.png | Bin ...rd-systemtray-update-disconnected-dark.ico | Bin ...rd-systemtray-update-disconnected-dark.png | Bin ...d-systemtray-update-disconnected-macos.png | Bin ...netbird-systemtray-update-disconnected.ico | Bin ...netbird-systemtray-update-disconnected.png | Bin client/ui/{ => assets}/netbird.ico | Bin client/ui/{ => assets}/netbird.png | Bin client/ui/{ => build}/banner.bmp | Bin client/ui/{ => build}/build-ui-linux.sh | 0 client/ui/{ => build}/netbird.desktop | 0 client/ui/client_ui.go | 189 ++++++++++-------- client/ui/const.go | 15 ++ client/ui/icons.go | 24 +-- client/ui/icons_windows.go | 26 +-- client/ui/network.go | 2 +- client/ui/{ => process}/process.go | 4 +- client/ui/{ => process}/process_nonwindows.go | 2 +- client/ui/{ => process}/process_windows.go | 2 +- 46 files changed, 160 insertions(+), 124 deletions(-) rename client/ui/{ => assets}/netbird-systemtray-connected-dark.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-connected-dark.png (100%) rename client/ui/{ => assets}/netbird-systemtray-connected-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-connected.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-connected.png (100%) rename client/ui/{ => assets}/netbird-systemtray-connecting-dark.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-connecting-dark.png (100%) rename client/ui/{ => assets}/netbird-systemtray-connecting-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-connecting.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-connecting.png (100%) rename client/ui/{ => assets}/netbird-systemtray-disconnected-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-disconnected.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-disconnected.png (100%) rename client/ui/{ => assets}/netbird-systemtray-error-dark.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-error-dark.png (100%) rename client/ui/{ => assets}/netbird-systemtray-error-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-error.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-error.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-connected-dark.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-update-connected-dark.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-connected-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-connected.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-update-connected.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-disconnected-dark.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-update-disconnected-dark.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-disconnected-macos.png (100%) rename client/ui/{ => assets}/netbird-systemtray-update-disconnected.ico (100%) rename client/ui/{ => assets}/netbird-systemtray-update-disconnected.png (100%) rename client/ui/{ => assets}/netbird.ico (100%) rename client/ui/{ => assets}/netbird.png (100%) rename client/ui/{ => build}/banner.bmp (100%) rename client/ui/{ => build}/build-ui-linux.sh (100%) rename client/ui/{ => build}/netbird.desktop (100%) create mode 100644 client/ui/const.go rename client/ui/{ => process}/process.go (90%) rename client/ui/{ => process}/process_nonwindows.go (96%) rename client/ui/{ => process}/process_windows.go (96%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 04874bdf4..919351f18 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: - name: Install goversioninfo run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@233067e - name: Generate windows syso amd64 - run: goversioninfo -icon client/ui/netbird.ico -manifest client/manifest.xml -product-name ${{ env.PRODUCT_NAME }} -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/resources_windows_amd64.syso + run: goversioninfo -icon client/ui/assets/netbird.ico -manifest client/manifest.xml -product-name ${{ env.PRODUCT_NAME }} -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/resources_windows_amd64.syso - name: Run GoReleaser uses: goreleaser/goreleaser-action@v4 with: @@ -150,7 +150,7 @@ jobs: - name: Install goversioninfo run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@233067e - name: Generate windows syso amd64 - run: goversioninfo -64 -icon client/ui/netbird.ico -manifest client/ui/manifest.xml -product-name ${{ env.PRODUCT_NAME }}-"UI" -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/ui/resources_windows_amd64.syso + run: goversioninfo -64 -icon client/ui/assets/netbird.ico -manifest client/ui/manifest.xml -product-name ${{ env.PRODUCT_NAME }}-"UI" -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/ui/resources_windows_amd64.syso - name: Run GoReleaser uses: goreleaser/goreleaser-action@v4 diff --git a/.goreleaser_ui.yaml b/.goreleaser_ui.yaml index 1dd649d1b..459f204d3 100644 --- a/.goreleaser_ui.yaml +++ b/.goreleaser_ui.yaml @@ -53,9 +53,9 @@ nfpms: scripts: postinstall: "release_files/ui-post-install.sh" contents: - - src: client/ui/netbird.desktop + - src: client/ui/build/netbird.desktop dst: /usr/share/applications/netbird.desktop - - src: client/ui/netbird.png + - src: client/ui/assets/netbird.png dst: /usr/share/pixmaps/netbird.png dependencies: - netbird @@ -72,9 +72,9 @@ nfpms: scripts: postinstall: "release_files/ui-post-install.sh" contents: - - src: client/ui/netbird.desktop + - src: client/ui/build/netbird.desktop dst: /usr/share/applications/netbird.desktop - - src: client/ui/netbird.png + - src: client/ui/assets/netbird.png dst: /usr/share/pixmaps/netbird.png dependencies: - netbird diff --git a/client/installer.nsis b/client/installer.nsis index af942a868..743c81a6d 100644 --- a/client/installer.nsis +++ b/client/installer.nsis @@ -6,8 +6,8 @@ !define DESCRIPTION "A WireGuard®-based mesh network that connects your devices into a single private network" !define INSTALLER_NAME "netbird-installer.exe" !define MAIN_APP_EXE "Netbird" -!define ICON "ui\\netbird.ico" -!define BANNER "ui\\banner.bmp" +!define ICON "ui\\assets\\netbird.ico" +!define BANNER "ui\\build\\banner.bmp" !define LICENSE_DATA "..\\LICENSE" !define INSTALL_DIR "$PROGRAMFILES64\${APP_NAME}" diff --git a/client/netbird.wxs b/client/netbird.wxs index ee9ab667f..5e03a014d 100644 --- a/client/netbird.wxs +++ b/client/netbird.wxs @@ -71,7 +71,7 @@ - + diff --git a/client/resources.rc b/client/resources.rc index ac411245e..696fd0dfa 100644 --- a/client/resources.rc +++ b/client/resources.rc @@ -5,5 +5,5 @@ #define STRINGIZE(x) #x #define EXPAND(x) STRINGIZE(x) CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml -7 ICON ui/netbird.ico +7 ICON ui/assets/netbird.ico wintun.dll RCDATA wintun.dll diff --git a/client/ui/netbird-systemtray-connected-dark.ico b/client/ui/assets/netbird-systemtray-connected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-connected-dark.ico rename to client/ui/assets/netbird-systemtray-connected-dark.ico diff --git a/client/ui/netbird-systemtray-connected-dark.png b/client/ui/assets/netbird-systemtray-connected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-connected-dark.png rename to client/ui/assets/netbird-systemtray-connected-dark.png diff --git a/client/ui/netbird-systemtray-connected-macos.png b/client/ui/assets/netbird-systemtray-connected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-connected-macos.png rename to client/ui/assets/netbird-systemtray-connected-macos.png diff --git a/client/ui/netbird-systemtray-connected.ico b/client/ui/assets/netbird-systemtray-connected.ico similarity index 100% rename from client/ui/netbird-systemtray-connected.ico rename to client/ui/assets/netbird-systemtray-connected.ico diff --git a/client/ui/netbird-systemtray-connected.png b/client/ui/assets/netbird-systemtray-connected.png similarity index 100% rename from client/ui/netbird-systemtray-connected.png rename to client/ui/assets/netbird-systemtray-connected.png diff --git a/client/ui/netbird-systemtray-connecting-dark.ico b/client/ui/assets/netbird-systemtray-connecting-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-connecting-dark.ico rename to client/ui/assets/netbird-systemtray-connecting-dark.ico diff --git a/client/ui/netbird-systemtray-connecting-dark.png b/client/ui/assets/netbird-systemtray-connecting-dark.png similarity index 100% rename from client/ui/netbird-systemtray-connecting-dark.png rename to client/ui/assets/netbird-systemtray-connecting-dark.png diff --git a/client/ui/netbird-systemtray-connecting-macos.png b/client/ui/assets/netbird-systemtray-connecting-macos.png similarity index 100% rename from client/ui/netbird-systemtray-connecting-macos.png rename to client/ui/assets/netbird-systemtray-connecting-macos.png diff --git a/client/ui/netbird-systemtray-connecting.ico b/client/ui/assets/netbird-systemtray-connecting.ico similarity index 100% rename from client/ui/netbird-systemtray-connecting.ico rename to client/ui/assets/netbird-systemtray-connecting.ico diff --git a/client/ui/netbird-systemtray-connecting.png b/client/ui/assets/netbird-systemtray-connecting.png similarity index 100% rename from client/ui/netbird-systemtray-connecting.png rename to client/ui/assets/netbird-systemtray-connecting.png diff --git a/client/ui/netbird-systemtray-disconnected-macos.png b/client/ui/assets/netbird-systemtray-disconnected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-disconnected-macos.png rename to client/ui/assets/netbird-systemtray-disconnected-macos.png diff --git a/client/ui/netbird-systemtray-disconnected.ico b/client/ui/assets/netbird-systemtray-disconnected.ico similarity index 100% rename from client/ui/netbird-systemtray-disconnected.ico rename to client/ui/assets/netbird-systemtray-disconnected.ico diff --git a/client/ui/netbird-systemtray-disconnected.png b/client/ui/assets/netbird-systemtray-disconnected.png similarity index 100% rename from client/ui/netbird-systemtray-disconnected.png rename to client/ui/assets/netbird-systemtray-disconnected.png diff --git a/client/ui/netbird-systemtray-error-dark.ico b/client/ui/assets/netbird-systemtray-error-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-error-dark.ico rename to client/ui/assets/netbird-systemtray-error-dark.ico diff --git a/client/ui/netbird-systemtray-error-dark.png b/client/ui/assets/netbird-systemtray-error-dark.png similarity index 100% rename from client/ui/netbird-systemtray-error-dark.png rename to client/ui/assets/netbird-systemtray-error-dark.png diff --git a/client/ui/netbird-systemtray-error-macos.png b/client/ui/assets/netbird-systemtray-error-macos.png similarity index 100% rename from client/ui/netbird-systemtray-error-macos.png rename to client/ui/assets/netbird-systemtray-error-macos.png diff --git a/client/ui/netbird-systemtray-error.ico b/client/ui/assets/netbird-systemtray-error.ico similarity index 100% rename from client/ui/netbird-systemtray-error.ico rename to client/ui/assets/netbird-systemtray-error.ico diff --git a/client/ui/netbird-systemtray-error.png b/client/ui/assets/netbird-systemtray-error.png similarity index 100% rename from client/ui/netbird-systemtray-error.png rename to client/ui/assets/netbird-systemtray-error.png diff --git a/client/ui/netbird-systemtray-update-connected-dark.ico b/client/ui/assets/netbird-systemtray-update-connected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-update-connected-dark.ico rename to client/ui/assets/netbird-systemtray-update-connected-dark.ico diff --git a/client/ui/netbird-systemtray-update-connected-dark.png b/client/ui/assets/netbird-systemtray-update-connected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected-dark.png rename to client/ui/assets/netbird-systemtray-update-connected-dark.png diff --git a/client/ui/netbird-systemtray-update-connected-macos.png b/client/ui/assets/netbird-systemtray-update-connected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected-macos.png rename to client/ui/assets/netbird-systemtray-update-connected-macos.png diff --git a/client/ui/netbird-systemtray-update-connected.ico b/client/ui/assets/netbird-systemtray-update-connected.ico similarity index 100% rename from client/ui/netbird-systemtray-update-connected.ico rename to client/ui/assets/netbird-systemtray-update-connected.ico diff --git a/client/ui/netbird-systemtray-update-connected.png b/client/ui/assets/netbird-systemtray-update-connected.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected.png rename to client/ui/assets/netbird-systemtray-update-connected.png diff --git a/client/ui/netbird-systemtray-update-disconnected-dark.ico b/client/ui/assets/netbird-systemtray-update-disconnected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-dark.ico rename to client/ui/assets/netbird-systemtray-update-disconnected-dark.ico diff --git a/client/ui/netbird-systemtray-update-disconnected-dark.png b/client/ui/assets/netbird-systemtray-update-disconnected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-dark.png rename to client/ui/assets/netbird-systemtray-update-disconnected-dark.png diff --git a/client/ui/netbird-systemtray-update-disconnected-macos.png b/client/ui/assets/netbird-systemtray-update-disconnected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-macos.png rename to client/ui/assets/netbird-systemtray-update-disconnected-macos.png diff --git a/client/ui/netbird-systemtray-update-disconnected.ico b/client/ui/assets/netbird-systemtray-update-disconnected.ico similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected.ico rename to client/ui/assets/netbird-systemtray-update-disconnected.ico diff --git a/client/ui/netbird-systemtray-update-disconnected.png b/client/ui/assets/netbird-systemtray-update-disconnected.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected.png rename to client/ui/assets/netbird-systemtray-update-disconnected.png diff --git a/client/ui/netbird.ico b/client/ui/assets/netbird.ico similarity index 100% rename from client/ui/netbird.ico rename to client/ui/assets/netbird.ico diff --git a/client/ui/netbird.png b/client/ui/assets/netbird.png similarity index 100% rename from client/ui/netbird.png rename to client/ui/assets/netbird.png diff --git a/client/ui/banner.bmp b/client/ui/build/banner.bmp similarity index 100% rename from client/ui/banner.bmp rename to client/ui/build/banner.bmp diff --git a/client/ui/build-ui-linux.sh b/client/ui/build/build-ui-linux.sh similarity index 100% rename from client/ui/build-ui-linux.sh rename to client/ui/build/build-ui-linux.sh diff --git a/client/ui/netbird.desktop b/client/ui/build/netbird.desktop similarity index 100% rename from client/ui/netbird.desktop rename to client/ui/build/netbird.desktop diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index 889db70d6..914d4f3b9 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -35,7 +35,9 @@ import ( "github.com/netbirdio/netbird/client/proto" "github.com/netbirdio/netbird/client/ui/desktop" "github.com/netbirdio/netbird/client/ui/event" + "github.com/netbirdio/netbird/client/ui/process" "github.com/netbirdio/netbird/util" + "github.com/netbirdio/netbird/version" ) @@ -44,94 +46,125 @@ const ( failFastTimeout = time.Second ) +const ( + censoredPreSharedKey = "**********" +) + func main() { - var daemonAddr string - - defaultDaemonAddr := "unix:///var/run/netbird.sock" - if runtime.GOOS == "windows" { - defaultDaemonAddr = "tcp://127.0.0.1:41731" - } - - flag.StringVar( - &daemonAddr, "daemon-addr", - defaultDaemonAddr, - "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") - - var showSettings bool - flag.BoolVar(&showSettings, "settings", false, "run settings windows") - var showRoutes bool - flag.BoolVar(&showRoutes, "networks", false, "run networks windows") - var errorMSG string - flag.StringVar(&errorMSG, "error-msg", "", "displays a error message window") - - tmpDir := "/tmp" - if runtime.GOOS == "windows" { - tmpDir = os.TempDir() - } - - var saveLogsInFile bool - flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", tmpDir)) - - flag.Parse() + daemonAddr, showSettings, showNetworks, errorMsg, saveLogsInFile := parseFlags() + // Initialize file logging if needed. if saveLogsInFile { - logFile := path.Join(tmpDir, fmt.Sprintf("netbird-ui-%d.log", os.Getpid())) - err := util.InitLog("trace", logFile) - if err != nil { + if err := initLogFile(); err != nil { log.Errorf("error while initializing log: %v", err) return } } + // Create the Fyne application. a := app.NewWithID("NetBird") a.SetIcon(fyne.NewStaticResource("netbird", iconDisconnected)) - if errorMSG != "" { - showErrorMSG(errorMSG) + // Show error message window if needed. + if errorMsg != "" { + showErrorMessage(errorMsg) return } - client := newServiceClient(daemonAddr, a, showSettings, showRoutes) + // Create the service client (this also builds the settings or networks UI if requested). + client := newServiceClient(daemonAddr, a, showSettings, showNetworks) + + // Watch for theme/settings changes to update the icon. + go watchSettingsChanges(a, client) + + // Run in window mode if any UI flag was set. + if showSettings || showNetworks { + a.Run() + return + } + + // Check for another running process. + running, err := process.IsAnotherProcessRunning() + if err != nil { + log.Errorf("error while checking process: %v", err) + return + } + if running { + log.Warn("another process is running") + return + } + + client.setDefaultFonts() + systray.Run(client.onTrayReady, client.onTrayExit) +} + +// parseFlags reads and returns all needed command-line flags. +func parseFlags() (daemonAddr string, showSettings, showNetworks bool, errorMsg string, saveLogsInFile bool) { + defaultDaemonAddr := "unix:///var/run/netbird.sock" + if runtime.GOOS == "windows" { + defaultDaemonAddr = "tcp://127.0.0.1:41731" + } + flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") + flag.BoolVar(&showSettings, "settings", false, "run settings window") + flag.BoolVar(&showNetworks, "networks", false, "run networks window") + flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window") + + tmpDir := "/tmp" + if runtime.GOOS == "windows" { + tmpDir = os.TempDir() + } + flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", tmpDir)) + flag.Parse() + return +} + +// initLogFile initializes logging into a file. +func initLogFile() error { + tmpDir := "/tmp" + if runtime.GOOS == "windows" { + tmpDir = os.TempDir() + } + logFile := path.Join(tmpDir, fmt.Sprintf("netbird-ui-%d.log", os.Getpid())) + return util.InitLog("trace", logFile) +} + +// watchSettingsChanges listens for Fyne theme/settings changes and updates the client icon. +func watchSettingsChanges(a fyne.App, client *serviceClient) { settingsChangeChan := make(chan fyne.Settings) a.Settings().AddChangeListener(settingsChangeChan) - go func() { - for range settingsChangeChan { - client.updateIcon() - } - }() - - if showSettings || showRoutes { - a.Run() - } else { - running, err := isAnotherProcessRunning() - if err != nil { - log.Errorf("error while checking process: %v", err) - } - if running { - log.Warn("another process is running") - return - } - client.setDefaultFonts() - systray.Run(client.onTrayReady, client.onTrayExit) + for range settingsChangeChan { + client.updateIcon() } } -//go:embed netbird-systemtray-connected-macos.png +// showErrorMessage displays an error message in a simple window. +func showErrorMessage(msg string) { + a := app.New() + w := a.NewWindow("NetBird Error") + label := widget.NewLabel(msg) + label.Wrapping = fyne.TextWrapWord + w.SetContent(label) + w.Resize(fyne.NewSize(400, 100)) + w.Show() + a.Run() +} + +//go:embed assets/netbird-systemtray-connected-macos.png var iconConnectedMacOS []byte -//go:embed netbird-systemtray-disconnected-macos.png +//go:embed assets/netbird-systemtray-disconnected-macos.png var iconDisconnectedMacOS []byte -//go:embed netbird-systemtray-update-disconnected-macos.png +//go:embed assets/netbird-systemtray-update-disconnected-macos.png var iconUpdateDisconnectedMacOS []byte -//go:embed netbird-systemtray-update-connected-macos.png +//go:embed assets/netbird-systemtray-update-connected-macos.png var iconUpdateConnectedMacOS []byte -//go:embed netbird-systemtray-connecting-macos.png +//go:embed assets/netbird-systemtray-connecting-macos.png var iconConnectingMacOS []byte -//go:embed netbird-systemtray-error-macos.png +//go:embed assets/netbird-systemtray-error-macos.png var iconErrorMacOS []byte type serviceClient struct { @@ -301,18 +334,6 @@ func (s *serviceClient) showSettingsUI() { s.wSettings.Show() } -// showErrorMSG opens a fyne app window to display the supplied message -func showErrorMSG(msg string) { - app := app.New() - w := app.NewWindow("NetBird Error") - content := widget.NewLabel(msg) - content.Wrapping = fyne.TextWrapWord - w.SetContent(content) - w.Resize(fyne.NewSize(400, 100)) - w.Show() - app.Run() -} - // getSettingsForm to embed it into settings window. func (s *serviceClient) getSettingsForm() *widget.Form { return &widget.Form{ @@ -328,7 +349,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form { }, SubmitText: "Save", OnSubmit: func() { - if s.iPreSharedKey.Text != "" && s.iPreSharedKey.Text != "**********" { + if s.iPreSharedKey.Text != "" && s.iPreSharedKey.Text != censoredPreSharedKey { // validate preSharedKey if it added if _, err := wgtypes.ParseKey(s.iPreSharedKey.Text); err != nil { dialog.ShowError(fmt.Errorf("Invalid Pre-shared Key Value"), s.wSettings) @@ -366,7 +387,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form { WireguardPort: &port, } - if s.iPreSharedKey.Text != "**********" { + if s.iPreSharedKey.Text != censoredPreSharedKey { loginRequest.OptionalPreSharedKey = &s.iPreSharedKey.Text } @@ -588,21 +609,21 @@ func (s *serviceClient) onTrayReady() { s.mAdminPanel = systray.AddMenuItem("Admin Panel", "Netbird Admin Panel") systray.AddSeparator() - s.mSettings = systray.AddMenuItem("Settings", "Settings of the application") - s.mAllowSSH = s.mSettings.AddSubMenuItemCheckbox("Allow SSH", "Allow SSH connections", false) - s.mAutoConnect = s.mSettings.AddSubMenuItemCheckbox("Connect on Startup", "Connect automatically when the service starts", false) - s.mEnableRosenpass = s.mSettings.AddSubMenuItemCheckbox("Enable Quantum-Resistance", "Enable post-quantum security via Rosenpass", false) - s.mNotifications = s.mSettings.AddSubMenuItemCheckbox("Notifications", "Enable notifications", false) - s.mAdvancedSettings = s.mSettings.AddSubMenuItem("Advanced Settings", "Advanced settings of the application") - s.mCreateDebugBundle = s.mSettings.AddSubMenuItem("Create Debug Bundle", "Create and open debug information bundle") + s.mSettings = systray.AddMenuItem("Settings", settingsMenuDescr) + s.mAllowSSH = s.mSettings.AddSubMenuItemCheckbox("Allow SSH", allowSSHMenuDescr, false) + s.mAutoConnect = s.mSettings.AddSubMenuItemCheckbox("Connect on Startup", autoConnectMenuDescr, false) + s.mEnableRosenpass = s.mSettings.AddSubMenuItemCheckbox("Enable Quantum-Resistance", quantumResistanceMenuDescr, false) + s.mNotifications = s.mSettings.AddSubMenuItemCheckbox("Notifications", notificationsMenuDescr, false) + s.mAdvancedSettings = s.mSettings.AddSubMenuItem("Advanced Settings", advancedSettingsMenuDescr) + s.mCreateDebugBundle = s.mSettings.AddSubMenuItem("Create Debug Bundle", debugBundleMenuDescr) s.loadSettings() s.exitNodeMu.Lock() - s.mExitNode = systray.AddMenuItem("Exit Node", "Select exit node for routing traffic") + s.mExitNode = systray.AddMenuItem("Exit Node", exitNodeMenuDescr) s.mExitNode.Disable() s.exitNodeMu.Unlock() - s.mNetworks = systray.AddMenuItem("Networks", "Open the networks management window") + s.mNetworks = systray.AddMenuItem("Networks", networksMenuDescr) s.mNetworks.Disable() systray.AddSeparator() @@ -619,11 +640,11 @@ func (s *serviceClient) onTrayReady() { s.mVersionDaemon.Disable() s.mVersionDaemon.Hide() - s.mUpdate = s.mAbout.AddSubMenuItem("Download latest version", "Download latest version") + s.mUpdate = s.mAbout.AddSubMenuItem("Download latest version", latestVersionMenuDescr) s.mUpdate.Hide() systray.AddSeparator() - s.mQuit = systray.AddMenuItem("Quit", "Quit the client app") + s.mQuit = systray.AddMenuItem("Quit", quitMenuDescr) // update exit node menu in case service is already connected go s.updateExitNodes() diff --git a/client/ui/const.go b/client/ui/const.go new file mode 100644 index 000000000..0253750d1 --- /dev/null +++ b/client/ui/const.go @@ -0,0 +1,15 @@ +package main + +const ( + settingsMenuDescr = "Settings of the application" + allowSSHMenuDescr = "Allow SSH connections" + autoConnectMenuDescr = "Connect automatically when the service starts" + quantumResistanceMenuDescr = "Enable post-quantum security via Rosenpass" + notificationsMenuDescr = "Enable notifications" + advancedSettingsMenuDescr = "Advanced settings of the application" + debugBundleMenuDescr = "Create and open debug information bundle" + exitNodeMenuDescr = "Select exit node for routing traffic" + networksMenuDescr = "Open the networks management window" + latestVersionMenuDescr = "Download latest version" + quitMenuDescr = "Quit the client app" +) diff --git a/client/ui/icons.go b/client/ui/icons.go index 6f3a9dbc9..e88fb9378 100644 --- a/client/ui/icons.go +++ b/client/ui/icons.go @@ -6,38 +6,38 @@ import ( _ "embed" ) -//go:embed netbird.png +//go:embed assets/netbird.png var iconAbout []byte -//go:embed netbird-systemtray-connected.png +//go:embed assets/netbird-systemtray-connected.png var iconConnected []byte -//go:embed netbird-systemtray-connected-dark.png +//go:embed assets/netbird-systemtray-connected-dark.png var iconConnectedDark []byte -//go:embed netbird-systemtray-disconnected.png +//go:embed assets/netbird-systemtray-disconnected.png var iconDisconnected []byte -//go:embed netbird-systemtray-update-disconnected.png +//go:embed assets/netbird-systemtray-update-disconnected.png var iconUpdateDisconnected []byte -//go:embed netbird-systemtray-update-disconnected-dark.png +//go:embed assets/netbird-systemtray-update-disconnected-dark.png var iconUpdateDisconnectedDark []byte -//go:embed netbird-systemtray-update-connected.png +//go:embed assets/netbird-systemtray-update-connected.png var iconUpdateConnected []byte -//go:embed netbird-systemtray-update-connected-dark.png +//go:embed assets/netbird-systemtray-update-connected-dark.png var iconUpdateConnectedDark []byte -//go:embed netbird-systemtray-connecting.png +//go:embed assets/netbird-systemtray-connecting.png var iconConnecting []byte -//go:embed netbird-systemtray-connecting-dark.png +//go:embed assets/netbird-systemtray-connecting-dark.png var iconConnectingDark []byte -//go:embed netbird-systemtray-error.png +//go:embed assets/netbird-systemtray-error.png var iconError []byte -//go:embed netbird-systemtray-error-dark.png +//go:embed assets/netbird-systemtray-error-dark.png var iconErrorDark []byte diff --git a/client/ui/icons_windows.go b/client/ui/icons_windows.go index a2a924763..2107d3852 100644 --- a/client/ui/icons_windows.go +++ b/client/ui/icons_windows.go @@ -1,41 +1,41 @@ package main import ( - _ "embed" + _ "embed" ) -//go:embed netbird.ico +//go:embed assets/netbird.ico var iconAbout []byte -//go:embed netbird-systemtray-connected.ico +//go:embed assets/netbird-systemtray-connected.ico var iconConnected []byte -//go:embed netbird-systemtray-connected-dark.ico +//go:embed assets/netbird-systemtray-connected-dark.ico var iconConnectedDark []byte -//go:embed netbird-systemtray-disconnected.ico +//go:embed assets/netbird-systemtray-disconnected.ico var iconDisconnected []byte -//go:embed netbird-systemtray-update-disconnected.ico +//go:embed assets/netbird-systemtray-update-disconnected.ico var iconUpdateDisconnected []byte -//go:embed netbird-systemtray-update-disconnected-dark.ico +//go:embed assets/netbird-systemtray-update-disconnected-dark.ico var iconUpdateDisconnectedDark []byte -//go:embed netbird-systemtray-update-connected.ico +//go:embed assets/netbird-systemtray-update-connected.ico var iconUpdateConnected []byte -//go:embed netbird-systemtray-update-connected-dark.ico +//go:embed assets/netbird-systemtray-update-connected-dark.ico var iconUpdateConnectedDark []byte -//go:embed netbird-systemtray-connecting.ico +//go:embed assets/netbird-systemtray-connecting.ico var iconConnecting []byte -//go:embed netbird-systemtray-connecting-dark.ico +//go:embed assets/netbird-systemtray-connecting-dark.ico var iconConnectingDark []byte -//go:embed netbird-systemtray-error.ico +//go:embed assets/netbird-systemtray-error.ico var iconError []byte -//go:embed netbird-systemtray-error-dark.ico +//go:embed assets/netbird-systemtray-error-dark.ico var iconErrorDark []byte diff --git a/client/ui/network.go b/client/ui/network.go index 750788cf3..b21554f09 100644 --- a/client/ui/network.go +++ b/client/ui/network.go @@ -363,7 +363,7 @@ func (s *serviceClient) recreateExitNodeMenu(exitNodes []*proto.Network) { if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" { s.mExitNode.Remove() - s.mExitNode = systray.AddMenuItem("Exit Node", "Select exit node for routing traffic") + s.mExitNode = systray.AddMenuItem("Exit Node", exitNodeMenuDescr) } for _, node := range exitNodes { diff --git a/client/ui/process.go b/client/ui/process/process.go similarity index 90% rename from client/ui/process.go rename to client/ui/process/process.go index bcb3dd879..f9a8a4fe9 100644 --- a/client/ui/process.go +++ b/client/ui/process/process.go @@ -1,4 +1,4 @@ -package main +package process import ( "os" @@ -8,7 +8,7 @@ import ( "github.com/shirou/gopsutil/v3/process" ) -func isAnotherProcessRunning() (bool, error) { +func IsAnotherProcessRunning() (bool, error) { processes, err := process.Processes() if err != nil { return false, err diff --git a/client/ui/process_nonwindows.go b/client/ui/process/process_nonwindows.go similarity index 96% rename from client/ui/process_nonwindows.go rename to client/ui/process/process_nonwindows.go index 0d17be2be..cf9f6443d 100644 --- a/client/ui/process_nonwindows.go +++ b/client/ui/process/process_nonwindows.go @@ -1,6 +1,6 @@ //go:build !windows -package main +package process import ( "os" diff --git a/client/ui/process_windows.go b/client/ui/process/process_windows.go similarity index 96% rename from client/ui/process_windows.go rename to client/ui/process/process_windows.go index b15b0ed24..2d211d1a4 100644 --- a/client/ui/process_windows.go +++ b/client/ui/process/process_windows.go @@ -1,4 +1,4 @@ -package main +package process import ( "os/user" From c111675dd8788ef8ab662989b1e5a90fc04a9a56 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:57:17 +0100 Subject: [PATCH 07/10] [client] Handle large DNS packets in dns route resolution (#3441) --- client/internal/routemanager/dnsinterceptor/handler.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/internal/routemanager/dnsinterceptor/handler.go b/client/internal/routemanager/dnsinterceptor/handler.go index f36285cc4..da1056e2d 100644 --- a/client/internal/routemanager/dnsinterceptor/handler.go +++ b/client/internal/routemanager/dnsinterceptor/handler.go @@ -160,6 +160,12 @@ func (d *DnsInterceptor) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { return } + // set the AuthenticatedData flag and the EDNS0 buffer size to 4096 bytes to support larger dns records + if r.Extra == nil { + r.SetEdns0(4096, false) + r.MsgHdr.AuthenticatedData = true + } + client := &dns.Client{ Timeout: 5 * time.Second, Net: "udp", From 062d1ec76f6b9fba60590a297f4063b713d6e6d0 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Thu, 6 Mar 2025 01:10:37 +0100 Subject: [PATCH 08/10] [misc] Update bug-issue-report.md template (#3449) --- .github/ISSUE_TEMPLATE/bug-issue-report.md | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-issue-report.md b/.github/ISSUE_TEMPLATE/bug-issue-report.md index 87f757f42..3633cca4f 100644 --- a/.github/ISSUE_TEMPLATE/bug-issue-report.md +++ b/.github/ISSUE_TEMPLATE/bug-issue-report.md @@ -31,14 +31,22 @@ Please specify whether you use NetBird Cloud or self-host NetBird's control plan `netbird version` -**NetBird status -dA output:** +**Is any other VPN software installed?** -If applicable, add the `netbird status -dA' command output. +If yes, which one? -**Do you face any (non-mobile) client issues?** +**Debug output** -Please provide the file created by `netbird debug for 1m -AS`. -We advise reviewing the anonymized files for any remaining PII. +To help us resolve the problem, please attach the following debug output + + netbird status -dA + +As well as the file created by + + netbird debug for 1m -AS + + +We advise reviewing the anonymized output for any remaining personal information. **Screenshots** @@ -47,3 +55,10 @@ If applicable, add screenshots to help explain your problem. **Additional context** Add any other context about the problem here. + +**Have you tried these troubleshooting steps?** +- [ ] Checked for newer NetBird versions +- [ ] Searched for similar issues on GitHub (including closed ones) +- [ ] Restarted the NetBird client +- [ ] Disabled other VPN software +- [ ] Checked firewall settings From 4b76d93cecedecf0985f805a164b5a00a04d1b56 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Fri, 7 Mar 2025 12:00:25 +0100 Subject: [PATCH 09/10] [client] Fix TURN-Relay switch (#3456) - When a peer is connected with TURN and a Relay connection is established, do not force switching to Relay. Keep using TURN until disconnection. -In the proxy preparation phase, the Bind Proxy does not set the remote conn as a fake address for Bind. When running the Work() function, the proper proxy instance updates the conn inside the Bind. --- client/iface/bind/ice_bind.go | 44 +++--------------------- client/iface/wgproxy/bind/proxy.go | 54 ++++++++++++++++++++---------- client/internal/peer/conn.go | 8 ++--- 3 files changed, 45 insertions(+), 61 deletions(-) diff --git a/client/iface/bind/ice_bind.go b/client/iface/bind/ice_bind.go index 41f415af7..6897f04a1 100644 --- a/client/iface/bind/ice_bind.go +++ b/client/iface/bind/ice_bind.go @@ -5,7 +5,6 @@ import ( "net" "net/netip" "runtime" - "strings" "sync" "github.com/pion/stun/v2" @@ -108,35 +107,17 @@ func (s *ICEBind) GetICEMux() (*UniversalUDPMuxDefault, error) { return s.udpMux, nil } -func (b *ICEBind) SetEndpoint(peerAddress *net.UDPAddr, conn net.Conn) (*net.UDPAddr, error) { - fakeUDPAddr, err := fakeAddress(peerAddress) - if err != nil { - return nil, err - } - - // force IPv4 - fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4()) - if !ok { - return nil, fmt.Errorf("failed to convert IP to netip.Addr") - } - +func (b *ICEBind) SetEndpoint(fakeIP netip.Addr, conn net.Conn) { b.endpointsMu.Lock() - b.endpoints[fakeAddr] = conn + b.endpoints[fakeIP] = conn b.endpointsMu.Unlock() - - return fakeUDPAddr, nil } -func (b *ICEBind) RemoveEndpoint(fakeUDPAddr *net.UDPAddr) { - fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4()) - if !ok { - log.Warnf("failed to convert IP to netip.Addr") - return - } - +func (b *ICEBind) RemoveEndpoint(fakeIP netip.Addr) { b.endpointsMu.Lock() defer b.endpointsMu.Unlock() - delete(b.endpoints, fakeAddr) + + delete(b.endpoints, fakeIP) } func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error { @@ -275,21 +256,6 @@ func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpo } } -// fakeAddress returns a fake address that is used to as an identifier for the peer. -// The fake address is in the format of 127.1.x.x where x.x is the last two octets of the peer address. -func fakeAddress(peerAddress *net.UDPAddr) (*net.UDPAddr, error) { - octets := strings.Split(peerAddress.IP.String(), ".") - if len(octets) != 4 { - return nil, fmt.Errorf("invalid IP format") - } - - newAddr := &net.UDPAddr{ - IP: net.ParseIP(fmt.Sprintf("127.1.%s.%s", octets[2], octets[3])), - Port: peerAddress.Port, - } - return newAddr, nil -} - func getMessages(msgsPool *sync.Pool) *[]ipv6.Message { return msgsPool.Get().(*[]ipv6.Message) } diff --git a/client/iface/wgproxy/bind/proxy.go b/client/iface/wgproxy/bind/proxy.go index 8a2e65382..614787e17 100644 --- a/client/iface/wgproxy/bind/proxy.go +++ b/client/iface/wgproxy/bind/proxy.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/netip" + "strings" "sync" log "github.com/sirupsen/logrus" @@ -16,13 +17,13 @@ import ( type ProxyBind struct { Bind *bind.ICEBind - wgAddr *net.UDPAddr - wgEndpoint *bind.Endpoint - remoteConn net.Conn - ctx context.Context - cancel context.CancelFunc - closeMu sync.Mutex - closed bool + fakeNetIP *netip.AddrPort + wgBindEndpoint *bind.Endpoint + remoteConn net.Conn + ctx context.Context + cancel context.CancelFunc + closeMu sync.Mutex + closed bool pausedMu sync.Mutex paused bool @@ -33,20 +34,24 @@ type ProxyBind struct { // endpoint is the NetBird address of the remote peer. The SetEndpoint return with the address what will be used in the // WireGuard configuration. func (p *ProxyBind) AddTurnConn(ctx context.Context, nbAddr *net.UDPAddr, remoteConn net.Conn) error { - addr, err := p.Bind.SetEndpoint(nbAddr, remoteConn) + fakeNetIP, err := fakeAddress(nbAddr) if err != nil { return err } - p.wgAddr = addr - p.wgEndpoint = addrToEndpoint(addr) + p.fakeNetIP = fakeNetIP + p.wgBindEndpoint = &bind.Endpoint{AddrPort: *fakeNetIP} p.remoteConn = remoteConn p.ctx, p.cancel = context.WithCancel(ctx) - return err + return nil } func (p *ProxyBind) EndpointAddr() *net.UDPAddr { - return p.wgAddr + return &net.UDPAddr{ + IP: p.fakeNetIP.Addr().AsSlice(), + Port: int(p.fakeNetIP.Port()), + Zone: p.fakeNetIP.Addr().Zone(), + } } func (p *ProxyBind) Work() { @@ -54,6 +59,8 @@ func (p *ProxyBind) Work() { return } + p.Bind.SetEndpoint(p.fakeNetIP.Addr(), p.remoteConn) + p.pausedMu.Lock() p.paused = false p.pausedMu.Unlock() @@ -93,7 +100,7 @@ func (p *ProxyBind) close() error { p.cancel() - p.Bind.RemoveEndpoint(p.wgAddr) + p.Bind.RemoveEndpoint(p.fakeNetIP.Addr()) if rErr := p.remoteConn.Close(); rErr != nil && !errors.Is(rErr, net.ErrClosed) { return rErr @@ -126,7 +133,7 @@ func (p *ProxyBind) proxyToLocal(ctx context.Context) { } msg := bind.RecvMessage{ - Endpoint: p.wgEndpoint, + Endpoint: p.wgBindEndpoint, Buffer: buf[:n], } p.Bind.RecvChan <- msg @@ -134,8 +141,19 @@ func (p *ProxyBind) proxyToLocal(ctx context.Context) { } } -func addrToEndpoint(addr *net.UDPAddr) *bind.Endpoint { - ip, _ := netip.AddrFromSlice(addr.IP.To4()) - addrPort := netip.AddrPortFrom(ip, uint16(addr.Port)) - return &bind.Endpoint{AddrPort: addrPort} +// fakeAddress returns a fake address that is used to as an identifier for the peer. +// The fake address is in the format of 127.1.x.x where x.x is the last two octets of the peer address. +func fakeAddress(peerAddress *net.UDPAddr) (*netip.AddrPort, error) { + octets := strings.Split(peerAddress.IP.String(), ".") + if len(octets) != 4 { + return nil, fmt.Errorf("invalid IP format") + } + + fakeIP, err := netip.ParseAddr(fmt.Sprintf("127.1.%s.%s", octets[2], octets[3])) + if err != nil { + return nil, fmt.Errorf("failed to parse new IP: %w", err) + } + + netipAddr := netip.AddrPortFrom(fakeIP, uint16(peerAddress.Port)) + return &netipAddr, nil } diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index 9b4d1a554..b91cfe33c 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -442,8 +442,8 @@ func (conn *Conn) onRelayConnectionIsReady(rci RelayConnInfo) { conn.log.Infof("created new wgProxy for relay connection: %s", wgProxy.EndpointAddr().String()) - if conn.iceP2PIsActive() { - conn.log.Debugf("do not switch to relay because current priority is: %s", conn.currentConnPriority.String()) + if conn.isICEActive() { + conn.log.Infof("do not switch to relay because current priority is: %s", conn.currentConnPriority.String()) conn.setRelayedProxy(wgProxy) conn.statusRelay.Set(StatusConnected) conn.updateRelayStatus(rci.relayedConn.RemoteAddr().String(), rci.rosenpassPubKey) @@ -711,8 +711,8 @@ func (conn *Conn) isReadyToUpgrade() bool { return conn.wgProxyRelay != nil && conn.currentConnPriority != connPriorityRelay } -func (conn *Conn) iceP2PIsActive() bool { - return conn.currentConnPriority == connPriorityICEP2P && conn.statusICE.Get() == StatusConnected +func (conn *Conn) isICEActive() bool { + return (conn.currentConnPriority == connPriorityICEP2P || conn.currentConnPriority == connPriorityICETurn) && conn.statusICE.Get() == StatusConnected } func (conn *Conn) removeWgPeer() error { From 53b9a2002fa8888136ed03fbb40e08b32a1e8740 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Fri, 7 Mar 2025 14:06:47 +0100 Subject: [PATCH 10/10] Print out the goroutine id (#3433) The TXT logger prints out the actual go routine ID This feature depends on 'loggoroutine' build tag ```go build -tags loggoroutine``` --- formatter/formatter.go | 83 ------------------- formatter/hook/additional_empty.go | 9 ++ formatter/hook/additional_goroutine.go | 12 +++ formatter/{ => hook}/hook.go | 5 +- formatter/{ => hook}/hook_test.go | 2 +- formatter/hook/keys.go | 6 ++ formatter/levels/levels.go | 3 + formatter/{ => logcat}/logcat.go | 18 ++-- formatter/{ => logcat}/logcat_test.go | 3 +- formatter/set.go | 20 +++-- formatter/syslog/formatter.go | 39 +++++++++ formatter/syslog/formatter_test.go | 26 ++++++ formatter/txt/format.go | 31 +++++++ formatter/txt/format_gorutines.go | 35 ++++++++ formatter/txt/formatter.go | 31 +++++++ formatter/{ => txt}/formatter_test.go | 19 +---- go.mod | 1 + go.sum | 2 + management/cmd/management.go | 10 +-- management/cmd/migration_up.go | 4 +- management/server/management_proto_test.go | 4 +- .../server/telemetry/http_api_metrics.go | 4 +- 22 files changed, 236 insertions(+), 131 deletions(-) delete mode 100644 formatter/formatter.go create mode 100644 formatter/hook/additional_empty.go create mode 100644 formatter/hook/additional_goroutine.go rename formatter/{ => hook}/hook.go (96%) rename formatter/{ => hook}/hook_test.go (98%) create mode 100644 formatter/hook/keys.go create mode 100644 formatter/levels/levels.go rename formatter/{ => logcat}/logcat.go (63%) rename formatter/{ => logcat}/logcat_test.go (97%) create mode 100644 formatter/syslog/formatter.go create mode 100644 formatter/syslog/formatter_test.go create mode 100644 formatter/txt/format.go create mode 100644 formatter/txt/format_gorutines.go create mode 100644 formatter/txt/formatter.go rename formatter/{ => txt}/formatter_test.go (55%) diff --git a/formatter/formatter.go b/formatter/formatter.go deleted file mode 100644 index 74de38603..000000000 --- a/formatter/formatter.go +++ /dev/null @@ -1,83 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/sirupsen/logrus" -) - -// TextFormatter formats logs into text with included source code's path -type TextFormatter struct { - timestampFormat string - levelDesc []string -} - -// SyslogFormatter formats logs into text -type SyslogFormatter struct { - levelDesc []string -} - -var validLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} - - -// NewTextFormatter create new MyTextFormatter instance -func NewTextFormatter() *TextFormatter { - return &TextFormatter{ - levelDesc: validLevelDesc, - timestampFormat: time.RFC3339, // or RFC3339 - } -} - -// NewSyslogFormatter create new MySyslogFormatter instance -func NewSyslogFormatter() *SyslogFormatter { - return &SyslogFormatter{ - levelDesc: validLevelDesc, - } -} - -// Format renders a single log entry -func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { - var fields string - keys := make([]string, 0, len(entry.Data)) - for k, v := range entry.Data { - if k == "source" { - continue - } - keys = append(keys, fmt.Sprintf("%s: %v", k, v)) - } - - if len(keys) > 0 { - fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) - } - - level := f.parseLevel(entry.Level) - - return []byte(fmt.Sprintf("%s %s %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, fields, entry.Data["source"], entry.Message)), nil -} - -func (f *TextFormatter) parseLevel(level logrus.Level) string { - if len(f.levelDesc) < int(level) { - return "" - } - - return f.levelDesc[level] -} - -// Format renders a single log entry -func (f *SyslogFormatter) Format(entry *logrus.Entry) ([]byte, error) { - var fields string - keys := make([]string, 0, len(entry.Data)) - for k, v := range entry.Data { - if k == "source" { - continue - } - keys = append(keys, fmt.Sprintf("%s: %v", k, v)) - } - - if len(keys) > 0 { - fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) - } - return []byte(fmt.Sprintf("%s%s\n", fields, entry.Message)), nil -} diff --git a/formatter/hook/additional_empty.go b/formatter/hook/additional_empty.go new file mode 100644 index 000000000..4f5069482 --- /dev/null +++ b/formatter/hook/additional_empty.go @@ -0,0 +1,9 @@ +//go:build !loggoroutine + +package hook + +import log "github.com/sirupsen/logrus" + +func additionalEntries(_ *log.Entry) { + // This function is empty and is used to demonstrate the use of additional hooks. +} diff --git a/formatter/hook/additional_goroutine.go b/formatter/hook/additional_goroutine.go new file mode 100644 index 000000000..fb4e09f47 --- /dev/null +++ b/formatter/hook/additional_goroutine.go @@ -0,0 +1,12 @@ +//go:build loggoroutine + +package hook + +import ( + "github.com/petermattis/goid" + log "github.com/sirupsen/logrus" +) + +func additionalEntries(entry *log.Entry) { + entry.Data[EntryKeyGoroutineID] = goid.Get() +} diff --git a/formatter/hook.go b/formatter/hook/hook.go similarity index 96% rename from formatter/hook.go rename to formatter/hook/hook.go index 12f27e67d..1b6ceccc9 100644 --- a/formatter/hook.go +++ b/formatter/hook/hook.go @@ -1,4 +1,4 @@ -package formatter +package hook import ( "fmt" @@ -41,7 +41,8 @@ func (hook ContextHook) Levels() []logrus.Level { // Fire extend with the source information the entry.Data func (hook ContextHook) Fire(entry *logrus.Entry) error { src := hook.parseSrc(entry.Caller.File) - entry.Data["source"] = fmt.Sprintf("%s:%v", src, entry.Caller.Line) + entry.Data[EntryKeySource] = fmt.Sprintf("%s:%v", src, entry.Caller.Line) + additionalEntries(entry) if entry.Context == nil { return nil diff --git a/formatter/hook_test.go b/formatter/hook/hook_test.go similarity index 98% rename from formatter/hook_test.go rename to formatter/hook/hook_test.go index a4bcb0284..802163244 100644 --- a/formatter/hook_test.go +++ b/formatter/hook/hook_test.go @@ -1,4 +1,4 @@ -package formatter +package hook import ( "testing" diff --git a/formatter/hook/keys.go b/formatter/hook/keys.go new file mode 100644 index 000000000..09781a88b --- /dev/null +++ b/formatter/hook/keys.go @@ -0,0 +1,6 @@ +package hook + +const ( + EntryKeySource = "source" + EntryKeyGoroutineID = "goroutine_id" +) diff --git a/formatter/levels/levels.go b/formatter/levels/levels.go new file mode 100644 index 000000000..41ae80db3 --- /dev/null +++ b/formatter/levels/levels.go @@ -0,0 +1,3 @@ +package levels + +var ValidLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} diff --git a/formatter/logcat.go b/formatter/logcat/logcat.go similarity index 63% rename from formatter/logcat.go rename to formatter/logcat/logcat.go index e8f606229..c561d3283 100644 --- a/formatter/logcat.go +++ b/formatter/logcat/logcat.go @@ -1,26 +1,28 @@ -package formatter +package logcat import ( "fmt" "strings" "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" ) -// LogcatFormatter formats logs into text what is fit for logcat -type LogcatFormatter struct { +// Formatter formats logs into text what is fit for logcat +type Formatter struct { levelDesc []string } // NewLogcatFormatter create new LogcatFormatter instance -func NewLogcatFormatter() *LogcatFormatter { - return &LogcatFormatter{ - levelDesc: []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"}, +func NewLogcatFormatter() *Formatter { + return &Formatter{ + levelDesc: levels.ValidLevelDesc, } } // Format renders a single log entry -func (f *LogcatFormatter) Format(entry *logrus.Entry) ([]byte, error) { +func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { var fields string keys := make([]string, 0, len(entry.Data)) for k, v := range entry.Data { @@ -39,7 +41,7 @@ func (f *LogcatFormatter) Format(entry *logrus.Entry) ([]byte, error) { return []byte(fmt.Sprintf("[%s] %s%s %s\n", level, fields, entry.Data["source"], entry.Message)), nil } -func (f *LogcatFormatter) parseLevel(level logrus.Level) string { +func (f *Formatter) parseLevel(level logrus.Level) string { if len(f.levelDesc) < int(level) { return "" } diff --git a/formatter/logcat_test.go b/formatter/logcat/logcat_test.go similarity index 97% rename from formatter/logcat_test.go rename to formatter/logcat/logcat_test.go index 45ba5bc46..fd4d92881 100644 --- a/formatter/logcat_test.go +++ b/formatter/logcat/logcat_test.go @@ -1,4 +1,4 @@ -package formatter +package logcat import ( "testing" @@ -25,4 +25,5 @@ func TestLogcatMessageFormat(t *testing.T) { if parsedString != expectedString && parsedString != expectedStringVariant { t.Errorf("The log messages don't match. Expected: '%s', got: '%s'", expectedString, parsedString) } + } diff --git a/formatter/set.go b/formatter/set.go index 9dfea5a7f..a609e7b48 100644 --- a/formatter/set.go +++ b/formatter/set.go @@ -2,31 +2,37 @@ package formatter import ( "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" + "github.com/netbirdio/netbird/formatter/logcat" + "github.com/netbirdio/netbird/formatter/syslog" + "github.com/netbirdio/netbird/formatter/txt" ) // SetTextFormatter set the text formatter for given logger. func SetTextFormatter(logger *logrus.Logger) { - logger.Formatter = NewTextFormatter() + logger.Formatter = txt.NewTextFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } + // SetSyslogFormatter set the text formatter for given logger. func SetSyslogFormatter(logger *logrus.Logger) { - logger.Formatter = NewSyslogFormatter() + logger.Formatter = syslog.NewSyslogFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } // SetJSONFormatter set the JSON formatter for given logger. func SetJSONFormatter(logger *logrus.Logger) { logger.Formatter = &logrus.JSONFormatter{} logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } // SetLogcatFormatter set the logcat formatter for given logger. func SetLogcatFormatter(logger *logrus.Logger) { - logger.Formatter = NewLogcatFormatter() + logger.Formatter = logcat.NewLogcatFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } diff --git a/formatter/syslog/formatter.go b/formatter/syslog/formatter.go new file mode 100644 index 000000000..e72c30347 --- /dev/null +++ b/formatter/syslog/formatter.go @@ -0,0 +1,39 @@ +package syslog + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" +) + +// Formatter formats logs into text +type Formatter struct { + levelDesc []string +} + +// NewSyslogFormatter create new MySyslogFormatter instance +func NewSyslogFormatter() *Formatter { + return &Formatter{ + levelDesc: levels.ValidLevelDesc, + } +} + +// Format renders a single log entry +func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == "source" { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + return []byte(fmt.Sprintf("%s%s\n", fields, entry.Message)), nil +} diff --git a/formatter/syslog/formatter_test.go b/formatter/syslog/formatter_test.go new file mode 100644 index 000000000..110a3390b --- /dev/null +++ b/formatter/syslog/formatter_test.go @@ -0,0 +1,26 @@ +package syslog + +import ( + "testing" + "time" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestLogSyslogFormat(t *testing.T) { + + someEntry := &logrus.Entry{ + Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, + Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), + Level: 3, + Message: "Some Message", + } + + formatter := NewSyslogFormatter() + result, _ := formatter.Format(someEntry) + + parsedString := string(result) + expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" + assert.Regexp(t, expectedString, parsedString) +} diff --git a/formatter/txt/format.go b/formatter/txt/format.go new file mode 100644 index 000000000..a88c41044 --- /dev/null +++ b/formatter/txt/format.go @@ -0,0 +1,31 @@ +//go:build !loggoroutine + +package txt + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" +) + +func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == hook.EntryKeySource { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + + level := f.parseLevel(entry.Level) + + return []byte(fmt.Sprintf("%s %s %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, fields, entry.Data[hook.EntryKeySource], entry.Message)), nil +} diff --git a/formatter/txt/format_gorutines.go b/formatter/txt/format_gorutines.go new file mode 100644 index 000000000..a39aee633 --- /dev/null +++ b/formatter/txt/format_gorutines.go @@ -0,0 +1,35 @@ +//go:build loggoroutine + +package txt + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" +) + +func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == hook.EntryKeySource { + continue + } + + if k == hook.EntryKeyGoroutineID { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + + level := f.parseLevel(entry.Level) + + return []byte(fmt.Sprintf("%s %s %d %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, entry.Data[hook.EntryKeyGoroutineID], fields, entry.Data[hook.EntryKeySource], entry.Message)), nil +} diff --git a/formatter/txt/formatter.go b/formatter/txt/formatter.go new file mode 100644 index 000000000..3b2a3fb4d --- /dev/null +++ b/formatter/txt/formatter.go @@ -0,0 +1,31 @@ +package txt + +import ( + "time" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" +) + +// TextFormatter formats logs into text with included source code's path +type TextFormatter struct { + timestampFormat string + levelDesc []string +} + +// NewTextFormatter create new MyTextFormatter instance +func NewTextFormatter() *TextFormatter { + return &TextFormatter{ + levelDesc: levels.ValidLevelDesc, + timestampFormat: time.RFC3339, // or RFC3339 + } +} + +func (f *TextFormatter) parseLevel(level logrus.Level) string { + if len(f.levelDesc) < int(level) { + return "" + } + + return f.levelDesc[level] +} diff --git a/formatter/formatter_test.go b/formatter/txt/formatter_test.go similarity index 55% rename from formatter/formatter_test.go rename to formatter/txt/formatter_test.go index 1ed207958..590af5d50 100644 --- a/formatter/formatter_test.go +++ b/formatter/txt/formatter_test.go @@ -1,4 +1,4 @@ -package formatter +package txt import ( "testing" @@ -24,20 +24,3 @@ func TestLogTextFormat(t *testing.T) { expectedString := "^2021-02-21T01:10:30Z WARN \\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] some/fancy/path.go:46: Some Message\\s+$" assert.Regexp(t, expectedString, parsedString) } - -func TestLogSyslogFormat(t *testing.T) { - - someEntry := &logrus.Entry{ - Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, - Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), - Level: 3, - Message: "Some Message", - } - - formatter := NewSyslogFormatter() - result, _ := formatter.Format(someEntry) - - parsedString := string(result) - expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" - assert.Regexp(t, expectedString, parsedString) -} diff --git a/go.mod b/go.mod index 3d71e8eb1..76605e155 100644 --- a/go.mod +++ b/go.mod @@ -65,6 +65,7 @@ require ( github.com/okta/okta-sdk-golang/v2 v2.18.0 github.com/oschwald/maxminddb-golang v1.12.0 github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 github.com/pion/logging v0.2.2 github.com/pion/randutil v0.1.0 github.com/pion/stun/v2 v2.0.0 diff --git a/go.sum b/go.sum index 36bca22d3..069b378d6 100644 --- a/go.sum +++ b/go.sum @@ -571,6 +571,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 h1:E7Kmf11E4K7B5hDti2K2NqPb1nlYlGYsu02S1JNd/Bs= +github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v2 v2.2.10 h1:u2Axk+FyIR1VFTPurktB+1zoEPGIW3bmyj3LEFrXjAA= github.com/pion/dtls/v2 v2.2.10/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= diff --git a/management/cmd/management.go b/management/cmd/management.go index 9712f04aa..e087a3d67 100644 --- a/management/cmd/management.go +++ b/management/cmd/management.go @@ -36,7 +36,7 @@ import ( "github.com/netbirdio/management-integrations/integrations" "github.com/netbirdio/netbird/encryption" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" mgmtProto "github.com/netbirdio/netbird/management/proto" "github.com/netbirdio/netbird/management/server" "github.com/netbirdio/netbird/management/server/auth" @@ -90,7 +90,7 @@ var ( flag.Parse() //nolint - ctx := context.WithValue(cmd.Context(), formatter.ExecutionContextKey, formatter.SystemSource) + ctx := context.WithValue(cmd.Context(), hook.ExecutionContextKey, hook.SystemSource) err := util.InitLog(logLevel, logFile) if err != nil { @@ -136,7 +136,7 @@ var ( ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() //nolint - ctx = context.WithValue(ctx, formatter.ExecutionContextKey, formatter.SystemSource) + ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.SystemSource) err := handleRebrand(cmd) if err != nil { @@ -374,7 +374,7 @@ func unaryInterceptor( ) (interface{}, error) { reqID := uuid.New().String() //nolint - ctx = context.WithValue(ctx, formatter.ExecutionContextKey, formatter.GRPCSource) + ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.GRPCSource) //nolint ctx = context.WithValue(ctx, nbContext.RequestIDKey, reqID) return handler(ctx, req) @@ -389,7 +389,7 @@ func streamInterceptor( reqID := uuid.New().String() wrapped := grpcMiddleware.WrapServerStream(ss) //nolint - ctx := context.WithValue(ss.Context(), formatter.ExecutionContextKey, formatter.GRPCSource) + ctx := context.WithValue(ss.Context(), hook.ExecutionContextKey, hook.GRPCSource) //nolint wrapped.WrappedContext = context.WithValue(ctx, nbContext.RequestIDKey, reqID) return handler(srv, wrapped) diff --git a/management/cmd/migration_up.go b/management/cmd/migration_up.go index 183fc554d..de061dca2 100644 --- a/management/cmd/migration_up.go +++ b/management/cmd/migration_up.go @@ -8,7 +8,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/util" ) @@ -30,7 +30,7 @@ var upCmd = &cobra.Command{ } //nolint - ctx := context.WithValue(cmd.Context(), formatter.ExecutionContextKey, formatter.SystemSource) + ctx := context.WithValue(cmd.Context(), hook.ExecutionContextKey, hook.SystemSource) if err := store.MigrateFileStoreToSqlite(ctx, mgmtDataDir); err != nil { return err diff --git a/management/server/management_proto_test.go b/management/server/management_proto_test.go index 4d0630f0f..28f5abf57 100644 --- a/management/server/management_proto_test.go +++ b/management/server/management_proto_test.go @@ -20,7 +20,7 @@ import ( "google.golang.org/grpc/keepalive" "github.com/netbirdio/netbird/encryption" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" mgmtProto "github.com/netbirdio/netbird/management/proto" "github.com/netbirdio/netbird/management/server/activity" "github.com/netbirdio/netbird/management/server/settings" @@ -424,7 +424,7 @@ func startManagementForTest(t *testing.T, testFile string, config *Config) (*grp peersUpdateManager := NewPeersUpdateManager(nil) eventStore := &activity.InMemoryEventStore{} - ctx := context.WithValue(context.Background(), formatter.ExecutionContextKey, formatter.SystemSource) //nolint:staticcheck + ctx := context.WithValue(context.Background(), hook.ExecutionContextKey, hook.SystemSource) //nolint:staticcheck metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) diff --git a/management/server/telemetry/http_api_metrics.go b/management/server/telemetry/http_api_metrics.go index 5ef9e6d02..ae27466d9 100644 --- a/management/server/telemetry/http_api_metrics.go +++ b/management/server/telemetry/http_api_metrics.go @@ -13,7 +13,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" nbContext "github.com/netbirdio/netbird/management/server/context" ) @@ -167,7 +167,7 @@ func (m *HTTPMiddleware) Handler(h http.Handler) http.Handler { reqStart := time.Now() //nolint - ctx := context.WithValue(r.Context(), formatter.ExecutionContextKey, formatter.HTTPSource) + ctx := context.WithValue(r.Context(), hook.ExecutionContextKey, hook.HTTPSource) reqID := uuid.New().String() //nolint