mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-11 07:59:08 +02:00
[management] update proxy mappings on peer IP change (#8139)
This commit is contained in:
@@ -2706,6 +2706,8 @@ func (am *DefaultAccountManager) UpdatePeerIP(ctx context.Context, accountID, us
|
||||
}
|
||||
|
||||
if updateNetworkMap {
|
||||
am.reloadServicesTargetingPeer(ctx, accountID, peerID)
|
||||
|
||||
peer, err := am.Store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, peerID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -2720,6 +2722,19 @@ func (am *DefaultAccountManager) UpdatePeerIP(ctx context.Context, accountID, us
|
||||
return nil
|
||||
}
|
||||
|
||||
// reloadServicesTargetingPeer resends the account's reverse proxy services unless none of them targets the peer.
|
||||
func (am *DefaultAccountManager) reloadServicesTargetingPeer(ctx context.Context, accountID, peerID string) {
|
||||
serviceID, err := am.serviceManager.GetServiceIDByTargetID(ctx, accountID, peerID)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to look up services targeting peer %s, reloading all: %v", peerID, err)
|
||||
} else if serviceID == "" {
|
||||
return
|
||||
}
|
||||
if err := am.serviceManager.ReloadAllServicesForAccount(ctx, accountID); err != nil {
|
||||
log.WithContext(ctx).Warnf("failed to reload services for account %s: %v", accountID, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) updatePeerIPInTransaction(ctx context.Context, accountID, userID, peerID string, newIP netip.Addr) (bool, error) {
|
||||
var updateNetworkMap bool
|
||||
err := am.Store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
|
||||
@@ -3,6 +3,7 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -4460,6 +4461,86 @@ func TestDefaultAccountManager_UpdatePeerIP(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestDefaultAccountManager_UpdatePeerIP_ReloadsTargetingServices(t *testing.T) {
|
||||
manager, _, err := createManager(t)
|
||||
require.NoError(t, err, "unable to create account manager")
|
||||
|
||||
ctx := context.Background()
|
||||
accountID, err := manager.GetAccountIDByUserID(ctx, auth.UserAuth{UserId: userID})
|
||||
require.NoError(t, err, "unable to create an account")
|
||||
|
||||
key, err := wgtypes.GenerateKey()
|
||||
require.NoError(t, err, "unable to generate WireGuard key")
|
||||
peer, _, _, _, err := manager.AddPeer(ctx, "", "", userID, &nbpeer.Peer{
|
||||
Key: key.PublicKey().String(),
|
||||
Meta: nbpeer.PeerSystemMeta{Hostname: "proxied-peer"},
|
||||
}, false)
|
||||
require.NoError(t, err, "unable to add peer")
|
||||
|
||||
account, err := manager.Store.GetAccount(ctx, accountID)
|
||||
require.NoError(t, err, "unable to get account")
|
||||
network := netip.MustParsePrefix(account.Network.Net.String())
|
||||
|
||||
t.Run("targeted peer reloads services", func(t *testing.T) {
|
||||
serviceManager := service.NewMockManager(gomock.NewController(t))
|
||||
manager.SetServiceManager(serviceManager)
|
||||
serviceManager.EXPECT().GetServiceIDByTargetID(gomock.Any(), accountID, peer.ID).Return("svc-1", nil)
|
||||
serviceManager.EXPECT().ReloadAllServicesForAccount(gomock.Any(), accountID).Return(nil)
|
||||
|
||||
current, err := manager.Store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, peer.ID)
|
||||
require.NoError(t, err)
|
||||
newIP, err := types.AllocatePeerIP(network, []netip.Addr{current.IP})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, manager.UpdatePeerIP(ctx, accountID, userID, peer.ID, newIP))
|
||||
})
|
||||
|
||||
t.Run("untargeted peer skips reload", func(t *testing.T) {
|
||||
serviceManager := service.NewMockManager(gomock.NewController(t))
|
||||
manager.SetServiceManager(serviceManager)
|
||||
serviceManager.EXPECT().GetServiceIDByTargetID(gomock.Any(), accountID, peer.ID).Return("", nil)
|
||||
|
||||
current, err := manager.Store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, peer.ID)
|
||||
require.NoError(t, err)
|
||||
newIP, err := types.AllocatePeerIP(network, []netip.Addr{current.IP})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, manager.UpdatePeerIP(ctx, accountID, userID, peer.ID, newIP))
|
||||
})
|
||||
|
||||
t.Run("lookup failure reloads services", func(t *testing.T) {
|
||||
serviceManager := service.NewMockManager(gomock.NewController(t))
|
||||
manager.SetServiceManager(serviceManager)
|
||||
serviceManager.EXPECT().GetServiceIDByTargetID(gomock.Any(), accountID, peer.ID).Return("", errors.New("store unavailable"))
|
||||
serviceManager.EXPECT().ReloadAllServicesForAccount(gomock.Any(), accountID).Return(nil)
|
||||
|
||||
current, err := manager.Store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, peer.ID)
|
||||
require.NoError(t, err)
|
||||
newIP, err := types.AllocatePeerIP(network, []netip.Addr{current.IP})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, manager.UpdatePeerIP(ctx, accountID, userID, peer.ID, newIP))
|
||||
})
|
||||
|
||||
t.Run("network map notification failure still reloads services", func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
serviceManager := service.NewMockManager(ctrl)
|
||||
manager.SetServiceManager(serviceManager)
|
||||
serviceManager.EXPECT().GetServiceIDByTargetID(gomock.Any(), accountID, peer.ID).Return("svc-1", nil)
|
||||
serviceManager.EXPECT().ReloadAllServicesForAccount(gomock.Any(), accountID).Return(nil)
|
||||
|
||||
originalController := manager.networkMapController
|
||||
t.Cleanup(func() { manager.networkMapController = originalController })
|
||||
networkMapController := network_map.NewMockController(ctrl)
|
||||
networkMapController.EXPECT().GetDNSDomain(gomock.Any()).Return("netbird.cloud").AnyTimes()
|
||||
networkMapController.EXPECT().OnPeersUpdated(gomock.Any(), accountID, []string{peer.ID}, gomock.Any()).Return(errors.New("notify failed"))
|
||||
manager.networkMapController = networkMapController
|
||||
|
||||
current, err := manager.Store.GetPeerByID(ctx, store.LockingStrengthNone, accountID, peer.ID)
|
||||
require.NoError(t, err)
|
||||
newIP, err := types.AllocatePeerIP(network, []netip.Addr{current.IP})
|
||||
require.NoError(t, err)
|
||||
require.Error(t, manager.UpdatePeerIP(ctx, accountID, userID, peer.ID, newIP))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddNewUserToDomainAccountWithApproval(t *testing.T) {
|
||||
manager, _, err := createManager(t)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user