ipn/ipnlocal: populate Groups field in profileFromView

This populates UserProfile.Groups in the WhoIs response from the
local backend with the groups of the corresponding user in the
netmap.

This allows tsnet apps to see (and e.g. forward) which groups a
user making a request belongs to - as long as the tsnet app runs
on a node that been granted the tailscale.com/visible-groups
capability via node attributes. If that's not the case or the
user doesn't belong to any groups allow-listed via the node
attribute, Groups won't be populated.

Updates tailscale/corp#31529

Signed-off-by: Gesa Stupperich <gesa@tailscale.com>
main
Gesa Stupperich 4 weeks ago committed by GitHub
parent ac19bd5e7a
commit ca9aa20255
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      ipn/ipnlocal/local.go
  2. 21
      ipn/ipnlocal/local_test.go

@ -1473,6 +1473,7 @@ func profileFromView(v tailcfg.UserProfileView) tailcfg.UserProfile {
LoginName: v.LoginName(),
DisplayName: v.DisplayName(),
ProfilePicURL: v.ProfilePicURL(),
Groups: v.Groups().AsSlice(),
}
}
return tailcfg.UserProfile{}

@ -2070,19 +2070,21 @@ func TestWhoIs(t *testing.T) {
}).View(),
20: (&tailcfg.UserProfile{
DisplayName: "Peer",
Groups: []string{"group:foo"},
}).View(),
},
})
tests := []struct {
q string
want tailcfg.NodeID // 0 means want ok=false
wantName string
q string
want tailcfg.NodeID // 0 means want ok=false
wantName string
wantGroups []string
}{
{"100.101.102.103:0", 1, "Myself"},
{"100.101.102.103:123", 1, "Myself"},
{"100.200.200.200:0", 2, "Peer"},
{"100.200.200.200:123", 2, "Peer"},
{"100.4.0.4:404", 0, ""},
{"100.101.102.103:0", 1, "Myself", nil},
{"100.101.102.103:123", 1, "Myself", nil},
{"100.200.200.200:0", 2, "Peer", []string{"group:foo"}},
{"100.200.200.200:123", 2, "Peer", []string{"group:foo"}},
{"100.4.0.4:404", 0, "", nil},
}
for _, tt := range tests {
t.Run(tt.q, func(t *testing.T) {
@ -2097,6 +2099,9 @@ func TestWhoIs(t *testing.T) {
if up.DisplayName != tt.wantName {
t.Errorf("got name %q; want %q", up.DisplayName, tt.wantName)
}
if !slices.Equal(up.Groups, tt.wantGroups) {
t.Errorf("got groups %q; want %q", up.Groups, tt.wantGroups)
}
})
}
}

Loading…
Cancel
Save