ipn/ipnlocal: handle untagging nodes better

We would end up with duplicate profiles for the node as the UserID
would have chnaged. In order to correctly deduplicate profiles, we
need to look at both the UserID and the NodeID. A single machine can
only ever have 1 profile per NodeID and 1 profile per UserID.

Note: UserID of a Node can change when the node is tagged/untagged,
and the NodeID of a device can change when the node is deleted so we
need to check for both.

Updates #713

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali
2022-11-17 19:05:02 +05:00
committed by Maisem Ali
parent f18dde6ad1
commit dd50dcd067
9 changed files with 122 additions and 38 deletions

View File

@@ -38,6 +38,7 @@ type Persist struct {
LoginName string
UserProfile tailcfg.UserProfile
NetworkLockKey key.NLPrivate
NodeID tailcfg.StableNodeID
}
// PublicNodeKey returns the public key for the node key.
@@ -68,7 +69,8 @@ func (p *Persist) Equals(p2 *Persist) bool {
p.Provider == p2.Provider &&
p.LoginName == p2.LoginName &&
p.UserProfile == p2.UserProfile &&
p.NetworkLockKey.Equal(p2.NetworkLockKey)
p.NetworkLockKey.Equal(p2.NetworkLockKey) &&
p.NodeID == p2.NodeID
}
func (p *Persist) Pretty() string {

View File

@@ -33,4 +33,5 @@ var _PersistCloneNeedsRegeneration = Persist(struct {
LoginName string
UserProfile tailcfg.UserProfile
NetworkLockKey key.NLPrivate
NodeID tailcfg.StableNodeID
}{})

View File

@@ -22,7 +22,7 @@ func fieldsOf(t reflect.Type) (fields []string) {
}
func TestPersistEqual(t *testing.T) {
persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "LoginName", "UserProfile", "NetworkLockKey"}
persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "LoginName", "UserProfile", "NetworkLockKey", "NodeID"}
if have := fieldsOf(reflect.TypeOf(Persist{})); !reflect.DeepEqual(have, persistHandles) {
t.Errorf("Persist.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, persistHandles)
@@ -123,6 +123,16 @@ func TestPersistEqual(t *testing.T) {
&Persist{NetworkLockKey: key.NewNLPrivate()},
false,
},
{
&Persist{NodeID: "abc"},
&Persist{NodeID: "abc"},
true,
},
{
&Persist{NodeID: ""},
&Persist{NodeID: "abc"},
false,
},
}
for i, test := range tests {
if got := test.a.Equals(test.b); got != test.want {

View File

@@ -71,6 +71,7 @@ func (v PersistView) Provider() string { return v.ж.Provider
func (v PersistView) LoginName() string { return v.ж.LoginName }
func (v PersistView) UserProfile() tailcfg.UserProfile { return v.ж.UserProfile }
func (v PersistView) NetworkLockKey() key.NLPrivate { return v.ж.NetworkLockKey }
func (v PersistView) NodeID() tailcfg.StableNodeID { return v.ж.NodeID }
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
var _PersistViewNeedsRegeneration = Persist(struct {
@@ -82,4 +83,5 @@ var _PersistViewNeedsRegeneration = Persist(struct {
LoginName string
UserProfile tailcfg.UserProfile
NetworkLockKey key.NLPrivate
NodeID tailcfg.StableNodeID
}{})