added support for per-account sync message versions

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
This commit is contained in:
Dmitri Dolguikh
2026-07-14 14:16:35 +02:00
parent bbe62e0223
commit c15e1cec1d
7 changed files with 75 additions and 27 deletions

View File

@@ -116,20 +116,21 @@ type SignalConfig struct {
// ManagementConfig contains management service settings
type ManagementConfig struct {
Enabled bool `yaml:"enabled"`
LogLevel string `yaml:"logLevel"`
DataDir string `yaml:"dataDir"`
DnsDomain string `yaml:"dnsDomain"`
DisableAnonymousMetrics bool `yaml:"disableAnonymousMetrics"`
DisableGeoliteUpdate bool `yaml:"disableGeoliteUpdate"`
DisableDefaultPolicy bool `yaml:"disableDefaultPolicy"`
Auth AuthConfig `yaml:"auth"`
Stuns []HostConfig `yaml:"stuns"`
Relays RelaysConfig `yaml:"relays"`
SignalURI string `yaml:"signalUri"`
Store StoreConfig `yaml:"store"`
ReverseProxy ReverseProxyConfig `yaml:"reverseProxy"`
SupportedSyncMessageVersions []string `yaml:"supportedSyncMessageVersions"`
Enabled bool `yaml:"enabled"`
LogLevel string `yaml:"logLevel"`
DataDir string `yaml:"dataDir"`
DnsDomain string `yaml:"dnsDomain"`
DisableAnonymousMetrics bool `yaml:"disableAnonymousMetrics"`
DisableGeoliteUpdate bool `yaml:"disableGeoliteUpdate"`
DisableDefaultPolicy bool `yaml:"disableDefaultPolicy"`
Auth AuthConfig `yaml:"auth"`
Stuns []HostConfig `yaml:"stuns"`
Relays RelaysConfig `yaml:"relays"`
SignalURI string `yaml:"signalUri"`
Store StoreConfig `yaml:"store"`
ReverseProxy ReverseProxyConfig `yaml:"reverseProxy"`
SupportedSyncMessageVersions []string `yaml:"supportedSyncMessageVersions"`
PerAccountSupportedSyncMessageVersions map[string][]string `yaml:"perAccountSupportedSyncMessageVersions"`
}
// AuthConfig contains authentication/identity provider settings

View File

@@ -510,6 +510,12 @@ func createManagementServer(cfg *CombinedConfig, mgmtConfig *nbconfig.Config) (m
return nil, err
}
for accountId, versions := range cfg.Management.PerAccountSupportedSyncMessageVersions {
if err := syncgrpc.ValidateSyncMessageVersions(versions); err != nil {
return nil, fmt.Errorf("unrecognized sync message version in perAccountSupportedSyncMessageVersions for account %s %w", accountId, err)
}
}
mgmtSrv := newServer(
&mgmtServer.Config{
NbConfig: mgmtConfig,

View File

@@ -159,6 +159,13 @@ func LoadMgmtConfig(ctx context.Context, mgmtConfigPath string) (*nbconfig.Confi
return nil, err
}
for account, versions := range loadedConfig.PerAccountSupportedSyncMessageVersions {
err := grpc.ValidateSyncMessageVersions(versions)
if err != nil {
return nil, fmt.Errorf("unrecognized sync message version for account %s, %w", account, err)
}
}
// Apply EmbeddedIdP config to HttpConfig if embedded IdP is enabled
err = ApplyEmbeddedIdPConfig(ctx, loadedConfig)
if err != nil {

View File

@@ -58,6 +58,8 @@ type Controller struct {
integratedPeerValidator integrated_validator.IntegratedValidator
serverSupportedSyncMessageVersions []grpc.SyncMessageVersion
perAccountServerSupportedSyncMessageVersions map[string][]grpc.SyncMessageVersion
}
type bufferUpdate struct {
@@ -92,9 +94,10 @@ func NewController(ctx context.Context, store store.Store, metrics telemetry.App
dnsDomain: dnsDomain,
config: config,
proxyController: proxyController,
EphemeralPeersManager: ephemeralPeersManager,
serverSupportedSyncMessageVersions: grpc.SyncMessageVersionsFromString(config.SupportedSyncMessageVersions),
proxyController: proxyController,
EphemeralPeersManager: ephemeralPeersManager,
serverSupportedSyncMessageVersions: grpc.SyncMessageVersionsFromString(config.SupportedSyncMessageVersions),
perAccountServerSupportedSyncMessageVersions: grpc.SyncMessageVersionsFromMap(config.PerAccountSupportedSyncMessageVersions),
}
}
@@ -230,7 +233,7 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
var update *proto.SyncResponse
commonSyncMessageVersions := grpc.CommonSyncMessageVersions(
c.serverSupportedSyncMessageVersions,
c.perAccountOrGlobalSupportedSyncMessageVersions(accountID),
grpc.SyncMessageVersionsFromProtoEnums(peer.Meta.Capabilities))
if commonSyncMessageVersions[0] == grpc.ComponentNetworkMap {
@@ -275,6 +278,13 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
return nil
}
func (c *Controller) perAccountOrGlobalSupportedSyncMessageVersions(accountId string) []grpc.SyncMessageVersion {
if perAccount, ok := c.perAccountServerSupportedSyncMessageVersions[accountId]; ok {
return perAccount
}
return c.serverSupportedSyncMessageVersions
}
// UpdatePeers updates all peers that belong to an account.
// Should be called when changes have to be synced to peers.
func (c *Controller) UpdateAccountPeers(ctx context.Context, accountID string, reason types.UpdateReason) error {
@@ -381,7 +391,7 @@ func (c *Controller) sendUpdateForAffectedPeers(ctx context.Context, accountID s
var update *proto.SyncResponse
commonSyncMessageVersions := grpc.CommonSyncMessageVersions(
c.serverSupportedSyncMessageVersions,
c.perAccountOrGlobalSupportedSyncMessageVersions(accountID),
grpc.SyncMessageVersionsFromProtoEnums(peer.Meta.Capabilities))
if commonSyncMessageVersions[0] == grpc.ComponentNetworkMap {
@@ -508,7 +518,7 @@ func (c *Controller) UpdateAccountPeer(ctx context.Context, accountId string, pe
var update *proto.SyncResponse
commonSyncMessageVersions := grpc.CommonSyncMessageVersions(
c.serverSupportedSyncMessageVersions,
c.perAccountOrGlobalSupportedSyncMessageVersions(accountId),
grpc.SyncMessageVersionsFromProtoEnums(peer.Meta.Capabilities))
if commonSyncMessageVersions[0] == grpc.ComponentNetworkMap {

View File

@@ -63,6 +63,8 @@ type Config struct {
EmbeddedIdP *idp.EmbeddedIdPConfig
SupportedSyncMessageVersions []string
PerAccountSupportedSyncMessageVersions map[string][]string
}
// GetAuthAudiences returns the audience from the http config and device authorization flow config

View File

@@ -86,8 +86,6 @@ type Server struct {
reverseProxyManager rpservice.Manager
reverseProxyMu sync.RWMutex
supportedSyncMessageVersions []SyncMessageVersion
}
// NewServer creates a new Management server
@@ -132,8 +130,6 @@ func NewServer(
}
}
syncMessageVersions := SyncMessageVersionsFromString(config.SupportedSyncMessageVersions)
return &Server{
jobManager: jobManager,
accountManager: accountManager,
@@ -153,8 +149,6 @@ func NewServer(
syncLim: syncLim,
syncLimEnabled: syncLimEnabled,
supportedSyncMessageVersions: syncMessageVersions,
}, nil
}
@@ -1028,7 +1022,7 @@ func (s *Server) sendInitialSync(ctx context.Context, peerKey wgtypes.Key, peer
var plainResp *proto.SyncResponse
commonSyncMessageVersions := CommonSyncMessageVersions(
SyncMessageVersionsFromString(s.config.SupportedSyncMessageVersions),
SyncMessageVersionsFromString(s.perAccountOrGlobalSyncMessageVersions(peer.AccountID)),
SyncMessageVersionsFromProtoEnums(peer.Meta.Capabilities))
if commonSyncMessageVersions[0] == ComponentNetworkMap {
@@ -1077,6 +1071,13 @@ func (s *Server) sendInitialSync(ctx context.Context, peerKey wgtypes.Key, peer
return nil
}
func (s *Server) perAccountOrGlobalSyncMessageVersions(accountId string) []string {
if versions, ok := s.config.PerAccountSupportedSyncMessageVersions[accountId]; ok {
return versions
}
return s.config.SupportedSyncMessageVersions
}
// GetDeviceAuthorizationFlow returns a device authorization flow information
// This is used for initiating an Oauth 2 device authorization grant flow
// which will be used by our clients to Login

View File

@@ -74,6 +74,27 @@ func SyncMessageVersionsFromString(toconvert []string) []SyncMessageVersion {
return toret
}
// convert per-account human-readable versions to enums
// please note no validation on versions strings is done, misses are silently discarded
// the assumption is ValidateSyncMessageVersions() has been called before using SyncMessageVersionsFromMap()
func SyncMessageVersionsFromMap(toconvert map[string][]string) map[string][]SyncMessageVersion {
// no per-account overrides
if len(toconvert) == 0 {
return nil
}
allversions := make(map[string]SyncMessageVersion, len(AllSyncMessageVersions))
for _, v := range AllSyncMessageVersions {
allversions[v.String()] = v
}
toret := make(map[string][]SyncMessageVersion, len(toconvert))
for account, versions := range toconvert {
toret[account] = SyncMessageVersionsFromString(versions)
}
return toret
}
func SyncMessageVersionsFromProtoEnums(peerCapabilities []int32) []SyncMessageVersion {
toret := make([]SyncMessageVersion, 0)
for _, pc := range peerCapabilities {