diff --git a/CHANGELOG.md b/CHANGELOG.md index 00a29f2da..30be662df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,7 +137,7 @@ clients, and how to run the same setup without Nix. - Fix SSH access surviving the removal of its policy rules; clients kept their last SSH rules, and a pending SSH check could still be approved [#3517](https://github.com/juanfont/headscale/pull/3517) - Fix SSH check periods coming from the first check rule for a node pair instead of the rule for the login user [#3517](https://github.com/juanfont/headscale/pull/3517) - Policy changes resend a node's SSH policy only when it changed, sparing clients a full netmap rebuild [#3517](https://github.com/juanfont/headscale/pull/3517) -- Map generation no longer resolves every policy rule's sources and destinations for each peer when the policy has no `via` grants, which made map responses slow and CPU-bound on large tailnets [#3512](https://github.com/juanfont/headscale/issues/3512) +- Fix every grant being fully resolved as if it had `via` when the policy has no `via` grants, slowing map generation on large tailnets [#3538](https://github.com/juanfont/headscale/pull/3538) ## 0.29.5 (202x-xx-xx) diff --git a/hscontrol/policy/v2/policy.go b/hscontrol/policy/v2/policy.go index 7f8b47958..be3fb6fad 100644 --- a/hscontrol/policy/v2/policy.go +++ b/hscontrol/policy/v2/policy.go @@ -1369,7 +1369,7 @@ func (pm *PolicyManager) ViaRoutesForPeer(viewer, peer types.NodeView) types.Via } // Only via grants can add to the result, and ACLs never carry via. - if !slices.ContainsFunc(pm.pol.Grants, grantHasVia) { + if !slices.ContainsFunc(pm.pol.Grants, Grant.HasVia) { return result } @@ -1419,7 +1419,7 @@ func (pm *PolicyManager) ViaRoutesForPeer(viewer, peer types.NodeView) types.Via } for i, grant := range grants { - if len(grant.Via) == 0 { + if !grant.HasVia() { continue } @@ -1502,7 +1502,7 @@ func (pm *PolicyManager) ViaRoutesForPeer(viewer, peer types.NodeView) types.Via // otherwise grants for other viewer groups would incorrectly // demote the peer. for i, grant := range grants { - if len(grant.Via) == 0 { + if !grant.HasVia() { continue } @@ -1552,7 +1552,7 @@ func (pm *PolicyManager) ViaRoutesForPeer(viewer, peer types.NodeView) types.Via // [state.State.RoutesForPeer] can apply normal // [policy.ReduceRoutes] + primary logic. for i, grant := range grants { - if len(grant.Via) > 0 { + if grant.HasVia() { continue } @@ -1590,10 +1590,6 @@ func (pm *PolicyManager) ViaRoutesForPeer(viewer, peer types.NodeView) types.Via return result } -func grantHasVia(grant Grant) bool { - return len(grant.Via) > 0 -} - // grantReachesInternet reports whether a grant's destinations include // the internet. Neither the wildcard nor autogroup:internet resolves // to 0.0.0.0/0, so check the aliases themselves. diff --git a/hscontrol/policy/v2/types.go b/hscontrol/policy/v2/types.go index 7d877b1be..4844b0725 100644 --- a/hscontrol/policy/v2/types.go +++ b/hscontrol/policy/v2/types.go @@ -1850,6 +1850,11 @@ type Grant struct { Via []Tag `json:"via,omitzero"` } +// HasVia reports whether the grant routes through via-tagged nodes. +func (g Grant) HasVia() bool { + return len(g.Via) > 0 +} + // NodeAttrGrant attaches Tailscale node capabilities (and/or an IP-pool // preference) to every node selected by Targets. The Targets aliases are // resolved exactly like ACL/grant sources, so users, groups, tags, hosts,