add network map support for clustering

This commit is contained in:
pascal
2026-02-10 14:29:20 +01:00
parent 79fed32f01
commit a803f47685
13 changed files with 229 additions and 211 deletions
+4 -4
View File
@@ -557,7 +557,7 @@ func (am *DefaultAccountManager) GetPeerNetwork(ctx context.Context, peerID stri
// Each new Peer will be assigned a new next net.IP from the Account.Network and Account.Network.LastIP will be updated (IP's are not reused).
// The peer property is just a placeholder for the Peer properties to pass further
func (am *DefaultAccountManager) AddPeer(ctx context.Context, accountID, setupKey, userID string, peer *nbpeer.Peer, temporary bool) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
if setupKey == "" && userID == "" && !peer.ProxyEmbedded {
if setupKey == "" && userID == "" && !peer.ProxyMeta.Embedded {
// no auth method provided => reject access
return nil, nil, nil, status.Errorf(status.Unauthenticated, "no peer auth method provided, please use a setup key or interactive SSO login")
}
@@ -637,7 +637,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, accountID, setupKe
return nil, nil, nil, status.Errorf(status.PreconditionFailed, "couldn't add peer: setup key doesn't allow extra DNS labels")
}
default:
if peer.ProxyEmbedded {
if peer.ProxyMeta.Embedded {
log.WithContext(ctx).Debugf("adding peer for proxy embedded, accountID: %s", accountID)
} else {
log.WithContext(ctx).Warnf("adding peer without setup key or userID, accountID: %s", accountID)
@@ -677,7 +677,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, accountID, setupKe
CreatedAt: registrationTime,
LoginExpirationEnabled: addedByUser && !temporary,
Ephemeral: ephemeral,
ProxyEmbedded: peer.ProxyEmbedded,
ProxyMeta: peer.ProxyMeta,
Location: peer.Location,
InactivityExpirationEnabled: addedByUser && !temporary,
ExtraDNSLabels: peer.ExtraDNSLabels,
@@ -744,7 +744,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, accountID, setupKe
}
}
if !peer.ProxyEmbedded {
if !peer.ProxyMeta.Embedded {
err = transaction.AddPeerToAllGroup(ctx, accountID, newPeer.ID)
if err != nil {
return fmt.Errorf("failed adding peer to All group: %w", err)
+9 -3
View File
@@ -24,6 +24,8 @@ type Peer struct {
IP net.IP `gorm:"serializer:json"` // uniqueness index per accountID (check migrations)
// Meta is a Peer system meta data
Meta PeerSystemMeta `gorm:"embedded;embeddedPrefix:meta_"`
// ProxyMeta is metadata related to proxy peers
ProxyMeta ProxyMeta `gorm:"embedded;embeddedPrefix:proxy_meta_"`
// Name is peer's name (machine name)
Name string `gorm:"index"`
// DNSLabel is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's
@@ -48,8 +50,7 @@ type Peer struct {
CreatedAt time.Time
// Indicate ephemeral peer attribute
Ephemeral bool `gorm:"index"`
// ProxyEmbedded indicates whether the peer is embedded in a reverse proxy
ProxyEmbedded bool `gorm:"index"`
// Geo location based on connection IP
Location Location `gorm:"embedded;embeddedPrefix:location_"`
@@ -59,6 +60,11 @@ type Peer struct {
AllowExtraDNSLabels bool
}
type ProxyMeta struct {
Embedded bool `gorm:"index"`
Cluster string `gorm:"index"`
}
type PeerStatus struct { //nolint:revive
// LastSeen is the last time peer was connected to the management service
LastSeen time.Time
@@ -226,7 +232,7 @@ func (p *Peer) Copy() *Peer {
LastLogin: p.LastLogin,
CreatedAt: p.CreatedAt,
Ephemeral: p.Ephemeral,
ProxyEmbedded: p.ProxyEmbedded,
ProxyMeta: p.ProxyMeta,
Location: p.Location,
InactivityExpirationEnabled: p.InactivityExpirationEnabled,
ExtraDNSLabels: slices.Clone(p.ExtraDNSLabels),
+7 -4
View File
@@ -1690,7 +1690,7 @@ func (s *SqlStore) getPeers(ctx context.Context, accountID string) ([]nbpeer.Pee
meta_kernel_version, meta_network_addresses, meta_system_serial_number, meta_system_product_name, meta_system_manufacturer,
meta_environment, meta_flags, meta_files, peer_status_last_seen, peer_status_connected, peer_status_login_expired,
peer_status_requires_approval, location_connection_ip, location_country_code, location_city_name,
location_geo_name_id, proxy_embedded FROM peers WHERE account_id = $1`
location_geo_name_id, proxy_meta_embedded, proxy_meta_cluster FROM peers WHERE account_id = $1`
rows, err := s.pool.Query(ctx, query, accountID)
if err != nil {
return nil, err
@@ -1708,7 +1708,7 @@ func (s *SqlStore) getPeers(ctx context.Context, accountID string) ([]nbpeer.Pee
metaHostname, metaGoOS, metaKernel, metaCore, metaPlatform sql.NullString
metaOS, metaOSVersion, metaWtVersion, metaUIVersion, metaKernelVersion sql.NullString
metaSystemSerialNumber, metaSystemProductName, metaSystemManufacturer sql.NullString
locationCountryCode, locationCityName sql.NullString
locationCountryCode, locationCityName, proxyCluster sql.NullString
locationGeoNameID sql.NullInt64
)
@@ -1718,7 +1718,7 @@ func (s *SqlStore) getPeers(ctx context.Context, accountID string) ([]nbpeer.Pee
&metaOS, &metaOSVersion, &metaWtVersion, &metaUIVersion, &metaKernelVersion, &netAddr,
&metaSystemSerialNumber, &metaSystemProductName, &metaSystemManufacturer, &env, &flags, &files,
&peerStatusLastSeen, &peerStatusConnected, &peerStatusLoginExpired, &peerStatusRequiresApproval, &connIP,
&locationCountryCode, &locationCityName, &locationGeoNameID, &proxyEmbedded)
&locationCountryCode, &locationCityName, &locationGeoNameID, &proxyEmbedded, &proxyCluster)
if err == nil {
if lastLogin.Valid {
@@ -1803,7 +1803,10 @@ func (s *SqlStore) getPeers(ctx context.Context, accountID string) ([]nbpeer.Pee
p.Location.GeoNameID = uint(locationGeoNameID.Int64)
}
if proxyEmbedded.Valid {
p.ProxyEmbedded = proxyEmbedded.Bool
p.ProxyMeta.Embedded = proxyEmbedded.Bool
}
if proxyCluster.Valid {
p.ProxyMeta.Cluster = proxyCluster.String
}
if ip != nil {
_ = json.Unmarshal(ip, &p.IP)
+15 -15
View File
@@ -422,7 +422,7 @@ func (a *Account) GetPeerProxyResources(peerID string, services []*reverseproxy.
aclPeers = proxyPeers
needsPeerRules := (target.TargetType == reverseproxy.TargetTypePeer && target.TargetId == peerID) ||
((target.TargetType == reverseproxy.TargetTypeHost || target.TargetType == reverseproxy.TargetTypeSubnet || target.TargetType == reverseproxy.TargetTypeDomain) && target.AccessLocal)
(target.TargetType == reverseproxy.TargetTypeHost || target.TargetType == reverseproxy.TargetTypeSubnet || target.TargetType == reverseproxy.TargetTypeDomain)
if needsPeerRules {
for _, proxyPeer := range proxyPeers {
@@ -1285,7 +1285,7 @@ func (a *Account) getAllPeersFromGroups(ctx context.Context, groups []string, pe
filteredPeers := make([]*nbpeer.Peer, 0, len(uniquePeerIDs))
for _, p := range uniquePeerIDs {
peer, ok := a.Peers[p]
if !ok || peer == nil || peer.ProxyEmbedded {
if !ok || peer == nil || peer.ProxyMeta.Embedded {
continue
}
@@ -1848,11 +1848,11 @@ func (a *Account) GetActiveGroupUsers() map[string][]string {
return groups
}
func (a *Account) GetProxyPeers() []*nbpeer.Peer {
var proxyPeers []*nbpeer.Peer
func (a *Account) GetProxyPeers() map[string][]*nbpeer.Peer {
proxyPeers := make(map[string][]*nbpeer.Peer)
for _, peer := range a.Peers {
if peer.ProxyEmbedded {
proxyPeers = append(proxyPeers, peer)
if peer.ProxyMeta.Embedded {
proxyPeers[peer.ProxyMeta.Cluster] = append(proxyPeers[peer.ProxyMeta.Cluster], peer)
}
}
return proxyPeers
@@ -1928,21 +1928,21 @@ func (a *Account) InjectProxyPolicies(ctx context.Context) {
return
}
proxyPeers := a.GetProxyPeers()
if len(proxyPeers) == 0 {
proxyPeersByCluster := a.GetProxyPeers()
if len(proxyPeersByCluster) == 0 {
return
}
for _, proxyPeer := range proxyPeers {
for _, service := range a.ReverseProxies {
if !service.Enabled {
for _, service := range a.ReverseProxies {
if !service.Enabled {
continue
}
for _, target := range service.Targets {
if !target.Enabled {
continue
}
for _, target := range service.Targets {
if !target.Enabled {
continue
}
for _, proxyPeer := range proxyPeersByCluster[service.ProxyCluster] {
port := target.Port
if port == 0 {
switch target.Protocol {