fix preauth key logging in as previous user (#1920)
* add test case to reproduce #1885 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * fix preauth key issue logging in as wrong user Fixes #1885 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * add test to gh Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
55b35f4160
commit
1c6bfc503c
3 changed files with 102 additions and 3 deletions
1
.github/workflows/test-integration.yaml
vendored
1
.github/workflows/test-integration.yaml
vendored
|
@ -26,6 +26,7 @@ jobs:
|
||||||
- TestPreAuthKeyCommand
|
- TestPreAuthKeyCommand
|
||||||
- TestPreAuthKeyCommandWithoutExpiry
|
- TestPreAuthKeyCommandWithoutExpiry
|
||||||
- TestPreAuthKeyCommandReusableEphemeral
|
- TestPreAuthKeyCommandReusableEphemeral
|
||||||
|
- TestPreAuthKeyCorrectUserLoggedInCommand
|
||||||
- TestApiKeyCommand
|
- TestApiKeyCommand
|
||||||
- TestNodeTagCommand
|
- TestNodeTagCommand
|
||||||
- TestNodeAdvertiseTagNoACLCommand
|
- TestNodeAdvertiseTagNoACLCommand
|
||||||
|
|
|
@ -315,13 +315,16 @@ func (h *Headscale) handleAuthKey(
|
||||||
|
|
||||||
node.NodeKey = nodeKey
|
node.NodeKey = nodeKey
|
||||||
node.AuthKeyID = uint(pak.ID)
|
node.AuthKeyID = uint(pak.ID)
|
||||||
err := h.db.NodeSetExpiry(node.ID, registerRequest.Expiry)
|
node.Expiry = ®isterRequest.Expiry
|
||||||
|
node.User = pak.User
|
||||||
|
node.UserID = pak.UserID
|
||||||
|
err := h.db.DB.Save(node).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().
|
log.Error().
|
||||||
Caller().
|
Caller().
|
||||||
Str("node", node.Hostname).
|
Str("node", node.Hostname).
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("Failed to refresh node")
|
Msg("failed to save node after logging in with auth key")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -344,7 +347,7 @@ func (h *Headscale) handleAuthKey(
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := types.NotifyCtx(context.Background(), "handle-authkey", "na")
|
ctx := types.NotifyCtx(context.Background(), "handle-authkey", "na")
|
||||||
h.nodeNotifier.NotifyWithIgnore(ctx, types.StateUpdateExpire(node.ID, registerRequest.Expiry), node.ID)
|
h.nodeNotifier.NotifyAll(ctx, types.StateUpdate{Type: types.StatePeerChanged, ChangeNodes: []types.NodeID{node.ID}})
|
||||||
} else {
|
} else {
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
|
||||||
|
|
|
@ -388,6 +388,101 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
|
||||||
assert.Len(t, listedPreAuthKeys, 3)
|
assert.Len(t, listedPreAuthKeys, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
|
||||||
|
IntegrationSkip(t)
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
user1 := "user1"
|
||||||
|
user2 := "user2"
|
||||||
|
|
||||||
|
scenario, err := NewScenario(dockertestMaxWait())
|
||||||
|
assertNoErr(t, err)
|
||||||
|
defer scenario.Shutdown()
|
||||||
|
|
||||||
|
spec := map[string]int{
|
||||||
|
user1: 1,
|
||||||
|
user2: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = scenario.CreateHeadscaleEnv(spec, []tsic.Option{}, hsic.WithTestName("clipak"))
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
headscale, err := scenario.Headscale()
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
var user2Key v1.PreAuthKey
|
||||||
|
|
||||||
|
err = executeAndUnmarshal(
|
||||||
|
headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"preauthkeys",
|
||||||
|
"--user",
|
||||||
|
user2,
|
||||||
|
"create",
|
||||||
|
"--reusable",
|
||||||
|
"--expiration",
|
||||||
|
"24h",
|
||||||
|
"--output",
|
||||||
|
"json",
|
||||||
|
"--tags",
|
||||||
|
"tag:test1,tag:test2",
|
||||||
|
},
|
||||||
|
&user2Key,
|
||||||
|
)
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
allClients, err := scenario.ListTailscaleClients()
|
||||||
|
assertNoErrListClients(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, allClients, 1)
|
||||||
|
|
||||||
|
client := allClients[0]
|
||||||
|
|
||||||
|
// Log out from user1
|
||||||
|
err = client.Logout()
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
err = scenario.WaitForTailscaleLogout()
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
status, err := client.Status()
|
||||||
|
assertNoErr(t, err)
|
||||||
|
if status.BackendState == "Starting" || status.BackendState == "Running" {
|
||||||
|
t.Fatalf("expected node to be logged out, backend state: %s", status.BackendState)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Login(headscale.GetEndpoint(), user2Key.GetKey())
|
||||||
|
assertNoErr(t, err)
|
||||||
|
|
||||||
|
status, err = client.Status()
|
||||||
|
assertNoErr(t, err)
|
||||||
|
if status.BackendState != "Running" {
|
||||||
|
t.Fatalf("expected node to be logged in, backend state: %s", status.BackendState)
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.Self.UserID.String() != "userid:2" {
|
||||||
|
t.Fatalf("expected node to be logged in as userid:2, got: %s", status.Self.UserID.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var listNodes []v1.Node
|
||||||
|
err = executeAndUnmarshal(
|
||||||
|
headscale,
|
||||||
|
[]string{
|
||||||
|
"headscale",
|
||||||
|
"nodes",
|
||||||
|
"list",
|
||||||
|
"--output",
|
||||||
|
"json",
|
||||||
|
},
|
||||||
|
&listNodes,
|
||||||
|
)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Len(t, listNodes, 1)
|
||||||
|
|
||||||
|
assert.Equal(t, "user2", listNodes[0].User.Name)
|
||||||
|
}
|
||||||
|
|
||||||
func TestApiKeyCommand(t *testing.T) {
|
func TestApiKeyCommand(t *testing.T) {
|
||||||
IntegrationSkip(t)
|
IntegrationSkip(t)
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
Loading…
Reference in a new issue