mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-24 06:19:08 +02:00
component types
This commit is contained in:
@@ -5,9 +5,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/networkmap"
|
"github.com/netbirdio/netbird/shared/management/networkmap"
|
||||||
@@ -166,7 +163,7 @@ func (e *componentEncoder) indexAllPeers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *componentEncoder) appendPeer(p *nbpeer.Peer) uint32 {
|
func (e *componentEncoder) appendPeer(p *types.ComponentPeer) uint32 {
|
||||||
if idx, ok := e.peerOrder[p.ID]; ok {
|
if idx, ok := e.peerOrder[p.ID]; ok {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
@@ -180,7 +177,7 @@ func (e *componentEncoder) appendPeer(p *nbpeer.Peer) uint32 {
|
|||||||
// (c.RouterPeers may contain peers not in c.Peers when validation rules drop
|
// (c.RouterPeers may contain peers not in c.Peers when validation rules drop
|
||||||
// them) and returns their wire indexes for the RouterPeerIndexes field. Must
|
// them) and returns their wire indexes for the RouterPeerIndexes field. Must
|
||||||
// run before any encoder that resolves peer ids via e.peerOrder.
|
// run before any encoder that resolves peer ids via e.peerOrder.
|
||||||
func (e *componentEncoder) indexRouterPeers(routers map[string]*nbpeer.Peer) []uint32 {
|
func (e *componentEncoder) indexRouterPeers(routers map[string]*types.ComponentPeer) []uint32 {
|
||||||
if len(routers) == 0 {
|
if len(routers) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -514,7 +511,7 @@ func encodeCustomZones(zones []nbdns.CustomZone) []*proto.CustomZone {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *componentEncoder) encodeNetworkResources(resources []*resourceTypes.NetworkResource) []*proto.NetworkResourceRaw {
|
func (e *componentEncoder) encodeNetworkResources(resources []*types.ComponentResource) []*proto.NetworkResourceRaw {
|
||||||
if len(resources) == 0 {
|
if len(resources) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -543,7 +540,7 @@ func (e *componentEncoder) encodeNetworkResources(resources []*resourceTypes.Net
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *componentEncoder) encodeRoutersMap(routersMap map[string]map[string]*routerTypes.NetworkRouter) map[string]*proto.NetworkRouterList {
|
func (e *componentEncoder) encodeRoutersMap(routersMap map[string]map[string]*types.ComponentRouter) map[string]*proto.NetworkRouterList {
|
||||||
if len(routersMap) == 0 {
|
if len(routersMap) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -692,20 +689,20 @@ func toAccountNetwork(n *types.Network) *proto.AccountNetwork {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPeerCompact(p *nbpeer.Peer) *proto.PeerCompact {
|
func toPeerCompact(p *types.ComponentPeer) *proto.PeerCompact {
|
||||||
pc := &proto.PeerCompact{
|
pc := &proto.PeerCompact{
|
||||||
WgPubKey: decodeWgKey(p.Key),
|
WgPubKey: decodeWgKey(p.Key),
|
||||||
SshPubKey: []byte(p.SSHKey),
|
SshPubKey: []byte(p.SSHKey),
|
||||||
DnsLabel: p.DNSLabel,
|
DnsLabel: p.DNSLabel,
|
||||||
AgentVersion: p.Meta.WtVersion,
|
AgentVersion: p.AgentVersion,
|
||||||
AddedWithSsoLogin: p.UserID != "",
|
AddedWithSsoLogin: p.AddedWithSSOLogin,
|
||||||
LoginExpirationEnabled: p.LoginExpirationEnabled,
|
LoginExpirationEnabled: p.LoginExpirationEnabled,
|
||||||
SshEnabled: p.SSHEnabled,
|
SshEnabled: p.SSHEnabled,
|
||||||
SupportsIpv6: p.SupportsIPv6(),
|
SupportsIpv6: p.SupportsIPv6,
|
||||||
SupportsSourcePrefixes: p.SupportsSourcePrefixes(),
|
SupportsSourcePrefixes: p.SupportsSourcePrefixes,
|
||||||
ServerSshAllowed: p.Meta.Flags.ServerSSHAllowed,
|
ServerSshAllowed: p.ServerSSHAllowed,
|
||||||
}
|
}
|
||||||
if p.LastLogin != nil {
|
if !p.LastLogin.IsZero() {
|
||||||
pc.LastLoginUnixNano = p.LastLogin.UnixNano()
|
pc.LastLoginUnixNano = p.LastLogin.UnixNano()
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ import (
|
|||||||
goproto "google.golang.org/protobuf/proto"
|
goproto "google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/proto"
|
"github.com/netbirdio/netbird/shared/management/proto"
|
||||||
@@ -155,29 +152,28 @@ func envelopesEquivalent(a, b *proto.NetworkMapEnvelope) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newTestComponents() *types.NetworkMapComponents {
|
func newTestComponents() *types.NetworkMapComponents {
|
||||||
peerA := &nbpeer.Peer{
|
peerA := &types.ComponentPeer{
|
||||||
ID: "peer-a",
|
ID: "peer-a",
|
||||||
Key: testWgKeyA,
|
Key: testWgKeyA,
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, 1}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, 1}),
|
||||||
DNSLabel: "peera",
|
DNSLabel: "peera",
|
||||||
SSHKey: "ssh-a",
|
SSHKey: "ssh-a",
|
||||||
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now()},
|
AgentVersion: "0.40.0",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
|
||||||
}
|
}
|
||||||
peerB := &nbpeer.Peer{
|
peerB := &types.ComponentPeer{
|
||||||
ID: "peer-b",
|
ID: "peer-b",
|
||||||
Key: testWgKeyB,
|
Key: testWgKeyB,
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, 2}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, 2}),
|
||||||
IPv6: netip.AddrFrom16([16]byte{0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}),
|
IPv6: netip.AddrFrom16([16]byte{0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}),
|
||||||
DNSLabel: "peerb",
|
DNSLabel: "peerb",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.25.0"},
|
AgentVersion: "0.25.0",
|
||||||
}
|
}
|
||||||
peerC := &nbpeer.Peer{
|
peerC := &types.ComponentPeer{
|
||||||
ID: "peer-c",
|
ID: "peer-c",
|
||||||
Key: testWgKeyC,
|
Key: testWgKeyC,
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, 3}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, 3}),
|
||||||
DNSLabel: "peerc",
|
DNSLabel: "peerc",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.NetworkMapComponents{
|
return &types.NetworkMapComponents{
|
||||||
@@ -191,12 +187,12 @@ func newTestComponents() *types.NetworkMapComponents {
|
|||||||
PeerLoginExpirationEnabled: true,
|
PeerLoginExpirationEnabled: true,
|
||||||
PeerLoginExpiration: 2 * time.Hour,
|
PeerLoginExpiration: 2 * time.Hour,
|
||||||
},
|
},
|
||||||
Peers: map[string]*nbpeer.Peer{
|
Peers: map[string]*types.ComponentPeer{
|
||||||
"peer-a": peerA,
|
"peer-a": peerA,
|
||||||
"peer-b": peerB,
|
"peer-b": peerB,
|
||||||
"peer-c": peerC,
|
"peer-c": peerC,
|
||||||
},
|
},
|
||||||
Groups: map[string]*types.Group{
|
Groups: map[string]*types.ComponentGroup{
|
||||||
"group-src": {ID: "group-src", PublicID: "1", Name: "Src", Peers: []string{"peer-a"}},
|
"group-src": {ID: "group-src", PublicID: "1", Name: "Src", Peers: []string{"peer-a"}},
|
||||||
"group-dst": {ID: "group-dst", PublicID: "2", Name: "Dst", Peers: []string{"peer-b", "peer-c"}},
|
"group-dst": {ID: "group-dst", PublicID: "2", Name: "Dst", Peers: []string{"peer-b", "peer-c"}},
|
||||||
},
|
},
|
||||||
@@ -215,7 +211,7 @@ func newTestComponents() *types.NetworkMapComponents {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RouterPeers: map[string]*nbpeer.Peer{"peer-c": peerC},
|
RouterPeers: map[string]*types.ComponentPeer{"peer-c": peerC},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,12 +377,12 @@ func TestEncodeNetworkMapEnvelope_MalformedWgKey(t *testing.T) {
|
|||||||
|
|
||||||
func TestEncodeNetworkMapEnvelope_IPv6OnlyPeer(t *testing.T) {
|
func TestEncodeNetworkMapEnvelope_IPv6OnlyPeer(t *testing.T) {
|
||||||
c := newTestComponents()
|
c := newTestComponents()
|
||||||
v6Only := &nbpeer.Peer{
|
v6Only := &types.ComponentPeer{
|
||||||
ID: "peer-v6",
|
ID: "peer-v6",
|
||||||
Key: testWgKeyA,
|
Key: testWgKeyA,
|
||||||
IPv6: netip.AddrFrom16([16]byte{0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}),
|
IPv6: netip.AddrFrom16([16]byte{0xfd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}),
|
||||||
DNSLabel: "peerv6",
|
DNSLabel: "peerv6",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
c.Peers["peer-v6"] = v6Only
|
c.Peers["peer-v6"] = v6Only
|
||||||
|
|
||||||
@@ -405,11 +401,11 @@ func TestEncodeNetworkMapEnvelope_IPv6OnlyPeer(t *testing.T) {
|
|||||||
|
|
||||||
func TestEncodeNetworkMapEnvelope_PeerWithoutIP(t *testing.T) {
|
func TestEncodeNetworkMapEnvelope_PeerWithoutIP(t *testing.T) {
|
||||||
c := newTestComponents()
|
c := newTestComponents()
|
||||||
c.Peers["peer-noip"] = &nbpeer.Peer{
|
c.Peers["peer-noip"] = &types.ComponentPeer{
|
||||||
ID: "peer-noip",
|
ID: "peer-noip",
|
||||||
Key: testWgKeyA,
|
Key: testWgKeyA,
|
||||||
DNSLabel: "peernoip",
|
DNSLabel: "peernoip",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
||||||
@@ -444,9 +440,9 @@ func TestEncodeNetworkMapEnvelope_EmptyInput(t *testing.T) {
|
|||||||
func TestEncodeNetworkMapEnvelope_PeerLoginExpirationFields(t *testing.T) {
|
func TestEncodeNetworkMapEnvelope_PeerLoginExpirationFields(t *testing.T) {
|
||||||
c := newTestComponents()
|
c := newTestComponents()
|
||||||
now := time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)
|
now := time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)
|
||||||
c.Peers["peer-a"].UserID = "user-1"
|
c.Peers["peer-a"].AddedWithSSOLogin = true
|
||||||
c.Peers["peer-a"].LoginExpirationEnabled = true
|
c.Peers["peer-a"].LoginExpirationEnabled = true
|
||||||
c.Peers["peer-a"].LastLogin = &now
|
c.Peers["peer-a"].LastLogin = now
|
||||||
|
|
||||||
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
||||||
|
|
||||||
@@ -557,7 +553,7 @@ func TestEncodeNetworkMapEnvelope_ResourceOnlyPolicyShippedAndIndexed(t *testing
|
|||||||
}
|
}
|
||||||
// Resource must appear in components.NetworkResources with a seq id —
|
// Resource must appear in components.NetworkResources with a seq id —
|
||||||
// encoder uses that to translate the xid map key to uint32.
|
// encoder uses that to translate the xid map key to uint32.
|
||||||
c.NetworkResources = []*resourceTypes.NetworkResource{
|
c.NetworkResources = []*types.ComponentResource{
|
||||||
{ID: "resource-x", PublicID: "77", Name: "res-x", Enabled: true},
|
{ID: "resource-x", PublicID: "77", Name: "res-x", Enabled: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,11 +621,11 @@ func TestEncodeNetworkMapEnvelope_PostureFailedPeers(t *testing.T) {
|
|||||||
func TestEncodeNetworkMapEnvelope_RoutersMap(t *testing.T) {
|
func TestEncodeNetworkMapEnvelope_RoutersMap(t *testing.T) {
|
||||||
c := newTestComponents()
|
c := newTestComponents()
|
||||||
c.NetworkXIDToPublicID = map[string]string{"net-1": "5"}
|
c.NetworkXIDToPublicID = map[string]string{"net-1": "5"}
|
||||||
c.RoutersMap = map[string]map[string]*routerTypes.NetworkRouter{
|
c.RoutersMap = map[string]map[string]*types.ComponentRouter{
|
||||||
"net-1": {
|
"net-1": {
|
||||||
"peer-c": {
|
"peer-c": {
|
||||||
ID: "router-1", PublicID: "200",
|
PublicID: "200",
|
||||||
Peer: "peer-c", Masquerade: true, Metric: 10, Enabled: true,
|
Peer: "peer-c", Masquerade: true, Metric: 10, Enabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -655,14 +651,14 @@ func TestEncodeNetworkMapEnvelope_RouterPeerNotInComponentsPeers(t *testing.T) {
|
|||||||
// peer_index reference must still resolve.
|
// peer_index reference must still resolve.
|
||||||
c := newTestComponents()
|
c := newTestComponents()
|
||||||
delete(c.Peers, "peer-c")
|
delete(c.Peers, "peer-c")
|
||||||
routerPeer := &nbpeer.Peer{
|
routerPeer := &types.ComponentPeer{
|
||||||
ID: "peer-c", Key: testWgKeyC, IP: netip.AddrFrom4([4]byte{100, 64, 0, 3}),
|
ID: "peer-c", Key: testWgKeyC, IP: netip.AddrFrom4([4]byte{100, 64, 0, 3}),
|
||||||
DNSLabel: "peerc", Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
DNSLabel: "peerc", AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
c.RouterPeers = map[string]*nbpeer.Peer{"peer-c": routerPeer}
|
c.RouterPeers = map[string]*types.ComponentPeer{"peer-c": routerPeer}
|
||||||
c.NetworkXIDToPublicID = map[string]string{"net-1": "5"}
|
c.NetworkXIDToPublicID = map[string]string{"net-1": "5"}
|
||||||
c.RoutersMap = map[string]map[string]*routerTypes.NetworkRouter{
|
c.RoutersMap = map[string]map[string]*types.ComponentRouter{
|
||||||
"net-1": {"peer-c": {ID: "r-1", PublicID: "1", Peer: "peer-c", Enabled: true}},
|
"net-1": {"peer-c": {PublicID: "1", Peer: "peer-c", Enabled: true}},
|
||||||
}
|
}
|
||||||
|
|
||||||
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
full := EncodeNetworkMapEnvelope(ComponentsEnvelopeInput{Components: c}).GetFull()
|
||||||
@@ -695,9 +691,9 @@ func TestToProxyPatch_EmptyInputReturnsNil(t *testing.T) {
|
|||||||
|
|
||||||
func TestToProxyPatch_PopulatesAllFields(t *testing.T) {
|
func TestToProxyPatch_PopulatesAllFields(t *testing.T) {
|
||||||
nm := &types.NetworkMap{
|
nm := &types.NetworkMap{
|
||||||
Peers: []*nbpeer.Peer{{
|
Peers: []*types.ComponentPeer{{
|
||||||
ID: "ext-peer", Key: testWgKeyA, IP: netip.AddrFrom4([4]byte{100, 64, 0, 9}),
|
ID: "ext-peer", Key: testWgKeyA, IP: netip.AddrFrom4([4]byte{100, 64, 0, 9}),
|
||||||
DNSLabel: "extpeer", Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
DNSLabel: "extpeer", AgentVersion: "0.40.0",
|
||||||
}},
|
}},
|
||||||
FirewallRules: []*types.FirewallRule{{
|
FirewallRules: []*types.FirewallRule{{
|
||||||
PeerIP: "100.64.0.9", Action: "accept", Direction: 0, Protocol: "tcp",
|
PeerIP: "100.64.0.9", Action: "accept", Direction: 0, Protocol: "tcp",
|
||||||
@@ -780,6 +776,6 @@ func TestEncodeNetworkMapEnvelope_AccountSettingsAlwaysEmitted(t *testing.T) {
|
|||||||
func emptyNetworkMapComponents() *types.NetworkMapComponents {
|
func emptyNetworkMapComponents() *types.NetworkMapComponents {
|
||||||
return types.EmptyNetworkMapComponents(
|
return types.EmptyNetworkMapComponents(
|
||||||
&types.NetworkMapComponents{
|
&types.NetworkMapComponents{
|
||||||
PeerID: "peer-id", Peers: map[string]*nbpeer.Peer{"peer-id": {}}},
|
PeerID: "peer-id", Peers: map[string]*types.ComponentPeer{"peer-id": {}}},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ func TestComputeSSHEnabledForPeer(t *testing.T) {
|
|||||||
|
|
||||||
mkComponents := func(rule *types.PolicyRule, sshEnabled bool) (*types.NetworkMapComponents, *nbpeer.Peer) {
|
mkComponents := func(rule *types.PolicyRule, sshEnabled bool) (*types.NetworkMapComponents, *nbpeer.Peer) {
|
||||||
peer := &nbpeer.Peer{ID: targetPeerID, SSHEnabled: sshEnabled}
|
peer := &nbpeer.Peer{ID: targetPeerID, SSHEnabled: sshEnabled}
|
||||||
group := &types.Group{ID: targetGroupID, Name: "dst", Peers: []string{targetPeerID}}
|
group := &types.ComponentGroup{ID: targetGroupID, Name: "dst", Peers: []string{targetPeerID}}
|
||||||
return &types.NetworkMapComponents{
|
return &types.NetworkMapComponents{
|
||||||
Peers: map[string]*nbpeer.Peer{targetPeerID: peer},
|
Peers: map[string]*types.ComponentPeer{targetPeerID: peer.ToComponent()},
|
||||||
Groups: map[string]*types.Group{targetGroupID: group},
|
Groups: map[string]*types.ComponentGroup{targetGroupID: group},
|
||||||
Policies: []*types.Policy{{
|
Policies: []*types.Policy{{
|
||||||
ID: "p",
|
ID: "p",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
@@ -158,8 +158,8 @@ func TestComputeSSHEnabledForPeer(t *testing.T) {
|
|||||||
func TestComputeSSHEnabledForPeer_TargetMissingFromComponents(t *testing.T) {
|
func TestComputeSSHEnabledForPeer_TargetMissingFromComponents(t *testing.T) {
|
||||||
peer := &nbpeer.Peer{ID: "missing", SSHEnabled: true}
|
peer := &nbpeer.Peer{ID: "missing", SSHEnabled: true}
|
||||||
c := &types.NetworkMapComponents{
|
c := &types.NetworkMapComponents{
|
||||||
Peers: map[string]*nbpeer.Peer{}, // target peer NOT present
|
Peers: map[string]*types.ComponentPeer{}, // target peer NOT present
|
||||||
Groups: map[string]*types.Group{
|
Groups: map[string]*types.ComponentGroup{
|
||||||
"g": {ID: "g", Peers: []string{"missing"}},
|
"g": {ID: "g", Peers: []string{"missing"}},
|
||||||
},
|
},
|
||||||
Policies: []*types.Policy{{
|
Policies: []*types.Policy{{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions"
|
"github.com/netbirdio/netbird/management/server/permissions"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
"github.com/netbirdio/netbird/management/server/permissions/modules"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions/operations"
|
"github.com/netbirdio/netbird/management/server/permissions/operations"
|
||||||
@@ -30,6 +31,10 @@ type managerImpl struct {
|
|||||||
accountManager account.Manager
|
accountManager account.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func eventMetaResource(group *types.Group, resource *resourceTypes.NetworkResource) map[string]any {
|
||||||
|
return map[string]any{"name": group.Name, "id": group.ID, "resource_name": resource.Name, "resource_id": resource.ID, "resource_type": resource.Type}
|
||||||
|
}
|
||||||
|
|
||||||
type mockManager struct {
|
type mockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +114,7 @@ func (m *managerImpl) AddResourceToGroupInTransaction(ctx context.Context, trans
|
|||||||
}
|
}
|
||||||
|
|
||||||
event := func() {
|
event := func() {
|
||||||
m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceAddedToGroup, group.EventMetaResource(networkResource))
|
m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceAddedToGroup, eventMetaResource(group, networkResource))
|
||||||
}
|
}
|
||||||
|
|
||||||
return event, nil
|
return event, nil
|
||||||
@@ -133,7 +138,7 @@ func (m *managerImpl) RemoveResourceFromGroupInTransaction(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
event := func() {
|
event := func() {
|
||||||
m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceRemovedFromGroup, group.EventMetaResource(networkResource))
|
m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceRemovedFromGroup, eventMetaResource(group, networkResource))
|
||||||
}
|
}
|
||||||
|
|
||||||
return event, nil
|
return event, nil
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ func (h *Handler) GetAccessiblePeers(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
netMap := account.GetPeerNetworkMapFromComponents(ctx, peerID, dns.CustomZone{}, nil, validPeers, account.GetResourcePoliciesMap(), account.GetResourceRoutersMap(), nil, account.GetActiveGroupUsers())
|
netMap := account.GetPeerNetworkMapFromComponents(ctx, peerID, dns.CustomZone{}, nil, validPeers, account.GetResourcePoliciesMap(), account.GetResourceRoutersMap(), nil, account.GetActiveGroupUsers())
|
||||||
|
|
||||||
util.WriteJSONObject(ctx, w, toAccessiblePeers(netMap, dnsDomain))
|
util.WriteJSONObject(ctx, w, toAccessiblePeers(netMap, account.Peers, dnsDomain))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) CreateTemporaryAccess(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) CreateTemporaryAccess(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -534,15 +534,20 @@ func (h *Handler) CreateTemporaryAccess(w http.ResponseWriter, r *http.Request)
|
|||||||
util.WriteJSONObject(r.Context(), w, resp)
|
util.WriteJSONObject(r.Context(), w, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toAccessiblePeers(netMap *types.NetworkMap, dnsDomain string) []api.AccessiblePeer {
|
// toAccessiblePeers rehydrates the calculated map's component peers into the
|
||||||
|
// account's full peer objects, which carry the location/status/meta fields
|
||||||
|
// the API response needs.
|
||||||
|
func toAccessiblePeers(netMap *types.NetworkMap, accountPeers map[string]*nbpeer.Peer, dnsDomain string) []api.AccessiblePeer {
|
||||||
accessiblePeers := make([]api.AccessiblePeer, 0, len(netMap.Peers)+len(netMap.OfflinePeers))
|
accessiblePeers := make([]api.AccessiblePeer, 0, len(netMap.Peers)+len(netMap.OfflinePeers))
|
||||||
for _, p := range netMap.Peers {
|
add := func(peers []*types.ComponentPeer) {
|
||||||
accessiblePeers = append(accessiblePeers, peerToAccessiblePeer(p, dnsDomain))
|
for _, p := range peers {
|
||||||
}
|
if peer := accountPeers[p.ID]; peer != nil {
|
||||||
|
accessiblePeers = append(accessiblePeers, peerToAccessiblePeer(peer, dnsDomain))
|
||||||
for _, p := range netMap.OfflinePeers {
|
}
|
||||||
accessiblePeers = append(accessiblePeers, peerToAccessiblePeer(p, dnsDomain))
|
}
|
||||||
}
|
}
|
||||||
|
add(netMap.Peers)
|
||||||
|
add(netMap.OfflinePeers)
|
||||||
|
|
||||||
return accessiblePeers
|
return accessiblePeers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
nbDomain "github.com/netbirdio/netbird/shared/management/domain"
|
nbDomain "github.com/netbirdio/netbird/shared/management/domain"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||||
|
sharedTypes "github.com/netbirdio/netbird/shared/management/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetworkResourceType string
|
type NetworkResourceType string
|
||||||
@@ -64,6 +65,27 @@ func NewNetworkResource(accountID, networkID, name, description, address string,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToComponent converts the resource to its self-contained components
|
||||||
|
// representation. Returns nil for a nil resource.
|
||||||
|
func (n *NetworkResource) ToComponent() *sharedTypes.ComponentResource {
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &sharedTypes.ComponentResource{
|
||||||
|
ID: n.ID,
|
||||||
|
PublicID: n.PublicID,
|
||||||
|
NetworkID: n.NetworkID,
|
||||||
|
AccountID: n.AccountID,
|
||||||
|
Name: n.Name,
|
||||||
|
Description: n.Description,
|
||||||
|
Type: sharedTypes.ComponentResourceType(n.Type),
|
||||||
|
Address: n.Address,
|
||||||
|
Domain: n.Domain,
|
||||||
|
Prefix: n.Prefix,
|
||||||
|
Enabled: n.Enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NetworkResource) ToAPIResponse(groups []api.GroupMinimum) *api.NetworkResource {
|
func (n *NetworkResource) ToAPIResponse(groups []api.GroupMinimum) *api.NetworkResource {
|
||||||
addr := n.Prefix.String()
|
addr := n.Prefix.String()
|
||||||
if n.Type == Domain {
|
if n.Type == Domain {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/networks/types"
|
"github.com/netbirdio/netbird/management/server/networks/types"
|
||||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||||
|
sharedTypes "github.com/netbirdio/netbird/shared/management/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetworkRouter struct {
|
type NetworkRouter struct {
|
||||||
@@ -21,6 +22,36 @@ type NetworkRouter struct {
|
|||||||
Enabled bool
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToComponent converts the router to its self-contained components
|
||||||
|
// representation. Returns nil for a nil router.
|
||||||
|
func (n *NetworkRouter) ToComponent() *sharedTypes.ComponentRouter {
|
||||||
|
if n == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &sharedTypes.ComponentRouter{
|
||||||
|
NetworkID: n.NetworkID,
|
||||||
|
PublicID: n.PublicID,
|
||||||
|
Peer: n.Peer,
|
||||||
|
PeerGroups: n.PeerGroups,
|
||||||
|
Masquerade: n.Masquerade,
|
||||||
|
Metric: n.Metric,
|
||||||
|
Enabled: n.Enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToComponentMap converts a peer-keyed router map to its components
|
||||||
|
// representation.
|
||||||
|
func ToComponentMap(routers map[string]*NetworkRouter) map[string]*sharedTypes.ComponentRouter {
|
||||||
|
if routers == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make(map[string]*sharedTypes.ComponentRouter, len(routers))
|
||||||
|
for id, r := range routers {
|
||||||
|
out[id] = r.ToComponent()
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func NewNetworkRouter(accountID string, networkID string, peer string, peerGroups []string, masquerade bool, metric int, enabled bool) (*NetworkRouter, error) {
|
func NewNetworkRouter(accountID string, networkID string, peer string, peerGroups []string, masquerade bool, metric int, enabled bool) (*NetworkRouter, error) {
|
||||||
r := &NetworkRouter{
|
r := &NetworkRouter{
|
||||||
ID: xid.New().String(),
|
ID: xid.New().String(),
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ func (am *DefaultAccountManager) CreatePeerJob(ctx context.Context, accountID, p
|
|||||||
return status.NewPeerNotPartOfAccountError()
|
return status.NewPeerNotPartOfAccountError()
|
||||||
}
|
}
|
||||||
|
|
||||||
meetMinVer, err := posture.MeetsMinVersion(remoteJobsMinVer, p.Meta.WtVersion)
|
meetMinVer, err := version.MeetsMinVersion(remoteJobsMinVer, p.Meta.WtVersion)
|
||||||
if !version.IsDevelopmentVersion(p.Meta.WtVersion) && (!meetMinVer || err != nil) {
|
if !version.IsDevelopmentVersion(p.Meta.WtVersion) && (!meetMinVer || err != nil) {
|
||||||
return status.Errorf(status.PreconditionFailed, "peer version %s does not meet the minimum required version %s for remote jobs", p.Meta.WtVersion, remoteJobsMinVer)
|
return status.Errorf(status.PreconditionFailed, "peer version %s does not meet the minimum required version %s for remote jobs", p.Meta.WtVersion, remoteJobsMinVer)
|
||||||
}
|
}
|
||||||
@@ -1588,7 +1588,7 @@ func affectedPeerIDsFromNetworkMap(nmap *types.NetworkMap, selfPeerID string) []
|
|||||||
}
|
}
|
||||||
seen := make(map[string]struct{}, len(nmap.Peers)+len(nmap.OfflinePeers))
|
seen := make(map[string]struct{}, len(nmap.Peers)+len(nmap.OfflinePeers))
|
||||||
ids := make([]string, 0, len(nmap.Peers)+len(nmap.OfflinePeers))
|
ids := make([]string, 0, len(nmap.Peers)+len(nmap.OfflinePeers))
|
||||||
add := func(peers []*nbpeer.Peer) {
|
add := func(peers []*types.ComponentPeer) {
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
if p == nil || p.ID == "" || p.ID == selfPeerID {
|
if p == nil || p.ID == "" || p.ID == selfPeerID {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/util"
|
"github.com/netbirdio/netbird/management/server/util"
|
||||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||||
|
sharedTypes "github.com/netbirdio/netbird/shared/management/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Peer capability constants mirror the proto enum values.
|
// Peer capability constants mirror the proto enum values.
|
||||||
@@ -205,6 +206,35 @@ func (p *Peer) AddedWithSSOLogin() bool {
|
|||||||
return p.UserID != ""
|
return p.UserID != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToComponent converts the peer to its self-contained components
|
||||||
|
// representation, carrying exactly the subset of peer data that crosses the
|
||||||
|
// components wire format. Returns nil for a nil peer so callers can convert
|
||||||
|
// possibly-missing peers without guarding.
|
||||||
|
func (p *Peer) ToComponent() *sharedTypes.ComponentPeer {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cp := &sharedTypes.ComponentPeer{
|
||||||
|
ID: p.ID,
|
||||||
|
Key: p.Key,
|
||||||
|
IP: p.IP,
|
||||||
|
IPv6: p.IPv6,
|
||||||
|
DNSLabel: p.DNSLabel,
|
||||||
|
SSHKey: p.SSHKey,
|
||||||
|
SSHEnabled: p.SSHEnabled,
|
||||||
|
ServerSSHAllowed: p.Meta.Flags.ServerSSHAllowed,
|
||||||
|
AgentVersion: p.Meta.WtVersion,
|
||||||
|
SupportsSourcePrefixes: p.SupportsSourcePrefixes(),
|
||||||
|
SupportsIPv6: p.SupportsIPv6(),
|
||||||
|
LoginExpirationEnabled: p.LoginExpirationEnabled,
|
||||||
|
AddedWithSSOLogin: p.AddedWithSSOLogin(),
|
||||||
|
}
|
||||||
|
if p.LastLogin != nil {
|
||||||
|
cp.LastLogin = *p.LastLogin
|
||||||
|
}
|
||||||
|
return cp
|
||||||
|
}
|
||||||
|
|
||||||
// HasCapability reports whether the peer has the given capability.
|
// HasCapability reports whether the peer has the given capability.
|
||||||
func (p *Peer) HasCapability(capability int32) bool {
|
func (p *Peer) HasCapability(capability int32) bool {
|
||||||
return slices.Contains(p.Meta.Capabilities, capability)
|
return slices.Contains(p.Meta.Capabilities, capability)
|
||||||
|
|||||||
@@ -1092,14 +1092,14 @@ func TestToSyncResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
networkMap := &types.NetworkMap{
|
networkMap := &types.NetworkMap{
|
||||||
Network: &types.Network{Net: *ipnet, Serial: 1000},
|
Network: &types.Network{Net: *ipnet, Serial: 1000},
|
||||||
Peers: []*nbpeer.Peer{{
|
Peers: []*types.ComponentPeer{{
|
||||||
IP: netip.MustParseAddr("192.168.1.2"),
|
IP: netip.MustParseAddr("192.168.1.2"),
|
||||||
IPv6: netip.MustParseAddr("fd00::2"),
|
IPv6: netip.MustParseAddr("fd00::2"),
|
||||||
Key: "peer2-key",
|
Key: "peer2-key",
|
||||||
DNSLabel: "peer2",
|
DNSLabel: "peer2",
|
||||||
SSHEnabled: true,
|
SSHEnabled: true,
|
||||||
SSHKey: "peer2-ssh-key"}},
|
SSHKey: "peer2-ssh-key"}},
|
||||||
OfflinePeers: []*nbpeer.Peer{{
|
OfflinePeers: []*types.ComponentPeer{{
|
||||||
IP: netip.MustParseAddr("192.168.1.3"),
|
IP: netip.MustParseAddr("192.168.1.3"),
|
||||||
IPv6: netip.MustParseAddr("fd00::3"),
|
IPv6: netip.MustParseAddr("fd00::3"),
|
||||||
Key: "peer3-key",
|
Key: "peer3-key",
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ package posture
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-version"
|
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
nbversion "github.com/netbirdio/netbird/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NBVersionCheck struct {
|
type NBVersionCheck struct {
|
||||||
@@ -16,14 +14,8 @@ type NBVersionCheck struct {
|
|||||||
|
|
||||||
var _ Check = (*NBVersionCheck)(nil)
|
var _ Check = (*NBVersionCheck)(nil)
|
||||||
|
|
||||||
// sanitizeVersion removes anything after the pre-release tag (e.g., "-dev", "-alpha", etc.)
|
|
||||||
func sanitizeVersion(version string) string {
|
|
||||||
parts := strings.Split(version, "-")
|
|
||||||
return parts[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NBVersionCheck) Check(ctx context.Context, peer nbpeer.Peer) (bool, error) {
|
func (n *NBVersionCheck) Check(ctx context.Context, peer nbpeer.Peer) (bool, error) {
|
||||||
meetsMin, err := MeetsMinVersion(n.MinVersion, peer.Meta.WtVersion)
|
meetsMin, err := nbversion.MeetsMinVersion(n.MinVersion, peer.Meta.WtVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -48,21 +40,3 @@ func (n *NBVersionCheck) Validate() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MeetsMinVersion checks if the peer's version meets or exceeds the minimum required version
|
|
||||||
func MeetsMinVersion(minVer, peerVer string) (bool, error) {
|
|
||||||
peerVer = sanitizeVersion(peerVer)
|
|
||||||
minVer = sanitizeVersion(minVer)
|
|
||||||
|
|
||||||
peerNBVer, err := version.NewVersion(peerVer)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
constraints, err := version.NewConstraint(">= " + minVer)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return constraints.Check(peerNBVer), nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -139,68 +139,3 @@ func TestNBVersionCheck_Validate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMeetsMinVersion(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
minVer string
|
|
||||||
peerVer string
|
|
||||||
want bool
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Peer version greater than min version",
|
|
||||||
minVer: "0.26.0",
|
|
||||||
peerVer: "0.60.1",
|
|
||||||
want: true,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Peer version equals min version",
|
|
||||||
minVer: "1.0.0",
|
|
||||||
peerVer: "1.0.0",
|
|
||||||
want: true,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Peer version less than min version",
|
|
||||||
minVer: "1.0.0",
|
|
||||||
peerVer: "0.9.9",
|
|
||||||
want: false,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Peer version with pre-release tag greater than min version",
|
|
||||||
minVer: "1.0.0",
|
|
||||||
peerVer: "1.0.1-alpha",
|
|
||||||
want: true,
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Invalid peer version format",
|
|
||||||
minVer: "1.0.0",
|
|
||||||
peerVer: "dev",
|
|
||||||
want: false,
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Invalid min version format",
|
|
||||||
minVer: "invalid.version",
|
|
||||||
peerVer: "1.0.0",
|
|
||||||
want: false,
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
got, err := MeetsMinVersion(tt.minVer, tt.peerVer)
|
|
||||||
if tt.wantErr {
|
|
||||||
assert.Error(t, err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
assert.Equal(t, tt.want, got)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -283,8 +283,8 @@ func (a *Account) SynthesizePrivateServiceZones(peerID string) []nbdns.CustomZon
|
|||||||
// it, adding a single private service would black-hole every
|
// it, adding a single private service would black-hole every
|
||||||
// other name under the zone apex.
|
// other name under the zone apex.
|
||||||
zone = &nbdns.CustomZone{
|
zone = &nbdns.CustomZone{
|
||||||
Domain: dns.Fqdn(serviceDomainZone),
|
Domain: dns.Fqdn(serviceDomainZone),
|
||||||
Records: []nbdns.SimpleRecord{},
|
Records: []nbdns.SimpleRecord{},
|
||||||
NonAuthoritative: true,
|
NonAuthoritative: true,
|
||||||
SearchDomainDisabled: true,
|
SearchDomainDisabled: true,
|
||||||
}
|
}
|
||||||
@@ -1082,6 +1082,7 @@ func (a *Account) connResourcesGenerator(ctx context.Context, targetPeer *nbpeer
|
|||||||
peersExists := make(map[string]struct{})
|
peersExists := make(map[string]struct{})
|
||||||
rules := make([]*FirewallRule, 0)
|
rules := make([]*FirewallRule, 0)
|
||||||
peers := make([]*nbpeer.Peer, 0)
|
peers := make([]*nbpeer.Peer, 0)
|
||||||
|
targetComponent := targetPeer.ToComponent()
|
||||||
|
|
||||||
return func(rule *PolicyRule, groupPeers []*nbpeer.Peer, direction int) {
|
return func(rule *PolicyRule, groupPeers []*nbpeer.Peer, direction int) {
|
||||||
for _, peer := range groupPeers {
|
for _, peer := range groupPeers {
|
||||||
@@ -1117,10 +1118,10 @@ func (a *Account) connResourcesGenerator(ctx context.Context, targetPeer *nbpeer
|
|||||||
if len(rule.Ports) == 0 && len(rule.PortRanges) == 0 {
|
if len(rule.Ports) == 0 && len(rule.PortRanges) == 0 {
|
||||||
rules = append(rules, &fr)
|
rules = append(rules, &fr)
|
||||||
} else {
|
} else {
|
||||||
rules = append(rules, ExpandPortsAndRanges(fr, rule, targetPeer)...)
|
rules = append(rules, ExpandPortsAndRanges(fr, rule, targetComponent)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
rules = AppendIPv6FirewallRule(rules, rulesExists, peer, targetPeer, rule, FirewallRuleContext{
|
rules = AppendIPv6FirewallRule(rules, rulesExists, peer.ToComponent(), targetComponent, rule, FirewallRuleContext{
|
||||||
Direction: direction,
|
Direction: direction,
|
||||||
DirStr: strconv.Itoa(direction),
|
DirStr: strconv.Itoa(direction),
|
||||||
ProtocolStr: string(protocol),
|
ProtocolStr: string(protocol),
|
||||||
@@ -1280,7 +1281,7 @@ func (a *Account) getRouteFirewallRules(ctx context.Context, peerID string, poli
|
|||||||
return fwRules
|
return fwRules
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) getRulePeers(rule *PolicyRule, postureChecks []string, peerID string, distributionPeers map[string]struct{}, validatedPeersMap map[string]struct{}) []*nbpeer.Peer {
|
func (a *Account) getRulePeers(rule *PolicyRule, postureChecks []string, peerID string, distributionPeers map[string]struct{}, validatedPeersMap map[string]struct{}) []*ComponentPeer {
|
||||||
distPeersWithPolicy := make(map[string]struct{})
|
distPeersWithPolicy := make(map[string]struct{})
|
||||||
for _, id := range rule.Sources {
|
for _, id := range rule.Sources {
|
||||||
group := a.Groups[id]
|
group := a.Groups[id]
|
||||||
@@ -1307,13 +1308,13 @@ func (a *Account) getRulePeers(rule *PolicyRule, postureChecks []string, peerID
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
distributionGroupPeers := make([]*nbpeer.Peer, 0, len(distPeersWithPolicy))
|
distributionGroupPeers := make([]*ComponentPeer, 0, len(distPeersWithPolicy))
|
||||||
for pID := range distPeersWithPolicy {
|
for pID := range distPeersWithPolicy {
|
||||||
peer := a.Peers[pID]
|
peer := a.Peers[pID]
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
distributionGroupPeers = append(distributionGroupPeers, peer)
|
distributionGroupPeers = append(distributionGroupPeers, peer.ToComponent())
|
||||||
}
|
}
|
||||||
return distributionGroupPeers
|
return distributionGroupPeers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import (
|
|||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/internals/modules/zones"
|
"github.com/netbirdio/netbird/management/internals/modules/zones"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
@@ -113,7 +111,7 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
PeerID: peerID,
|
PeerID: peerID,
|
||||||
Network: a.Network.Copy(),
|
Network: a.Network.Copy(),
|
||||||
// must include the target peer as it's required on the client
|
// must include the target peer as it's required on the client
|
||||||
Peers: map[string]*nbpeer.Peer{peerID: peer},
|
Peers: map[string]*ComponentPeer{peerID: peer.ToComponent()},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +124,7 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
PeerID: peerID,
|
PeerID: peerID,
|
||||||
Network: a.Network.Copy(),
|
Network: a.Network.Copy(),
|
||||||
// must include the target peer as it's required on the client
|
// must include the target peer as it's required on the client
|
||||||
Peers: map[string]*nbpeer.Peer{peerID: peer},
|
Peers: map[string]*ComponentPeer{peerID: peer.ToComponent()},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,10 +134,10 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
NameServerGroups: make([]*nbdns.NameServerGroup, 0),
|
NameServerGroups: make([]*nbdns.NameServerGroup, 0),
|
||||||
CustomZoneDomain: peersCustomZone.Domain,
|
CustomZoneDomain: peersCustomZone.Domain,
|
||||||
ResourcePoliciesMap: make(map[string][]*Policy),
|
ResourcePoliciesMap: make(map[string][]*Policy),
|
||||||
RoutersMap: make(map[string]map[string]*routerTypes.NetworkRouter),
|
RoutersMap: make(map[string]map[string]*ComponentRouter),
|
||||||
NetworkResources: make([]*resourceTypes.NetworkResource, 0),
|
NetworkResources: make([]*ComponentResource, 0),
|
||||||
PostureFailedPeers: make(map[string]map[string]struct{}, len(a.PostureChecks)),
|
PostureFailedPeers: make(map[string]map[string]struct{}, len(a.PostureChecks)),
|
||||||
RouterPeers: make(map[string]*nbpeer.Peer),
|
RouterPeers: make(map[string]*ComponentPeer),
|
||||||
NetworkXIDToPublicID: make(map[string]string, len(a.Networks)),
|
NetworkXIDToPublicID: make(map[string]string, len(a.Networks)),
|
||||||
PostureCheckXIDToPublicID: make(map[string]string, len(a.PostureChecks)),
|
PostureCheckXIDToPublicID: make(map[string]string, len(a.PostureChecks)),
|
||||||
}
|
}
|
||||||
@@ -174,7 +172,7 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
components.Peers = relevantPeers
|
components.Peers = relevantPeers
|
||||||
components.Groups = relevantGroups
|
components.Groups = GroupsToComponent(relevantGroups)
|
||||||
components.Policies = relevantPolicies
|
components.Policies = relevantPolicies
|
||||||
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())
|
||||||
@@ -223,7 +221,7 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
}
|
}
|
||||||
for _, pID := range a.getPostureValidPeersSaveFailed(peers, policy.SourcePostureChecks, validatedPeersMap, &components.PostureFailedPeers) {
|
for _, pID := range a.getPostureValidPeersSaveFailed(peers, policy.SourcePostureChecks, validatedPeersMap, &components.PostureFailedPeers) {
|
||||||
if _, exists := components.Peers[pID]; !exists {
|
if _, exists := components.Peers[pID]; !exists {
|
||||||
components.Peers[pID] = a.GetPeer(pID)
|
components.Peers[pID] = a.GetPeer(pID).ToComponent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -256,14 +254,14 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
for _, srcGroupID := range rule.Sources {
|
for _, srcGroupID := range rule.Sources {
|
||||||
if g := a.Groups[srcGroupID]; g != nil {
|
if g := a.Groups[srcGroupID]; g != nil {
|
||||||
if _, exists := components.Groups[srcGroupID]; !exists {
|
if _, exists := components.Groups[srcGroupID]; !exists {
|
||||||
components.Groups[srcGroupID] = g
|
components.Groups[srcGroupID] = g.ToComponent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, dstGroupID := range rule.Destinations {
|
for _, dstGroupID := range rule.Destinations {
|
||||||
if g := a.Groups[dstGroupID]; g != nil {
|
if g := a.Groups[dstGroupID]; g != nil {
|
||||||
if _, exists := components.Groups[dstGroupID]; !exists {
|
if _, exists := components.Groups[dstGroupID]; !exists {
|
||||||
components.Groups[dstGroupID] = g
|
components.Groups[dstGroupID] = g.ToComponent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,20 +276,22 @@ func (a *Account) GetPeerNetworkMapComponents(
|
|||||||
// network in the account — accounts with many tenants/networks
|
// network in the account — accounts with many tenants/networks
|
||||||
// shipped tens of unrelated peers in `peers[]` and `routers_map`.
|
// shipped tens of unrelated peers in `peers[]` and `routers_map`.
|
||||||
if addSourcePeers {
|
if addSourcePeers {
|
||||||
components.RoutersMap[resource.NetworkID] = networkRoutingPeers
|
components.RoutersMap[resource.NetworkID] = routerTypes.ToComponentMap(networkRoutingPeers)
|
||||||
for peerIDKey := range networkRoutingPeers {
|
for peerIDKey := range networkRoutingPeers {
|
||||||
if p := a.Peers[peerIDKey]; p != nil {
|
if p := a.Peers[peerIDKey]; p != nil {
|
||||||
if _, exists := components.RouterPeers[peerIDKey]; !exists {
|
cp := components.RouterPeers[peerIDKey]
|
||||||
components.RouterPeers[peerIDKey] = p
|
if cp == nil {
|
||||||
|
cp = p.ToComponent()
|
||||||
|
components.RouterPeers[peerIDKey] = cp
|
||||||
}
|
}
|
||||||
if _, exists := components.Peers[peerIDKey]; !exists {
|
if _, exists := components.Peers[peerIDKey]; !exists {
|
||||||
if _, validated := validatedPeersMap[peerIDKey]; validated {
|
if _, validated := validatedPeersMap[peerIDKey]; validated {
|
||||||
components.Peers[peerIDKey] = p
|
components.Peers[peerIDKey] = cp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
components.NetworkResources = append(components.NetworkResources, resource)
|
components.NetworkResources = append(components.NetworkResources, resource.ToComponent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,14 +312,14 @@ func (a *Account) getPeersGroupsPoliciesRoutes(
|
|||||||
peerSSHEnabled bool,
|
peerSSHEnabled bool,
|
||||||
validatedPeersMap map[string]struct{},
|
validatedPeersMap map[string]struct{},
|
||||||
postureFailedPeers *map[string]map[string]struct{},
|
postureFailedPeers *map[string]map[string]struct{},
|
||||||
) (map[string]*nbpeer.Peer, map[string]*Group, []*Policy, []*route.Route, sshRequirements) {
|
) (map[string]*ComponentPeer, map[string]*Group, []*Policy, []*route.Route, sshRequirements) {
|
||||||
relevantPeerIDs := make(map[string]*nbpeer.Peer, len(a.Peers)/4)
|
relevantPeerIDs := make(map[string]*ComponentPeer, len(a.Peers)/4)
|
||||||
relevantGroupIDs := make(map[string]*Group, len(a.Groups)/4)
|
relevantGroupIDs := make(map[string]*Group, len(a.Groups)/4)
|
||||||
relevantPolicies := make([]*Policy, 0, len(a.Policies))
|
relevantPolicies := make([]*Policy, 0, len(a.Policies))
|
||||||
relevantRoutes := make([]*route.Route, 0, len(a.Routes))
|
relevantRoutes := make([]*route.Route, 0, len(a.Routes))
|
||||||
sshReqs := sshRequirements{neededGroupIDs: make(map[string]struct{})}
|
sshReqs := sshRequirements{neededGroupIDs: make(map[string]struct{})}
|
||||||
|
|
||||||
relevantPeerIDs[peerID] = a.GetPeer(peerID)
|
relevantPeerIDs[peerID] = a.GetPeer(peerID).ToComponent()
|
||||||
|
|
||||||
peerGroupSet := make(map[string]struct{}, 8)
|
peerGroupSet := make(map[string]struct{}, 8)
|
||||||
for groupID, group := range a.Groups {
|
for groupID, group := range a.Groups {
|
||||||
@@ -384,7 +384,7 @@ func (a *Account) getPeersGroupsPoliciesRoutes(
|
|||||||
if r.Peer != "" {
|
if r.Peer != "" {
|
||||||
if _, ok := validatedPeersMap[r.Peer]; ok {
|
if _, ok := validatedPeersMap[r.Peer]; ok {
|
||||||
if p := a.GetPeer(r.Peer); p != nil {
|
if p := a.GetPeer(r.Peer); p != nil {
|
||||||
relevantPeerIDs[r.Peer] = p
|
relevantPeerIDs[r.Peer] = p.ToComponent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,7 +401,7 @@ func (a *Account) getPeersGroupsPoliciesRoutes(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if p := a.GetPeer(pid); p != nil {
|
if p := a.GetPeer(pid); p != nil {
|
||||||
relevantPeerIDs[pid] = p
|
relevantPeerIDs[pid] = p.ToComponent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,7 +458,9 @@ func (a *Account) getPeersGroupsPoliciesRoutes(
|
|||||||
if peerInSources {
|
if peerInSources {
|
||||||
policyRelevant = true
|
policyRelevant = true
|
||||||
for _, pid := range destinationPeers {
|
for _, pid := range destinationPeers {
|
||||||
relevantPeerIDs[pid] = a.GetPeer(pid)
|
if _, exists := relevantPeerIDs[pid]; !exists {
|
||||||
|
relevantPeerIDs[pid] = a.GetPeer(pid).ToComponent()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, dstGroupID := range rule.Destinations {
|
for _, dstGroupID := range rule.Destinations {
|
||||||
relevantGroupIDs[dstGroupID] = a.GetGroup(dstGroupID)
|
relevantGroupIDs[dstGroupID] = a.GetGroup(dstGroupID)
|
||||||
@@ -468,7 +470,9 @@ func (a *Account) getPeersGroupsPoliciesRoutes(
|
|||||||
if peerInDestinations {
|
if peerInDestinations {
|
||||||
policyRelevant = true
|
policyRelevant = true
|
||||||
for _, pid := range sourcePeers {
|
for _, pid := range sourcePeers {
|
||||||
relevantPeerIDs[pid] = a.GetPeer(pid)
|
if _, exists := relevantPeerIDs[pid]; !exists {
|
||||||
|
relevantPeerIDs[pid] = a.GetPeer(pid).ToComponent()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, srcGroupID := range rule.Sources {
|
for _, srcGroupID := range rule.Sources {
|
||||||
relevantGroupIDs[srcGroupID] = a.GetGroup(srcGroupID)
|
relevantGroupIDs[srcGroupID] = a.GetGroup(srcGroupID)
|
||||||
@@ -624,7 +628,7 @@ func (a *Account) getPostureValidPeersSaveFailed(inputPeers []string, postureChe
|
|||||||
// that name them. Calculate() tolerates groups with empty Peers (the inner
|
// that name them. Calculate() tolerates groups with empty Peers (the inner
|
||||||
// loops simply iterate zero times), so retaining them is behaviourally a
|
// loops simply iterate zero times), so retaining them is behaviourally a
|
||||||
// no-op for the legacy path that consumes the same NetworkMapComponents.
|
// no-op for the legacy path that consumes the same NetworkMapComponents.
|
||||||
func filterGroupPeers(groups *map[string]*Group, peers map[string]*nbpeer.Peer) {
|
func filterGroupPeers(groups *map[string]*ComponentGroup, peers map[string]*ComponentPeer) {
|
||||||
for groupID, groupInfo := range *groups {
|
for groupID, groupInfo := range *groups {
|
||||||
filteredPeers := make([]string, 0, len(groupInfo.Peers))
|
filteredPeers := make([]string, 0, len(groupInfo.Peers))
|
||||||
for _, pid := range groupInfo.Peers {
|
for _, pid := range groupInfo.Peers {
|
||||||
@@ -634,14 +638,14 @@ func filterGroupPeers(groups *map[string]*Group, peers map[string]*nbpeer.Peer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(filteredPeers) != len(groupInfo.Peers) {
|
if len(filteredPeers) != len(groupInfo.Peers) {
|
||||||
ng := groupInfo.Copy()
|
ng := *groupInfo
|
||||||
ng.Peers = filteredPeers
|
ng.Peers = filteredPeers
|
||||||
(*groups)[groupID] = ng
|
(*groups)[groupID] = &ng
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterPostureFailedPeers(postureFailedPeers *map[string]map[string]struct{}, policies []*Policy, resourcePoliciesMap map[string][]*Policy, peers map[string]*nbpeer.Peer) {
|
func filterPostureFailedPeers(postureFailedPeers *map[string]map[string]struct{}, policies []*Policy, resourcePoliciesMap map[string][]*Policy, peers map[string]*ComponentPeer) {
|
||||||
if len(*postureFailedPeers) == 0 {
|
if len(*postureFailedPeers) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -676,7 +680,7 @@ func filterPostureFailedPeers(postureFailedPeers *map[string]map[string]struct{}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterDNSRecordsByPeers(records []nbdns.SimpleRecord, peers map[string]*nbpeer.Peer, includeIPv6 bool) []nbdns.SimpleRecord {
|
func filterDNSRecordsByPeers(records []nbdns.SimpleRecord, peers map[string]*ComponentPeer, includeIPv6 bool) []nbdns.SimpleRecord {
|
||||||
if len(records) == 0 || len(peers) == 0 {
|
if len(records) == 0 || len(peers) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPrivateService_NetworkMap_UserPeer_AndProxyPeer(t *testing.T) {
|
func TestPrivateService_NetworkMap_UserPeer_AndProxyPeer(t *testing.T) {
|
||||||
@@ -49,7 +48,7 @@ func TestPrivateService_NetworkMap_UserPeer_AndProxyPeer(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func netmapPeerIDs(peers []*nbpeer.Peer) []string {
|
func netmapPeerIDs(peers []*ComponentPeer) []string {
|
||||||
ids := make([]string, 0, len(peers))
|
ids := make([]string, 0, len(peers))
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ func Test_ExpandPortsAndRanges_SSHRuleExpansion(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := ExpandPortsAndRanges(tt.base, tt.rule, tt.peer)
|
result := ExpandPortsAndRanges(tt.base, tt.rule, tt.peer.ToComponent())
|
||||||
|
|
||||||
var ports []string
|
var ports []string
|
||||||
for _, fr := range result {
|
for _, fr := range result {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "github.com/netbirdio/netbird/route"
|
||||||
sharedtypes "github.com/netbirdio/netbird/shared/management/types"
|
sharedtypes "github.com/netbirdio/netbird/shared/management/types"
|
||||||
)
|
)
|
||||||
@@ -18,9 +17,6 @@ type DNSSettings = sharedtypes.DNSSettings
|
|||||||
|
|
||||||
type FirewallRule = sharedtypes.FirewallRule
|
type FirewallRule = sharedtypes.FirewallRule
|
||||||
|
|
||||||
type Group = sharedtypes.Group
|
|
||||||
type GroupPeer = sharedtypes.GroupPeer
|
|
||||||
|
|
||||||
type Network = sharedtypes.Network
|
type Network = sharedtypes.Network
|
||||||
type NetworkMap = sharedtypes.NetworkMap
|
type NetworkMap = sharedtypes.NetworkMap
|
||||||
type ForwardingRule = sharedtypes.ForwardingRule
|
type ForwardingRule = sharedtypes.ForwardingRule
|
||||||
@@ -42,6 +38,18 @@ type RouteFirewallRule = sharedtypes.RouteFirewallRule
|
|||||||
|
|
||||||
type NetworkMapComponents = sharedtypes.NetworkMapComponents
|
type NetworkMapComponents = sharedtypes.NetworkMapComponents
|
||||||
|
|
||||||
|
type ComponentPeer = sharedtypes.ComponentPeer
|
||||||
|
type ComponentGroup = sharedtypes.ComponentGroup
|
||||||
|
type ComponentRouter = sharedtypes.ComponentRouter
|
||||||
|
type ComponentResource = sharedtypes.ComponentResource
|
||||||
|
type ComponentResourceType = sharedtypes.ComponentResourceType
|
||||||
|
|
||||||
|
const (
|
||||||
|
ComponentResourceHost = sharedtypes.ComponentResourceHost
|
||||||
|
ComponentResourceSubnet = sharedtypes.ComponentResourceSubnet
|
||||||
|
ComponentResourceDomain = sharedtypes.ComponentResourceDomain
|
||||||
|
)
|
||||||
|
|
||||||
var EmptyNetworkMapComponents = sharedtypes.EmptyNetworkMapComponents
|
var EmptyNetworkMapComponents = sharedtypes.EmptyNetworkMapComponents
|
||||||
|
|
||||||
type AccountSettingsInfo = sharedtypes.AccountSettingsInfo
|
type AccountSettingsInfo = sharedtypes.AccountSettingsInfo
|
||||||
@@ -52,12 +60,7 @@ type NetworkMapComponentsCompact = sharedtypes.NetworkMapComponentsCompact
|
|||||||
type LookupMap = sharedtypes.LookupMap
|
type LookupMap = sharedtypes.LookupMap
|
||||||
type FirewallRuleContext = sharedtypes.FirewallRuleContext
|
type FirewallRuleContext = sharedtypes.FirewallRuleContext
|
||||||
|
|
||||||
const (
|
const GroupAllName = sharedtypes.GroupAllName
|
||||||
GroupIssuedAPI = sharedtypes.GroupIssuedAPI
|
|
||||||
GroupIssuedJWT = sharedtypes.GroupIssuedJWT
|
|
||||||
GroupIssuedIntegration = sharedtypes.GroupIssuedIntegration
|
|
||||||
GroupAllName = sharedtypes.GroupAllName
|
|
||||||
)
|
|
||||||
|
|
||||||
// Function forwarders preserve types.X(...) call sites that previously
|
// Function forwarders preserve types.X(...) call sites that previously
|
||||||
// resolved to package-local funcs. Plain forwarders (not var aliases) keep
|
// resolved to package-local funcs. Plain forwarders (not var aliases) keep
|
||||||
@@ -67,11 +70,11 @@ func PolicyRuleImpliesLegacySSH(rule *PolicyRule) bool {
|
|||||||
return sharedtypes.PolicyRuleImpliesLegacySSH(rule)
|
return sharedtypes.PolicyRuleImpliesLegacySSH(rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExpandPortsAndRanges(base FirewallRule, rule *PolicyRule, peer *nbpeer.Peer) []*FirewallRule {
|
func ExpandPortsAndRanges(base FirewallRule, rule *PolicyRule, peer *ComponentPeer) []*FirewallRule {
|
||||||
return sharedtypes.ExpandPortsAndRanges(base, rule, peer)
|
return sharedtypes.ExpandPortsAndRanges(base, rule, peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AppendIPv6FirewallRule(rules []*FirewallRule, rulesExists map[string]struct{}, peer, targetPeer *nbpeer.Peer, rule *PolicyRule, rc FirewallRuleContext) []*FirewallRule {
|
func AppendIPv6FirewallRule(rules []*FirewallRule, rulesExists map[string]struct{}, peer, targetPeer *ComponentPeer, rule *PolicyRule, rc FirewallRuleContext) []*FirewallRule {
|
||||||
return sharedtypes.AppendIPv6FirewallRule(rules, rulesExists, peer, targetPeer, rule, rc)
|
return sharedtypes.AppendIPv6FirewallRule(rules, rulesExists, peer, targetPeer, rule, rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +82,7 @@ func CalculateNetworkMapFromComponents(ctx context.Context, components *NetworkM
|
|||||||
return sharedtypes.CalculateNetworkMapFromComponents(ctx, components)
|
return sharedtypes.CalculateNetworkMapFromComponents(ctx, components)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule *PolicyRule, groupPeers []*nbpeer.Peer, direction int, includeIPv6 bool) []*RouteFirewallRule {
|
func GenerateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule *PolicyRule, groupPeers []*ComponentPeer, direction int, includeIPv6 bool) []*RouteFirewallRule {
|
||||||
return sharedtypes.GenerateRouteFirewallRules(ctx, route, rule, groupPeers, direction, includeIPv6)
|
return sharedtypes.GenerateRouteFirewallRules(ctx, route, rule, groupPeers, direction, includeIPv6)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/netbirdio/netbird/management/server/integration_reference"
|
"github.com/netbirdio/netbird/management/server/integration_reference"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -68,10 +67,6 @@ func (g *Group) EventMeta() map[string]any {
|
|||||||
return map[string]any{"name": g.Name}
|
return map[string]any{"name": g.Name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) EventMetaResource(resource *types.NetworkResource) map[string]any {
|
|
||||||
return map[string]any{"name": g.Name, "id": g.ID, "resource_name": resource.Name, "resource_id": resource.ID, "resource_type": resource.Type}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Group) Copy() *Group {
|
func (g *Group) Copy() *Group {
|
||||||
group := &Group{
|
group := &Group{
|
||||||
ID: g.ID,
|
ID: g.ID,
|
||||||
@@ -95,14 +90,39 @@ func (g *Group) HasPeers() bool {
|
|||||||
return len(g.Peers) > 0
|
return len(g.Peers) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupAllName is the reserved name of the default group that contains every peer in an account.
|
|
||||||
const GroupAllName = "All"
|
|
||||||
|
|
||||||
// IsGroupAll checks if the group is a default "All" group.
|
// IsGroupAll checks if the group is a default "All" group.
|
||||||
func (g *Group) IsGroupAll() bool {
|
func (g *Group) IsGroupAll() bool {
|
||||||
return g.Name == GroupAllName
|
return g.Name == GroupAllName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToComponent converts the group to its self-contained components
|
||||||
|
// representation. The Peers slice is shared, not copied — components are
|
||||||
|
// treated as immutable snapshots. Returns nil for a nil group.
|
||||||
|
func (g *Group) ToComponent() *ComponentGroup {
|
||||||
|
if g == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ComponentGroup{
|
||||||
|
ID: g.ID,
|
||||||
|
PublicID: g.PublicID,
|
||||||
|
Name: g.Name,
|
||||||
|
Peers: g.Peers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsToComponent converts an id-keyed group map to its components
|
||||||
|
// representation, preserving nil entries.
|
||||||
|
func GroupsToComponent(groups map[string]*Group) map[string]*ComponentGroup {
|
||||||
|
if groups == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make(map[string]*ComponentGroup, len(groups))
|
||||||
|
for id, g := range groups {
|
||||||
|
out[id] = g.ToComponent()
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// AddPeer adds peerID to Peers if not present, returning true if added.
|
// AddPeer adds peerID to Peers if not present, returning true if added.
|
||||||
func (g *Group) AddPeer(peerID string) bool {
|
func (g *Group) AddPeer(peerID string) bool {
|
||||||
if peerID == "" {
|
if peerID == "" {
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNetworkMapComponents_IPv6EndToEnd(t *testing.T) {
|
func TestNetworkMapComponents_IPv6EndToEnd(t *testing.T) {
|
||||||
@@ -104,7 +105,7 @@ func TestNetworkMapComponents_RemotePeerWithoutCapability(t *testing.T) {
|
|||||||
require.NotNil(t, nm)
|
require.NotNil(t, nm)
|
||||||
|
|
||||||
t.Run("AllowedIPs include remote v6", func(t *testing.T) {
|
t.Run("AllowedIPs include remote v6", func(t *testing.T) {
|
||||||
var dst *nbpeer.Peer
|
var dst *types.ComponentPeer
|
||||||
for _, p := range nm.Peers {
|
for _, p := range nm.Peers {
|
||||||
if p.ID == "peer-dst-1" {
|
if p.ID == "peer-dst-1" {
|
||||||
dst = p
|
dst = p
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func allPeersValidated(account *types.Account, excludePeerIDs ...string) map[str
|
|||||||
return validated
|
return validated
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerIDs(peers []*nbpeer.Peer) []string {
|
func peerIDs(peers []*types.ComponentPeer) []string {
|
||||||
ids := make([]string, len(peers))
|
ids := make([]string, len(peers))
|
||||||
for i, p := range peers {
|
for i, p := range peers {
|
||||||
ids[i] = p.ID
|
ids[i] = p.ID
|
||||||
|
|||||||
@@ -19,34 +19,3 @@ func Difference(a, b []string) []string {
|
|||||||
func ToPtr[T any](value T) *T {
|
func ToPtr[T any](value T) *T {
|
||||||
return &value
|
return &value
|
||||||
}
|
}
|
||||||
|
|
||||||
type comparableObject[T any] interface {
|
|
||||||
Equal(other T) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func MergeUnique[T comparableObject[T]](arr1, arr2 []T) []T {
|
|
||||||
var result []T
|
|
||||||
|
|
||||||
for _, item := range arr1 {
|
|
||||||
if !contains(result, item) {
|
|
||||||
result = append(result, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, item := range arr2 {
|
|
||||||
if !contains(result, item) {
|
|
||||||
result = append(result, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains[T comparableObject[T]](slice []T, element T) bool {
|
|
||||||
for _, item := range slice {
|
|
||||||
if item.Equal(element) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "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/proto"
|
"github.com/netbirdio/netbird/shared/management/proto"
|
||||||
@@ -38,17 +35,17 @@ func DecodeEnvelope(env *proto.NetworkMapEnvelope) (*types.NetworkMapComponents,
|
|||||||
Network: decodeAccountNetwork(full.Network),
|
Network: decodeAccountNetwork(full.Network),
|
||||||
AccountSettings: decodeAccountSettings(full.AccountSettings),
|
AccountSettings: decodeAccountSettings(full.AccountSettings),
|
||||||
CustomZoneDomain: full.CustomZoneDomain,
|
CustomZoneDomain: full.CustomZoneDomain,
|
||||||
Peers: make(map[string]*nbpeer.Peer, len(full.Peers)),
|
Peers: make(map[string]*types.ComponentPeer, len(full.Peers)),
|
||||||
Groups: make(map[string]*types.Group, len(full.Groups)),
|
Groups: make(map[string]*types.ComponentGroup, len(full.Groups)),
|
||||||
Policies: make([]*types.Policy, 0, len(full.Policies)),
|
Policies: make([]*types.Policy, 0, len(full.Policies)),
|
||||||
Routes: make([]*nbroute.Route, 0, len(full.Routes)),
|
Routes: make([]*nbroute.Route, 0, len(full.Routes)),
|
||||||
NameServerGroups: make([]*nbdns.NameServerGroup, 0, len(full.NameserverGroups)),
|
NameServerGroups: make([]*nbdns.NameServerGroup, 0, len(full.NameserverGroups)),
|
||||||
AllDNSRecords: decodeSimpleRecords(full.AllDnsRecords),
|
AllDNSRecords: decodeSimpleRecords(full.AllDnsRecords),
|
||||||
AccountZones: decodeCustomZones(full.AccountZones),
|
AccountZones: decodeCustomZones(full.AccountZones),
|
||||||
ResourcePoliciesMap: make(map[string][]*types.Policy),
|
ResourcePoliciesMap: make(map[string][]*types.Policy),
|
||||||
RoutersMap: make(map[string]map[string]*routerTypes.NetworkRouter),
|
RoutersMap: make(map[string]map[string]*types.ComponentRouter),
|
||||||
NetworkResources: make([]*resourceTypes.NetworkResource, 0, len(full.NetworkResources)),
|
NetworkResources: make([]*types.ComponentResource, 0, len(full.NetworkResources)),
|
||||||
RouterPeers: make(map[string]*nbpeer.Peer),
|
RouterPeers: make(map[string]*types.ComponentPeer),
|
||||||
AllowedUserIDs: stringSliceToSet(full.AllowedUserIds),
|
AllowedUserIDs: stringSliceToSet(full.AllowedUserIds),
|
||||||
PostureFailedPeers: make(map[string]map[string]struct{}, len(full.PostureFailedPeers)),
|
PostureFailedPeers: make(map[string]map[string]struct{}, len(full.PostureFailedPeers)),
|
||||||
GroupIDToUserIDs: make(map[string][]string, len(full.GroupIdToUserIds)),
|
GroupIDToUserIDs: make(map[string][]string, len(full.GroupIdToUserIds)),
|
||||||
@@ -101,7 +98,7 @@ func DecodeEnvelope(env *proto.NetworkMapEnvelope) (*types.NetworkMapComponents,
|
|||||||
log.WithField("peer idx", idx).Error("unrecognized peer idx during decoding")
|
log.WithField("peer idx", idx).Error("unrecognized peer idx during decoding")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
group := &types.Group{
|
group := &types.ComponentGroup{
|
||||||
ID: groupID,
|
ID: groupID,
|
||||||
PublicID: gc.Id,
|
PublicID: gc.Id,
|
||||||
Peers: peerIDs,
|
Peers: peerIDs,
|
||||||
@@ -151,7 +148,7 @@ func DecodeEnvelope(env *proto.NetworkMapEnvelope) (*types.NetworkMapComponents,
|
|||||||
// Phase 7: routers_map (outer key = network seq id, inner key = peer-id
|
// Phase 7: routers_map (outer key = network seq id, inner key = peer-id
|
||||||
// reconstructed from peer_index). Synthesized network id is "net_<seq>".
|
// reconstructed from peer_index). Synthesized network id is "net_<seq>".
|
||||||
for networkID, list := range full.RoutersMap {
|
for networkID, list := range full.RoutersMap {
|
||||||
inner := make(map[string]*routerTypes.NetworkRouter, len(list.Entries))
|
inner := make(map[string]*types.ComponentRouter, len(list.Entries))
|
||||||
for _, entry := range list.Entries {
|
for _, entry := range list.Entries {
|
||||||
if !entry.PeerIndexSet {
|
if !entry.PeerIndexSet {
|
||||||
continue
|
continue
|
||||||
@@ -161,8 +158,7 @@ func DecodeEnvelope(env *proto.NetworkMapEnvelope) (*types.NetworkMapComponents,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
peerID := peerIDByIndex[entry.PeerIndex]
|
peerID := peerIDByIndex[entry.PeerIndex]
|
||||||
inner[peerID] = &routerTypes.NetworkRouter{
|
inner[peerID] = &types.ComponentRouter{
|
||||||
ID: "",
|
|
||||||
NetworkID: networkID,
|
NetworkID: networkID,
|
||||||
PublicID: entry.Id,
|
PublicID: entry.Id,
|
||||||
Peer: peerID,
|
Peer: peerID,
|
||||||
@@ -264,40 +260,22 @@ func decodeAccountSettings(as *proto.AccountSettingsCompact) *types.AccountSetti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodePeerCompact(pc *proto.PeerCompact, peerID string) *nbpeer.Peer {
|
func decodePeerCompact(pc *proto.PeerCompact, peerID string) *types.ComponentPeer {
|
||||||
var caps []int32
|
peer := &types.ComponentPeer{
|
||||||
if pc.SupportsSourcePrefixes {
|
|
||||||
caps = append(caps, nbpeer.PeerCapabilitySourcePrefixes)
|
|
||||||
}
|
|
||||||
if pc.SupportsIpv6 {
|
|
||||||
caps = append(caps, nbpeer.PeerCapabilityIPv6Overlay)
|
|
||||||
}
|
|
||||||
peer := &nbpeer.Peer{
|
|
||||||
ID: peerID,
|
ID: peerID,
|
||||||
Key: peerID,
|
Key: peerID,
|
||||||
SSHKey: string(pc.SshPubKey),
|
SSHKey: string(pc.SshPubKey),
|
||||||
SSHEnabled: pc.SshEnabled,
|
SSHEnabled: pc.SshEnabled,
|
||||||
DNSLabel: pc.DnsLabel,
|
DNSLabel: pc.DnsLabel,
|
||||||
LoginExpirationEnabled: pc.LoginExpirationEnabled,
|
LoginExpirationEnabled: pc.LoginExpirationEnabled,
|
||||||
Meta: nbpeer.PeerSystemMeta{
|
AgentVersion: pc.AgentVersion,
|
||||||
WtVersion: pc.AgentVersion,
|
SupportsSourcePrefixes: pc.SupportsSourcePrefixes,
|
||||||
Capabilities: caps,
|
SupportsIPv6: pc.SupportsIpv6,
|
||||||
Flags: nbpeer.Flags{
|
ServerSSHAllowed: pc.ServerSshAllowed,
|
||||||
ServerSSHAllowed: pc.ServerSshAllowed,
|
AddedWithSSOLogin: pc.AddedWithSsoLogin,
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if pc.AddedWithSsoLogin {
|
|
||||||
// Set a non-empty UserID so (*Peer).AddedWithSSOLogin() returns true.
|
|
||||||
// The original UserID isn't on the wire; the value is intentionally
|
|
||||||
// visibly synthetic so any future consumer that mistakes UserID for a
|
|
||||||
// real account user xid won't silently match (or worse, write the
|
|
||||||
// sentinel into a downstream record).
|
|
||||||
peer.UserID = "<env-sso>"
|
|
||||||
}
|
}
|
||||||
if pc.LastLoginUnixNano != 0 {
|
if pc.LastLoginUnixNano != 0 {
|
||||||
t := time.Unix(0, pc.LastLoginUnixNano)
|
peer.LastLogin = time.Unix(0, pc.LastLoginUnixNano)
|
||||||
peer.LastLogin = &t
|
|
||||||
}
|
}
|
||||||
switch len(pc.Ip) {
|
switch len(pc.Ip) {
|
||||||
case 4:
|
case 4:
|
||||||
@@ -424,14 +402,14 @@ func decodeNameServerGroupRaw(nsg *proto.NameServerGroupRaw) *nbdns.NameServerGr
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeNetworkResource(nr *proto.NetworkResourceRaw) *resourceTypes.NetworkResource {
|
func decodeNetworkResource(nr *proto.NetworkResourceRaw) *types.ComponentResource {
|
||||||
out := &resourceTypes.NetworkResource{
|
out := &types.ComponentResource{
|
||||||
ID: nr.Id,
|
ID: nr.Id,
|
||||||
PublicID: nr.Id,
|
PublicID: nr.Id,
|
||||||
NetworkID: nr.NetworkSeq,
|
NetworkID: nr.NetworkSeq,
|
||||||
Name: nr.Name,
|
Name: nr.Name,
|
||||||
Description: nr.Description,
|
Description: nr.Description,
|
||||||
Type: resourceTypes.NetworkResourceType(nr.Type),
|
Type: types.ComponentResourceType(nr.Type),
|
||||||
Address: nr.Address,
|
Address: nr.Address,
|
||||||
Domain: nr.DomainValue,
|
Domain: nr.DomainValue,
|
||||||
Enabled: nr.Enabled,
|
Enabled: nr.Enabled,
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ import (
|
|||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/shared/management/types"
|
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/proto"
|
"github.com/netbirdio/netbird/shared/management/proto"
|
||||||
|
"github.com/netbirdio/netbird/shared/management/types"
|
||||||
"github.com/netbirdio/netbird/shared/netiputil"
|
"github.com/netbirdio/netbird/shared/netiputil"
|
||||||
"github.com/netbirdio/netbird/shared/sshauth"
|
"github.com/netbirdio/netbird/shared/sshauth"
|
||||||
)
|
)
|
||||||
@@ -274,7 +273,7 @@ func ToProtocolDNSConfig(update nbdns.Config, cache DNSConfigCache, forwardPort
|
|||||||
|
|
||||||
// AppendRemotePeerConfig appends typed peers as proto.RemotePeerConfig
|
// AppendRemotePeerConfig appends typed peers as proto.RemotePeerConfig
|
||||||
// entries to dst and returns the result.
|
// entries to dst and returns the result.
|
||||||
func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*nbpeer.Peer, dnsName string, includeIPv6 bool) []*proto.RemotePeerConfig {
|
func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*types.ComponentPeer, dnsName string, includeIPv6 bool) []*proto.RemotePeerConfig {
|
||||||
for _, rPeer := range peers {
|
for _, rPeer := range peers {
|
||||||
allowedIPs := []string{rPeer.IP.String() + "/32"}
|
allowedIPs := []string{rPeer.IP.String() + "/32"}
|
||||||
if includeIPv6 && rPeer.IPv6.IsValid() {
|
if includeIPv6 && rPeer.IPv6.IsValid() {
|
||||||
@@ -285,7 +284,7 @@ func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*nbpeer.Peer,
|
|||||||
AllowedIps: allowedIPs,
|
AllowedIps: allowedIPs,
|
||||||
SshConfig: &proto.SSHConfig{SshPubKey: []byte(rPeer.SSHKey)},
|
SshConfig: &proto.SSHConfig{SshPubKey: []byte(rPeer.SSHKey)},
|
||||||
Fqdn: rPeer.FQDN(dnsName),
|
Fqdn: rPeer.FQDN(dnsName),
|
||||||
AgentVersion: rPeer.Meta.WtVersion,
|
AgentVersion: rPeer.AgentVersion,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return dst
|
return dst
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ func EnvelopeToNetworkMap(ctx context.Context, env *proto.NetworkMapEnvelope, lo
|
|||||||
}
|
}
|
||||||
components.PeerID = canonicalKey
|
components.PeerID = canonicalKey
|
||||||
|
|
||||||
includeIPv6 := localPeer.SupportsIPv6() && localPeer.IPv6.IsValid()
|
includeIPv6 := localPeer.SupportsIPv6 && localPeer.IPv6.IsValid()
|
||||||
useSourcePrefixes := localPeer.SupportsSourcePrefixes()
|
useSourcePrefixes := localPeer.SupportsSourcePrefixes
|
||||||
|
|
||||||
typedNM := components.Calculate(ctx)
|
typedNM := components.Calculate(ctx)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
goproto "google.golang.org/protobuf/proto"
|
goproto "google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
mgmtgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
|
mgmtgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
nbnetworkmap "github.com/netbirdio/netbird/shared/management/networkmap"
|
nbnetworkmap "github.com/netbirdio/netbird/shared/management/networkmap"
|
||||||
"github.com/netbirdio/netbird/shared/management/proto"
|
"github.com/netbirdio/netbird/shared/management/proto"
|
||||||
@@ -144,14 +143,14 @@ func TestDecodeEnvelope_MalformedWgKeyPeerSkipped(t *testing.T) {
|
|||||||
func TestEnvelopeRoundTrip_AllGroupShortCircuitParity(t *testing.T) {
|
func TestEnvelopeRoundTrip_AllGroupShortCircuitParity(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
peers := map[string]*nbpeer.Peer{}
|
peers := map[string]*types.ComponentPeer{}
|
||||||
for i, id := range []string{"peer-T", "peer-S", "peer-ALL", "peer-O"} {
|
for i, id := range []string{"peer-T", "peer-S", "peer-ALL", "peer-O"} {
|
||||||
peers[id] = &nbpeer.Peer{
|
peers[id] = &types.ComponentPeer{
|
||||||
ID: id,
|
ID: id,
|
||||||
Key: randomWgKey(t),
|
Key: randomWgKey(t),
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, byte(i + 1)}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, byte(i + 1)}),
|
||||||
DNSLabel: id,
|
DNSLabel: id,
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +164,7 @@ func TestEnvelopeRoundTrip_AllGroupShortCircuitParity(t *testing.T) {
|
|||||||
AccountSettings: &types.AccountSettingsInfo{},
|
AccountSettings: &types.AccountSettingsInfo{},
|
||||||
DNSSettings: &types.DNSSettings{},
|
DNSSettings: &types.DNSSettings{},
|
||||||
Peers: peers,
|
Peers: peers,
|
||||||
Groups: map[string]*types.Group{
|
Groups: map[string]*types.ComponentGroup{
|
||||||
"g-src": {ID: "g-src", PublicID: "1", Name: "staff", Peers: []string{"peer-T", "peer-S"}},
|
"g-src": {ID: "g-src", PublicID: "1", Name: "staff", Peers: []string{"peer-T", "peer-S"}},
|
||||||
"g-all": {ID: "g-all", PublicID: "2", Name: "All", Peers: []string{"peer-ALL"}},
|
"g-all": {ID: "g-all", PublicID: "2", Name: "All", Peers: []string{"peer-ALL"}},
|
||||||
"g-two": {ID: "g-two", PublicID: "3", Name: "second", Peers: []string{"peer-T", "peer-O"}},
|
"g-two": {ID: "g-two", PublicID: "3", Name: "second", Peers: []string{"peer-T", "peer-O"}},
|
||||||
@@ -232,22 +231,22 @@ func buildSmokeComponents(t *testing.T) (*types.NetworkMapComponents, string) {
|
|||||||
peerAKey := randomWgKey(t)
|
peerAKey := randomWgKey(t)
|
||||||
peerBKey := randomWgKey(t)
|
peerBKey := randomWgKey(t)
|
||||||
|
|
||||||
peerA := &nbpeer.Peer{
|
peerA := &types.ComponentPeer{
|
||||||
ID: "peer-A",
|
ID: "peer-A",
|
||||||
Key: peerAKey,
|
Key: peerAKey,
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, 1}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, 1}),
|
||||||
DNSLabel: "peerA",
|
DNSLabel: "peerA",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
peerB := &nbpeer.Peer{
|
peerB := &types.ComponentPeer{
|
||||||
ID: "peer-B",
|
ID: "peer-B",
|
||||||
Key: peerBKey,
|
Key: peerBKey,
|
||||||
IP: netip.AddrFrom4([4]byte{100, 64, 0, 2}),
|
IP: netip.AddrFrom4([4]byte{100, 64, 0, 2}),
|
||||||
DNSLabel: "peerB",
|
DNSLabel: "peerB",
|
||||||
Meta: nbpeer.PeerSystemMeta{WtVersion: "0.40.0"},
|
AgentVersion: "0.40.0",
|
||||||
}
|
}
|
||||||
|
|
||||||
group := &types.Group{
|
group := &types.ComponentGroup{
|
||||||
ID: "group-all", PublicID: "1", Name: "All",
|
ID: "group-all", PublicID: "1", Name: "All",
|
||||||
Peers: []string{"peer-A", "peer-B"},
|
Peers: []string{"peer-A", "peer-B"},
|
||||||
}
|
}
|
||||||
@@ -274,11 +273,11 @@ func buildSmokeComponents(t *testing.T) (*types.NetworkMapComponents, string) {
|
|||||||
},
|
},
|
||||||
AccountSettings: &types.AccountSettingsInfo{},
|
AccountSettings: &types.AccountSettingsInfo{},
|
||||||
DNSSettings: &types.DNSSettings{},
|
DNSSettings: &types.DNSSettings{},
|
||||||
Peers: map[string]*nbpeer.Peer{
|
Peers: map[string]*types.ComponentPeer{
|
||||||
"peer-A": peerA,
|
"peer-A": peerA,
|
||||||
"peer-B": peerB,
|
"peer-B": peerB,
|
||||||
},
|
},
|
||||||
Groups: map[string]*types.Group{
|
Groups: map[string]*types.ComponentGroup{
|
||||||
"group-all": group,
|
"group-all": group,
|
||||||
},
|
},
|
||||||
Policies: []*types.Policy{policy},
|
Policies: []*types.Policy{policy},
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComponentPeer is the self-contained peer representation used by
|
||||||
|
// NetworkMapComponents and the calculated NetworkMap. It carries exactly the
|
||||||
|
// subset of peer data that crosses the components wire format, so the shared
|
||||||
|
// calculation layer stays independent of the management server's domain
|
||||||
|
// types.
|
||||||
|
type ComponentPeer struct {
|
||||||
|
ID string
|
||||||
|
Key string
|
||||||
|
IP netip.Addr
|
||||||
|
IPv6 netip.Addr
|
||||||
|
DNSLabel string
|
||||||
|
SSHKey string
|
||||||
|
SSHEnabled bool
|
||||||
|
ServerSSHAllowed bool
|
||||||
|
AgentVersion string
|
||||||
|
SupportsSourcePrefixes bool
|
||||||
|
SupportsIPv6 bool
|
||||||
|
LoginExpirationEnabled bool
|
||||||
|
AddedWithSSOLogin bool
|
||||||
|
LastLogin time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// FQDN returns the peer's FQDN combined of the peer's DNS label and the system's DNS domain.
|
||||||
|
func (p *ComponentPeer) FQDN(dnsDomain string) string {
|
||||||
|
if dnsDomain == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.DNSLabel + "." + dnsDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoginExpired indicates whether the peer's login has expired, mirroring the
|
||||||
|
// server-side peer semantics: only SSO-added peers with login expiration
|
||||||
|
// enabled can expire.
|
||||||
|
func (p *ComponentPeer) LoginExpired(expiresIn time.Duration) (bool, time.Duration) {
|
||||||
|
if !p.AddedWithSSOLogin || !p.LoginExpirationEnabled {
|
||||||
|
return false, 0
|
||||||
|
}
|
||||||
|
timeLeft := time.Until(p.LastLogin.Add(expiresIn))
|
||||||
|
return timeLeft <= 0, timeLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupAllName is the reserved name of the default group that contains every peer in an account.
|
||||||
|
const GroupAllName = "All"
|
||||||
|
|
||||||
|
// ComponentGroup is the self-contained group representation used by
|
||||||
|
// NetworkMapComponents: just the membership view the network-map calculation
|
||||||
|
// needs, without the server's storage fields.
|
||||||
|
type ComponentGroup struct {
|
||||||
|
ID string
|
||||||
|
PublicID string
|
||||||
|
Name string
|
||||||
|
Peers []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGroupAll checks if the group is a default "All" group.
|
||||||
|
func (g *ComponentGroup) IsGroupAll() bool {
|
||||||
|
return g.Name == GroupAllName
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComponentRouter is the self-contained network-router representation used by
|
||||||
|
// NetworkMapComponents.
|
||||||
|
type ComponentRouter struct {
|
||||||
|
NetworkID string
|
||||||
|
PublicID string
|
||||||
|
Peer string
|
||||||
|
PeerGroups []string
|
||||||
|
Masquerade bool
|
||||||
|
Metric int
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComponentResourceType mirrors the network-resource type enum on the
|
||||||
|
// components wire format.
|
||||||
|
type ComponentResourceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ComponentResourceHost ComponentResourceType = "host"
|
||||||
|
ComponentResourceSubnet ComponentResourceType = "subnet"
|
||||||
|
ComponentResourceDomain ComponentResourceType = "domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ComponentResource is the self-contained network-resource representation
|
||||||
|
// used by NetworkMapComponents.
|
||||||
|
type ComponentResource struct {
|
||||||
|
ID string
|
||||||
|
PublicID string
|
||||||
|
NetworkID string
|
||||||
|
AccountID string
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Type ComponentResourceType
|
||||||
|
Address string
|
||||||
|
Domain string
|
||||||
|
Prefix netip.Prefix
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ package types
|
|||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
|
||||||
"github.com/netbirdio/netbird/version"
|
"github.com/netbirdio/netbird/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,8 +46,8 @@ func portsIncludesSSH(ports []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExpandPortsAndRanges expands Ports and PortRanges of a rule into individual firewall rules.
|
// ExpandPortsAndRanges expands Ports and PortRanges of a rule into individual firewall rules.
|
||||||
func ExpandPortsAndRanges(base FirewallRule, rule *PolicyRule, peer *nbpeer.Peer) []*FirewallRule {
|
func ExpandPortsAndRanges(base FirewallRule, rule *PolicyRule, peer *ComponentPeer) []*FirewallRule {
|
||||||
features := peerSupportedFirewallFeatures(peer.Meta.WtVersion)
|
features := peerSupportedFirewallFeatures(peer.AgentVersion)
|
||||||
|
|
||||||
var expanded []*FirewallRule
|
var expanded []*FirewallRule
|
||||||
|
|
||||||
@@ -106,8 +104,8 @@ func isPortInRule(portString string, portInt uint16, rule *FirewallRule) bool {
|
|||||||
return rule.Port == portString || (rule.PortRange.Start <= portInt && portInt <= rule.PortRange.End)
|
return rule.Port == portString || (rule.PortRange.Start <= portInt && portInt <= rule.PortRange.End)
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldCheckRulesForNativeSSH(supportsNative bool, rule *PolicyRule, peer *nbpeer.Peer) bool {
|
func shouldCheckRulesForNativeSSH(supportsNative bool, rule *PolicyRule, peer *ComponentPeer) bool {
|
||||||
return supportsNative && peer.SSHEnabled && peer.Meta.Flags.ServerSSHAllowed && rule.Protocol == PolicyRuleProtocolTCP
|
return supportsNative && peer.SSHEnabled && peer.ServerSSHAllowed && rule.Protocol == PolicyRuleProtocolTCP
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerSupportedFirewallFeatures(peerVer string) supportedFeatures {
|
func peerSupportedFirewallFeatures(peerVer string) supportedFeatures {
|
||||||
@@ -117,13 +115,13 @@ func peerSupportedFirewallFeatures(peerVer string) supportedFeatures {
|
|||||||
|
|
||||||
var features supportedFeatures
|
var features supportedFeatures
|
||||||
|
|
||||||
meetMinVer, err := posture.MeetsMinVersion(firewallRuleMinNativeSSHVer, peerVer)
|
meetMinVer, err := version.MeetsMinVersion(firewallRuleMinNativeSSHVer, peerVer)
|
||||||
features.nativeSSH = err == nil && meetMinVer
|
features.nativeSSH = err == nil && meetMinVer
|
||||||
|
|
||||||
if features.nativeSSH {
|
if features.nativeSSH {
|
||||||
features.portRanges = true
|
features.portRanges = true
|
||||||
} else {
|
} else {
|
||||||
meetMinVer, err = posture.MeetsMinVersion(firewallRuleMinPortRangesVer, peerVer)
|
meetMinVer, err = version.MeetsMinVersion(firewallRuleMinPortRangesVer, peerVer)
|
||||||
features.portRanges = err == nil && meetMinVer
|
features.portRanges = err == nil && meetMinVer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
nbroute "github.com/netbirdio/netbird/route"
|
nbroute "github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ func (r *FirewallRule) Equal(other *FirewallRule) bool {
|
|||||||
// For static routes, source ranges match the destination family (v4 or v6).
|
// For static routes, source ranges match the destination family (v4 or v6).
|
||||||
// For dynamic routes (domain-based), separate v4 and v6 rules are generated
|
// For dynamic routes (domain-based), separate v4 and v6 rules are generated
|
||||||
// so the routing peer's forwarding chain allows both address families.
|
// so the routing peer's forwarding chain allows both address families.
|
||||||
func GenerateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule *PolicyRule, groupPeers []*nbpeer.Peer, direction int, includeIPv6 bool) []*RouteFirewallRule {
|
func GenerateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule *PolicyRule, groupPeers []*ComponentPeer, direction int, includeIPv6 bool) []*RouteFirewallRule {
|
||||||
rulesExists := make(map[string]struct{})
|
rulesExists := make(map[string]struct{})
|
||||||
rules := make([]*RouteFirewallRule, 0)
|
rules := make([]*RouteFirewallRule, 0)
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ func GenerateRouteFirewallRules(ctx context.Context, route *nbroute.Route, rule
|
|||||||
}
|
}
|
||||||
|
|
||||||
// splitPeerSourcesByFamily separates peer IPs into v4 (/32) and v6 (/128) source ranges.
|
// splitPeerSourcesByFamily separates peer IPs into v4 (/32) and v6 (/128) source ranges.
|
||||||
func splitPeerSourcesByFamily(groupPeers []*nbpeer.Peer) (v4, v6 []string) {
|
func splitPeerSourcesByFamily(groupPeers []*ComponentPeer) (v4, v6 []string) {
|
||||||
v4 = make([]string, 0, len(groupPeers))
|
v4 = make([]string, 0, len(groupPeers))
|
||||||
v6 = make([]string, 0, len(groupPeers))
|
v6 = make([]string, 0, len(groupPeers))
|
||||||
for _, peer := range groupPeers {
|
for _, peer := range groupPeers {
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSplitPeerSourcesByFamily(t *testing.T) {
|
func TestSplitPeerSourcesByFamily(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("100.64.0.1"),
|
IP: netip.MustParseAddr("100.64.0.1"),
|
||||||
IPv6: netip.MustParseAddr("fd00::1"),
|
IPv6: netip.MustParseAddr("fd00::1"),
|
||||||
@@ -36,7 +35,7 @@ func TestSplitPeerSourcesByFamily(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateRouteFirewallRules_V4Route(t *testing.T) {
|
func TestGenerateRouteFirewallRules_V4Route(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("100.64.0.1"),
|
IP: netip.MustParseAddr("100.64.0.1"),
|
||||||
IPv6: netip.MustParseAddr("fd00::1"),
|
IPv6: netip.MustParseAddr("fd00::1"),
|
||||||
@@ -65,7 +64,7 @@ func TestGenerateRouteFirewallRules_V4Route(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateRouteFirewallRules_V6Route(t *testing.T) {
|
func TestGenerateRouteFirewallRules_V6Route(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("100.64.0.1"),
|
IP: netip.MustParseAddr("100.64.0.1"),
|
||||||
IPv6: netip.MustParseAddr("fd00::1"),
|
IPv6: netip.MustParseAddr("fd00::1"),
|
||||||
@@ -93,7 +92,7 @@ func TestGenerateRouteFirewallRules_V6Route(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateRouteFirewallRules_DynamicRoute_DualStack(t *testing.T) {
|
func TestGenerateRouteFirewallRules_DynamicRoute_DualStack(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("100.64.0.1"),
|
IP: netip.MustParseAddr("100.64.0.1"),
|
||||||
IPv6: netip.MustParseAddr("fd00::1"),
|
IPv6: netip.MustParseAddr("fd00::1"),
|
||||||
@@ -126,7 +125,7 @@ func TestGenerateRouteFirewallRules_DynamicRoute_DualStack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateRouteFirewallRules_DynamicRoute_NoV6Peers(t *testing.T) {
|
func TestGenerateRouteFirewallRules_DynamicRoute_NoV6Peers(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{IP: netip.MustParseAddr("100.64.0.1")},
|
{IP: netip.MustParseAddr("100.64.0.1")},
|
||||||
{IP: netip.MustParseAddr("100.64.0.2")},
|
{IP: netip.MustParseAddr("100.64.0.2")},
|
||||||
}
|
}
|
||||||
@@ -150,7 +149,7 @@ func TestGenerateRouteFirewallRules_DynamicRoute_NoV6Peers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateRouteFirewallRules_IncludeIPv6False(t *testing.T) {
|
func TestGenerateRouteFirewallRules_IncludeIPv6False(t *testing.T) {
|
||||||
peers := []*nbpeer.Peer{
|
peers := []*ComponentPeer{
|
||||||
{
|
{
|
||||||
IP: netip.MustParseAddr("100.64.0.1"),
|
IP: netip.MustParseAddr("100.64.0.1"),
|
||||||
IPv6: netip.MustParseAddr("fd00::1"),
|
IPv6: netip.MustParseAddr("fd00::1"),
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import (
|
|||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/management/server/util"
|
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
"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"
|
||||||
@@ -39,11 +37,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type NetworkMap struct {
|
type NetworkMap struct {
|
||||||
Peers []*nbpeer.Peer
|
Peers []*ComponentPeer
|
||||||
Network *Network
|
Network *Network
|
||||||
Routes []*route.Route
|
Routes []*route.Route
|
||||||
DNSConfig nbdns.Config
|
DNSConfig nbdns.Config
|
||||||
OfflinePeers []*nbpeer.Peer
|
OfflinePeers []*ComponentPeer
|
||||||
FirewallRules []*FirewallRule
|
FirewallRules []*FirewallRule
|
||||||
RoutesFirewallRules []*RouteFirewallRule
|
RoutesFirewallRules []*RouteFirewallRule
|
||||||
ForwardingRules []*ForwardingRule
|
ForwardingRules []*ForwardingRule
|
||||||
@@ -53,15 +51,46 @@ type NetworkMap struct {
|
|||||||
|
|
||||||
func (nm *NetworkMap) Merge(other *NetworkMap) {
|
func (nm *NetworkMap) Merge(other *NetworkMap) {
|
||||||
nm.Peers = mergeUniquePeersByID(nm.Peers, other.Peers)
|
nm.Peers = mergeUniquePeersByID(nm.Peers, other.Peers)
|
||||||
nm.Routes = util.MergeUnique(nm.Routes, other.Routes)
|
nm.Routes = mergeUnique(nm.Routes, other.Routes)
|
||||||
nm.OfflinePeers = mergeUniquePeersByID(nm.OfflinePeers, other.OfflinePeers)
|
nm.OfflinePeers = mergeUniquePeersByID(nm.OfflinePeers, other.OfflinePeers)
|
||||||
nm.FirewallRules = util.MergeUnique(nm.FirewallRules, other.FirewallRules)
|
nm.FirewallRules = mergeUnique(nm.FirewallRules, other.FirewallRules)
|
||||||
nm.RoutesFirewallRules = util.MergeUnique(nm.RoutesFirewallRules, other.RoutesFirewallRules)
|
nm.RoutesFirewallRules = mergeUnique(nm.RoutesFirewallRules, other.RoutesFirewallRules)
|
||||||
nm.ForwardingRules = util.MergeUnique(nm.ForwardingRules, other.ForwardingRules)
|
nm.ForwardingRules = mergeUnique(nm.ForwardingRules, other.ForwardingRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeUniquePeersByID(peers1, peers2 []*nbpeer.Peer) []*nbpeer.Peer {
|
type comparableObject[T any] interface {
|
||||||
result := make(map[string]*nbpeer.Peer)
|
Equal(other T) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeUnique[T comparableObject[T]](arr1, arr2 []T) []T {
|
||||||
|
var result []T
|
||||||
|
|
||||||
|
for _, item := range arr1 {
|
||||||
|
if !containsEqual(result, item) {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range arr2 {
|
||||||
|
if !containsEqual(result, item) {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsEqual[T comparableObject[T]](slice []T, element T) bool {
|
||||||
|
for _, item := range slice {
|
||||||
|
if item.Equal(element) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeUniquePeersByID(peers1, peers2 []*ComponentPeer) []*ComponentPeer {
|
||||||
|
result := make(map[string]*ComponentPeer)
|
||||||
for _, peer := range peers1 {
|
for _, peer := range peers1 {
|
||||||
result[peer.ID] = peer
|
result[peer.ID] = peer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package util
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -17,7 +17,7 @@ func (t testObject) Equal(other testObject) bool {
|
|||||||
func Test_MergeUniqueArraysWithoutDuplicates(t *testing.T) {
|
func Test_MergeUniqueArraysWithoutDuplicates(t *testing.T) {
|
||||||
arr1 := []testObject{{value: 1}, {value: 2}}
|
arr1 := []testObject{{value: 1}, {value: 2}}
|
||||||
arr2 := []testObject{{value: 2}, {value: 3}}
|
arr2 := []testObject{{value: 2}, {value: 3}}
|
||||||
result := MergeUnique(arr1, arr2)
|
result := mergeUnique(arr1, arr2)
|
||||||
assert.Len(t, result, 3)
|
assert.Len(t, result, 3)
|
||||||
assert.Contains(t, result, testObject{value: 1})
|
assert.Contains(t, result, testObject{value: 1})
|
||||||
assert.Contains(t, result, testObject{value: 2})
|
assert.Contains(t, result, testObject{value: 2})
|
||||||
@@ -27,14 +27,14 @@ func Test_MergeUniqueArraysWithoutDuplicates(t *testing.T) {
|
|||||||
func Test_MergeUniqueHandlesEmptyArrays(t *testing.T) {
|
func Test_MergeUniqueHandlesEmptyArrays(t *testing.T) {
|
||||||
arr1 := []testObject{}
|
arr1 := []testObject{}
|
||||||
arr2 := []testObject{}
|
arr2 := []testObject{}
|
||||||
result := MergeUnique(arr1, arr2)
|
result := mergeUnique(arr1, arr2)
|
||||||
assert.Empty(t, result)
|
assert.Empty(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_MergeUniqueHandlesOneEmptyArray(t *testing.T) {
|
func Test_MergeUniqueHandlesOneEmptyArray(t *testing.T) {
|
||||||
arr1 := []testObject{{value: 1}, {value: 2}}
|
arr1 := []testObject{{value: 1}, {value: 2}}
|
||||||
arr2 := []testObject{}
|
arr2 := []testObject{}
|
||||||
result := MergeUnique(arr1, arr2)
|
result := mergeUnique(arr1, arr2)
|
||||||
assert.Len(t, result, 2)
|
assert.Len(t, result, 2)
|
||||||
assert.Contains(t, result, testObject{value: 1})
|
assert.Contains(t, result, testObject{value: 1})
|
||||||
assert.Contains(t, result, testObject{value: 2})
|
assert.Contains(t, result, testObject{value: 2})
|
||||||
@@ -12,9 +12,6 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/client/ssh/auth"
|
"github.com/netbirdio/netbird/client/ssh/auth"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
)
|
)
|
||||||
@@ -27,22 +24,22 @@ type NetworkMapComponents struct {
|
|||||||
DNSSettings *DNSSettings
|
DNSSettings *DNSSettings
|
||||||
CustomZoneDomain string
|
CustomZoneDomain string
|
||||||
|
|
||||||
Peers map[string]*nbpeer.Peer
|
Peers map[string]*ComponentPeer
|
||||||
Groups map[string]*Group
|
Groups map[string]*ComponentGroup
|
||||||
Policies []*Policy
|
Policies []*Policy
|
||||||
Routes []*route.Route
|
Routes []*route.Route
|
||||||
NameServerGroups []*nbdns.NameServerGroup
|
NameServerGroups []*nbdns.NameServerGroup
|
||||||
AllDNSRecords []nbdns.SimpleRecord
|
AllDNSRecords []nbdns.SimpleRecord
|
||||||
AccountZones []nbdns.CustomZone
|
AccountZones []nbdns.CustomZone
|
||||||
ResourcePoliciesMap map[string][]*Policy
|
ResourcePoliciesMap map[string][]*Policy
|
||||||
RoutersMap map[string]map[string]*routerTypes.NetworkRouter
|
RoutersMap map[string]map[string]*ComponentRouter
|
||||||
NetworkResources []*resourceTypes.NetworkResource
|
NetworkResources []*ComponentResource
|
||||||
|
|
||||||
GroupIDToUserIDs map[string][]string
|
GroupIDToUserIDs map[string][]string
|
||||||
AllowedUserIDs map[string]struct{}
|
AllowedUserIDs map[string]struct{}
|
||||||
PostureFailedPeers map[string]map[string]struct{}
|
PostureFailedPeers map[string]map[string]struct{}
|
||||||
|
|
||||||
RouterPeers map[string]*nbpeer.Peer
|
RouterPeers map[string]*ComponentPeer
|
||||||
|
|
||||||
// NetworkXIDToPublicID maps Network.ID (xid) → PublicID.
|
// NetworkXIDToPublicID maps Network.ID (xid) → PublicID.
|
||||||
// Consumed by the envelope encoder to
|
// Consumed by the envelope encoder to
|
||||||
@@ -78,15 +75,15 @@ func EmptyNetworkMapComponents(nm *NetworkMapComponents) *NetworkMapComponents {
|
|||||||
return nm
|
return nm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) GetPeerInfo(peerID string) *nbpeer.Peer {
|
func (c *NetworkMapComponents) GetPeerInfo(peerID string) *ComponentPeer {
|
||||||
return c.Peers[peerID]
|
return c.Peers[peerID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) GetRouterPeerInfo(peerID string) *nbpeer.Peer {
|
func (c *NetworkMapComponents) GetRouterPeerInfo(peerID string) *ComponentPeer {
|
||||||
return c.RouterPeers[peerID]
|
return c.RouterPeers[peerID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) GetGroupInfo(groupID string) *Group {
|
func (c *NetworkMapComponents) GetGroupInfo(groupID string) *ComponentGroup {
|
||||||
return c.Groups[groupID]
|
return c.Groups[groupID]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +139,7 @@ func (c *NetworkMapComponents) Calculate(ctx context.Context) *NetworkMap {
|
|||||||
|
|
||||||
includeIPv6 := false
|
includeIPv6 := false
|
||||||
if p := c.Peers[targetPeerID]; p != nil {
|
if p := c.Peers[targetPeerID]; p != nil {
|
||||||
includeIPv6 = p.SupportsIPv6() && p.IPv6.IsValid()
|
includeIPv6 = p.SupportsIPv6 && p.IPv6.IsValid()
|
||||||
}
|
}
|
||||||
routesUpdate := filterAndExpandRoutes(c.getRoutesToSync(targetPeerID, peersToConnect, peerGroups), includeIPv6)
|
routesUpdate := filterAndExpandRoutes(c.getRoutesToSync(targetPeerID, peersToConnect, peerGroups), includeIPv6)
|
||||||
routesFirewallRules := c.getPeerRoutesFirewallRules(ctx, targetPeerID, includeIPv6)
|
routesFirewallRules := c.getPeerRoutesFirewallRules(ctx, targetPeerID, includeIPv6)
|
||||||
@@ -200,7 +197,7 @@ func (c *NetworkMapComponents) IsEmpty() bool {
|
|||||||
return c.empty
|
return c.empty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getPeerConnectionResources(targetPeerID string) ([]*nbpeer.Peer, []*FirewallRule, map[string]map[string]struct{}, bool) {
|
func (c *NetworkMapComponents) getPeerConnectionResources(targetPeerID string) ([]*ComponentPeer, []*FirewallRule, map[string]map[string]struct{}, bool) {
|
||||||
targetPeer := c.GetPeerInfo(targetPeerID)
|
targetPeer := c.GetPeerInfo(targetPeerID)
|
||||||
if targetPeer == nil {
|
if targetPeer == nil {
|
||||||
return nil, nil, nil, false
|
return nil, nil, nil, false
|
||||||
@@ -220,7 +217,7 @@ func (c *NetworkMapComponents) getPeerConnectionResources(targetPeerID string) (
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourcePeers, destinationPeers []*nbpeer.Peer
|
var sourcePeers, destinationPeers []*ComponentPeer
|
||||||
var peerInSources, peerInDestinations bool
|
var peerInSources, peerInDestinations bool
|
||||||
|
|
||||||
if rule.SourceResource.Type == ResourceTypePeer && rule.SourceResource.ID != "" {
|
if rule.SourceResource.Type == ResourceTypePeer && rule.SourceResource.ID != "" {
|
||||||
@@ -303,13 +300,13 @@ func (c *NetworkMapComponents) getAllowedUserIDs() map[string]struct{} {
|
|||||||
return make(map[string]struct{})
|
return make(map[string]struct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) connResourcesGenerator(targetPeer *nbpeer.Peer) (func(*PolicyRule, []*nbpeer.Peer, int), func() ([]*nbpeer.Peer, []*FirewallRule)) {
|
func (c *NetworkMapComponents) connResourcesGenerator(targetPeer *ComponentPeer) (func(*PolicyRule, []*ComponentPeer, int), func() ([]*ComponentPeer, []*FirewallRule)) {
|
||||||
rulesExists := make(map[string]struct{})
|
rulesExists := make(map[string]struct{})
|
||||||
peersExists := make(map[string]struct{})
|
peersExists := make(map[string]struct{})
|
||||||
rules := make([]*FirewallRule, 0)
|
rules := make([]*FirewallRule, 0)
|
||||||
peers := make([]*nbpeer.Peer, 0)
|
peers := make([]*ComponentPeer, 0)
|
||||||
|
|
||||||
return func(rule *PolicyRule, groupPeers []*nbpeer.Peer, direction int) {
|
return func(rule *PolicyRule, groupPeers []*ComponentPeer, direction int) {
|
||||||
protocol := rule.Protocol
|
protocol := rule.Protocol
|
||||||
if protocol == PolicyRuleProtocolNetbirdSSH {
|
if protocol == PolicyRuleProtocolNetbirdSSH {
|
||||||
protocol = PolicyRuleProtocolTCP
|
protocol = PolicyRuleProtocolTCP
|
||||||
@@ -361,15 +358,15 @@ func (c *NetworkMapComponents) connResourcesGenerator(targetPeer *nbpeer.Peer) (
|
|||||||
PortsJoined: portsJoined,
|
PortsJoined: portsJoined,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, func() ([]*nbpeer.Peer, []*FirewallRule) {
|
}, func() ([]*ComponentPeer, []*FirewallRule) {
|
||||||
return peers, rules
|
return peers, rules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getAllPeersFromGroups(groups []string, peerID string, sourcePostureChecksIDs []string) ([]*nbpeer.Peer, bool) {
|
func (c *NetworkMapComponents) getAllPeersFromGroups(groups []string, peerID string, sourcePostureChecksIDs []string) ([]*ComponentPeer, bool) {
|
||||||
peerInGroups := false
|
peerInGroups := false
|
||||||
uniquePeerIDs := c.getUniquePeerIDsFromGroupsIDs(groups)
|
uniquePeerIDs := c.getUniquePeerIDsFromGroupsIDs(groups)
|
||||||
filteredPeers := make([]*nbpeer.Peer, 0, len(uniquePeerIDs))
|
filteredPeers := make([]*ComponentPeer, 0, len(uniquePeerIDs))
|
||||||
|
|
||||||
for _, p := range uniquePeerIDs {
|
for _, p := range uniquePeerIDs {
|
||||||
peerInfo := c.GetPeerInfo(p)
|
peerInfo := c.GetPeerInfo(p)
|
||||||
@@ -421,22 +418,22 @@ func (c *NetworkMapComponents) getUniquePeerIDsFromGroupsIDs(groups []string) []
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getPeerFromResource(resource Resource, peerID string) ([]*nbpeer.Peer, bool) {
|
func (c *NetworkMapComponents) getPeerFromResource(resource Resource, peerID string) ([]*ComponentPeer, bool) {
|
||||||
if resource.ID == peerID {
|
if resource.ID == peerID {
|
||||||
return []*nbpeer.Peer{}, true
|
return []*ComponentPeer{}, true
|
||||||
}
|
}
|
||||||
|
|
||||||
peerInfo := c.GetPeerInfo(resource.ID)
|
peerInfo := c.GetPeerInfo(resource.ID)
|
||||||
if peerInfo == nil {
|
if peerInfo == nil {
|
||||||
return []*nbpeer.Peer{}, false
|
return []*ComponentPeer{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return []*nbpeer.Peer{peerInfo}, false
|
return []*ComponentPeer{peerInfo}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) filterPeersByLoginExpiration(aclPeers []*nbpeer.Peer) ([]*nbpeer.Peer, []*nbpeer.Peer) {
|
func (c *NetworkMapComponents) filterPeersByLoginExpiration(aclPeers []*ComponentPeer) ([]*ComponentPeer, []*ComponentPeer) {
|
||||||
peersToConnect := make([]*nbpeer.Peer, 0, len(aclPeers))
|
peersToConnect := make([]*ComponentPeer, 0, len(aclPeers))
|
||||||
var expiredPeers []*nbpeer.Peer
|
var expiredPeers []*ComponentPeer
|
||||||
|
|
||||||
for _, p := range aclPeers {
|
for _, p := range aclPeers {
|
||||||
expired, _ := p.LoginExpired(c.AccountSettings.PeerLoginExpiration)
|
expired, _ := p.LoginExpired(c.AccountSettings.PeerLoginExpiration)
|
||||||
@@ -518,7 +515,7 @@ func filterAndExpandRoutes(routes []*route.Route, includeIPv6 bool) []*route.Rou
|
|||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getRoutesToSync(peerID string, aclPeers []*nbpeer.Peer, peerGroups LookupMap) []*route.Route {
|
func (c *NetworkMapComponents) getRoutesToSync(peerID string, aclPeers []*ComponentPeer, peerGroups LookupMap) []*route.Route {
|
||||||
routes, peerDisabledRoutes := c.getRoutingPeerRoutes(peerID)
|
routes, peerDisabledRoutes := c.getRoutingPeerRoutes(peerID)
|
||||||
peerRoutesMembership := make(LookupMap)
|
peerRoutesMembership := make(LookupMap)
|
||||||
for _, r := range append(routes, peerDisabledRoutes...) {
|
for _, r := range append(routes, peerDisabledRoutes...) {
|
||||||
@@ -732,7 +729,7 @@ func (c *NetworkMapComponents) getRouteFirewallRules(ctx context.Context, peerID
|
|||||||
return fwRules
|
return fwRules
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getRulePeers(rule *PolicyRule, postureChecks []string, peerID string, distributionPeers map[string]struct{}) []*nbpeer.Peer {
|
func (c *NetworkMapComponents) getRulePeers(rule *PolicyRule, postureChecks []string, peerID string, distributionPeers map[string]struct{}) []*ComponentPeer {
|
||||||
distPeersWithPolicy := make(map[string]struct{})
|
distPeersWithPolicy := make(map[string]struct{})
|
||||||
for _, id := range rule.Sources {
|
for _, id := range rule.Sources {
|
||||||
group := c.GetGroupInfo(id)
|
group := c.GetGroupInfo(id)
|
||||||
@@ -759,7 +756,7 @@ func (c *NetworkMapComponents) getRulePeers(rule *PolicyRule, postureChecks []st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
distributionGroupPeers := make([]*nbpeer.Peer, 0, len(distPeersWithPolicy))
|
distributionGroupPeers := make([]*ComponentPeer, 0, len(distPeersWithPolicy))
|
||||||
for pID := range distPeersWithPolicy {
|
for pID := range distPeersWithPolicy {
|
||||||
peerInfo := c.GetPeerInfo(pID)
|
peerInfo := c.GetPeerInfo(pID)
|
||||||
if peerInfo == nil {
|
if peerInfo == nil {
|
||||||
@@ -799,8 +796,8 @@ func (c *NetworkMapComponents) getNetworkResourcesRoutesToSync(peerID string) (b
|
|||||||
|
|
||||||
func (c *NetworkMapComponents) processResourcePolicies(
|
func (c *NetworkMapComponents) processResourcePolicies(
|
||||||
peerID string,
|
peerID string,
|
||||||
resource *resourceTypes.NetworkResource,
|
resource *ComponentResource,
|
||||||
networkRoutingPeers map[string]*routerTypes.NetworkRouter,
|
networkRoutingPeers map[string]*ComponentRouter,
|
||||||
addSourcePeers bool,
|
addSourcePeers bool,
|
||||||
allSourcePeers map[string]struct{},
|
allSourcePeers map[string]struct{},
|
||||||
) []*route.Route {
|
) []*route.Route {
|
||||||
@@ -833,7 +830,7 @@ func (c *NetworkMapComponents) getResourcePolicyPeers(policy *Policy) []string {
|
|||||||
return c.getUniquePeerIDsFromGroupsIDs(policy.SourceGroups())
|
return c.getUniquePeerIDsFromGroupsIDs(policy.SourceGroups())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) getNetworkResourcesRoutes(resource *resourceTypes.NetworkResource, peerID string, router *routerTypes.NetworkRouter) []*route.Route {
|
func (c *NetworkMapComponents) getNetworkResourcesRoutes(resource *ComponentResource, peerID string, router *ComponentRouter) []*route.Route {
|
||||||
resourceAppliedPolicies := c.ResourcePoliciesMap[resource.ID]
|
resourceAppliedPolicies := c.ResourcePoliciesMap[resource.ID]
|
||||||
|
|
||||||
var routes []*route.Route
|
var routes []*route.Route
|
||||||
@@ -847,7 +844,7 @@ func (c *NetworkMapComponents) getNetworkResourcesRoutes(resource *resourceTypes
|
|||||||
return routes
|
return routes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponents) networkResourceToRoute(resource *resourceTypes.NetworkResource, peer *nbpeer.Peer, router *routerTypes.NetworkRouter) *route.Route {
|
func (c *NetworkMapComponents) networkResourceToRoute(resource *ComponentResource, peer *ComponentPeer, router *ComponentRouter) *route.Route {
|
||||||
r := &route.Route{
|
r := &route.Route{
|
||||||
ID: route.ID(resource.ID + ":" + peer.ID),
|
ID: route.ID(resource.ID + ":" + peer.ID),
|
||||||
AccountID: resource.AccountID,
|
AccountID: resource.AccountID,
|
||||||
@@ -861,7 +858,7 @@ func (c *NetworkMapComponents) networkResourceToRoute(resource *resourceTypes.Ne
|
|||||||
Description: resource.Description,
|
Description: resource.Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
if resource.Type == resourceTypes.Host || resource.Type == resourceTypes.Subnet {
|
if resource.Type == ComponentResourceHost || resource.Type == ComponentResourceSubnet {
|
||||||
r.Network = resource.Prefix
|
r.Network = resource.Prefix
|
||||||
|
|
||||||
r.NetworkType = route.IPv4Network
|
r.NetworkType = route.IPv4Network
|
||||||
@@ -870,7 +867,7 @@ func (c *NetworkMapComponents) networkResourceToRoute(resource *resourceTypes.Ne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if resource.Type == resourceTypes.Domain {
|
if resource.Type == ComponentResourceDomain {
|
||||||
domainList, err := domain.FromStringList([]string{resource.Domain})
|
domainList, err := domain.FromStringList([]string{resource.Domain})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
r.Domains = domainList
|
r.Domains = domainList
|
||||||
@@ -948,11 +945,11 @@ func (c *NetworkMapComponents) getPoliciesSourcePeers(policies []*Policy) map[st
|
|||||||
func (c *NetworkMapComponents) addNetworksRoutingPeers(
|
func (c *NetworkMapComponents) addNetworksRoutingPeers(
|
||||||
networkResourcesRoutes []*route.Route,
|
networkResourcesRoutes []*route.Route,
|
||||||
peerID string,
|
peerID string,
|
||||||
peersToConnect []*nbpeer.Peer,
|
peersToConnect []*ComponentPeer,
|
||||||
expiredPeers []*nbpeer.Peer,
|
expiredPeers []*ComponentPeer,
|
||||||
isRouter bool,
|
isRouter bool,
|
||||||
sourcePeers map[string]struct{},
|
sourcePeers map[string]struct{},
|
||||||
) []*nbpeer.Peer {
|
) []*ComponentPeer {
|
||||||
|
|
||||||
networkRoutesPeers := make(map[string]struct{}, len(networkResourcesRoutes))
|
networkRoutesPeers := make(map[string]struct{}, len(networkResourcesRoutes))
|
||||||
for _, r := range networkResourcesRoutes {
|
for _, r := range networkResourcesRoutes {
|
||||||
@@ -1002,8 +999,8 @@ type FirewallRuleContext struct {
|
|||||||
PortsJoined string
|
PortsJoined string
|
||||||
}
|
}
|
||||||
|
|
||||||
func AppendIPv6FirewallRule(rules []*FirewallRule, rulesExists map[string]struct{}, peer, targetPeer *nbpeer.Peer, rule *PolicyRule, rc FirewallRuleContext) []*FirewallRule {
|
func AppendIPv6FirewallRule(rules []*FirewallRule, rulesExists map[string]struct{}, peer, targetPeer *ComponentPeer, rule *PolicyRule, rc FirewallRuleContext) []*FirewallRule {
|
||||||
if !peer.IPv6.IsValid() || !targetPeer.SupportsIPv6() || !targetPeer.IPv6.IsValid() {
|
if !peer.IPv6.IsValid() || !targetPeer.SupportsIPv6 || !targetPeer.IPv6.IsValid() {
|
||||||
return rules
|
return rules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
|
||||||
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,7 +18,7 @@ type NetworkMapComponentsCompact struct {
|
|||||||
DNSSettings *DNSSettings
|
DNSSettings *DNSSettings
|
||||||
CustomZoneDomain string
|
CustomZoneDomain string
|
||||||
|
|
||||||
AllPeers []*nbpeer.Peer
|
AllPeers []*ComponentPeer
|
||||||
PeerIndexes []int
|
PeerIndexes []int
|
||||||
RouterPeerIndexes []int
|
RouterPeerIndexes []int
|
||||||
|
|
||||||
@@ -34,8 +31,8 @@ type NetworkMapComponentsCompact struct {
|
|||||||
AllDNSRecords []nbdns.SimpleRecord
|
AllDNSRecords []nbdns.SimpleRecord
|
||||||
AccountZones []nbdns.CustomZone
|
AccountZones []nbdns.CustomZone
|
||||||
|
|
||||||
RoutersMap map[string]map[string]*routerTypes.NetworkRouter
|
RoutersMap map[string]map[string]*ComponentRouter
|
||||||
NetworkResources []*resourceTypes.NetworkResource
|
NetworkResources []*ComponentResource
|
||||||
|
|
||||||
GroupIDToUserIDs map[string][]string
|
GroupIDToUserIDs map[string][]string
|
||||||
AllowedUserIDs map[string]struct{}
|
AllowedUserIDs map[string]struct{}
|
||||||
@@ -44,7 +41,7 @@ type NetworkMapComponentsCompact struct {
|
|||||||
|
|
||||||
func (c *NetworkMapComponents) ToCompact() *NetworkMapComponentsCompact {
|
func (c *NetworkMapComponents) ToCompact() *NetworkMapComponentsCompact {
|
||||||
peerToIndex := make(map[string]int)
|
peerToIndex := make(map[string]int)
|
||||||
var allPeers []*nbpeer.Peer
|
var allPeers []*ComponentPeer
|
||||||
|
|
||||||
for id, peer := range c.Peers {
|
for id, peer := range c.Peers {
|
||||||
if _, exists := peerToIndex[id]; !exists {
|
if _, exists := peerToIndex[id]; !exists {
|
||||||
@@ -150,7 +147,7 @@ func (c *NetworkMapComponents) ToCompact() *NetworkMapComponentsCompact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkMapComponentsCompact) ToFull() *NetworkMapComponents {
|
func (c *NetworkMapComponentsCompact) ToFull() *NetworkMapComponents {
|
||||||
peers := make(map[string]*nbpeer.Peer, len(c.PeerIndexes))
|
peers := make(map[string]*ComponentPeer, len(c.PeerIndexes))
|
||||||
for _, idx := range c.PeerIndexes {
|
for _, idx := range c.PeerIndexes {
|
||||||
if idx >= 0 && idx < len(c.AllPeers) {
|
if idx >= 0 && idx < len(c.AllPeers) {
|
||||||
peer := c.AllPeers[idx]
|
peer := c.AllPeers[idx]
|
||||||
@@ -158,7 +155,7 @@ func (c *NetworkMapComponentsCompact) ToFull() *NetworkMapComponents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
routerPeers := make(map[string]*nbpeer.Peer, len(c.RouterPeerIndexes))
|
routerPeers := make(map[string]*ComponentPeer, len(c.RouterPeerIndexes))
|
||||||
for _, idx := range c.RouterPeerIndexes {
|
for _, idx := range c.RouterPeerIndexes {
|
||||||
if idx >= 0 && idx < len(c.AllPeers) {
|
if idx >= 0 && idx < len(c.AllPeers) {
|
||||||
peer := c.AllPeers[idx]
|
peer := c.AllPeers[idx]
|
||||||
@@ -166,7 +163,7 @@ func (c *NetworkMapComponentsCompact) ToFull() *NetworkMapComponents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groups := make(map[string]*Group, len(c.Groups))
|
groups := make(map[string]*ComponentGroup, len(c.Groups))
|
||||||
for id, gc := range c.Groups {
|
for id, gc := range c.Groups {
|
||||||
peerIDs := make([]string, 0, len(gc.PeerIndexes))
|
peerIDs := make([]string, 0, len(gc.PeerIndexes))
|
||||||
for _, idx := range gc.PeerIndexes {
|
for _, idx := range gc.PeerIndexes {
|
||||||
@@ -174,7 +171,7 @@ func (c *NetworkMapComponentsCompact) ToFull() *NetworkMapComponents {
|
|||||||
peerIDs = append(peerIDs, c.AllPeers[idx].ID)
|
peerIDs = append(peerIDs, c.AllPeers[idx].ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groups[id] = &Group{
|
groups[id] = &ComponentGroup{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: gc.Name,
|
Name: gc.Name,
|
||||||
Peers: peerIDs,
|
Peers: peerIDs,
|
||||||
|
|||||||
@@ -71,6 +71,30 @@ func NetbirdCommit() string {
|
|||||||
return revision
|
return revision
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanitizeVersion removes anything after the pre-release tag (e.g., "-dev", "-alpha", etc.)
|
||||||
|
func sanitizeVersion(version string) string {
|
||||||
|
parts := strings.Split(version, "-")
|
||||||
|
return parts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MeetsMinVersion checks if the peer's version meets or exceeds the minimum required version
|
||||||
|
func MeetsMinVersion(minVer, peerVer string) (bool, error) {
|
||||||
|
peerVer = sanitizeVersion(peerVer)
|
||||||
|
minVer = sanitizeVersion(minVer)
|
||||||
|
|
||||||
|
peerNBVer, err := v.NewVersion(peerVer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints, err := v.NewConstraint(">= " + minVer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return constraints.Check(peerNBVer), nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsDevelopmentVersion reports whether the given version string identifies
|
// IsDevelopmentVersion reports whether the given version string identifies
|
||||||
// a non-release / development build. It is the single source of truth for
|
// a non-release / development build. It is the single source of truth for
|
||||||
// "is this a dev build" checks across the codebase; use it instead of
|
// "is this a dev build" checks across the codebase; use it instead of
|
||||||
|
|||||||
+70
-1
@@ -1,6 +1,10 @@
|
|||||||
package version
|
package version
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
func TestIsDevelopmentVersion(t *testing.T) {
|
func TestIsDevelopmentVersion(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@@ -26,3 +30,68 @@ func TestIsDevelopmentVersion(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMeetsMinVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
minVer string
|
||||||
|
peerVer string
|
||||||
|
want bool
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Peer version greater than min version",
|
||||||
|
minVer: "0.26.0",
|
||||||
|
peerVer: "0.60.1",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version equals min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "1.0.0",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version less than min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "0.9.9",
|
||||||
|
want: false,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Peer version with pre-release tag greater than min version",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "1.0.1-alpha",
|
||||||
|
want: true,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid peer version format",
|
||||||
|
minVer: "1.0.0",
|
||||||
|
peerVer: "dev",
|
||||||
|
want: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Invalid min version format",
|
||||||
|
minVer: "invalid.version",
|
||||||
|
peerVer: "1.0.0",
|
||||||
|
want: false,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := MeetsMinVersion(tt.minVer, tt.peerVer)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user