mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-30 10:39:08 +02:00
Merge branch 'main' into embedded-vnc
This commit is contained in:
@@ -1111,8 +1111,17 @@ func ruleHasDestination(rule *PolicyRule, peerID string, peerGroupIDs map[string
|
||||
// Important: Posture checks are applicable only to source group peers,
|
||||
// for destination group peers, call this method with an empty list of sourcePostureChecksIDs
|
||||
func (a *Account) getAllPeersFromGroups(ctx context.Context, groups []string, peerID string, sourcePostureChecksIDs []string, validatedPeersMap map[string]struct{}) ([]*nbpeer.Peer, bool) {
|
||||
return a.filterPolicyPeers(ctx, a.getUniquePeerIDsFromGroupsIDs(ctx, groups), peerID, sourcePostureChecksIDs, validatedPeersMap)
|
||||
}
|
||||
|
||||
// getPeerFromResource resolves a rule side that names a peer directly, admitting it
|
||||
// like a member of a group holding only that peer.
|
||||
func (a *Account) getPeerFromResource(ctx context.Context, resource Resource, peerID string, sourcePostureChecksIDs []string, validatedPeersMap map[string]struct{}) ([]*nbpeer.Peer, bool) {
|
||||
return a.filterPolicyPeers(ctx, []string{resource.ID}, peerID, sourcePostureChecksIDs, validatedPeersMap)
|
||||
}
|
||||
|
||||
func (a *Account) filterPolicyPeers(ctx context.Context, uniquePeerIDs []string, peerID string, sourcePostureChecksIDs []string, validatedPeersMap map[string]struct{}) ([]*nbpeer.Peer, bool) {
|
||||
peerInGroups := false
|
||||
uniquePeerIDs := a.getUniquePeerIDsFromGroupsIDs(ctx, groups)
|
||||
filteredPeers := make([]*nbpeer.Peer, 0, len(uniquePeerIDs))
|
||||
for _, p := range uniquePeerIDs {
|
||||
peer, ok := a.Peers[p]
|
||||
|
||||
@@ -93,7 +93,7 @@ func (a *Account) toNetworkMapData(
|
||||
}
|
||||
for _, pc := range a.PostureChecks {
|
||||
if pc != nil {
|
||||
nmd.PostureChecks[pc.ID] = twinPostureChecks(pc)
|
||||
nmd.PostureChecks[pc.ID] = TwinPostureChecks(pc)
|
||||
nmd.PostureCheckXIDToPublicID[pc.ID] = pc.PublicID
|
||||
}
|
||||
}
|
||||
@@ -393,7 +393,17 @@ func TwinNetwork(n *Network) *nmdata.Network {
|
||||
}
|
||||
}
|
||||
|
||||
func twinPostureChecks(pc *posture.Checks) *nmdata.PostureChecks {
|
||||
// TwinPostureChecksList converts posture checks to their slim nmdata twins.
|
||||
func TwinPostureChecksList(checks []*posture.Checks) []*nmdata.PostureChecks {
|
||||
out := make([]*nmdata.PostureChecks, 0, len(checks))
|
||||
for _, pc := range checks {
|
||||
out = append(out, TwinPostureChecks(pc))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// TwinPostureChecks converts posture checks to their slim nmdata twin.
|
||||
func TwinPostureChecks(pc *posture.Checks) *nmdata.PostureChecks {
|
||||
if pc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -875,6 +875,89 @@ func TestComponents_PeerAsSourceResource(t *testing.T) {
|
||||
assert.True(t, has443, "peer-0 as source resource should have port 443 rule")
|
||||
}
|
||||
|
||||
func hasFirewallRuleTo(nm *types.NetworkMap, peerIP, port string) bool {
|
||||
for _, rule := range nm.FirewallRules {
|
||||
if rule.PeerIP == peerIP && rule.Port == port {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TestComponents_PeerAsSourceResource_PostureChecks verifies that a directly referenced
|
||||
// source peer is gated by the policy's posture checks like a member of a group holding only
|
||||
// that peer: peer-1 (0.25.0) fails the 0.26.0 minimum, peer-2 (0.40.0) passes.
|
||||
func TestComponents_PeerAsSourceResource_PostureChecks(t *testing.T) {
|
||||
account, validatedPeers := scalableTestAccountWithoutDefaultPolicy(20, 2)
|
||||
|
||||
for _, sourcePeerID := range []string{"peer-1", "peer-2"} {
|
||||
account.Policies = append(account.Policies, &types.Policy{
|
||||
ID: "policy-peer-src-" + sourcePeerID, Name: "Peer Source " + sourcePeerID, Enabled: true, AccountID: "test-account",
|
||||
SourcePostureChecks: []string{"posture-check-ver"},
|
||||
Rules: []*types.PolicyRule{{
|
||||
ID: "rule-peer-src-" + sourcePeerID, Enabled: true,
|
||||
Action: types.PolicyTrafficActionAccept,
|
||||
Protocol: types.PolicyRuleProtocolTCP,
|
||||
Bidirectional: true,
|
||||
Ports: []string{"9443"},
|
||||
SourceResource: types.Resource{ID: sourcePeerID, Type: types.ResourceTypePeer},
|
||||
Destinations: []string{"group-0"},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
nm0 := componentsNetworkMap(account, "peer-0", validatedPeers)
|
||||
require.NotNil(t, nm0)
|
||||
assert.False(t, hasFirewallRuleTo(nm0, "100.64.0.1", "9443"), "destination must not see the direct source peer failing the posture check")
|
||||
assert.True(t, hasFirewallRuleTo(nm0, "100.64.0.2", "9443"), "destination must see the direct source peer passing the posture check")
|
||||
|
||||
nm1 := componentsNetworkMap(account, "peer-1", validatedPeers)
|
||||
require.NotNil(t, nm1)
|
||||
assert.False(t, hasFirewallRuleTo(nm1, "100.64.0.0", "9443"), "a direct source peer failing the posture check gets no policy connectivity")
|
||||
|
||||
nm2 := componentsNetworkMap(account, "peer-2", validatedPeers)
|
||||
require.NotNil(t, nm2)
|
||||
assert.True(t, hasFirewallRuleTo(nm2, "100.64.0.0", "9443"), "a direct source peer passing the posture check gets policy connectivity")
|
||||
}
|
||||
|
||||
// TestComponents_PeerAsResource_Unvalidated verifies that a directly referenced peer is
|
||||
// subject to approval like a group member, whether it is the rule's source or destination.
|
||||
func TestComponents_PeerAsResource_Unvalidated(t *testing.T) {
|
||||
account, validatedPeers := scalableTestAccountWithoutDefaultPolicy(20, 2)
|
||||
delete(validatedPeers, "peer-2")
|
||||
|
||||
account.Policies = append(account.Policies,
|
||||
&types.Policy{
|
||||
ID: "policy-unval-src", Name: "Unvalidated Source", Enabled: true, AccountID: "test-account",
|
||||
Rules: []*types.PolicyRule{{
|
||||
ID: "rule-unval-src", Enabled: true,
|
||||
Action: types.PolicyTrafficActionAccept, Protocol: types.PolicyRuleProtocolTCP, Bidirectional: true,
|
||||
Ports: []string{"9443"},
|
||||
SourceResource: types.Resource{ID: "peer-2", Type: types.ResourceTypePeer},
|
||||
Destinations: []string{"group-0"},
|
||||
}},
|
||||
},
|
||||
&types.Policy{
|
||||
ID: "policy-unval-dst", Name: "Unvalidated Destination", Enabled: true, AccountID: "test-account",
|
||||
Rules: []*types.PolicyRule{{
|
||||
ID: "rule-unval-dst", Enabled: true,
|
||||
Action: types.PolicyTrafficActionAccept, Protocol: types.PolicyRuleProtocolTCP, Bidirectional: true,
|
||||
Ports: []string{"9444"},
|
||||
Sources: []string{"group-0"},
|
||||
DestinationResource: types.Resource{ID: "peer-2", Type: types.ResourceTypePeer},
|
||||
}},
|
||||
},
|
||||
)
|
||||
|
||||
nm0 := componentsNetworkMap(account, "peer-0", validatedPeers)
|
||||
require.NotNil(t, nm0)
|
||||
assert.False(t, hasFirewallRuleTo(nm0, "100.64.0.2", "9443"), "an unvalidated direct source peer must not be admitted")
|
||||
assert.False(t, hasFirewallRuleTo(nm0, "100.64.0.2", "9444"), "an unvalidated direct destination peer must not be admitted")
|
||||
for _, p := range nm0.Peers {
|
||||
assert.NotEqual(t, "peer-2", p.ID, "an unvalidated direct peer must not be shipped as a remote peer")
|
||||
}
|
||||
}
|
||||
|
||||
// TestComponents_PeerAsDestinationResource verifies that a policy with DestinationResource.Type=Peer
|
||||
// targets only that specific peer as the destination.
|
||||
func TestComponents_PeerAsDestinationResource(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user