control/controlclient: let clients opt in to Sharer-vs-User split model
Updates tailscale/corp#1183
@@ -117,6 +117,7 @@ type Direct struct {
discoPubKey tailcfg.DiscoKey
machinePrivKey wgkey.Private
debugFlags []string
+ keepSharerAndUserSplit bool
mu sync.Mutex // mutex guards the following fields
serverKey wgkey.Key
@@ -144,6 +145,10 @@ type Options struct {
Logf logger.Logf
HTTPTestClient *http.Client // optional HTTP client to use (for tests only)
DebugFlags []string // debug settings to send to control
+
+ // KeepSharerAndUserSplit controls whether the client
+ // understands Node.Sharer. If false, the Sharer is mapped to the User.
+ KeepSharerAndUserSplit bool
}
type Decompressor interface {
@@ -201,6 +206,7 @@ func NewDirect(opts Options) (*Direct, error) {
authKey: opts.AuthKey,
discoPubKey: opts.DiscoPublicKey,
debugFlags: opts.DebugFlags,
+ keepSharerAndUserSplit: opts.KeepSharerAndUserSplit,
}
if opts.Hostinfo == nil {
c.SetHostinfo(NewHostinfo())
@@ -785,20 +791,13 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*Netw
}
addUserProfile(nm.User)
for _, peer := range resp.Peers {
- // TODO(bradfitz): ideally we'd push down the semantically correct
- // Nodes with differing User vs Sharer fields, but that means
- // updating Windows, macOS, and tailscale status to respect all
- // those fields, but until we have a plan for what the UI should
- // be later when we treat them differently, it's easier to just
- // merge it together here. The server will anonymize UserProfile
- // records of those not in your network and not a sharer, which
- // will be most of the peer.Users so it'll be rare when a node's
- // owner-who's-different-from-sharer will have a non-scrubbed
- // UserProfile: they would've also needed to share a node
- // themselves. Until we care, merge the data here.
if !peer.Sharer.IsZero() {
+ if c.keepSharerAndUserSplit {
+ addUserProfile(peer.Sharer)
+ } else {
peer.User = peer.Sharer
}
+ }
addUserProfile(peer.User)
}
if resp.Node.MachineAuthorized {
