policy/v2: fix empty grants/acls returning FilterAllowAll

compileFilterRules, compileGrants, and updateLocked guarded the
"no rules so allow all" fallback with len(pol.Grants) == 0, which
matches both an absent grants field and an explicit empty array.
JSON {"grants": []} unmarshals to a non-nil empty slice; it should
compile to zero filter rules (deny all) to match Tailscale SaaS,
but the length check sent it down the FilterAllowAll path.

Distinguish absent (nil) from explicit-empty by switching the guard
to pol.Grants == nil, the same asymmetry already used for ACLs.
{} keeps allowing all; {"acls": []} and {"grants": []} now both
deny all.

Fixes #3211
This commit is contained in:
Kristoffer Dalby 2026-04-28 09:21:18 +00:00
parent 174e409da6
commit 2e1a716a9a
6 changed files with 63 additions and 5 deletions

View file

@ -101,7 +101,7 @@ func (pol *Policy) compileGrants(
users types.Users,
nodes views.Slice[types.NodeView],
) []compiledGrant {
if pol == nil || (pol.ACLs == nil && len(pol.Grants) == 0) {
if pol == nil || (pol.ACLs == nil && pol.Grants == nil) {
return nil
}