ipn/ipnlocal,cmd/tailscale: persist tailnet name in user profile

This PR starts to persist the NetMap tailnet name in SetPrefs so that tailscaled
clients can use this value to disambiguate fast user switching from one tailnet
to another that are under the same exact login. We will also try to backfill
this information during backend starts and profile switches so that users don't
have to re-authenticate their profile. The first client to use this new
information is the CLI in 'tailscale switch -list' which now uses text/tabwriter
to display the ID, Tailnet, and Account. Since account names are ambiguous, we
allow the user to pass 'tailscale switch ID' to specify the exact tailnet they
want to switch to.

Updates #9286

Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
This commit is contained in:
Marwan Sulaiman
2023-11-16 21:40:23 -05:00
committed by Marwan Sulaiman
parent e75be017e4
commit 2dc0645368
10 changed files with 131 additions and 44 deletions

View File

@@ -341,7 +341,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
return nil, err
}
p.ApplyEdits(&mp)
if err := pm.SetPrefs(p.View(), ""); err != nil {
if err := pm.SetPrefs(p.View(), ipn.NetworkProfile{}); err != nil {
return nil, err
}
}
@@ -1105,10 +1105,19 @@ func (b *LocalBackend) SetControlClientStatus(c controlclient.Client, st control
prefsChanged = true
}
// Until recently, we did not store the account's tailnet name. So check if this is the case,
// and backfill it on incoming status update.
if b.pm.requiresBackfill() && st.NetMap != nil && st.NetMap.Domain != "" {
prefsChanged = true
}
// Perform all mutations of prefs based on the netmap here.
if prefsChanged {
// Prefs will be written out if stale; this is not safe unless locked or cloned.
if err := b.pm.SetPrefs(prefs.View(), st.NetMap.MagicDNSSuffix()); err != nil {
if err := b.pm.SetPrefs(prefs.View(), ipn.NetworkProfile{
MagicDNSName: st.NetMap.MagicDNSSuffix(),
DomainName: st.NetMap.DomainName(),
}); err != nil {
b.logf("Failed to save new controlclient state: %v", err)
}
}
@@ -1164,7 +1173,10 @@ func (b *LocalBackend) SetControlClientStatus(c controlclient.Client, st control
b.mu.Lock()
prefs.WantRunning = false
p := prefs.View()
if err := b.pm.SetPrefs(p, st.NetMap.MagicDNSSuffix()); err != nil {
if err := b.pm.SetPrefs(p, ipn.NetworkProfile{
MagicDNSName: st.NetMap.MagicDNSSuffix(),
DomainName: st.NetMap.DomainName(),
}); err != nil {
b.logf("Failed to save new controlclient state: %v", err)
}
b.mu.Unlock()
@@ -1573,7 +1585,10 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
newPrefs := opts.UpdatePrefs.Clone()
newPrefs.Persist = oldPrefs.Persist().AsStruct()
pv := newPrefs.View()
if err := b.pm.SetPrefs(pv, b.netMap.MagicDNSSuffix()); err != nil {
if err := b.pm.SetPrefs(pv, ipn.NetworkProfile{
MagicDNSName: b.netMap.MagicDNSSuffix(),
DomainName: b.netMap.DomainName(),
}); err != nil {
b.logf("failed to save UpdatePrefs state: %v", err)
}
b.setAtomicValuesFromPrefsLocked(pv)
@@ -2479,7 +2494,10 @@ func (b *LocalBackend) migrateStateLocked(prefs *ipn.Prefs) (err error) {
// Backend owns the state, but frontend is trying to migrate
// state into the backend.
b.logf("importing frontend prefs into backend store; frontend prefs: %s", prefs.Pretty())
if err := b.pm.SetPrefs(prefs.View(), b.netMap.MagicDNSSuffix()); err != nil {
if err := b.pm.SetPrefs(prefs.View(), ipn.NetworkProfile{
MagicDNSName: b.netMap.MagicDNSSuffix(),
DomainName: b.netMap.DomainName(),
}); err != nil {
return fmt.Errorf("store.WriteState: %v", err)
}
}
@@ -3060,7 +3078,10 @@ func (b *LocalBackend) setPrefsLockedOnEntry(caller string, newp *ipn.Prefs) ipn
}
prefs := newp.View()
if err := b.pm.SetPrefs(prefs, b.netMap.MagicDNSSuffix()); err != nil {
if err := b.pm.SetPrefs(prefs, ipn.NetworkProfile{
MagicDNSName: b.netMap.MagicDNSSuffix(),
DomainName: b.netMap.DomainName(),
}); err != nil {
b.logf("failed to save new controlclient state: %v", err)
}
b.lastProfileID = b.pm.CurrentProfile().ID