Skip to content
This repository was archived by the owner on Nov 6, 2025. It is now read-only.

Commit 1de02f4

Browse files
McSim85artis3n
andauthored
[FEAT] Improve tags support (#407)
* better tags handling * better tags handling * fix * Apply suggestions from code review Co-authored-by: Ari Kalfus <[email protected]> * fix review comments * tailscale_up_timeout to README --------- Co-authored-by: Ari Kalfus <[email protected]>
1 parent bafec71 commit 1de02f4

File tree

6 files changed

+83
-27
lines changed

6 files changed

+83
-27
lines changed

README.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ In most cases you will use `tailscale_authkey`.
6969

7070
If you are uninstalling Tailscale (`state: absent`), neither `tailscale_authkey` nor `tailscale_up_skip` is required.
7171

72+
If you are authenticating with an OAuth key, you must also set `tailscale_tags` (see below).
73+
7274
### tailscale_authkey
7375

7476
Is **not** required if `tailscale_up_skip` is set to `true`.
@@ -81,7 +83,7 @@ A Node Authorization key can be generated under your Tailscale account. The role
8183
- OAuth key (`tskey-client-XXX-YYYY`) <https://login.tailscale.com/admin/settings/oauth>
8284

8385
> [!IMPORTANT]
84-
> Using an OAuth key requires additionally setting the following variables: `tailscale_oauth_ephemeral`, `tailscale_oauth_preauthorized`, and `tailscale_oauth_tags`.
86+
> Using an OAuth key requires additionally setting the following variables: `tailscale_tags` (must be provided), `tailscale_oauth_ephemeral` (defailts to `true`) and `tailscale_oauth_preauthorized` (defaults to `false`).
8587
8688
Note that auth keys expire up to a maximum of 90 days after they are generated. OAuth secrets do not expire unless revoked, and the generated OAuth access token expires after 1 hour.
8789

@@ -111,15 +113,18 @@ Register as an [ephemeral node](https://tailscale.com/kb/1111/ephemeral-nodes),
111113

112114
Skip [manual device approval](https://tailscale.com/kb/1099/device-approval), if `true`.
113115

114-
### tailscale_oauth_tags
116+
### tailscale_tags
115117

116-
> [!NOTE]
117-
> Used only when `tailscale_authkey` is an OAuth key.
118+
**Default**: `[]`
118119

119-
**Default**: `""`
120+
Apply supplied tags to the Tailscale nodes configured by this role (via the `--advertise-tags` flag to `tailscale up`).
121+
For more information, see [What are tags?](https://tailscale.com/kb/1068/acl-tags?q=acl%20tag#what-are-acl-tags)
120122

121-
Registering new nodes using OAuth credentials requires advertising one or more tags.
122-
Tags are required for OAuth clients managing devices.
123+
> [!NOTE]
124+
> Tags are required for OAuth clients (`tailscale_authkey` OAuth key).
125+
126+
Entries should not include `tag:`.
127+
For example, `tailscale_args: ['worker']` translates to `--advertise-tags=tag:worker`.
123128

124129
> Auth keys generated by this OAuth client must assign tags (or tags managed by these tags) to devices they authorize.
125130
@@ -190,9 +195,11 @@ Only `tailscale up` arguments can be passed in.
190195
> **Do not use this for `--authkey`.**
191196
> Use the `tailscale_authkey` variable instead.
192197
>
193-
> **If authenticating with an OAuth key, do not use this for `--advertise-tags`.**
194-
> Use the `tailscale_oauth_tags` variable instead.
195-
> `--advertise-tags` may be used in this variable if you are not authenticating to Tailscale with OAuth.
198+
> **Do not use this for `--advertise-tags`.**
199+
> Use the `tailscale_tags` variable instead.
200+
>
201+
> **Do not use this for `--timeout`.**
202+
> Use the `tailscale_up_timeout` variable instead.
196203
197204
Any stdout/stderr output from the `tailscale` binary will be printed. Since the tasks move quickly in this section, a 5 second pause is introduced to grant more time for users to realize a message was printed.
198205

@@ -202,6 +209,16 @@ Stderrs will continue to fail the role's execution.
202209
The sensitive `--authkey` value will be redacted by default.
203210
If you need to view the unredacted value, see [`insecurely_log_authkey`](#insecurely_log_authkey).
204211

212+
### tailscale_up_timeout
213+
214+
**Default**: `120s`
215+
216+
Defines the timeout duration for the `tailscale up` command.
217+
218+
> --timeout duration
219+
>
220+
> maximum amount of time to wait for tailscaled to enter a Running state
221+
205222
### verbose
206223

207224
**Default**: `false`
@@ -276,7 +293,8 @@ Connect using an OAuth client secret:
276293
vars:
277294
verbose: true
278295
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_OAUTH_CLIENT_SECRET') }}"
279-
tailscale_oauth_tags: "tag:oauth"
296+
tailscale_tags:
297+
- "oauth"
280298
# Optionally, also include:
281299
tailscale_oauth_ephemeral: true
282300
tailscale_oauth_preauthorized: false

defaults/main.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ state: latest
77
tailscale_authkey: ""
88
# Optional command-line arguments for 'tailscale up'
99
tailscale_args: ""
10+
# Apply provided tags to node
11+
tailscale_tags: []
12+
# Set timeout for 'tailscale up' command
13+
tailscale_up_timeout: "120s"
1014

1115
# Used for OAuth authentication
1216
# Register as an ephemeral node (recommended)
1317
tailscale_oauth_ephemeral: true
1418
# Skip manual device approval
1519
tailscale_oauth_preauthorized: false
16-
# Required device tags to advertise
17-
tailscale_oauth_tags: ""
1820

1921
# Whether to output debug information during role execution
2022
verbose: false

molecule/oauth/converge.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
name: artis3n.tailscale
1111
vars:
1212
verbose: true
13-
tailscale_oauth_tags: "tag:ci-worker"
13+
tailscale_tags:
14+
- "ci-worker"

tasks/install.yml

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,12 @@
7676
msg: "Ver: {{ tailscale_version }} Online: {{ tailscale_is_online }}"
7777
when: verbose
7878

79-
- name: Install | Save State
80-
ansible.builtin.template:
81-
src: state.j2
82-
dest: "{{ tailscale_state_folder }}/artis3n-tailscale/state"
83-
owner: "{{ ansible_user_uid }}"
84-
group: "{{ ansible_user_gid }}"
85-
mode: '0644'
86-
register: state_file
79+
- name: Install | Prepend 'tag:' to each item in the list
80+
ansible.builtin.set_fact:
81+
tailscale_prepared_tags: "{{ tailscale_tags | map('regex_replace', '^', 'tag:') | list }}"
8782

8883
# OAuth key starts with 'tskey-client-', auth key starts with 'tskey-auth-', with headscale it can be 'unused'
89-
- name: Install | Create authkey string
84+
- name: Install | Build `tailscale up` arguments strings
9085
ansible.builtin.set_fact:
9186
tailscale_authkey_type: >-
9287
{# Check if the key is an OAuth key #}
@@ -100,21 +95,43 @@
10095
tailscale_authkey_sting: >-
10196
{# Check if the key is an OAuth key #}
10297
{% if tailscale_authkey.startswith('tskey-client-') %}
103-
{{ tailscale_authkey }}?ephemeral={{ tailscale_oauth_ephemeral | bool }}&preauthorized={{ tailscale_oauth_preauthorized | bool }} --advertise-tags={{ tailscale_oauth_tags | trim }}
98+
{{ tailscale_authkey }}?ephemeral={{ tailscale_oauth_ephemeral | bool }}&preauthorized={{ tailscale_oauth_preauthorized | bool }}
10499
{# Check if the key is not OAuth (regular authkey or unused) #}
105100
{% else %}
106101
{{ tailscale_authkey }}
107102
{% endif %}
103+
tailscale_tags_string: >-
104+
{% if tailscale_tags | length > 0 %}
105+
--advertise-tags={{ tailscale_prepared_tags | join(',') }}
106+
{% endif %}
108107
no_log: "{{ not (insecurely_log_authkey | bool) }}"
109108

110109
- name: Install | Authkey Type
111110
ansible.builtin.debug:
112111
msg: "{{ tailscale_authkey_type | trim }}"
113112
when: verbose
114113

114+
- name: Install | Build the final tailscale_args
115+
ansible.builtin.set_fact:
116+
tailscale_args_string: "{{ tailscale_args }} {{ tailscale_tags_string | trim }} --timeout={{ tailscale_up_timeout | trim }}"
117+
118+
- name: Install | Final `tailscale up` arguments string
119+
ansible.builtin.debug:
120+
msg: "{{ tailscale_args_string | trim }}"
121+
when: verbose
122+
123+
- name: Install | Save State
124+
ansible.builtin.template:
125+
src: state.j2
126+
dest: "{{ tailscale_state_folder }}/artis3n-tailscale/state"
127+
owner: "{{ ansible_user_uid }}"
128+
group: "{{ ansible_user_gid }}"
129+
mode: '0644'
130+
register: state_file
131+
115132
- name: Install | Bring Tailscale Up
116133
become: true
117-
ansible.builtin.command: "tailscale up {{ tailscale_args | trim }} --authkey={{ tailscale_authkey_sting | trim }}"
134+
ansible.builtin.command: "tailscale up {{ tailscale_args_string | trim }} --authkey={{ tailscale_authkey_sting | trim }}"
118135
# Since the auth key is included in this task's output, we do not want to log output
119136
no_log: "{{ not (insecurely_log_authkey | bool) }}"
120137
changed_when: true

tasks/main.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@
1818
- not tailscale_up_skip
1919
- state != "absent"
2020

21+
- name: Tailscale Tags Required with OAuth Key
22+
ansible.builtin.fail:
23+
msg: "When `tailscale_authkey` is an OAuth key, you must supply one or more tags in `tailscale_tags`."
24+
when:
25+
- tailscale_authkey.startswith('tskey-client-')
26+
- not tailscale_tags
27+
- state != "absent"
28+
- not tailscale_up_skip
29+
30+
- name: Use tailscale_tags instead of tailscale_args for tags
31+
ansible.builtin.debug:
32+
msg: You must use `tailscale_tags` instead of `tailscale_args` to assign tags.
33+
when:
34+
- '"--advertise-tags" in tailscale_args'
35+
- not tailscale_tags
36+
- state != "absent"
37+
- not tailscale_up_skip
38+
2139
- name: Skipping Authentication
2240
ansible.builtin.debug:
2341
msg: You have set 'tailscale_up_skip', so this node will not authenticate to your Tailscale network.

tasks/templates/state.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{%- if auth_key_in_state -%}
2-
{{ (tailscale_args + ' --authkey=' + tailscale_authkey) | trim | hash('sha256') }}
2+
{{ (tailscale_args_string + ' --authkey=' + tailscale_authkey) | trim | hash('sha256') }}
33
{% else %}
4-
{{ tailscale_args | trim | hash('sha256') }}
4+
{{ tailscale_args_string | trim | hash('sha256') }}
55
{%- endif -%}

0 commit comments

Comments
 (0)