mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-09 15:09:08 +02:00
hookup network map store
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map"
|
"github.com/netbirdio/netbird/management/internals/controllers/network_map"
|
||||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller/cache"
|
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller/cache"
|
||||||
"github.com/netbirdio/netbird/management/internals/modules/peers/ephemeral"
|
"github.com/netbirdio/netbird/management/internals/modules/peers/ephemeral"
|
||||||
|
networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db"
|
||||||
"github.com/netbirdio/netbird/management/internals/server/config"
|
"github.com/netbirdio/netbird/management/internals/server/config"
|
||||||
"github.com/netbirdio/netbird/management/internals/shared/grpc"
|
"github.com/netbirdio/netbird/management/internals/shared/grpc"
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
@@ -30,6 +31,8 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
sharedgrpc "github.com/netbirdio/netbird/shared/management/grpc"
|
sharedgrpc "github.com/netbirdio/netbird/shared/management/grpc"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/networkmap"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
|
||||||
"github.com/netbirdio/netbird/shared/management/proto"
|
"github.com/netbirdio/netbird/shared/management/proto"
|
||||||
"github.com/netbirdio/netbird/shared/management/status"
|
"github.com/netbirdio/netbird/shared/management/status"
|
||||||
"github.com/netbirdio/netbird/util"
|
"github.com/netbirdio/netbird/util"
|
||||||
@@ -61,6 +64,8 @@ type Controller struct {
|
|||||||
serverSupportedSyncMessageVersion sharedgrpc.SyncMessageVersion
|
serverSupportedSyncMessageVersion sharedgrpc.SyncMessageVersion
|
||||||
|
|
||||||
perAccountServerSupportedSyncMessageVersions map[string]sharedgrpc.SyncMessageVersion
|
perAccountServerSupportedSyncMessageVersions map[string]sharedgrpc.SyncMessageVersion
|
||||||
|
|
||||||
|
nmdataStore networkmapdb.NetworkMapDBStore
|
||||||
}
|
}
|
||||||
|
|
||||||
type bufferUpdate struct {
|
type bufferUpdate struct {
|
||||||
@@ -78,7 +83,7 @@ type bufferAffectedUpdate struct {
|
|||||||
|
|
||||||
var _ network_map.Controller = (*Controller)(nil)
|
var _ network_map.Controller = (*Controller)(nil)
|
||||||
|
|
||||||
func NewController(ctx context.Context, store store.Store, metrics telemetry.AppMetrics, peersUpdateManager network_map.PeersUpdateManager, requestBuffer account.RequestBuffer, integratedPeerValidator integrated_validator.IntegratedValidator, settingsManager settings.Manager, dnsDomain string, proxyController port_forwarding.Controller, ephemeralPeersManager ephemeral.Manager, config *config.Config) *Controller {
|
func NewController(ctx context.Context, store store.Store, metrics telemetry.AppMetrics, peersUpdateManager network_map.PeersUpdateManager, requestBuffer account.RequestBuffer, integratedPeerValidator integrated_validator.IntegratedValidator, settingsManager settings.Manager, dnsDomain string, proxyController port_forwarding.Controller, ephemeralPeersManager ephemeral.Manager, config *config.Config, nmdataStore networkmapdb.NetworkMapDBStore) *Controller {
|
||||||
nMetrics, err := newMetrics(metrics.UpdateChannelMetrics())
|
nMetrics, err := newMetrics(metrics.UpdateChannelMetrics())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(fmt.Errorf("error creating metrics: %w", err))
|
log.Fatal(fmt.Errorf("error creating metrics: %w", err))
|
||||||
@@ -99,6 +104,7 @@ func NewController(ctx context.Context, store store.Store, metrics telemetry.App
|
|||||||
EphemeralPeersManager: ephemeralPeersManager,
|
EphemeralPeersManager: ephemeralPeersManager,
|
||||||
serverSupportedSyncMessageVersion: sharedgrpc.SyncMessageVersionFromConfig(config.HighestSupportedSyncMessageVersion),
|
serverSupportedSyncMessageVersion: sharedgrpc.SyncMessageVersionFromConfig(config.HighestSupportedSyncMessageVersion),
|
||||||
perAccountServerSupportedSyncMessageVersions: sharedgrpc.SyncMessageVersionsFromMap(config.PerAccountHighestSupportedSyncMessageVersion),
|
perAccountServerSupportedSyncMessageVersions: sharedgrpc.SyncMessageVersionsFromMap(config.PerAccountHighestSupportedSyncMessageVersion),
|
||||||
|
nmdataStore: nmdataStore,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +153,11 @@ func (c *Controller) CountStreams() int {
|
|||||||
|
|
||||||
func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID string, reason types.UpdateReason) error {
|
func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID string, reason types.UpdateReason) error {
|
||||||
log.WithContext(ctx).Tracef("updating peers for account %s from %s", accountID, util.GetCallerName())
|
log.WithContext(ctx).Tracef("updating peers for account %s from %s", accountID, util.GetCallerName())
|
||||||
|
|
||||||
|
if nmData := c.getNetworkMapData(ctx, accountID); nmData != nil {
|
||||||
|
return c.sendUpdateAccountPeersFromData(ctx, accountID, reason, nmData)
|
||||||
|
}
|
||||||
|
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get account: %v", err)
|
return fmt.Errorf("failed to get account: %v", err)
|
||||||
@@ -254,7 +265,7 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
|
|||||||
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
||||||
// the client merges it into Calculate()'s output the same
|
// the client merges it into Calculate()'s output the same
|
||||||
// way the legacy server did via NetworkMap.Merge.
|
// way the legacy server did via NetworkMap.Merge.
|
||||||
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, account.Settings, extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(p), nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, types.TwinAccountSettings(account.Settings), extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
c.metrics.CountToComponentSyncResponseDuration(time.Since(start))
|
c.metrics.CountToComponentSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
@@ -275,7 +286,7 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, nmap, dnsDomain, postureChecks, dnsCache, account.Settings, extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(p), nil, nil, nmap, dnsDomain, postureChecks, dnsCache, types.TwinAccountSettings(account.Settings), extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
c.metrics.CountToSyncResponseDuration(time.Since(start))
|
c.metrics.CountToSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
@@ -293,6 +304,247 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendUpdateAccountPeersFromData is the account-free variant of
|
||||||
|
// sendUpdateAccountPeers: everything is computed from the network-map DB
|
||||||
|
// store's twin data; only extra settings and validated peers are resolved at
|
||||||
|
// runtime. Proxy network maps and policy injection, private-service zones,
|
||||||
|
// group-to-user SSH mappings and forced routing-peer DNS resolution have no
|
||||||
|
// DB-backed source yet and are omitted.
|
||||||
|
func (c *Controller) sendUpdateAccountPeersFromData(ctx context.Context, accountID string, reason types.UpdateReason, nmData *networkmap.NetworkMapData) error {
|
||||||
|
peersToUpdate := c.connectedPeersFromData(nmData, nil)
|
||||||
|
if len(peersToUpdate) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.sendUpdatesFromData(ctx, accountID, nmData, peersToUpdate, &reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendUpdateForAffectedPeersFromData is the account-free variant of
|
||||||
|
// sendUpdateForAffectedPeers.
|
||||||
|
func (c *Controller) sendUpdateForAffectedPeersFromData(ctx context.Context, accountID string, peerIDs []string, nmData *networkmap.NetworkMapData) error {
|
||||||
|
affected := make(map[string]struct{}, len(peerIDs))
|
||||||
|
for _, id := range peerIDs {
|
||||||
|
affected[id] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
peersToUpdate := c.connectedPeersFromData(nmData, affected)
|
||||||
|
if len(peersToUpdate) == 0 {
|
||||||
|
log.WithContext(ctx).Tracef("sendUpdateForAffectedPeersFromData: no peers to update (affected peers not found in data or no channels)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WithContext(ctx).Tracef("sendUpdateForAffectedPeersFromData: sending network map to %d connected peers", len(peersToUpdate))
|
||||||
|
|
||||||
|
return c.sendUpdatesFromData(ctx, accountID, nmData, peersToUpdate, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) connectedPeersFromData(nmData *networkmap.NetworkMapData, affected map[string]struct{}) []*nmdata.Peer {
|
||||||
|
var result []*nmdata.Peer
|
||||||
|
for _, peer := range nmData.Peers {
|
||||||
|
if affected != nil {
|
||||||
|
if _, ok := affected[peer.ID]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.peersUpdateManager.HasChannel(peer.ID) {
|
||||||
|
result = append(result, peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) sendUpdatesFromData(ctx context.Context, accountID string, nmData *networkmap.NetworkMapData, peersToUpdate []*nmdata.Peer, reason *types.UpdateReason) error {
|
||||||
|
globalStart := time.Now()
|
||||||
|
|
||||||
|
extraSettings, err := c.settingsManager.GetExtraSettings(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get flow enabled status: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsCache := &cache.DNSConfigCache{}
|
||||||
|
dnsDomain := c.getDNSDomainFromData(nmData.AccountSettings)
|
||||||
|
peersCustomZone := networkmap.PeersCustomZone(ctx, accountID, dnsDomain, nmData.Peers, ipv6AllowedPeersFromData(nmData))
|
||||||
|
|
||||||
|
dnsFwdPort := computeForwarderPortFromData(nmData.Peers, network_map.DnsForwarderPortMinVersion)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
semaphore := make(chan struct{}, 10)
|
||||||
|
|
||||||
|
for _, peer := range peersToUpdate {
|
||||||
|
if reason != nil && c.accountManagerMetrics != nil {
|
||||||
|
c.accountManagerMetrics.CountNmapTriggered(string(reason.Resource), string(reason.Operation))
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
semaphore <- struct{}{}
|
||||||
|
go func(p *nmdata.Peer) {
|
||||||
|
defer wg.Done()
|
||||||
|
defer func() { <-semaphore }()
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
postureChecks := peerPostureChecksFromData(nmData, p.ID)
|
||||||
|
|
||||||
|
c.metrics.CountCalcPostureChecksDuration(time.Since(start))
|
||||||
|
start = time.Now()
|
||||||
|
|
||||||
|
peerGroups := maps.Keys(nmData.GetPeerGroups(p.ID))
|
||||||
|
var update *proto.SyncResponse
|
||||||
|
|
||||||
|
commonSyncMessageVersion := sharedgrpc.HighestCommonSyncMessageVersion(
|
||||||
|
c.perAccountOrGlobalSupportedSyncMessageVersions(accountID),
|
||||||
|
sharedgrpc.SyncMessageVersionFromConfig(&p.Meta.SyncMessageVersion))
|
||||||
|
|
||||||
|
log.WithContext(ctx).
|
||||||
|
WithFields(log.Fields{
|
||||||
|
"sync_message_version": commonSyncMessageVersion,
|
||||||
|
"server_sync_message_version": c.perAccountOrGlobalSupportedSyncMessageVersions(accountID),
|
||||||
|
"peer_sync_message_version": sharedgrpc.SyncMessageVersionFromConfig(&p.Meta.SyncMessageVersion),
|
||||||
|
}).Debug("common highest sync message version")
|
||||||
|
|
||||||
|
if commonSyncMessageVersion == sharedgrpc.ComponentNetworkMap {
|
||||||
|
components := nmData.GetPeerNetworkMapComponents(p.ID, peersCustomZone)
|
||||||
|
|
||||||
|
c.metrics.CountCalcPeerNetworkMapDuration(time.Since(start))
|
||||||
|
|
||||||
|
start = time.Now()
|
||||||
|
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, components, nil, dnsDomain, postureChecks, nmData.AccountSettings, extraSettings, peerGroups, dnsFwdPort)
|
||||||
|
c.metrics.CountToComponentSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
|
Update: update,
|
||||||
|
MessageType: network_map.MessageTypeNetworkMap,
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nmap := networkMapFromData(ctx, nmData, p.ID, peersCustomZone)
|
||||||
|
|
||||||
|
c.metrics.CountCalcPeerNetworkMapDuration(time.Since(start))
|
||||||
|
|
||||||
|
start = time.Now()
|
||||||
|
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, nmap, dnsDomain, postureChecks, dnsCache, nmData.AccountSettings, extraSettings, peerGroups, dnsFwdPort)
|
||||||
|
c.metrics.CountToSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
|
Update: update,
|
||||||
|
MessageType: network_map.MessageTypeNetworkMap,
|
||||||
|
})
|
||||||
|
}(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
if c.accountManagerMetrics != nil {
|
||||||
|
c.accountManagerMetrics.CountUpdateAccountPeersDuration(time.Since(globalStart))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) getNetworkMapData(ctx context.Context, accountID string) *networkmap.NetworkMapData {
|
||||||
|
if c.nmdataStore == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nmData, err := c.nmdataStore.GetNetworkMapData(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
log.WithContext(ctx).Errorf("failed to get network map data for account %s, falling back to account-based computation: %v", accountID, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nmData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) getDNSDomainFromData(settings *nmdata.AccountSettingsInfo) string {
|
||||||
|
if settings == nil || settings.DNSDomain == "" {
|
||||||
|
return c.dnsDomain
|
||||||
|
}
|
||||||
|
return settings.DNSDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipv6AllowedPeersFromData(nmData *networkmap.NetworkMapData) map[string]struct{} {
|
||||||
|
result := make(map[string]struct{})
|
||||||
|
if nmData.AccountSettings != nil {
|
||||||
|
for _, groupID := range nmData.AccountSettings.IPv6EnabledGroups {
|
||||||
|
group := nmData.Groups[groupID]
|
||||||
|
if group == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, peerID := range group.Peers {
|
||||||
|
result[peerID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for id, p := range nmData.Peers {
|
||||||
|
if p != nil && p.ProxyMeta.Embedded {
|
||||||
|
result[id] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func networkMapFromData(ctx context.Context, nmData *networkmap.NetworkMapData, peerID string, peersCustomZone nmdata.CustomZone) *types.NetworkMap {
|
||||||
|
components := nmData.GetPeerNetworkMapComponents(peerID, peersCustomZone)
|
||||||
|
if components.IsEmpty() {
|
||||||
|
return &types.NetworkMap{Network: components.Network}
|
||||||
|
}
|
||||||
|
return types.CalculateNetworkMapFromComponents(ctx, components)
|
||||||
|
}
|
||||||
|
|
||||||
|
// peerPostureChecksFromData mirrors getPeerPostureChecks on the twin store. The
|
||||||
|
// sync response only encodes process-check file paths, so only ProcessCheck is
|
||||||
|
// converted back to the server posture type.
|
||||||
|
func peerPostureChecksFromData(nmData *networkmap.NetworkMapData, peerID string) []*posture.Checks {
|
||||||
|
if len(nmData.PostureChecks) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
peerPostureChecks := make(map[string]*posture.Checks)
|
||||||
|
for _, policy := range nmData.Policies {
|
||||||
|
if policy == nil || !policy.Enabled || len(policy.SourcePostureChecks) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !isPeerInPolicySourceGroupsFromData(nmData, peerID, policy) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, checkID := range policy.SourcePostureChecks {
|
||||||
|
twin := nmData.PostureChecks[checkID]
|
||||||
|
if twin == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
peerPostureChecks[checkID] = postureChecksFromTwin(twin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maps.Values(peerPostureChecks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPeerInPolicySourceGroupsFromData(nmData *networkmap.NetworkMapData, peerID string, policy *nmdata.Policy) bool {
|
||||||
|
for _, rule := range policy.Rules {
|
||||||
|
if rule == nil || !rule.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, groupID := range rule.Sources {
|
||||||
|
if group := nmData.Groups[groupID]; group != nil && slices.Contains(group.Peers, peerID) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func postureChecksFromTwin(twin *nmdata.PostureChecks) *posture.Checks {
|
||||||
|
checks := &posture.Checks{ID: twin.ID}
|
||||||
|
if twin.Checks.ProcessCheck != nil {
|
||||||
|
processes := make([]posture.Process, 0, len(twin.Checks.ProcessCheck.Processes))
|
||||||
|
for _, p := range twin.Checks.ProcessCheck.Processes {
|
||||||
|
processes = append(processes, posture.Process{LinuxPath: p.LinuxPath, MacPath: p.MacPath, WindowsPath: p.WindowsPath})
|
||||||
|
}
|
||||||
|
checks.Checks.ProcessCheck = &posture.ProcessCheck{Processes: processes}
|
||||||
|
}
|
||||||
|
return checks
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) perAccountOrGlobalSupportedSyncMessageVersions(accountId string) sharedgrpc.SyncMessageVersion {
|
func (c *Controller) perAccountOrGlobalSupportedSyncMessageVersions(accountId string) sharedgrpc.SyncMessageVersion {
|
||||||
if perAccount, ok := c.perAccountServerSupportedSyncMessageVersions[accountId]; ok {
|
if perAccount, ok := c.perAccountServerSupportedSyncMessageVersions[accountId]; ok {
|
||||||
return perAccount
|
return perAccount
|
||||||
@@ -325,6 +577,10 @@ func (c *Controller) sendUpdateForAffectedPeers(ctx context.Context, accountID s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nmData := c.getNetworkMapData(ctx, accountID); nmData != nil {
|
||||||
|
return c.sendUpdateForAffectedPeersFromData(ctx, accountID, peerIDs, nmData)
|
||||||
|
}
|
||||||
|
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get account: %v", err)
|
return fmt.Errorf("failed to get account: %v", err)
|
||||||
@@ -426,7 +682,7 @@ func (c *Controller) sendUpdateForAffectedPeers(ctx context.Context, accountID s
|
|||||||
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
||||||
// the client merges it into Calculate()'s output the same
|
// the client merges it into Calculate()'s output the same
|
||||||
// way the legacy server did via NetworkMap.Merge.
|
// way the legacy server did via NetworkMap.Merge.
|
||||||
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, account.Settings, extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(p), nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, types.TwinAccountSettings(account.Settings), extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
c.metrics.CountToComponentSyncResponseDuration(time.Since(start))
|
c.metrics.CountToComponentSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
@@ -447,7 +703,7 @@ func (c *Controller) sendUpdateForAffectedPeers(ctx context.Context, accountID s
|
|||||||
}
|
}
|
||||||
|
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, p, nil, nil, nmap, dnsDomain, postureChecks, dnsCache, account.Settings, extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(p), nil, nil, nmap, dnsDomain, postureChecks, dnsCache, types.TwinAccountSettings(account.Settings), extraSetting, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
c.metrics.CountToSyncResponseDuration(time.Since(start))
|
c.metrics.CountToSyncResponseDuration(time.Since(start))
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, p.ID, &network_map.UpdateMessage{
|
||||||
@@ -564,7 +820,7 @@ func (c *Controller) UpdateAccountPeer(ctx context.Context, accountId string, pe
|
|||||||
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
// proxyNetworkMap rides the envelope as a ProxyPatch sidecar;
|
||||||
// the client merges it into Calculate()'s output the same
|
// the client merges it into Calculate()'s output the same
|
||||||
// way the legacy server did via NetworkMap.Merge.
|
// way the legacy server did via NetworkMap.Merge.
|
||||||
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, peer, nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, account.Settings, extraSettings, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToComponentSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(peer), nil, nil, components, proxyNetworkMap, dnsDomain, postureChecks, types.TwinAccountSettings(account.Settings), extraSettings, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, peer.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, peer.ID, &network_map.UpdateMessage{
|
||||||
Update: update,
|
Update: update,
|
||||||
@@ -581,7 +837,7 @@ func (c *Controller) UpdateAccountPeer(ctx context.Context, accountId string, pe
|
|||||||
nmap.Merge(proxyNetworkMap)
|
nmap.Merge(proxyNetworkMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, peer, nil, nil, nmap, dnsDomain, postureChecks, dnsCache, account.Settings, extraSettings, maps.Keys(peerGroups), dnsFwdPort)
|
update = grpc.ToSyncResponse(ctx, nil, c.config.HttpConfig, c.config.DeviceAuthorizationFlow, types.TwinPeer(peer), nil, nil, nmap, dnsDomain, postureChecks, dnsCache, types.TwinAccountSettings(account.Settings), extraSettings, maps.Keys(peerGroups), dnsFwdPort)
|
||||||
|
|
||||||
c.peersUpdateManager.SendUpdate(ctx, peer.ID, &network_map.UpdateMessage{
|
c.peersUpdateManager.SendUpdate(ctx, peer.ID, &network_map.UpdateMessage{
|
||||||
Update: update,
|
Update: update,
|
||||||
@@ -908,20 +1164,36 @@ func (c *Controller) StartWarmup(ctx context.Context) {
|
|||||||
// computeForwarderPort checks if all peers in the account have updated to a specific version or newer.
|
// computeForwarderPort checks if all peers in the account have updated to a specific version or newer.
|
||||||
// If all peers have the required version, it returns the new well-known port (22054), otherwise returns 0.
|
// If all peers have the required version, it returns the new well-known port (22054), otherwise returns 0.
|
||||||
func computeForwarderPort(peers []*nbpeer.Peer, requiredVersion string) int64 {
|
func computeForwarderPort(peers []*nbpeer.Peer, requiredVersion string) int64 {
|
||||||
if len(peers) == 0 {
|
versions := make([]string, 0, len(peers))
|
||||||
|
for _, peer := range peers {
|
||||||
|
versions = append(versions, peer.Meta.WtVersion)
|
||||||
|
}
|
||||||
|
return computeForwarderPortFromVersions(versions, requiredVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeForwarderPortFromData(peers map[string]*nmdata.Peer, requiredVersion string) int64 {
|
||||||
|
versions := make([]string, 0, len(peers))
|
||||||
|
for _, peer := range peers {
|
||||||
|
versions = append(versions, peer.Meta.WtVersion)
|
||||||
|
}
|
||||||
|
return computeForwarderPortFromVersions(versions, requiredVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeForwarderPortFromVersions(wtVersions []string, requiredVersion string) int64 {
|
||||||
|
if len(wtVersions) == 0 {
|
||||||
return int64(network_map.OldForwarderPort)
|
return int64(network_map.OldForwarderPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqVer := semver.Canonical(requiredVersion)
|
reqVer := semver.Canonical(requiredVersion)
|
||||||
|
|
||||||
// Check if all peers have the required version or newer
|
// Check if all peers have the required version or newer
|
||||||
for _, peer := range peers {
|
for _, wtVersion := range wtVersions {
|
||||||
|
|
||||||
// Development version is always supported
|
// Development version is always supported
|
||||||
if version.IsDevelopmentVersion(peer.Meta.WtVersion) {
|
if version.IsDevelopmentVersion(wtVersion) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
peerVersion := semver.Canonical("v" + peer.Meta.WtVersion)
|
peerVersion := semver.Canonical("v" + wtVersion)
|
||||||
if peerVersion == "" {
|
if peerVersion == "" {
|
||||||
// If any peer doesn't have version info, return 0
|
// If any peer doesn't have version info, return 0
|
||||||
return int64(network_map.OldForwarderPort)
|
return int64(network_map.OldForwarderPort)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package networkmap_pgsql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
@@ -14,7 +15,14 @@ const (
|
|||||||
select settings_peer_login_expiration_enabled as peer_login_expiration_enabled,
|
select settings_peer_login_expiration_enabled as peer_login_expiration_enabled,
|
||||||
settings_peer_login_expiration as peer_login_expiration,
|
settings_peer_login_expiration as peer_login_expiration,
|
||||||
settings_peer_inactivity_expiration_enabled as peer_inactivity_expiration_enabled,
|
settings_peer_inactivity_expiration_enabled as peer_inactivity_expiration_enabled,
|
||||||
settings_peer_inactivity_expiration as peer_inactivity_expiration
|
settings_peer_inactivity_expiration as peer_inactivity_expiration,
|
||||||
|
settings_dns_domain as dns_domain,
|
||||||
|
settings_ipv6_enabled_groups as ipv6_enabled_groups,
|
||||||
|
settings_routing_peer_dns_resolution_enabled as routing_peer_dns_resolution_enabled,
|
||||||
|
settings_lazy_connection_enabled as lazy_connection_enabled,
|
||||||
|
settings_auto_update_version as auto_update_version,
|
||||||
|
settings_auto_update_always as auto_update_always,
|
||||||
|
settings_metrics_push_enabled as metrics_push_enabled
|
||||||
from accounts
|
from accounts
|
||||||
where id=$1
|
where id=$1
|
||||||
`
|
`
|
||||||
@@ -40,12 +48,25 @@ func GetAccountSettingsViaPgxConnection(ctx context.Context, con *pgx.Conn, acco
|
|||||||
return nmdata.AccountSettingsInfo{}, err
|
return nmdata.AccountSettingsInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nmdata.AccountSettingsInfo{
|
settingsInfo := nmdata.AccountSettingsInfo{
|
||||||
PeerLoginExpirationEnabled: settings.PeerLoginExpirationEnabled.Bool,
|
PeerLoginExpirationEnabled: settings.PeerLoginExpirationEnabled.Bool,
|
||||||
PeerLoginExpiration: time.Duration(settings.PeerLoginExpiration.Int64),
|
PeerLoginExpiration: time.Duration(settings.PeerLoginExpiration.Int64),
|
||||||
PeerInactivityExpirationEnabled: settings.PeerLoginExpirationEnabled.Bool,
|
PeerInactivityExpirationEnabled: settings.PeerInactivityExpirationEnabled.Bool,
|
||||||
PeerInactivityExpiration: time.Duration(settings.PeerInactivityExpiration.Int64),
|
PeerInactivityExpiration: time.Duration(settings.PeerInactivityExpiration.Int64),
|
||||||
}, nil
|
DNSDomain: settings.DNSDomain.String,
|
||||||
|
RoutingPeerDNSResolutionEnabled: settings.RoutingPeerDNSResolutionEnabled.Bool,
|
||||||
|
LazyConnectionEnabled: settings.LazyConnectionEnabled.Bool,
|
||||||
|
AutoUpdateVersion: settings.AutoUpdateVersion.String,
|
||||||
|
AutoUpdateAlways: settings.AutoUpdateAlways.Bool,
|
||||||
|
MetricsPushEnabled: settings.MetricsPushEnabled.Bool,
|
||||||
|
}
|
||||||
|
if settings.IPv6EnabledGroups != nil {
|
||||||
|
if err := json.Unmarshal(settings.IPv6EnabledGroups, &settingsInfo.IPv6EnabledGroups); err != nil {
|
||||||
|
return nmdata.AccountSettingsInfo{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return settingsInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type account struct {
|
type account struct {
|
||||||
@@ -53,4 +74,11 @@ type account struct {
|
|||||||
PeerLoginExpiration sql.NullInt64
|
PeerLoginExpiration sql.NullInt64
|
||||||
PeerInactivityExpirationEnabled sql.NullBool
|
PeerInactivityExpirationEnabled sql.NullBool
|
||||||
PeerInactivityExpiration sql.NullInt64
|
PeerInactivityExpiration sql.NullInt64
|
||||||
|
DNSDomain sql.NullString
|
||||||
|
IPv6EnabledGroups json.RawMessage
|
||||||
|
RoutingPeerDNSResolutionEnabled sql.NullBool
|
||||||
|
LazyConnectionEnabled sql.NullBool
|
||||||
|
AutoUpdateVersion sql.NullString
|
||||||
|
AutoUpdateAlways sql.NullBool
|
||||||
|
MetricsPushEnabled sql.NullBool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
GetPeersQuery = `
|
GetPeersQuery = `
|
||||||
select id, key, ssh_key, dns_label, user_id, ssh_enabled, login_expiration_enabled, last_login, ip, ipv6,
|
select id, key, ssh_key, dns_label, extra_dns_labels, user_id, ssh_enabled, login_expiration_enabled, last_login, ip, ipv6,
|
||||||
peer_status_requires_approval, proxy_meta_embedded, proxy_meta_cluster,
|
peer_status_requires_approval, proxy_meta_embedded, proxy_meta_cluster,
|
||||||
meta_wt_version, meta_go_os, meta_os_version, meta_kernel_version, meta_network_addresses, meta_files, meta_capabilities, meta_flags,
|
meta_wt_version, meta_go_os, meta_os_version, meta_kernel_version, meta_network_addresses, meta_files, meta_capabilities, meta_flags, meta_sync_message_version,
|
||||||
location_country_code, location_city_name, location_connection_ip
|
location_country_code, location_city_name, location_connection_ip
|
||||||
from peers
|
from peers
|
||||||
where account_id = $1
|
where account_id = $1
|
||||||
@@ -60,6 +60,9 @@ func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId stri
|
|||||||
if p.MetaWtVersion.Valid {
|
if p.MetaWtVersion.Valid {
|
||||||
dp.Meta.WtVersion = p.MetaWtVersion.String
|
dp.Meta.WtVersion = p.MetaWtVersion.String
|
||||||
}
|
}
|
||||||
|
if p.MetaSyncMessageVersion.Valid {
|
||||||
|
dp.Meta.SyncMessageVersion = int(p.MetaSyncMessageVersion.Int64)
|
||||||
|
}
|
||||||
if p.MetaGoOS.Valid {
|
if p.MetaGoOS.Valid {
|
||||||
dp.Meta.GoOS = p.MetaGoOS.String
|
dp.Meta.GoOS = p.MetaGoOS.String
|
||||||
}
|
}
|
||||||
@@ -105,6 +108,8 @@ func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId stri
|
|||||||
return toret, nil, err
|
return toret, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toret = append(toret, dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toret, clusterToPeerIdx, nil
|
return toret, clusterToPeerIdx, nil
|
||||||
@@ -116,6 +121,7 @@ type peer struct {
|
|||||||
Key sql.NullString
|
Key sql.NullString
|
||||||
SSHKey sql.NullString
|
SSHKey sql.NullString
|
||||||
DNSLabel sql.NullString
|
DNSLabel sql.NullString
|
||||||
|
ExtraDNSLabels json.RawMessage
|
||||||
UserID sql.NullString
|
UserID sql.NullString
|
||||||
LastLogin sql.NullTime
|
LastLogin sql.NullTime
|
||||||
SSHEnabled sql.NullBool
|
SSHEnabled sql.NullBool
|
||||||
@@ -134,6 +140,7 @@ type peer struct {
|
|||||||
MetaGoOS sql.NullString `nmap:"skip"`
|
MetaGoOS sql.NullString `nmap:"skip"`
|
||||||
MetaOSVersion sql.NullString `nmap:"skip"`
|
MetaOSVersion sql.NullString `nmap:"skip"`
|
||||||
MetaKernelVersion sql.NullString `nmap:"skip"`
|
MetaKernelVersion sql.NullString `nmap:"skip"`
|
||||||
|
MetaSyncMessageVersion sql.NullInt64 `nmap:"skip"`
|
||||||
LocationCountryCode sql.NullString `nmap:"skip"`
|
LocationCountryCode sql.NullString `nmap:"skip"`
|
||||||
LocationCityName sql.NullString `nmap:"skip"`
|
LocationCityName sql.NullString `nmap:"skip"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -24,13 +25,15 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/encryption"
|
"github.com/netbirdio/netbird/encryption"
|
||||||
"github.com/netbirdio/netbird/formatter/hook"
|
"github.com/netbirdio/netbird/formatter/hook"
|
||||||
|
"github.com/netbirdio/netbird/management/internals/modules/agentnetwork"
|
||||||
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs"
|
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs"
|
||||||
accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager"
|
accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager"
|
||||||
rpservice "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/service"
|
rpservice "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/service"
|
||||||
|
networkmapdb "github.com/netbirdio/netbird/management/internals/network_map_db"
|
||||||
|
networkmap_pgsql "github.com/netbirdio/netbird/management/internals/network_map_db/pgsql"
|
||||||
nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
|
nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
activitystore "github.com/netbirdio/netbird/management/server/activity/store"
|
activitystore "github.com/netbirdio/netbird/management/server/activity/store"
|
||||||
"github.com/netbirdio/netbird/management/internals/modules/agentnetwork"
|
|
||||||
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
nbcache "github.com/netbirdio/netbird/management/server/cache"
|
||||||
nbContext "github.com/netbirdio/netbird/management/server/context"
|
nbContext "github.com/netbirdio/netbird/management/server/context"
|
||||||
nbhttp "github.com/netbirdio/netbird/management/server/http"
|
nbhttp "github.com/netbirdio/netbird/management/server/http"
|
||||||
@@ -99,6 +102,22 @@ func (s *BaseServer) Store() store.Store {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *BaseServer) NetworkMapStore() networkmapdb.NetworkMapDBStore {
|
||||||
|
return Create(s, func() networkmapdb.NetworkMapDBStore {
|
||||||
|
dsn := os.Getenv("NETBIRD_NMAP_STORE_DSN") // Todo: this needs to be hoocked up properly
|
||||||
|
if dsn == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
store, err := networkmap_pgsql.NewPostgresqlStore(context.Background(), dsn)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to create network map store: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return store
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *BaseServer) EventStore() activity.Store {
|
func (s *BaseServer) EventStore() activity.Store {
|
||||||
return Create(s, func() activity.Store {
|
return Create(s, func() activity.Store {
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ func (s *BaseServer) EphemeralManager() ephemeral.Manager {
|
|||||||
|
|
||||||
func (s *BaseServer) NetworkMapController() network_map.Controller {
|
func (s *BaseServer) NetworkMapController() network_map.Controller {
|
||||||
return Create(s, func() network_map.Controller {
|
return Create(s, func() network_map.Controller {
|
||||||
return nmapcontroller.NewController(context.Background(), s.Store(), s.Metrics(), s.PeersUpdateManager(), s.AccountRequestBuffer(), s.IntegratedValidator(), s.SettingsManager(), s.DNSDomain(), s.ProxyController(), s.EphemeralManager(), s.Config)
|
return nmapcontroller.NewController(context.Background(), s.Store(), s.Metrics(), s.PeersUpdateManager(), s.AccountRequestBuffer(), s.IntegratedValidator(), s.SettingsManager(), s.DNSDomain(), s.ProxyController(), s.EphemeralManager(), s.Config, s.NetworkMapStore())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/client/ssh/auth"
|
"github.com/netbirdio/netbird/client/ssh/auth"
|
||||||
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
sharedgrpc "github.com/netbirdio/netbird/shared/management/grpc"
|
sharedgrpc "github.com/netbirdio/netbird/shared/management/grpc"
|
||||||
@@ -32,14 +31,14 @@ func ToComponentSyncResponse(
|
|||||||
config *nbconfig.Config,
|
config *nbconfig.Config,
|
||||||
httpConfig *nbconfig.HttpServerConfig,
|
httpConfig *nbconfig.HttpServerConfig,
|
||||||
deviceFlowConfig *nbconfig.DeviceAuthorizationFlow,
|
deviceFlowConfig *nbconfig.DeviceAuthorizationFlow,
|
||||||
peer *nbpeer.Peer,
|
peer *nmdata.Peer,
|
||||||
turnCredentials *Token,
|
turnCredentials *Token,
|
||||||
relayCredentials *Token,
|
relayCredentials *Token,
|
||||||
components *types.NetworkMapComponents,
|
components *types.NetworkMapComponents,
|
||||||
proxyPatch *types.NetworkMap,
|
proxyPatch *types.NetworkMap,
|
||||||
dnsName string,
|
dnsName string,
|
||||||
checks []*posture.Checks,
|
checks []*posture.Checks,
|
||||||
settings *types.Settings,
|
settings *nmdata.AccountSettingsInfo,
|
||||||
extraSettings *types.ExtraSettings,
|
extraSettings *types.ExtraSettings,
|
||||||
peerGroups []string,
|
peerGroups []string,
|
||||||
dnsFwdPort int64,
|
dnsFwdPort int64,
|
||||||
@@ -146,7 +145,7 @@ func toProxyPatch(nm *types.NetworkMap, dnsName string, includeIPv6, useSourcePr
|
|||||||
//
|
//
|
||||||
// The full SSH AuthorizedUsers map is still produced by the client when it
|
// The full SSH AuthorizedUsers map is still produced by the client when it
|
||||||
// runs Calculate() over the envelope.
|
// runs Calculate() over the envelope.
|
||||||
func computeSSHEnabledForPeer(c *types.NetworkMapComponents, peer *nbpeer.Peer) bool {
|
func computeSSHEnabledForPeer(c *types.NetworkMapComponents, peer *nmdata.Peer) bool {
|
||||||
if c == nil || peer == nil {
|
if c == nil || peer == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -171,7 +170,7 @@ func computeSSHEnabledForPeer(c *types.NetworkMapComponents, peer *nbpeer.Peer)
|
|||||||
// ruleEnablesSSHForPeer returns true when rule is active, targets peer, and
|
// ruleEnablesSSHForPeer returns true when rule is active, targets peer, and
|
||||||
// either explicitly authorises SSH or covers the legacy TCP/22 path while the
|
// either explicitly authorises SSH or covers the legacy TCP/22 path while the
|
||||||
// peer itself has SSH enabled locally.
|
// peer itself has SSH enabled locally.
|
||||||
func ruleEnablesSSHForPeer(c *types.NetworkMapComponents, rule *nmdata.PolicyRule, peer *nbpeer.Peer) bool {
|
func ruleEnablesSSHForPeer(c *types.NetworkMapComponents, rule *nmdata.PolicyRule, peer *nmdata.Peer) bool {
|
||||||
if rule == nil || !rule.Enabled {
|
if rule == nil || !rule.Enabled {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
|
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
|
||||||
)
|
)
|
||||||
@@ -18,10 +17,10 @@ func TestComputeSSHEnabledForPeer(t *testing.T) {
|
|||||||
const targetPeerID = "target"
|
const targetPeerID = "target"
|
||||||
const targetGroupID = "g_dst"
|
const targetGroupID = "g_dst"
|
||||||
|
|
||||||
mkComponents := func(rule *nmdata.PolicyRule, sshEnabled bool) (*types.NetworkMapComponents, *nbpeer.Peer) {
|
mkComponents := func(rule *nmdata.PolicyRule, sshEnabled bool) (*types.NetworkMapComponents, *nmdata.Peer) {
|
||||||
peer := &nbpeer.Peer{ID: targetPeerID, SSHEnabled: sshEnabled}
|
peer := &nmdata.Peer{ID: targetPeerID, SSHEnabled: sshEnabled}
|
||||||
return &types.NetworkMapComponents{
|
return &types.NetworkMapComponents{
|
||||||
Peers: map[string]*nmdata.Peer{targetPeerID: types.TwinPeer(peer)},
|
Peers: map[string]*nmdata.Peer{targetPeerID: peer},
|
||||||
Groups: map[string]*nmdata.Group{targetGroupID: {Name: "dst", Peers: []string{targetPeerID}}},
|
Groups: map[string]*nmdata.Group{targetGroupID: {Name: "dst", Peers: []string{targetPeerID}}},
|
||||||
Policies: []*nmdata.Policy{{
|
Policies: []*nmdata.Policy{{
|
||||||
ID: "p",
|
ID: "p",
|
||||||
@@ -156,7 +155,7 @@ func TestComputeSSHEnabledForPeer(t *testing.T) {
|
|||||||
// belt-and-suspenders presence guard mirroring Calculate's
|
// belt-and-suspenders presence guard mirroring Calculate's
|
||||||
// getAllPeersFromGroups invariant.
|
// getAllPeersFromGroups invariant.
|
||||||
func TestComputeSSHEnabledForPeer_TargetMissingFromComponents(t *testing.T) {
|
func TestComputeSSHEnabledForPeer_TargetMissingFromComponents(t *testing.T) {
|
||||||
peer := &nbpeer.Peer{ID: "missing", SSHEnabled: true}
|
peer := &nmdata.Peer{ID: "missing", SSHEnabled: true}
|
||||||
c := &types.NetworkMapComponents{
|
c := &types.NetworkMapComponents{
|
||||||
Peers: map[string]*nmdata.Peer{}, // target peer NOT present
|
Peers: map[string]*nmdata.Peer{}, // target peer NOT present
|
||||||
Groups: map[string]*nmdata.Group{
|
Groups: map[string]*nmdata.Group{
|
||||||
@@ -179,6 +178,6 @@ func TestComputeSSHEnabledForPeer_TargetMissingFromComponents(t *testing.T) {
|
|||||||
// exported indirectly via ToComponentSyncResponse and may receive nil
|
// exported indirectly via ToComponentSyncResponse and may receive nil
|
||||||
// components on graceful-degrade paths.
|
// components on graceful-degrade paths.
|
||||||
func TestComputeSSHEnabledForPeer_NilInputs(t *testing.T) {
|
func TestComputeSSHEnabledForPeer_NilInputs(t *testing.T) {
|
||||||
assert.False(t, computeSSHEnabledForPeer(nil, &nbpeer.Peer{ID: "x"}))
|
assert.False(t, computeSSHEnabledForPeer(nil, &nmdata.Peer{ID: "x"}))
|
||||||
assert.False(t, computeSSHEnabledForPeer(&types.NetworkMapComponents{}, nil))
|
assert.False(t, computeSSHEnabledForPeer(&types.NetworkMapComponents{}, nil))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller/cache"
|
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller/cache"
|
||||||
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
"github.com/netbirdio/netbird/shared/management/networkmap"
|
"github.com/netbirdio/netbird/shared/management/networkmap"
|
||||||
@@ -48,7 +47,7 @@ func init() {
|
|||||||
// nil when no server config is set (the fan-out network-map path) because clients treat any
|
// nil when no server config is set (the fan-out network-map path) because clients treat any
|
||||||
// non-nil config as authoritative: a config without a relay section is interpreted as relay
|
// non-nil config as authoritative: a config without a relay section is interpreted as relay
|
||||||
// disabled and wipes the clients' relay URLs.
|
// disabled and wipes the clients' relay URLs.
|
||||||
func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken *Token, extraSettings *types.ExtraSettings, settings *types.Settings) *proto.NetbirdConfig {
|
func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken *Token, extraSettings *types.ExtraSettings, settings *nmdata.AccountSettingsInfo) *proto.NetbirdConfig {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -120,7 +119,7 @@ func toNetbirdConfig(config *nbconfig.Config, turnCredentials *Token, relayToken
|
|||||||
return nbConfig
|
return nbConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPeerConfig(peer *nbpeer.Peer, network *nmdata.Network, dnsName string, settings *types.Settings, httpConfig *nbconfig.HttpServerConfig, deviceFlowConfig *nbconfig.DeviceAuthorizationFlow, enableSSH bool, forceRoutingPeerDNS bool) *proto.PeerConfig {
|
func toPeerConfig(peer *nmdata.Peer, network *nmdata.Network, dnsName string, settings *nmdata.AccountSettingsInfo, httpConfig *nbconfig.HttpServerConfig, deviceFlowConfig *nbconfig.DeviceAuthorizationFlow, enableSSH bool, forceRoutingPeerDNS bool) *proto.PeerConfig {
|
||||||
netmask, _ := network.Net.Mask.Size()
|
netmask, _ := network.Net.Mask.Size()
|
||||||
fqdn := peer.FQDN(dnsName)
|
fqdn := peer.FQDN(dnsName)
|
||||||
|
|
||||||
@@ -155,7 +154,7 @@ func toPeerConfig(peer *nbpeer.Peer, network *nmdata.Network, dnsName string, se
|
|||||||
return peerConfig
|
return peerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToSyncResponse(ctx context.Context, config *nbconfig.Config, httpConfig *nbconfig.HttpServerConfig, deviceFlowConfig *nbconfig.DeviceAuthorizationFlow, peer *nbpeer.Peer, turnCredentials *Token, relayCredentials *Token, networkMap *types.NetworkMap, dnsName string, checks []*posture.Checks, dnsCache *cache.DNSConfigCache, settings *types.Settings, extraSettings *types.ExtraSettings, peerGroups []string, dnsFwdPort int64) *proto.SyncResponse {
|
func ToSyncResponse(ctx context.Context, config *nbconfig.Config, httpConfig *nbconfig.HttpServerConfig, deviceFlowConfig *nbconfig.DeviceAuthorizationFlow, peer *nmdata.Peer, turnCredentials *Token, relayCredentials *Token, networkMap *types.NetworkMap, dnsName string, checks []*posture.Checks, dnsCache *cache.DNSConfigCache, settings *nmdata.AccountSettingsInfo, extraSettings *types.ExtraSettings, peerGroups []string, dnsFwdPort int64) *proto.SyncResponse {
|
||||||
// IPv6 data in AllowedIPs and SourcePrefixes wildcard expansion depends on
|
// IPv6 data in AllowedIPs and SourcePrefixes wildcard expansion depends on
|
||||||
// whether the target peer supports IPv6. Routes and firewall rules are already
|
// whether the target peer supports IPv6. Routes and firewall rules are already
|
||||||
// filtered at the source (network map builder).
|
// filtered at the source (network map builder).
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ func TestToNetbirdConfig_RelayInvariant(t *testing.T) {
|
|||||||
settings := &types.Settings{MetricsPushEnabled: true}
|
settings := &types.Settings{MetricsPushEnabled: true}
|
||||||
|
|
||||||
t.Run("nil server config returns nil config", func(t *testing.T) {
|
t.Run("nil server config returns nil config", func(t *testing.T) {
|
||||||
nbCfg := toNetbirdConfig(nil, nil, nil, nil, settings)
|
nbCfg := toNetbirdConfig(nil, nil, nil, nil, types.TwinAccountSettings(settings))
|
||||||
assert.Nil(t, nbCfg, "fan-out updates must not carry a partial NetbirdConfig even when settings are present")
|
assert.Nil(t, nbCfg, "fan-out updates must not carry a partial NetbirdConfig even when settings are present")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ func TestToNetbirdConfig_RelayInvariant(t *testing.T) {
|
|||||||
}
|
}
|
||||||
relayToken := &Token{Payload: "token-payload", Signature: "token-signature"}
|
relayToken := &Token{Payload: "token-payload", Signature: "token-signature"}
|
||||||
|
|
||||||
nbCfg := toNetbirdConfig(cfg, nil, relayToken, nil, settings)
|
nbCfg := toNetbirdConfig(cfg, nil, relayToken, nil, types.TwinAccountSettings(settings))
|
||||||
require.NotNil(t, nbCfg)
|
require.NotNil(t, nbCfg)
|
||||||
require.NotNil(t, nbCfg.Relay, "non-nil NetbirdConfig must include the relay section")
|
require.NotNil(t, nbCfg.Relay, "non-nil NetbirdConfig must include the relay section")
|
||||||
assert.Equal(t, cfg.Relay.Addresses, nbCfg.Relay.Urls, "relay URLs should match the server config")
|
assert.Equal(t, cfg.Relay.Addresses, nbCfg.Relay.Urls, "relay URLs should match the server config")
|
||||||
|
|||||||
@@ -920,8 +920,8 @@ func (s *Server) prepareLoginResponse(ctx context.Context, peer *nbpeer.Peer, ne
|
|||||||
|
|
||||||
// if peer has reached this point then it has logged in
|
// if peer has reached this point then it has logged in
|
||||||
loginResp := &proto.LoginResponse{
|
loginResp := &proto.LoginResponse{
|
||||||
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken, nil, settings),
|
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken, nil, types.TwinAccountSettings(settings)),
|
||||||
PeerConfig: toPeerConfig(peer, types.TwinNetwork(network), s.networkMapController.GetDNSDomain(settings), settings, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, enableSSH, false),
|
PeerConfig: toPeerConfig(types.TwinPeer(peer), types.TwinNetwork(network), s.networkMapController.GetDNSDomain(settings), types.TwinAccountSettings(settings), s.config.HttpConfig, s.config.DeviceAuthorizationFlow, enableSSH, false),
|
||||||
Checks: toProtocolChecks(ctx, postureChecks),
|
Checks: toProtocolChecks(ctx, postureChecks),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,9 +1052,9 @@ func (s *Server) sendInitialSync(ctx context.Context, peerKey wgtypes.Key, peer
|
|||||||
log.WithContext(ctx).Errorf("failed to build components for peer %s on initial sync: %v", peer.ID, err)
|
log.WithContext(ctx).Errorf("failed to build components for peer %s on initial sync: %v", peer.ID, err)
|
||||||
return status.Errorf(codes.Internal, "failed to build initial sync envelope")
|
return status.Errorf(codes.Internal, "failed to build initial sync envelope")
|
||||||
}
|
}
|
||||||
plainResp = ToComponentSyncResponse(ctx, s.config, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, freshPeer, turnToken, relayToken, components, proxyPatch, dnsName, freshPostureChecks, settings, settings.Extra, peerGroups, freshDnsFwdPort)
|
plainResp = ToComponentSyncResponse(ctx, s.config, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, types.TwinPeer(freshPeer), turnToken, relayToken, components, proxyPatch, dnsName, freshPostureChecks, types.TwinAccountSettings(settings), settings.Extra, peerGroups, freshDnsFwdPort)
|
||||||
} else {
|
} else {
|
||||||
plainResp = ToSyncResponse(ctx, s.config, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, peer, turnToken, relayToken, networkMap, dnsName, postureChecks, nil, settings, settings.Extra, peerGroups, dnsFwdPort)
|
plainResp = ToSyncResponse(ctx, s.config, s.config.HttpConfig, s.config.DeviceAuthorizationFlow, types.TwinPeer(peer), turnToken, relayToken, networkMap, dnsName, postureChecks, nil, types.TwinAccountSettings(settings), settings.Extra, peerGroups, dnsFwdPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := s.secretsManager.GetWGKey()
|
key, err := s.secretsManager.GetWGKey()
|
||||||
|
|||||||
@@ -3330,7 +3330,7 @@ func createManager(t testing.TB) (*DefaultAccountManager, *update_channel.PeersU
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{}, nil)
|
||||||
manager, err := BuildManager(ctx, &config.Config{}, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
manager, err := BuildManager(ctx, &config.Config{}, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.test", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.test", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
return BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
return BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ func BuildApiBlackBoxWithDBState(t testing_tools.TB, sqlFile string, expectedPee
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestBuffer := server.NewAccountRequestBuffer(ctx, store)
|
requestBuffer := server.NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, peersUpdateManager, requestBuffer, server.MockIntegratedValidator{}, settingsManager, "", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManager), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, peersUpdateManager, requestBuffer, server.MockIntegratedValidator{}, settingsManager, "", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManager), &config.Config{}, nil)
|
||||||
am, err := server.BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false, cacheStore)
|
am, err := server.BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create manager: %v", err)
|
t.Fatalf("Failed to create manager: %v", err)
|
||||||
@@ -226,7 +226,7 @@ func BuildApiBlackBoxWithDBStateAndPeerChannel(t testing_tools.TB, sqlFile strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
requestBuffer := server.NewAccountRequestBuffer(ctx, store)
|
requestBuffer := server.NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, peersUpdateManager, requestBuffer, server.MockIntegratedValidator{}, settingsManager, "", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManager), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, peersUpdateManager, requestBuffer, server.MockIntegratedValidator{}, settingsManager, "", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManager), &config.Config{}, nil)
|
||||||
am, err := server.BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false, cacheStore)
|
am, err := server.BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager, permissionsManager, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create manager: %v", err)
|
t.Fatalf("Failed to create manager: %v", err)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func createManagerWithEmbeddedIdP(t testing.TB) (*DefaultAccountManager, *update
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, testStore)
|
requestBuffer := NewAccountRequestBuffer(ctx, testStore)
|
||||||
networkMapController := controller.NewController(ctx, testStore, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(testStore, peersManager), &config.Config{})
|
networkMapController := controller.NewController(ctx, testStore, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(testStore, peersManager), &config.Config{}, nil)
|
||||||
manager, err := BuildManager(ctx, &config.Config{}, testStore, networkMapController, job.NewJobManager(nil, testStore, peersManager), idpManager, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
manager, err := BuildManager(ctx, &config.Config{}, testStore, networkMapController, job.NewJobManager(nil, testStore, peersManager), idpManager, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ func startManagementForTest(t *testing.T, testFile string, config *config.Config
|
|||||||
return nil, nil, "", cleanup, err
|
return nil, nil, "", cleanup, err
|
||||||
}
|
}
|
||||||
|
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeralMgr, config)
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeralMgr, config, nil)
|
||||||
accountManager, err := BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "",
|
accountManager, err := BuildManager(ctx, nil, store, networkMapController, jobManager, nil, "",
|
||||||
eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ func startServer(
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := server.NewAccountRequestBuffer(ctx, str)
|
requestBuffer := server.NewAccountRequestBuffer(ctx, str)
|
||||||
networkMapController := controller.NewController(ctx, str, metrics, updateManager, requestBuffer, server.MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(str, peers.NewManager(str, permissionsManager)), config)
|
networkMapController := controller.NewController(ctx, str, metrics, updateManager, requestBuffer, server.MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(str, peers.NewManager(str, permissionsManager)), config, nil)
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(
|
accountManager, err := server.BuildManager(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
|
|||||||
@@ -803,7 +803,7 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
return BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
return BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1181,7 +1181,7 @@ func TestToSyncResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
dnsCache := &cache.DNSConfigCache{}
|
dnsCache := &cache.DNSConfigCache{}
|
||||||
accountSettings := &types.Settings{RoutingPeerDNSResolutionEnabled: true}
|
accountSettings := &types.Settings{RoutingPeerDNSResolutionEnabled: true}
|
||||||
response := grpc.ToSyncResponse(context.Background(), config, config.HttpConfig, config.DeviceAuthorizationFlow, peer, turnRelayToken, turnRelayToken, networkMap, dnsName, checks, dnsCache, accountSettings, nil, []string{}, int64(dnsForwarderPort))
|
response := grpc.ToSyncResponse(context.Background(), config, config.HttpConfig, config.DeviceAuthorizationFlow, types.TwinPeer(peer), turnRelayToken, turnRelayToken, networkMap, dnsName, checks, dnsCache, types.TwinAccountSettings(accountSettings), nil, []string{}, int64(dnsForwarderPort))
|
||||||
|
|
||||||
assert.NotNil(t, response)
|
assert.NotNil(t, response)
|
||||||
// assert peer config
|
// assert peer config
|
||||||
@@ -1301,7 +1301,7 @@ func Test_RegisterPeerByUser(t *testing.T) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -1392,7 +1392,7 @@ func Test_RegisterPeerBySetupKey(t *testing.T) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -1551,7 +1551,7 @@ func Test_RegisterPeerRollbackOnFailure(t *testing.T) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -1636,7 +1636,7 @@ func Test_LoginPeer(t *testing.T) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
requestBuffer := NewAccountRequestBuffer(ctx, s)
|
||||||
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, s, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.cloud", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(s, peers.NewManager(s, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
am, err := BuildManager(context.Background(), nil, s, networkMapController, job.NewJobManager(nil, s, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -1299,7 +1299,7 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, *update_channel.
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
requestBuffer := NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{})
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peers.NewManager(store, permissionsManager)), &config.Config{}, nil)
|
||||||
|
|
||||||
am, err := BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
am, err := BuildManager(context.Background(), nil, store, networkMapController, job.NewJobManager(nil, store, peersManager), nil, "", eventStore, nil, false, MockIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManager, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -26,6 +25,8 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/util"
|
"github.com/netbirdio/netbird/management/server/util"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/networkmap"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
|
||||||
"github.com/netbirdio/netbird/shared/management/status"
|
"github.com/netbirdio/netbird/shared/management/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -380,94 +381,11 @@ func peerInDistributionGroups(peerGroups LookupMap, distributionGroups []string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) GetPeersCustomZone(ctx context.Context, dnsDomain string) nbdns.CustomZone {
|
func (a *Account) GetPeersCustomZone(ctx context.Context, dnsDomain string) nbdns.CustomZone {
|
||||||
var merr *multierror.Error
|
twins := make(map[string]*nmdata.Peer, len(a.Peers))
|
||||||
|
for id, p := range a.Peers {
|
||||||
if dnsDomain == "" {
|
twins[id] = twinPeer(p)
|
||||||
log.WithContext(ctx).Error("no dns domain is set, returning empty zone")
|
|
||||||
return nbdns.CustomZone{}
|
|
||||||
}
|
}
|
||||||
|
return fromTwinCustomZone(networkmap.PeersCustomZone(ctx, a.Id, dnsDomain, twins, a.peerIPv6AllowedSet()))
|
||||||
customZone := nbdns.CustomZone{
|
|
||||||
Domain: dns.Fqdn(dnsDomain),
|
|
||||||
Records: make([]nbdns.SimpleRecord, 0, len(a.Peers)),
|
|
||||||
}
|
|
||||||
|
|
||||||
domainSuffix := "." + dnsDomain
|
|
||||||
|
|
||||||
ipv6AllowedPeers := a.peerIPv6AllowedSet()
|
|
||||||
|
|
||||||
var sb strings.Builder
|
|
||||||
for _, peer := range a.Peers {
|
|
||||||
if peer.DNSLabel == "" {
|
|
||||||
merr = multierror.Append(merr, fmt.Errorf("peer %s has an empty DNS label", peer.Name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Grow(len(peer.DNSLabel) + len(domainSuffix))
|
|
||||||
sb.WriteString(peer.DNSLabel)
|
|
||||||
sb.WriteString(domainSuffix)
|
|
||||||
|
|
||||||
fqdn := sb.String()
|
|
||||||
customZone.Records = append(customZone.Records, nbdns.SimpleRecord{
|
|
||||||
Name: fqdn,
|
|
||||||
Type: int(dns.TypeA),
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: defaultTTL,
|
|
||||||
RData: peer.IP.String(),
|
|
||||||
})
|
|
||||||
// Only advertise AAAA for peers that have a valid IPv6, whose client supports it,
|
|
||||||
// and that belong to an IPv6-enabled group. Old clients don't configure v6 on their
|
|
||||||
// WireGuard interface, so resolving their AAAA causes connections to hang.
|
|
||||||
// Capability changes (client upgrade/downgrade, --disable-ipv6 toggle) propagate
|
|
||||||
// to other peers via SyncPeer/LoginPeer regardless of version change, so AAAA
|
|
||||||
// records refresh when a peer first reports the IPv6 overlay capability.
|
|
||||||
_, peerAllowed := ipv6AllowedPeers[peer.ID]
|
|
||||||
hasIPv6 := peer.IPv6.IsValid() && peer.SupportsIPv6() && peerAllowed
|
|
||||||
if hasIPv6 {
|
|
||||||
customZone.Records = append(customZone.Records, nbdns.SimpleRecord{
|
|
||||||
Name: fqdn,
|
|
||||||
Type: int(dns.TypeAAAA),
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: defaultTTL,
|
|
||||||
RData: peer.IPv6.String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sb.Reset()
|
|
||||||
|
|
||||||
for _, extraLabel := range peer.ExtraDNSLabels {
|
|
||||||
sb.Grow(len(extraLabel) + len(domainSuffix))
|
|
||||||
sb.WriteString(extraLabel)
|
|
||||||
sb.WriteString(domainSuffix)
|
|
||||||
|
|
||||||
extraFqdn := sb.String()
|
|
||||||
customZone.Records = append(customZone.Records, nbdns.SimpleRecord{
|
|
||||||
Name: extraFqdn,
|
|
||||||
Type: int(dns.TypeA),
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: defaultTTL,
|
|
||||||
RData: peer.IP.String(),
|
|
||||||
})
|
|
||||||
if hasIPv6 {
|
|
||||||
customZone.Records = append(customZone.Records, nbdns.SimpleRecord{
|
|
||||||
Name: extraFqdn,
|
|
||||||
Type: int(dns.TypeAAAA),
|
|
||||||
Class: nbdns.DefaultClass,
|
|
||||||
TTL: defaultTTL,
|
|
||||||
RData: peer.IPv6.String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sb.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if merr != nil {
|
|
||||||
log.WithContext(ctx).Errorf("error generating custom zone for account %s: %v", a.Id, merr)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return customZone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExpiredPeers returns peers that have been expired
|
// GetExpiredPeers returns peers that have been expired
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
groupIDToUserIDs map[string][]string,
|
groupIDToUserIDs map[string][]string,
|
||||||
) *NetworkMapComponents {
|
) *NetworkMapComponents {
|
||||||
nmd := a.toNetworkMapData(accountZones, validatedPeersMap, resourcePolicies, routers, groupIDToUserIDs)
|
nmd := a.toNetworkMapData(accountZones, validatedPeersMap, resourcePolicies, routers, groupIDToUserIDs)
|
||||||
components := nmd.GetPeerNetworkMapComponents(peerID, toTwinCustomZone(peersCustomZone))
|
components := nmd.GetPeerNetworkMapComponents(peerID, TwinCustomZone(peersCustomZone))
|
||||||
if components != nil {
|
if components != nil {
|
||||||
components.ForceRoutingPeerDNSResolution = a.forcesRoutingPeerDNSResolution(peerID, routers)
|
components.ForceRoutingPeerDNSResolution = a.forcesRoutingPeerDNSResolution(peerID, routers)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,14 +45,7 @@ func (a *Account) toNetworkMapData(
|
|||||||
nmd.Network = TwinNetwork(a.Network)
|
nmd.Network = TwinNetwork(a.Network)
|
||||||
}
|
}
|
||||||
nmd.DNSSettings = &nmdata.DNSSettings{DisabledManagementGroups: a.DNSSettings.DisabledManagementGroups}
|
nmd.DNSSettings = &nmdata.DNSSettings{DisabledManagementGroups: a.DNSSettings.DisabledManagementGroups}
|
||||||
if a.Settings != nil {
|
nmd.AccountSettings = TwinAccountSettings(a.Settings)
|
||||||
nmd.AccountSettings = &nmdata.AccountSettingsInfo{
|
|
||||||
PeerLoginExpirationEnabled: a.Settings.PeerLoginExpirationEnabled,
|
|
||||||
PeerLoginExpiration: a.Settings.PeerLoginExpiration,
|
|
||||||
PeerInactivityExpirationEnabled: a.Settings.PeerInactivityExpirationEnabled,
|
|
||||||
PeerInactivityExpiration: a.Settings.PeerInactivityExpiration,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id, p := range a.Peers {
|
for id, p := range a.Peers {
|
||||||
nmd.Peers[id] = twinPeer(p)
|
nmd.Peers[id] = twinPeer(p)
|
||||||
@@ -145,15 +138,17 @@ func twinPeer(p *nbpeer.Peer) *nmdata.Peer {
|
|||||||
IP: p.IP,
|
IP: p.IP,
|
||||||
IPv6: p.IPv6,
|
IPv6: p.IPv6,
|
||||||
RequiresApproval: p.Status != nil && p.Status.RequiresApproval,
|
RequiresApproval: p.Status != nil && p.Status.RequiresApproval,
|
||||||
|
ExtraDNSLabels: p.ExtraDNSLabels,
|
||||||
ProxyMeta: nmdata.ProxyMeta{Embedded: p.ProxyMeta.Embedded},
|
ProxyMeta: nmdata.ProxyMeta{Embedded: p.ProxyMeta.Embedded},
|
||||||
Meta: nmdata.PeerSystemMeta{
|
Meta: nmdata.PeerSystemMeta{
|
||||||
WtVersion: p.Meta.WtVersion,
|
WtVersion: p.Meta.WtVersion,
|
||||||
GoOS: p.Meta.GoOS,
|
GoOS: p.Meta.GoOS,
|
||||||
OSVersion: p.Meta.OSVersion,
|
OSVersion: p.Meta.OSVersion,
|
||||||
KernelVersion: p.Meta.KernelVersion,
|
KernelVersion: p.Meta.KernelVersion,
|
||||||
NetworkAddresses: networkAddresses,
|
NetworkAddresses: networkAddresses,
|
||||||
Files: files,
|
Files: files,
|
||||||
Capabilities: p.Meta.Capabilities,
|
Capabilities: p.Meta.Capabilities,
|
||||||
|
SyncMessageVersion: p.Meta.SyncMessageVersion,
|
||||||
Flags: nmdata.Flags{
|
Flags: nmdata.Flags{
|
||||||
ServerSSHAllowed: p.Meta.Flags.ServerSSHAllowed,
|
ServerSSHAllowed: p.Meta.Flags.ServerSSHAllowed,
|
||||||
DisableIPv6: p.Meta.Flags.DisableIPv6,
|
DisableIPv6: p.Meta.Flags.DisableIPv6,
|
||||||
@@ -508,7 +503,50 @@ func (a *Account) buildPrivateServiceCandidates() []networkmap.PrivateServiceCan
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func toTwinCustomZone(z nbdns.CustomZone) nmdata.CustomZone {
|
// TwinAccountSettings converts real account settings to the slim nmdata twin.
|
||||||
|
// Exported for callers of the twin-based sync response builders.
|
||||||
|
func TwinAccountSettings(s *Settings) *nmdata.AccountSettingsInfo {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &nmdata.AccountSettingsInfo{
|
||||||
|
PeerLoginExpirationEnabled: s.PeerLoginExpirationEnabled,
|
||||||
|
PeerLoginExpiration: s.PeerLoginExpiration,
|
||||||
|
PeerInactivityExpirationEnabled: s.PeerInactivityExpirationEnabled,
|
||||||
|
PeerInactivityExpiration: s.PeerInactivityExpiration,
|
||||||
|
DNSDomain: s.DNSDomain,
|
||||||
|
IPv6EnabledGroups: s.IPv6EnabledGroups,
|
||||||
|
RoutingPeerDNSResolutionEnabled: s.RoutingPeerDNSResolutionEnabled,
|
||||||
|
LazyConnectionEnabled: s.LazyConnectionEnabled,
|
||||||
|
AutoUpdateVersion: s.AutoUpdateVersion,
|
||||||
|
AutoUpdateAlways: s.AutoUpdateAlways,
|
||||||
|
MetricsPushEnabled: s.MetricsPushEnabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromTwinCustomZone(z nmdata.CustomZone) nbdns.CustomZone {
|
||||||
|
records := make([]nbdns.SimpleRecord, 0, len(z.Records))
|
||||||
|
for _, r := range z.Records {
|
||||||
|
records = append(records, nbdns.SimpleRecord{
|
||||||
|
Name: r.Name,
|
||||||
|
Type: r.Type,
|
||||||
|
Class: r.Class,
|
||||||
|
TTL: r.TTL,
|
||||||
|
RData: r.RData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nbdns.CustomZone{
|
||||||
|
Domain: z.Domain,
|
||||||
|
Records: records,
|
||||||
|
SearchDomainDisabled: z.SearchDomainDisabled,
|
||||||
|
NonAuthoritative: z.NonAuthoritative,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TwinCustomZone converts a real DNS custom zone to its slim nmdata twin.
|
||||||
|
// Exported for the network-map controller's DB-store path, which feeds real
|
||||||
|
// zones into the twin-based components calculation.
|
||||||
|
func TwinCustomZone(z nbdns.CustomZone) nmdata.CustomZone {
|
||||||
records := make([]nmdata.SimpleRecord, 0, len(z.Records))
|
records := make([]nmdata.SimpleRecord, 0, len(z.Records))
|
||||||
for _, r := range z.Records {
|
for _, r := range z.Records {
|
||||||
records = append(records, nmdata.SimpleRecord{
|
records = append(records, nmdata.SimpleRecord{
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func BenchmarkNetworkMapWireEncode(b *testing.B) {
|
|||||||
|
|
||||||
// Pre-encode once so the size metric is identical for every run inside
|
// Pre-encode once so the size metric is identical for every run inside
|
||||||
// the same scale; the b.Loop call only re-runs encode + Marshal.
|
// the same scale; the b.Loop call only re-runs encode + Marshal.
|
||||||
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, peer, nil, nil, networkMap, "netbird.cloud", nil, dnsCache, settings, nil, nil, 0)
|
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, types.TwinPeer(peer), nil, nil, networkMap, "netbird.cloud", nil, dnsCache, types.TwinAccountSettings(settings), nil, nil, 0)
|
||||||
legacyBytes, err := goproto.Marshal(legacyResp.NetworkMap)
|
legacyBytes, err := goproto.Marshal(legacyResp.NetworkMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("marshal legacy networkmap: %v", err)
|
b.Fatalf("marshal legacy networkmap: %v", err)
|
||||||
@@ -88,7 +88,7 @@ func BenchmarkNetworkMapWireEncode(b *testing.B) {
|
|||||||
b.ReportMetric(float64(len(legacyBytes)), "bytes/msg")
|
b.ReportMetric(float64(len(legacyBytes)), "bytes/msg")
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for range b.N {
|
for range b.N {
|
||||||
resp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, peer, nil, nil, networkMap, "netbird.cloud", nil, dnsCache, settings, nil, nil, 0)
|
resp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, types.TwinPeer(peer), nil, nil, networkMap, "netbird.cloud", nil, dnsCache, types.TwinAccountSettings(settings), nil, nil, 0)
|
||||||
if _, err := goproto.Marshal(resp.NetworkMap); err != nil {
|
if _, err := goproto.Marshal(resp.NetworkMap); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ func BenchmarkNetworkMapWireSize(b *testing.B) {
|
|||||||
dnsCache := &cache.DNSConfigCache{}
|
dnsCache := &cache.DNSConfigCache{}
|
||||||
settings := &types.Settings{}
|
settings := &types.Settings{}
|
||||||
|
|
||||||
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, peer, nil, nil, networkMap, "netbird.cloud", nil, dnsCache, settings, nil, nil, 0)
|
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, types.TwinPeer(peer), nil, nil, networkMap, "netbird.cloud", nil, dnsCache, types.TwinAccountSettings(settings), nil, nil, 0)
|
||||||
legacyBytes, err := goproto.Marshal(legacyResp.NetworkMap)
|
legacyBytes, err := goproto.Marshal(legacyResp.NetworkMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("marshal legacy networkmap: %v", err)
|
b.Fatalf("marshal legacy networkmap: %v", err)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestNetworkMapWireBreakdown(t *testing.T) {
|
|||||||
dnsCache := &cache.DNSConfigCache{}
|
dnsCache := &cache.DNSConfigCache{}
|
||||||
settings := &types.Settings{}
|
settings := &types.Settings{}
|
||||||
|
|
||||||
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, peer, nil, nil, networkMap, "netbird.cloud", nil, dnsCache, settings, nil, nil, 0)
|
legacyResp := mgmtgrpc.ToSyncResponse(ctx, nil, nil, nil, types.TwinPeer(peer), nil, nil, networkMap, "netbird.cloud", nil, dnsCache, types.TwinAccountSettings(settings), nil, nil, 0)
|
||||||
legacyTotal := mustMarshalSize(t, legacyResp.NetworkMap)
|
legacyTotal := mustMarshalSize(t, legacyResp.NetworkMap)
|
||||||
|
|
||||||
envelope := mgmtgrpc.EncodeNetworkMapEnvelope(mgmtgrpc.ComponentsEnvelopeInput{
|
envelope := mgmtgrpc.EncodeNetworkMapEnvelope(mgmtgrpc.ComponentsEnvelopeInput{
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
|
|
||||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||||
requestBuffer := mgmt.NewAccountRequestBuffer(ctx, store)
|
requestBuffer := mgmt.NewAccountRequestBuffer(ctx, store)
|
||||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, mgmt.MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManger), config)
|
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, mgmt.MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), ephemeral_manager.NewEphemeralManager(store, peersManger), config, nil)
|
||||||
accountManager, err := mgmt.BuildManager(context.Background(), config, store, networkMapController, jobManager, nil, "", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false, cacheStore)
|
accountManager, err := mgmt.BuildManager(context.Background(), config, store, networkMapController, jobManager, nil, "", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false, cacheStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func (nmd *NetworkMapData) GetPeerNetworkMapComponents(peerID string, peersCusto
|
|||||||
components.Routes = relevantRoutes
|
components.Routes = relevantRoutes
|
||||||
components.AllDNSRecords = filterDNSRecordsByPeers(peersCustomZone.Records, relevantPeers, peer.SupportsIPv6() && peer.IPv6.IsValid())
|
components.AllDNSRecords = filterDNSRecordsByPeers(peersCustomZone.Records, relevantPeers, peer.SupportsIPv6() && peer.IPv6.IsValid())
|
||||||
|
|
||||||
peerGroups := nmd.getPeerGroups(peerID)
|
peerGroups := nmd.GetPeerGroups(peerID)
|
||||||
components.AccountZones = nmd.appliedZones(peerGroups)
|
components.AccountZones = nmd.appliedZones(peerGroups)
|
||||||
components.AccountZones = append(components.AccountZones, nmd.privateServiceZones(peerGroups)...)
|
components.AccountZones = append(components.AccountZones, nmd.privateServiceZones(peerGroups)...)
|
||||||
|
|
||||||
@@ -473,7 +473,7 @@ func (nmd *NetworkMapData) getPostureValidPeersSaveFailed(inputPeers []string, p
|
|||||||
return dest
|
return dest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nmd *NetworkMapData) getPeerGroups(peerID string) map[string]struct{} {
|
func (nmd *NetworkMapData) GetPeerGroups(peerID string) map[string]struct{} {
|
||||||
groups := make(map[string]struct{})
|
groups := make(map[string]struct{})
|
||||||
for groupID, group := range nmd.Groups {
|
for groupID, group := range nmd.Groups {
|
||||||
if slices.Contains(group.Peers, peerID) {
|
if slices.Contains(group.Peers, peerID) {
|
||||||
|
|||||||
@@ -8,4 +8,11 @@ type AccountSettingsInfo struct {
|
|||||||
PeerLoginExpiration time.Duration
|
PeerLoginExpiration time.Duration
|
||||||
PeerInactivityExpirationEnabled bool
|
PeerInactivityExpirationEnabled bool
|
||||||
PeerInactivityExpiration time.Duration
|
PeerInactivityExpiration time.Duration
|
||||||
|
DNSDomain string
|
||||||
|
IPv6EnabledGroups []string
|
||||||
|
RoutingPeerDNSResolutionEnabled bool
|
||||||
|
LazyConnectionEnabled bool
|
||||||
|
AutoUpdateVersion string
|
||||||
|
AutoUpdateAlways bool
|
||||||
|
MetricsPushEnabled bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type Peer struct {
|
|||||||
IP netip.Addr
|
IP netip.Addr
|
||||||
IPv6 netip.Addr
|
IPv6 netip.Addr
|
||||||
RequiresApproval bool
|
RequiresApproval bool
|
||||||
|
ExtraDNSLabels []string
|
||||||
Meta PeerSystemMeta
|
Meta PeerSystemMeta
|
||||||
ProxyMeta ProxyMeta
|
ProxyMeta ProxyMeta
|
||||||
Location PeerLocation
|
Location PeerLocation
|
||||||
@@ -37,14 +38,15 @@ type ProxyMeta struct {
|
|||||||
|
|
||||||
// PeerSystemMeta is the slim twin of peer.PeerSystemMeta.
|
// PeerSystemMeta is the slim twin of peer.PeerSystemMeta.
|
||||||
type PeerSystemMeta struct {
|
type PeerSystemMeta struct {
|
||||||
WtVersion string
|
WtVersion string
|
||||||
GoOS string
|
GoOS string
|
||||||
OSVersion string
|
OSVersion string
|
||||||
KernelVersion string
|
KernelVersion string
|
||||||
NetworkAddresses []NetworkAddress
|
NetworkAddresses []NetworkAddress
|
||||||
Files []File
|
Files []File
|
||||||
Capabilities []int32
|
Capabilities []int32
|
||||||
Flags Flags
|
Flags Flags
|
||||||
|
SyncMessageVersion int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flags is the slim twin of peer.Flags.
|
// Flags is the slim twin of peer.Flags.
|
||||||
@@ -101,6 +103,18 @@ func (p *Peer) GetLastLogin() time.Time {
|
|||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SessionExpiresAt mirrors peer.Peer.SessionExpiresAt.
|
||||||
|
func (p *Peer) SessionExpiresAt(accountExpirationEnabled bool, expiresIn time.Duration) time.Time {
|
||||||
|
if !accountExpirationEnabled || !p.AddedWithSSOLogin() || !p.LoginExpirationEnabled {
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
last := p.GetLastLogin()
|
||||||
|
if last.IsZero() {
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
return last.Add(expiresIn).UTC()
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Peer) LoginExpired(expiresIn time.Duration) (bool, time.Duration) {
|
func (p *Peer) LoginExpired(expiresIn time.Duration) (bool, time.Duration) {
|
||||||
if !p.AddedWithSSOLogin() || !p.LoginExpirationEnabled {
|
if !p.AddedWithSSOLogin() || !p.LoginExpirationEnabled {
|
||||||
return false, 0
|
return false, 0
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package networkmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/networkmap/nmdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
const peersZoneRecordTTL = 300
|
||||||
|
|
||||||
|
// PeersCustomZone builds the peers DNS zone from twin peer rows. It is the
|
||||||
|
// single source of the zone-record logic; Account.GetPeersCustomZone delegates
|
||||||
|
// here via twins.
|
||||||
|
func PeersCustomZone(ctx context.Context, accountID string, dnsDomain string, peers map[string]*nmdata.Peer, ipv6AllowedPeers map[string]struct{}) nmdata.CustomZone {
|
||||||
|
var merr *multierror.Error
|
||||||
|
|
||||||
|
if dnsDomain == "" {
|
||||||
|
log.WithContext(ctx).Error("no dns domain is set, returning empty zone")
|
||||||
|
return nmdata.CustomZone{}
|
||||||
|
}
|
||||||
|
|
||||||
|
customZone := nmdata.CustomZone{
|
||||||
|
Domain: dns.Fqdn(dnsDomain),
|
||||||
|
Records: make([]nmdata.SimpleRecord, 0, len(peers)),
|
||||||
|
}
|
||||||
|
|
||||||
|
domainSuffix := "." + dnsDomain
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
for _, peer := range peers {
|
||||||
|
if peer == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if peer.DNSLabel == "" {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("peer %s has an empty DNS label", peer.ID))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Grow(len(peer.DNSLabel) + len(domainSuffix))
|
||||||
|
sb.WriteString(peer.DNSLabel)
|
||||||
|
sb.WriteString(domainSuffix)
|
||||||
|
|
||||||
|
fqdn := sb.String()
|
||||||
|
customZone.Records = append(customZone.Records, nmdata.SimpleRecord{
|
||||||
|
Name: fqdn,
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: peersZoneRecordTTL,
|
||||||
|
RData: peer.IP.String(),
|
||||||
|
})
|
||||||
|
// Only advertise AAAA for peers that have a valid IPv6, whose client supports it,
|
||||||
|
// and that belong to an IPv6-enabled group. Old clients don't configure v6 on their
|
||||||
|
// WireGuard interface, so resolving their AAAA causes connections to hang.
|
||||||
|
// Capability changes (client upgrade/downgrade, --disable-ipv6 toggle) propagate
|
||||||
|
// to other peers via SyncPeer/LoginPeer regardless of version change, so AAAA
|
||||||
|
// records refresh when a peer first reports the IPv6 overlay capability.
|
||||||
|
_, peerAllowed := ipv6AllowedPeers[peer.ID]
|
||||||
|
hasIPv6 := peer.IPv6.IsValid() && peer.SupportsIPv6() && peerAllowed
|
||||||
|
if hasIPv6 {
|
||||||
|
customZone.Records = append(customZone.Records, nmdata.SimpleRecord{
|
||||||
|
Name: fqdn,
|
||||||
|
Type: int(dns.TypeAAAA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: peersZoneRecordTTL,
|
||||||
|
RData: peer.IPv6.String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sb.Reset()
|
||||||
|
|
||||||
|
for _, extraLabel := range peer.ExtraDNSLabels {
|
||||||
|
sb.Grow(len(extraLabel) + len(domainSuffix))
|
||||||
|
sb.WriteString(extraLabel)
|
||||||
|
sb.WriteString(domainSuffix)
|
||||||
|
|
||||||
|
extraFqdn := sb.String()
|
||||||
|
customZone.Records = append(customZone.Records, nmdata.SimpleRecord{
|
||||||
|
Name: extraFqdn,
|
||||||
|
Type: int(dns.TypeA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: peersZoneRecordTTL,
|
||||||
|
RData: peer.IP.String(),
|
||||||
|
})
|
||||||
|
if hasIPv6 {
|
||||||
|
customZone.Records = append(customZone.Records, nmdata.SimpleRecord{
|
||||||
|
Name: extraFqdn,
|
||||||
|
Type: int(dns.TypeAAAA),
|
||||||
|
Class: nbdns.DefaultClass,
|
||||||
|
TTL: peersZoneRecordTTL,
|
||||||
|
RData: peer.IPv6.String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sb.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if merr != nil {
|
||||||
|
log.WithContext(ctx).Errorf("error generating custom zone for account %s: %v", accountID, merr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return customZone
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user