tailcfg: reintroduce UserProfile.Groups

This change reintroduces UserProfile.Groups, a slice that contains
the ACL-defined and synced groups that a user is a member of.

The slice will only be non-nil for clients with the node attribute
see-groups, and will only contain groups that the client is allowed
to see as per the app payload of the see-groups node attribute.

For example:
```
"nodeAttrs": [
  {
    "target": ["tag:dev"],
    "app": {
      "tailscale.com/see-groups": [{"groups": ["group:dev"]}]
    }
  },

  [...]

]
```

UserProfile.Groups will also be gated by a feature flag for the time
being.

Updates tailscale/corp#31529

Signed-off-by: Gesa Stupperich <gesa@tailscale.com>
This commit is contained in:
Gesa Stupperich
2026-02-17 13:15:02 +00:00
committed by Gesa Stupperich
parent ac74dfa5cd
commit 6a19995f13
11 changed files with 35 additions and 15 deletions
+3 -3
View File
@@ -606,7 +606,7 @@ func runTestStateMachine(t *testing.T, seamless bool) {
cc.assertCalls()
c.Assert(nn[0].LoginFinished, qt.IsNotNil)
c.Assert(nn[1].Prefs, qt.IsNotNil)
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName, qt.Equals, "user1")
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName(), qt.Equals, "user1")
// nn[2] is a state notification after login
// Verify login finished but need machine auth using backend state
c.Assert(isFullyAuthenticated(b), qt.IsTrue)
@@ -818,7 +818,7 @@ func runTestStateMachine(t *testing.T, seamless bool) {
c.Assert(nn[1].Prefs, qt.IsNotNil)
c.Assert(nn[1].Prefs.Persist(), qt.IsNotNil)
// Prefs after finishing the login, so LoginName updated.
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName, qt.Equals, "user2")
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName(), qt.Equals, "user2")
c.Assert(nn[1].Prefs.LoggedOut(), qt.IsFalse)
// If a user initiates an interactive login, they also expect WantRunning to become true.
c.Assert(nn[1].Prefs.WantRunning(), qt.IsTrue)
@@ -964,7 +964,7 @@ func runTestStateMachine(t *testing.T, seamless bool) {
c.Assert(nn[0].LoginFinished, qt.IsNotNil)
c.Assert(nn[1].Prefs, qt.IsNotNil)
// Prefs after finishing the login, so LoginName updated.
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName, qt.Equals, "user3")
c.Assert(nn[1].Prefs.Persist().UserProfile().LoginName(), qt.Equals, "user3")
c.Assert(nn[1].Prefs.LoggedOut(), qt.IsFalse)
c.Assert(nn[1].Prefs.WantRunning(), qt.IsTrue)
// nn[2] is state notification (Starting) - verify using backend state