API interface for start preauthkeys not set expiration properly #570

Closed
opened 2025-12-29 02:20:37 +01:00 by adam · 9 comments
Owner

Originally created by @proitlab on GitHub (Oct 18, 2023).

I am trying to integrate Headscale API v1 into our internal application. In creation new preauth keys, I noticed something in preauth expiration field.

Bug description

I created preauthkeys via HTTPS with POST method to https://apiurl/api/preauthkeys with json body

body = {
'user': 'admin',
'reusable': false,
'ephemeral': false
}

The respond:

{'preAuthKey': {'user': 'admins', 'id': '3', 'key': '0a7e0ebbf68709168fb4f53fa61f82c10e70437ee4e21a6c', 'reusable': False, 'ephemeral': False, 'used': False, 'expiration': '0001-01-01T00:00:00Z', 'createdAt': '2023-10-18T07:58:12.643916467Z', 'aclTags': []}}

I noticed:
'expiration': '0001-01-01T00:00:00Z'

When I created preauthkeys using headscale command in container, the expiration field is properly populated, which is 60 minutes later, even without specifying expiration paramater in command line:

headscale preauthkeys create -u admins

These are all my preauthkeys:
{'preAuthKeys': [{'user': 'admins', 'id': '1', 'key': '44f5dce35262edd4780f05b40968205c83b9a5a3743f3c82', 'reusable': False, 'ephemeral': False, 'used': True, 'expiration': '2023-10-17T10:47:13.729136Z', 'createdAt': '2023-10-17T09:47:13.731139Z', 'aclTags': []}, {'user': 'admins', 'id': '2', 'key': '38dea3a1f04b83db9dfc22ec6d19f9d9d3ff7dcfc488723c', 'reusable': True, 'ephemeral': False, 'used': True, 'expiration': '2023-10-17T10:54:53.951718Z', 'createdAt': '2023-10-17T09:54:53.954325Z', 'aclTags': []}, {'user': 'admins', 'id': '3', 'key': '0a7e0ebbf68709168fb4f53fa61f82c10e70437ee4e21a6c', 'reusable': False, 'ephemeral': False, 'used': False, 'expiration': '0001-01-01T00:00:00Z', 'createdAt': '2023-10-18T07:58:12.643916Z', 'aclTags': []}]}

Environment

  • postgresdb

  • docker

  • OS: Ubuntu 22.04

  • Headscale version: 0.23.0-alpha

To Reproduce

  • Create preauthkeys via API with body not including expiration field.
Originally created by @proitlab on GitHub (Oct 18, 2023). I am trying to integrate Headscale API v1 into our internal application. In creation new preauth keys, I noticed something in preauth expiration field. ## Bug description I created preauthkeys via HTTPS with POST method to https://apiurl/api/preauthkeys with json body body = { 'user': 'admin', 'reusable': false, 'ephemeral': false } The respond: {'preAuthKey': {'user': 'admins', 'id': '3', 'key': '0a7e0ebbf68709168fb4f53fa61f82c10e70437ee4e21a6c', 'reusable': False, 'ephemeral': False, 'used': False, 'expiration': '0001-01-01T00:00:00Z', 'createdAt': '2023-10-18T07:58:12.643916467Z', 'aclTags': []}} I noticed: 'expiration': '0001-01-01T00:00:00Z' When I created preauthkeys using headscale command in container, the expiration field is properly populated, which is 60 minutes later, even without specifying expiration paramater in command line: headscale preauthkeys create -u admins These are all my preauthkeys: {'preAuthKeys': [{'user': 'admins', 'id': '1', 'key': '44f5dce35262edd4780f05b40968205c83b9a5a3743f3c82', 'reusable': False, 'ephemeral': False, 'used': True, 'expiration': '2023-10-17T10:47:13.729136Z', 'createdAt': '2023-10-17T09:47:13.731139Z', 'aclTags': []}, {'user': 'admins', 'id': '2', 'key': '38dea3a1f04b83db9dfc22ec6d19f9d9d3ff7dcfc488723c', 'reusable': True, 'ephemeral': False, 'used': True, 'expiration': '2023-10-17T10:54:53.951718Z', 'createdAt': '2023-10-17T09:54:53.954325Z', 'aclTags': []}, {'user': 'admins', 'id': '3', 'key': '0a7e0ebbf68709168fb4f53fa61f82c10e70437ee4e21a6c', 'reusable': False, 'ephemeral': False, 'used': False, 'expiration': '0001-01-01T00:00:00Z', 'createdAt': '2023-10-18T07:58:12.643916Z', 'aclTags': []}]} ## Environment - postgresdb - docker - OS: Ubuntu 22.04 - Headscale version: 0.23.0-alpha ## To Reproduce - Create preauthkeys via API with body not including expiration field.
adam added the bug label 2025-12-29 02:20:37 +01:00
adam closed this issue 2025-12-29 02:20:37 +01:00
Author
Owner

@BeyondEvil commented on GitHub (Jan 2, 2024):

Can confirm.

