Skip to content

Commit ef403f0

Browse files
committed
action.yml,src: add support for workload identity federation
Add support for workload identity federation based authentication. Updates tailscale/corp#31264 Signed-off-by: Mario Minardi <mario@tailscale.com>
1 parent c8de7fa commit ef403f0

File tree

7 files changed

+191
-51
lines changed

7 files changed

+191
-51
lines changed

.github/workflows/test.yml

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
name: "Integration Tests"
22

3+
permissions:
4+
id-token: write # This is required for requesting the JWT for workload identity
5+
36
on:
47
pull_request:
58
workflow_dispatch:
@@ -11,7 +14,7 @@ jobs:
1114
# Matrix test for all supported platforms and architectures
1215

1316
integration-tests:
14-
name: ${{ matrix.os }} (${{ matrix.arch }}) tailscale-${{ matrix.version }}
17+
name: ${{ matrix.os }} (${{ matrix.arch }}) (${{ matrix.credential-type }}) tailscale-${{ matrix.version }}
1518
strategy:
1619
fail-fast: false
1720
matrix:
@@ -22,63 +25,90 @@ jobs:
2225
arch: amd64
2326
version: latest
2427
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
28+
credential-type: oauth
2529

2630
# Try unstable too
2731
- os: ubuntu-latest
2832
runner-os: Linux
2933
arch: amd64
3034
version: unstable
35+
credential-type: oauth
3136

3237
# Try a pinned version
3338
- os: ubuntu-latest
3439
runner-os: Linux
3540
arch: amd64
41+
credential-type: oauth
3642
# leave version blank to fall back to default
3743

3844
# Linux tests (ARM64)
3945
- os: ubuntu-24.04-arm
4046
runner-os: Linux
4147
arch: arm64
4248
version: latest
49+
credential-type: oauth
4350

4451
# Windows tests (AMD64)
4552
- os: windows-latest
4653
runner-os: Windows
4754
arch: amd64
4855
version: latest
4956
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
50-
51-
- os: windows-latest
52-
runner-os: Windows
53-
arch: amd64
54-
version: unstable
57+
credential-type: oauth
5558

5659
# Windows tests (ARM64)
5760
- os: windows-11-arm
5861
runner-os: Windows
5962
arch: arm64
6063
version: latest
64+
credential-type: oauth
6165

6266
# macOS 13 (AMD64)
6367
- os: macos-13
6468
runner-os: macOS
6569
arch: amd64
6670
version: latest
6771
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
72+
credential-type: oauth
6873

6974
# macOS 14 (ARM)
7075
- os: macos-14
7176
runner-os: macOS
7277
arch: arm64
7378
version: latest
7479
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
80+
credential-type: oauth
7581

7682
# macOS latest (ARM)
7783
- os: macos-latest
7884
runner-os: macOS
7985
arch: arm64
8086
version: latest
8187
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
88+
credential-type: oauth
89+
90+
# Try workload identity for each platform
91+
- os: macos-latest
92+
runner-os: macOS
93+
arch: amd64
94+
version: latest
95+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
96+
credential-type: workload-identity
97+
98+
- os: windows-latest
99+
runner-os: Windows
100+
arch: amd64
101+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
102+
credential-type: workload-identity
103+
# leave version blank to fall back to default
104+
105+
# Try adding in an unstable
106+
- os: ubuntu-latest
107+
runner-os: Linux
108+
arch: amd64
109+
version: unstable
110+
credential-type: workload-identity
111+
82112

83113
runs-on: ${{ matrix.os }}
84114

@@ -103,8 +133,9 @@ jobs:
103133
id: tailscale-oauth
104134
uses: ./
105135
with:
106-
oauth-client-id: ${{ secrets.TS_AUTH_KEYS_OAUTH_CLIENT_ID }}
107-
oauth-secret: ${{ secrets.TS_AUTH_KEYS_OAUTH_CLIENT_SECRET }}
136+
oauth-client-id: ${{ matrix.credential-type == 'oauth' && secrets.TS_AUTH_KEYS_OAUTH_CLIENT_ID || secrets.TS_WORKLOAD_IDENTITY_CLIENT_ID }}
137+
oauth-secret: ${{ matrix.credential-type == 'oauth' && secrets.TS_AUTH_KEYS_OAUTH_CLIENT_SECRET || '' }}
138+
audience: ${{ matrix.credential-type == 'workload-identity' && secrets.TS_AUDIENCE || ''}}
108139
tags: "tag:ci"
109140
version: "${{ matrix.version }}"
110141
use-cache: false

