diff --git a/kube/authkey/authkey.go b/kube/authkey/authkey.go index 5698f55f0..c56301b12 100644 --- a/kube/authkey/authkey.go +++ b/kube/authkey/authkey.go @@ -19,6 +19,7 @@ import ( "log" "time" + "tailscale.com/ipn" "tailscale.com/ipn/conffile" "tailscale.com/kube/kubeapi" "tailscale.com/kube/kubeclient" @@ -46,11 +47,27 @@ func SetReissueAuthKey(ctx context.Context, kc kubeclient.Client, stateSecretNam // ClearReissueAuthKey removes the reissue_authkey marker from the state Secret // to signal to the operator that we've successfully received the new key. func ClearReissueAuthKey(ctx context.Context, kc kubeclient.Client, stateSecretName string, fieldManager string) error { + existing, err := kc.GetSecret(ctx, stateSecretName) + if err != nil { + return fmt.Errorf("error getting state secret: %w", err) + } + s := &kubeapi.Secret{ Data: map[string][]byte{ - kubetypes.KeyReissueAuthkey: nil, + kubetypes.KeyReissueAuthkey: nil, + kubetypes.KeyDeviceID: nil, + kubetypes.KeyDeviceFQDN: nil, + kubetypes.KeyDeviceIPs: nil, + string(ipn.MachineKeyStateKey): nil, + string(ipn.CurrentProfileStateKey): nil, + string(ipn.KnownProfilesStateKey): nil, }, } + + if profileKey := string(existing.Data["_current-profile"]); profileKey != "" { + s.Data[profileKey] = nil + } + return kc.StrategicMergePatchSecret(ctx, stateSecretName, s, fieldManager) } diff --git a/kube/authkey/authkey_test.go b/kube/authkey/authkey_test.go index bb01b6a44..268bc46d6 100644 --- a/kube/authkey/authkey_test.go +++ b/kube/authkey/authkey_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "tailscale.com/ipn" "tailscale.com/kube/kubeapi" "tailscale.com/kube/kubeclient" "tailscale.com/kube/kubetypes" @@ -42,6 +43,15 @@ func TestSetReissueAuthKey(t *testing.T) { func TestClearReissueAuthKey(t *testing.T) { var patched map[string][]byte kc := &kubeclient.FakeClient{ + GetSecretImpl: func(ctx context.Context, name string) (*kubeapi.Secret, error) { + return &kubeapi.Secret{ + Data: map[string][]byte{ + "_current-profile": []byte("profile-abc1"), + "profile-abc1": []byte("some-profile-data"), + "_machinekey": []byte("machine-key-data"), + }, + }, nil + }, StrategicMergePatchSecretImpl: func(ctx context.Context, name string, secret *kubeapi.Secret, _ string) error { patched = secret.Data return nil @@ -54,7 +64,14 @@ func TestClearReissueAuthKey(t *testing.T) { } want := map[string][]byte{ - kubetypes.KeyReissueAuthkey: nil, + kubetypes.KeyReissueAuthkey: nil, + kubetypes.KeyDeviceID: nil, + kubetypes.KeyDeviceFQDN: nil, + kubetypes.KeyDeviceIPs: nil, + string(ipn.MachineKeyStateKey): nil, + string(ipn.CurrentProfileStateKey): nil, + string(ipn.KnownProfilesStateKey): nil, + "profile-abc1": nil, } if diff := cmp.Diff(want, patched); diff != "" { t.Errorf("ClearReissueAuthKey() mismatch (-want +got):\n%s", diff) diff --git a/kube/state/state.go b/kube/state/state.go index ebedb2f72..a7f00b7f2 100644 --- a/kube/state/state.go +++ b/kube/state/state.go @@ -30,19 +30,8 @@ const ( keyDeviceFQDN = ipn.StateKey(kubetypes.KeyDeviceFQDN) ) -// SetInitialKeys sets Pod UID and cap ver and clears tailnet device state -// keys to help stop the operator using stale tailnet device state. +// SetInitialKeys sets Pod UID and cap ver. func SetInitialKeys(store ipn.StateStore, podUID string) error { - // Clear device state keys first so the operator knows if the pod UID - // matches, the other values are definitely not stale. - for _, key := range []ipn.StateKey{keyDeviceID, keyDeviceFQDN, keyDeviceIPs} { - if _, err := store.ReadState(key); err == nil { - if err := store.WriteState(key, nil); err != nil { - return fmt.Errorf("error writing %q to state store: %w", key, err) - } - } - } - if err := store.WriteState(keyPodUID, []byte(podUID)); err != nil { return fmt.Errorf("error writing pod UID to state store: %w", err) }