diff --git a/hscontrol/auth.go b/hscontrol/auth.go index ed135783e..327a1d459 100644 --- a/hscontrol/auth.go +++ b/hscontrol/auth.go @@ -258,9 +258,10 @@ func (h *Headscale) handleLogout( return nil, fmt.Errorf("deleting ephemeral node: %w", err) } + // The node was authorised to log out; Tailscale answers so too. return &tailcfg.RegisterResponse{ NodeKeyExpired: true, - MachineAuthorized: false, + MachineAuthorized: true, }, nil } diff --git a/hscontrol/auth_test.go b/hscontrol/auth_test.go index 0e0f64951..d536a25a4 100644 --- a/hscontrol/auth_test.go +++ b/hscontrol/auth_test.go @@ -660,10 +660,10 @@ func TestAuthenticationFlows(t *testing.T) { } }, machineKey: machineKey1.Public, + wantAuth: true, // the logout is answered as authorised wantExpired: true, validate: func(t *testing.T, resp *tailcfg.RegisterResponse, app *Headscale) { //nolint:thelper //nolint:thelper assert.True(t, resp.NodeKeyExpired) - assert.False(t, resp.MachineAuthorized) // Ephemeral node should be deleted, not just marked expired _, found := app.state.GetNodeByNodeKey(nodeKey1.Public()) diff --git a/hscontrol/servertest/lifecycle_compat_test.go b/hscontrol/servertest/lifecycle_compat_test.go index b4c01dfa1..a54d26015 100644 --- a/hscontrol/servertest/lifecycle_compat_test.go +++ b/hscontrol/servertest/lifecycle_compat_test.go @@ -36,16 +36,12 @@ import ( // the step of what killed nodes leave behind. A listed check that matches // fails, so a fix must delete its entry. var lifecycleSkipReasons = map[string]string{ - "ephemeral-lifecycle/E1-logout/eph-logout/outcome": logoutAnswerUnauthorized, - "ephemeral-lifecycle/E1-logout/eph-logout-user/outcome": logoutAnswerUnauthorized, - "ephemeral-lifecycle/E3-key-delete/2/keys": deletedKeyListed, "ephemeral-lifecycle/E3-key-delete/3/keys": deletedKeyListed, "ephemeral-lifecycle/E3-key-delete/4/status": deletedKeyDeleteNotFound, } const ( - logoutAnswerUnauthorized = "LOGOUT_ANSWER_UNAUTHORIZED: headscale answers the logout that deletes an ephemeral node with MachineAuthorized false; SaaS answers true" deletedKeyListed = "DELETED_KEY_LISTED: headscale lists a deleted auth key; SaaS leaves it out of both key lists, while a read by ID still answers" deletedKeyDeleteNotFound = "DELETED_KEY_DELETE_NOT_FOUND: headscale answers 404 to a second delete of an auth key; SaaS answers 200" )