README.md

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,58 @@ by adding a step to your workflow.
1414
1515
Subsequent steps in the Action can then access nodes in your Tailnet.
1616
17-
oauth-client-id and oauth-secret are an [OAuth client](https://tailscale.com/s/oauth-clients/)
17+
oauth-client-id and oauth-secret are an [OAuth client][kb-oauth-clients]
1818
for the tailnet to be accessed. We recommend storing these as
1919
[GitHub Encrypted Secrets.](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
2020
OAuth clients used for this purpose must have the
21-
[`auth_keys` scope.](https://tailscale.com/kb/1215/oauth-clients#scopes)
21+
[`auth_keys` scope.][kb-trust-credentials-scopes]
2222

23-
tags is a comma-separated list of one or more [ACL Tags](https://tailscale.com/kb/1068/acl-tags/)
23+
tags is a comma-separated list of one or more [Tags][kb-tags]
2424
for the node. At least one tag is required: an OAuth client is not associated
2525
with any of the Users on the tailnet, it has to Tag its nodes.
2626

27-
Nodes created by this Action are [marked as Ephemeral](https://tailscale.com/s/ephemeral-nodes) to
27+
Nodes created by this Action are [marked as Ephemeral][kb-ephemeral-nodes] to
2828
and log out immediately after finishing their CI run, at which point they are automatically removed
29-
by the coordination server. The nodes are also [marked Preapproved](https://tailscale.com/kb/1085/auth-keys/)
30-
on tailnets which use [Device Approval](https://tailscale.com/kb/1099/device-approval/)
29+
by the coordination server. The nodes are also [marked Preapproved][kb-auth-keys]
30+
on tailnets which use [Device Approval][kb-device-approval]
31+
32+
33+
### Workload identity federation
34+
[Workload identity federation][kb-workload-identity-federation] can also be used for authenticating nodes with your tailnet:
35+
36+
```yaml
37+
- name: Tailscale
38+
uses: tailscale/github-action@v4
39+
with:
40+
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
41+
audience: ${{ secrets.TS_AUDIENCE }}
42+
tags: tag:ci
43+
```
44+
45+
Workload identity federation requires the `id-token: write` [permission setting](https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-cloud-providers#adding-permissions-settings) for the workflow:
46+
47+
```yaml
48+
permissions:
49+
id-token: write # This is required for the tailscale action to request a JWT from GitHub
50+
```
51+
52+
OIDC federated identity credentials used for this purpose must have the [`auth_keys` scope.][kb-trust-credentials-scopes]
53+
54+
tags is a comma-separated list of one or more [Tags][kb-tags]
55+
for the node. At least one tag is required: a federated identity is not associated
56+
with any of the Users on the tailnet, it has to Tag its nodes.
57+
58+
> [!IMPORTANT]
59+
> Tailscale version `1.90.1` or later is required for workload identity federation.
3160

3261
## Prerequisites
3362

3463
Before using the Tailscale GitHub Action, ensure you have the following:
3564

36-
1. A Tailscale account with <Role>Owner, Admin, or Network admin</Role> permissions.
65+
1. A Tailscale account with Owner, Admin, or Network admin permissions.
3766
1. A GitHub repository that you have admin access to (required to set up the GitHub Action).
38-
1. At least one configured [tag][kb-tags].
39-
1. An [OAuth client][kb-oauth-clients] ID and secret OR an [auth key][kb-auth-keys].
67+
1. At least one configured [tag][kb-tags] if using OAuth or workload identity federation.
68+
1. An [OAuth client][kb-oauth-clients] ID and secret, [federated identity][kb-workload-identity-federation] client ID and audience, OR an [auth key][kb-auth-keys].
4069
1. A runner image version >= 2.237.1 (required to support running Node.js 24).
4170

4271
## Eventual consistency
@@ -55,22 +84,21 @@ You can do this by adding a list of hosts to ping to the action configuration:
5584
ping: 100.x.y.z,my-machine.my-tailnet.ts.net
5685
```
5786

58-
or with the [tailscale ping](https://tailscale.com/kb/1080/cli#ping) command if you do not know the peers at the time of installing Tailscale in the workflow:
87+
or with the [tailscale ping][kb-cli-ping] command if you do not know the peers at the time of installing Tailscale in the workflow:
5988

6089
```bash
6190
tailscale ping my-target.my-tailnet.ts.net
6291
```
6392

64-
The `ping` option will wait up to to 3 minutes for a connection (direct or relayed).
93+
The `ping` option will wait up to 3 minutes for a connection (direct or relayed).
6594

6695
## Tailnet Lock
6796

68-
If you are using this Action in a [Tailnet
69-
Lock](https://tailscale.com/kb/1226/tailnet-lock) enabled network, you need to:
97+
If you are using this Action in a [Tailnet Lock][kb-tailnet-lock] enabled network, you need to:
7098

71-
- Authenticate using an ephemeral reusable [pre-signed auth key](https://tailscale.com/kb/1226/tailnet-lock#add-a-node-using-a-pre-signed-auth-key)
99+
- Authenticate using an ephemeral reusable [pre-signed auth key][kb-tailnet-lock-pre-signed]
72100
rather than an OAuth client.
73-
- Specify a [state directory](https://tailscale.com/kb/1278/tailscaled#flags-to-tailscaled) for the
101+
- Specify a [state directory][kb-tailscaled-flags] for the
74102
client to store the Tailnet Key Authority data in.
75103

76104
```yaml
@@ -139,4 +167,18 @@ the GitHub Action leaves tailscale binaries installed but stops the tailscale ba
139167

140168
### requested tags [tag:mytag] are invalid or not permitted
141169

142-
You may encounter this error when using an OAuth client. OAuth clients must have the [`auth_keys` scope](https://tailscale.com/kb/1215/oauth-clients#scopes) with one or more [tags](https://tailscale.com/kb/1068/acl-tags/), and the tags specified with `tags` must match all tags on the OAuth client.
170+
You may encounter this error when using a trust credential (OAuth client or OIDC federated identity).
171+
Trust credentials must have the writable [`auth_keys` scope][kb-trust-credentials-scopes] with one or more [tags][kb-tags],
172+
and the tags specified with `tags` must match all tags on the trust credential or be tags owned by the tags on the trust credential.
173+
174+
[kb-auth-keys]: https://tailscale.com/kb/1085/auth-keys
175+
[kb-cli-ping]: https://tailscale.com/kb/1080/cli#ping
176+
[kb-device-approval]: https://tailscale.com/kb/1099/device-approval
177+
[kb-ephemeral-nodes]: https://tailscale.com/kb/1111/ephemeral-nodes
178+
[kb-oauth-clients]: https://tailscale.com/kb/1215/oauth-clients
179+
[kb-tags]: https://tailscale.com/kb/1068/tags
180+
[kb-tailnet-lock]: https://tailscale.com/kb/1226/tailnet-lock
181+
[kb-tailnet-lock-pre-signed]: https://tailscale.com/kb/1226/tailnet-lock#add-a-node-using-a-pre-signed-auth-key
182+
[kb-tailscaled-flags]: https://tailscale.com/kb/1278/tailscaled#flags-to-tailscaled
183+
[kb-trust-credentials-scopes]: https://tailscale.com/kb/1623/trust-credentials#scopes
184+
[kb-workload-identity-federation]: https://tailscale.com/kb/1581/workload-identity-federation

action.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ inputs:
1313
required: false
1414
deprecationMessage: 'An OAuth API client https://tailscale.com/s/oauth-clients is recommended instead of an authkey'
1515
oauth-client-id:
16-
description: 'Your Tailscale OAuth Client ID.'
16+
description: 'Your Tailscale OAuth or OIDC Federated Identity clientID.'
17+
required: false
18+
audience:
19+
description: 'Your Tailscale OIDC Federated Identity Audience'
1720
required: false
1821
oauth-secret:
1922
description: 'Your Tailscale OAuth Client Secret.'
@@ -24,7 +27,7 @@ inputs:
2427
version:
2528
description: 'Tailscale version to use. Specify `latest` to use the latest stable version, and `unstable` to use the latest development version.'
2629
required: true
27-
default: '1.88.3'
30+
default: '1.90.4'
2831
args:
2932
description: 'Optional additional arguments to `tailscale up`.'
3033
required: false
@@ -66,4 +69,3 @@ runs:
6669
using: 'node24'
6770
main: 'dist/index.js'
6871
post: 'dist/logout/index.js'
69-

dist/index.js

Lines changed: 36 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)