Merge remote-tracking branch 'origin/revert/component-types' into revert/component-types

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
This commit is contained in:
Dmitri Dolguikh
2026-08-10 14:08:23 +02:00
5 changed files with 217 additions and 4 deletions

View File

@@ -372,6 +372,8 @@ func (c *Controller) sendUpdatesFromData(ctx context.Context, accountID string,
return fmt.Errorf("failed to get flow enabled status: %v", err)
}
nmData.PrecomputePostureValidation()
dnsCache := &cache.DNSConfigCache{}
dnsDomain := c.getDNSDomainFromData(nmData.AccountSettings)
peersCustomZone := networkmap.PeersCustomZone(ctx, accountID, dnsDomain, nmData.Peers, ipv6AllowedPeersFromData(nmData))

View File

@@ -465,6 +465,13 @@ func (nmd *NetworkMapData) validatePostureChecksOnPeerGetFailed(sourcePostureChe
}
for _, postureChecksID := range sourcePostureChecksID {
if valid, cached := nmd.cachedPostureCheckResult(postureChecksID, peerID); cached {
if !valid {
return false, postureChecksID
}
continue
}
postureChecks := nmd.PostureChecks[postureChecksID]
if postureChecks == nil {
continue
@@ -476,6 +483,76 @@ func (nmd *NetworkMapData) validatePostureChecksOnPeerGetFailed(sourcePostureChe
return true, ""
}
func (nmd *NetworkMapData) PrecomputePostureValidation() {
if len(nmd.PostureChecks) == 0 {
nmd.PostureValidation = nil
return
}
checkPeerIDs := make(map[string]map[string]struct{})
for _, policy := range nmd.Policies {
if policy == nil || !policy.Enabled || len(policy.SourcePostureChecks) == 0 {
continue
}
groupPeerIDs := nmd.getUniquePeerIDsFromGroupsIDs(policy.SourceGroups())
for _, postureChecksID := range policy.SourcePostureChecks {
set := checkPeerIDs[postureChecksID]
if set == nil {
set = make(map[string]struct{}, len(groupPeerIDs))
checkPeerIDs[postureChecksID] = set
}
for _, pid := range groupPeerIDs {
set[pid] = struct{}{}
}
for _, rule := range policy.Rules {
if rule == nil {
continue
}
if rule.SourceResource.Type == string(types.ResourceTypePeer) && rule.SourceResource.ID != "" {
set[rule.SourceResource.ID] = struct{}{}
}
}
}
}
results := make(map[string]map[string]bool, len(checkPeerIDs))
for postureChecksID, peerIDs := range checkPeerIDs {
results[postureChecksID] = nmd.evaluatePostureChecksForPeers(postureChecksID, peerIDs)
}
nmd.PostureValidation = results
}
func (nmd *NetworkMapData) evaluatePostureChecksForPeers(postureChecksID string, peerIDs map[string]struct{}) map[string]bool {
postureChecks := nmd.PostureChecks[postureChecksID]
if postureChecks == nil {
return nil
}
checks := postureChecks.GetChecks()
results := make(map[string]bool, len(peerIDs))
for peerID := range peerIDs {
peer := nmd.Peers[peerID]
if peer == nil {
continue
}
results[peerID] = nmdata.PassesChecks(checks, peer)
}
return results
}
func (nmd *NetworkMapData) cachedPostureCheckResult(postureChecksID, peerID string) (bool, bool) {
results, ok := nmd.PostureValidation[postureChecksID]
if !ok {
return false, false
}
if results == nil {
return true, true
}
valid, found := results[peerID]
return valid, found
}
func (nmd *NetworkMapData) getPostureValidPeersSaveFailed(inputPeers []string, postureChecksIDs []string, postureFailedPeers *map[string]map[string]struct{}) []string {
var dest []string
for _, peerID := range inputPeers {

View File

@@ -1475,6 +1475,126 @@ func TestGetPeerNetworkMapComponents_StoreImmutableAndDeterministic(t *testing.T
assert.Equal(t, first.GroupIDToUserIDs, second.GroupIDToUserIDs)
}
func TestPrecomputePostureValidation(t *testing.T) {
newFixture := func() *networkmap.NetworkMapData {
target := newPeer(targetID, 1)
srcPass := newPeer("peer-src-pass", 2)
srcFail := newPeer("peer-src-fail", 3)
srcFail.Meta.WtVersion = failingVersion
other := newPeer("peer-other", 4)
other.Meta.WtVersion = failingVersion
nmd := newNMD(target, srcPass, srcFail, other)
addVersionCheck(nmd, "pc-1", postureMinVersion)
addGroup(nmd, "g-src", srcPass.ID, srcFail.ID)
addGroup(nmd, "g-dst", targetID)
addGroup(nmd, "g-open", srcPass.ID, srcFail.ID, other.ID)
checked := newPolicy("p-checked", newRule([]string{"g-src"}, []string{"g-dst"}))
checked.SourcePostureChecks = []string{"pc-1"}
open := newPolicy("p-open", newRule([]string{"g-open"}, []string{"g-dst"}))
disabled := newPolicy("p-disabled", newRule([]string{"g-open"}, []string{"g-dst"}))
disabled.Enabled = false
disabled.SourcePostureChecks = []string{"pc-1"}
nmd.Policies = []*nmdata.Policy{checked, open, disabled}
return nmd
}
type snapshot struct {
peers []string
postureFailedPeers map[string]map[string]struct{}
}
snapshotAll := func(nmd *networkmap.NetworkMapData) map[string]snapshot {
out := make(map[string]snapshot, len(nmd.Peers))
for peerID := range nmd.Peers {
c := compute(nmd, peerID)
out[peerID] = snapshot{peers: peerIDSet(c.Peers), postureFailedPeers: c.PostureFailedPeers}
}
return out
}
t.Run("memoized results match direct evaluation", func(t *testing.T) {
nmd := newFixture()
direct := snapshotAll(nmd)
nmd.PrecomputePostureValidation()
memoized := snapshotAll(nmd)
require.Len(t, memoized, len(direct))
for peerID, want := range direct {
assert.ElementsMatch(t, want.peers, memoized[peerID].peers, "visible peers changed for %s", peerID)
assert.Equal(t, want.postureFailedPeers, memoized[peerID].postureFailedPeers, "posture failures changed for %s", peerID)
}
})
t.Run("only source peers of enabled checked policies are evaluated", func(t *testing.T) {
nmd := newFixture()
nmd.PrecomputePostureValidation()
assert.Equal(t, map[string]map[string]bool{
"pc-1": {"peer-src-pass": true, "peer-src-fail": false},
}, nmd.PostureValidation)
})
t.Run("peer source resources are evaluated", func(t *testing.T) {
nmd := newFixture()
resourcePolicy := newPolicy("p-resource", newRule(nil, []string{"g-dst"}))
resourcePolicy.Rules[0].SourceResource = nmdata.Resource{ID: "peer-other", Type: string(nbtypes.ResourceTypePeer)}
resourcePolicy.SourcePostureChecks = []string{"pc-1"}
nmd.Policies = append(nmd.Policies, resourcePolicy)
nmd.PrecomputePostureValidation()
assert.Equal(t, map[string]bool{"peer-src-pass": true, "peer-src-fail": false, "peer-other": false},
nmd.PostureValidation["pc-1"])
})
t.Run("memoized result wins over direct evaluation", func(t *testing.T) {
nmd := newFixture()
nmd.PostureValidation = map[string]map[string]bool{
"pc-1": {"peer-src-pass": false, "peer-src-fail": true},
}
c := compute(nmd, targetID)
assert.Equal(t, map[string]map[string]struct{}{"pc-1": {"peer-src-pass": {}}}, c.PostureFailedPeers)
})
t.Run("no posture checks clears the memo", func(t *testing.T) {
nmd := newFixture()
nmd.PrecomputePostureValidation()
require.NotEmpty(t, nmd.PostureValidation)
nmd.PostureChecks = nil
nmd.PrecomputePostureValidation()
assert.Nil(t, nmd.PostureValidation)
})
t.Run("unresolvable check id memoized as passing", func(t *testing.T) {
nmd := newFixture()
nmd.Policies[0].SourcePostureChecks = []string{"pc-ghost"}
nmd.PrecomputePostureValidation()
require.Contains(t, nmd.PostureValidation, "pc-ghost")
assert.Nil(t, nmd.PostureValidation["pc-ghost"])
c := compute(nmd, targetID)
assert.ElementsMatch(t, []string{targetID, "peer-src-pass", "peer-src-fail", "peer-other"}, peerIDSet(c.Peers))
assert.Empty(t, c.PostureFailedPeers)
})
t.Run("peers missing from the memo fall back to direct evaluation", func(t *testing.T) {
nmd := newFixture()
nmd.PostureValidation = map[string]map[string]bool{"pc-1": {"peer-src-pass": true}}
c := compute(nmd, targetID)
assert.Equal(t, map[string]map[string]struct{}{"pc-1": {"peer-src-fail": {}}}, c.PostureFailedPeers)
})
}
func TestNetworkMapData_GetPeerGroups(t *testing.T) {
target := newPeer(targetID, 1)
other := newPeer("peer-other", 2)

View File

@@ -25,6 +25,12 @@ type NetworkMapData struct { //nolint:revive // established name across the code
PostureChecks map[string]*nmdata.PostureChecks
// PostureValidation holds the precomputed posture-check results, keyed by
// posture check ID then peer ID. Filled by PrecomputePostureValidation; a
// present but nil inner map marks a check ID that resolves to no posture
// check, which the calc treats as passing.
PostureValidation map[string]map[string]bool
AllowedUserIDs map[string]struct{}
NetworkXIDToPublicID map[string]string
PostureCheckXIDToPublicID map[string]string

View File

@@ -20,7 +20,9 @@ type ChecksDefinition struct {
ProcessCheck *ProcessCheck
}
type postureCheck interface {
// Check is the slim twin of posture.Check. It is sealed: only the check types
// in this package implement it.
type Check interface {
check(peer *Peer) (bool, error)
}
@@ -28,7 +30,13 @@ type postureCheck interface {
// mirrors the server posture path: a check returning (false, _) — including on
// an evaluation error — fails the bundle.
func (pc *PostureChecks) Passes(peer *Peer) bool {
for _, c := range pc.GetChecks() {
return PassesChecks(pc.GetChecks(), peer)
}
// PassesChecks is Passes over an already built check set, for callers that
// evaluate many peers against the same bundle.
func PassesChecks(checks []Check, peer *Peer) bool {
for _, c := range checks {
valid, _ := c.check(peer)
if !valid {
return false
@@ -38,8 +46,8 @@ func (pc *PostureChecks) Passes(peer *Peer) bool {
}
// GetChecks returns the initialized checks in the same order as posture.Checks.GetChecks.
func (pc *PostureChecks) GetChecks() []postureCheck {
var checks []postureCheck
func (pc *PostureChecks) GetChecks() []Check {
var checks []Check
if pc.Checks.NBVersionCheck != nil {
checks = append(checks, pc.Checks.NBVersionCheck)
}