Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Improve tags support #407

Merged
merged 6 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ In most cases you will use `tailscale_authkey`.

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

If you are authenticating with an OAuth key, you must also set `tailscale_tags` (see below).

### tailscale_authkey

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

> [!IMPORTANT]
> Using an OAuth key requires additionally setting the following variables: `tailscale_oauth_ephemeral`, `tailscale_oauth_preauthorized`, and `tailscale_oauth_tags`.
> 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`).

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.

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

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

### tailscale_oauth_tags
### tailscale_tags

> [!NOTE]
> Used only when `tailscale_authkey` is an OAuth key.
**Default**: `[]`

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

Registering new nodes using OAuth credentials requires advertising one or more tags.
Tags are required for OAuth clients managing devices.
> [!NOTE]
> Tags are required for OAuth clients (`tailscale_authkey` OAuth key).

Entries should not include `tag:`.
For example, `tailscale_args: ['worker']` translates to `--advertise-tags=tag:worker`.

> Auth keys generated by this OAuth client must assign tags (or tags managed by these tags) to devices they authorize.

Expand Down Expand Up @@ -190,9 +195,11 @@ Only `tailscale up` arguments can be passed in.
> **Do not use this for `--authkey`.**
> Use the `tailscale_authkey` variable instead.
>
> **If authenticating with an OAuth key, do not use this for `--advertise-tags`.**
> Use the `tailscale_oauth_tags` variable instead.
> `--advertise-tags` may be used in this variable if you are not authenticating to Tailscale with OAuth.
> **Do not use this for `--advertise-tags`.**
> Use the `tailscale_tags` variable instead.
>
> **Do not use this for `--timeout`.**
> Use the `tailscale_up_timeout` variable instead.

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.

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

### tailscale_up_timeout

**Default**: `120s`

Defines the timeout duration for the `tailscale up` command.

> --timeout duration
>
> maximum amount of time to wait for tailscaled to enter a Running state

### verbose

**Default**: `false`
Expand Down Expand Up @@ -276,7 +293,8 @@ Connect using an OAuth client secret:
vars:
verbose: true
tailscale_authkey: "{{ lookup('env', 'TAILSCALE_OAUTH_CLIENT_SECRET') }}"
tailscale_oauth_tags: "tag:oauth"
tailscale_tags:
- "oauth"
# Optionally, also include:
tailscale_oauth_ephemeral: true
tailscale_oauth_preauthorized: false
Expand Down
6 changes: 4 additions & 2 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ state: latest
tailscale_authkey: ""
# Optional command-line arguments for 'tailscale up'
tailscale_args: ""
# Apply provided tags to node
tailscale_tags: []
# Set timeout for 'tailscale up' command
tailscale_up_timeout: "120s"

# Used for OAuth authentication
# Register as an ephemeral node (recommended)
tailscale_oauth_ephemeral: true
# Skip manual device approval
tailscale_oauth_preauthorized: false
# Required device tags to advertise
tailscale_oauth_tags: ""

# Whether to output debug information during role execution
verbose: false
Expand Down
3 changes: 2 additions & 1 deletion molecule/oauth/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
name: artis3n.tailscale
vars:
verbose: true
tailscale_oauth_tags: "tag:ci-worker"
tailscale_tags:
- "ci-worker"
39 changes: 28 additions & 11 deletions tasks/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,12 @@
msg: "Ver: {{ tailscale_version }} Online: {{ tailscale_is_online }}"
when: verbose

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

# OAuth key starts with 'tskey-client-', auth key starts with 'tskey-auth-', with headscale it can be 'unused'
- name: Install | Create authkey string
- name: Install | Build `tailscale up` arguments strings
ansible.builtin.set_fact:
tailscale_authkey_type: >-
{# Check if the key is an OAuth key #}
Expand All @@ -100,21 +95,43 @@
tailscale_authkey_sting: >-
{# Check if the key is an OAuth key #}
{% if tailscale_authkey.startswith('tskey-client-') %}
{{ tailscale_authkey }}?ephemeral={{ tailscale_oauth_ephemeral | bool }}&preauthorized={{ tailscale_oauth_preauthorized | bool }} --advertise-tags={{ tailscale_oauth_tags | trim }}
{{ tailscale_authkey }}?ephemeral={{ tailscale_oauth_ephemeral | bool }}&preauthorized={{ tailscale_oauth_preauthorized | bool }}
{# Check if the key is not OAuth (regular authkey or unused) #}
{% else %}
{{ tailscale_authkey }}
{% endif %}
tailscale_tags_string: >-
{% if tailscale_tags | length > 0 %}
--advertise-tags={{ tailscale_prepared_tags | join(',') }}
{% endif %}
no_log: "{{ not (insecurely_log_authkey | bool) }}"

- name: Install | Authkey Type
ansible.builtin.debug:
msg: "{{ tailscale_authkey_type | trim }}"
when: verbose

- name: Install | Build the final tailscale_args
ansible.builtin.set_fact:
tailscale_args_string: "{{ tailscale_args }} {{ tailscale_tags_string | trim }} --timeout={{ tailscale_up_timeout | trim }}"

- name: Install | Final `tailscale up` arguments string
ansible.builtin.debug:
msg: "{{ tailscale_args_string | trim }}"
when: verbose

- name: Install | Save State
ansible.builtin.template:
src: state.j2
dest: "{{ tailscale_state_folder }}/artis3n-tailscale/state"
owner: "{{ ansible_user_uid }}"
group: "{{ ansible_user_gid }}"
mode: '0644'
register: state_file

- name: Install | Bring Tailscale Up
become: true
ansible.builtin.command: "tailscale up {{ tailscale_args | trim }} --authkey={{ tailscale_authkey_sting | trim }}"
ansible.builtin.command: "tailscale up {{ tailscale_args_string | trim }} --authkey={{ tailscale_authkey_sting | trim }}"
# Since the auth key is included in this task's output, we do not want to log output
no_log: "{{ not (insecurely_log_authkey | bool) }}"
changed_when: true
Expand Down
18 changes: 18 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@
- not tailscale_up_skip
- state != "absent"

- name: Tailscale Tags Required with OAuth Key
ansible.builtin.fail:
msg: "When `tailscale_authkey` is an OAuth key, you must supply one or more tags in `tailscale_tags`."
when:
- tailscale_authkey.startswith('tskey-client-')
- not tailscale_tags
- state != "absent"
- not tailscale_up_skip

- name: Use tailscale_tags instead of tailscale_args for tags
McSim85 marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.debug:
msg: You must use `tailscale_tags` instead of `tailscale_args` to assign tags.
when:
- '"--advertise-tags" in tailscale_args'
- not tailscale_tags
- state != "absent"
- not tailscale_up_skip

- name: Skipping Authentication
ansible.builtin.debug:
msg: You have set 'tailscale_up_skip', so this node will not authenticate to your Tailscale network.
Expand Down
4 changes: 2 additions & 2 deletions tasks/templates/state.j2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{%- if auth_key_in_state -%}
{{ (tailscale_args + ' --authkey=' + tailscale_authkey) | trim | hash('sha256') }}
{{ (tailscale_args_string + ' --authkey=' + tailscale_authkey) | trim | hash('sha256') }}
{% else %}
{{ tailscale_args | trim | hash('sha256') }}
{{ tailscale_args_string | trim | hash('sha256') }}
{%- endif -%}