An updated version of Headscale has been found (0.23.0-alpha2 vs. your current v0.22.3). Check it out https://github.com/juanfont/headscale/releases
ID | Hostname           | Name                        | MachineKey | NodeKey | User    | IP addresses                  | Ephemeral | Last seen           | Expiration          | Online  | Expired
1  | adguard.domain.net | adguard.domain.net          | [Q1UzQ]    | [YUdWe] | adguard | 100.64.0.1, fd7a:115c:a1e0::1 | false     | 2024-01-02 01:08:36 | 2024-01-02 01:08:37 | offline | yes
2  | adguard.domain.net | adguard.domain.net-smqnci6a | [rDYHo]    | [CCf4Y] | adguard | 100.64.0.2, fd7a:115c:a1e0::2 | false     | 2024-01-02 01:38:04 | 0001-01-01 00:00:00 | online  | no

Key was created with:
headscale preauthkeys create --user adguard --expiration 2d --reusable

Command that was run (both times):

> tailscale up \
  --advertise-routes=${private_cidr} \
  --authkey="$${auth_key}" \
  --hostname="adguard.domain.net" \
  --login-server="https://headscale.domain.net"

I would've expected the node to be replaced, and not added.

Happy to share more information upon request.

@BeyondEvil commented on GitHub (Jan 2, 2024): Can confirm. ```sh An updated version of Headscale has been found (0.23.0-alpha2 vs. your current v0.22.3). Check it out https://github.com/juanfont/headscale/releases ID | Hostname | Name | MachineKey | NodeKey | User | IP addresses | Ephemeral | Last seen | Expiration | Online | Expired 1 | adguard.domain.net | adguard.domain.net | [Q1UzQ] | [YUdWe] | adguard | 100.64.0.1, fd7a:115c:a1e0::1 | false | 2024-01-02 01:08:36 | 2024-01-02 01:08:37 | offline | yes 2 | adguard.domain.net | adguard.domain.net-smqnci6a | [rDYHo] | [CCf4Y] | adguard | 100.64.0.2, fd7a:115c:a1e0::2 | false | 2024-01-02 01:38:04 | 0001-01-01 00:00:00 | online | no ``` Key was created with: `headscale preauthkeys create --user adguard --expiration 2d --reusable` Command that was run (both times): ```sh > tailscale up \ --advertise-routes=${private_cidr} \ --authkey="$${auth_key}" \ --hostname="adguard.domain.net" \ --login-server="https://headscale.domain.net" ``` I would've expected the node to be replaced, and not added. Happy to share more information upon request.
Author
Owner

@github-actions[bot] commented on GitHub (Apr 2, 2024):

This issue is stale because it has been open for 90 days with no activity.

@github-actions[bot] commented on GitHub (Apr 2, 2024): This issue is stale because it has been open for 90 days with no activity.
Author
Owner

@BeyondEvil commented on GitHub (Apr 7, 2024):

I believe this is still relevant.

@BeyondEvil commented on GitHub (Apr 7, 2024): I believe this is still relevant.
Author
Owner

@fluential commented on GitHub (Apr 12, 2024):

Seems relevant to me

@fluential commented on GitHub (Apr 12, 2024): Seems relevant to me
Author
Owner

@github-actions[bot] commented on GitHub (Jul 11, 2024):

This issue is stale because it has been open for 90 days with no activity.

@github-actions[bot] commented on GitHub (Jul 11, 2024): This issue is stale because it has been open for 90 days with no activity.
Author
Owner

@BeyondEvil commented on GitHub (Jul 12, 2024):

Still relevant afaict.

@BeyondEvil commented on GitHub (Jul 12, 2024): Still relevant afaict.
Author
Owner

@yeyeoke commented on GitHub (Aug 26, 2024):

This is still happening in beta2.

@yeyeoke commented on GitHub (Aug 26, 2024): This is still happening in beta2.
Author
Owner

@kradalby commented on GitHub (Aug 30, 2024):

This isnt really a bug, it is intentional, the CLI has a default 1h expiry, but the API does not have a default and it is the callers responsibility to set the expiry.
The field to set the expiry is available in the API: https://github.com/juanfont/headscale/blob/main/proto/headscale/v1/preauthkey.proto#L23

As for "should the CLI have a default and not the API", it depends, I do not think there is a right answer here, the way I see it is:

The API is a clean slate and you tell it exactly what you want it to do, and it is from there, deterministic.

The CLI implements a client using the API, and in the CLI we have made the decision to set a default for the CLI to improve the user experience of the tool (also allowing you to define it in a "duration from now" instead of a timestamp).

@kradalby commented on GitHub (Aug 30, 2024): This isnt really a bug, it is intentional, the CLI has a default 1h expiry, but the API does not have a default and it is the callers responsibility to set the expiry. The field to set the expiry is available in the API: https://github.com/juanfont/headscale/blob/main/proto/headscale/v1/preauthkey.proto#L23 As for "should the CLI have a default and not the API", it depends, I do not think there is a right answer here, the way I see it is: The API is a clean slate and you tell it exactly what you want it to do, and it is from there, deterministic. The CLI _implements_ a client using the API, and in the CLI we have made the decision to set a default for the CLI to improve the user experience of the tool (also allowing you to define it in a "duration from now" instead of a timestamp).
Author
Owner

@kradalby commented on GitHub (Aug 30, 2024):

@BeyondEvil I think your issue is separate to the posted one, please create a separate issue for it.
Please include if this is a regression between 0.22.3 and 0.23.x or if it has been present the whole time.

@kradalby commented on GitHub (Aug 30, 2024): @BeyondEvil I think your issue is separate to the posted one, please create a separate issue for it. Please include if this is a regression between 0.22.3 and 0.23.x or if it has been present the whole time.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#570