Skip to content

Commit 479eaf1

Browse files
committed
action.yml: add support for workload identity federation
Add support for authenticating via workload identity federation. Updates tailscale/corp#34172 Signed-off-by: Mario Minardi <mario@tailscale.com>
1 parent 6191a18 commit 479eaf1

2 files changed

Lines changed: 45 additions & 24 deletions

File tree

README.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,28 @@ as your source of truth.
1313
panel](https://login.tailscale.com/admin) and copying down the name next to the
1414
Tailscale logo in the upper left hand corner of the page.
1515

16+
### `oauth-client-id` and `audience`
17+
18+
**Optional** The ID and audience for a [federated identity](https://tailscale.com/kb/1581/workload-identity-federation)
19+
for your tailnet. The federated identity must have the `policy_file` scope.
20+
21+
Either `api-key`, `oauth-client-id` and `oauth-secret`, or `oauth-client-id` and `audience` are required.
22+
1623
### `api-key`
1724

1825
**Optional** An API key authorized for your tailnet. You can get one [in the
1926
admin panel](https://login.tailscale.com/admin/settings/keys).
20-
Either `api-key` or `oauth-client-id` and `oauth-secret` are required.
27+
Either `api-key`, `oauth-client-id` and `oauth-secret`, or `oauth-client-id` and `audience` are required.
2128

2229
Please note that API keys will expire in 90 days. Set up a monthly event to
23-
rotate your Tailscale API key, or use an OAuth client.
30+
rotate your Tailscale API key, or use a trust credential (OAuth client or federated identity).
2431

2532
### `oauth-client-id` and `oauth-secret`
2633

2734
**Optional** The ID and secret for an [OAuth client](https://tailscale.com/kb/1215/oauth-clients)
28-
for your tailnet. The client must have the `acl` scope.
35+
for your tailnet. The client must have the `policy_file` scope.
2936

30-
Either `api-key` or `oauth-client-id` and `oauth-secret` are required.
37+
Either `api-key`, `oauth-client-id` and `oauth-secret`, or `oauth-client-id` and `audience` are required.
3138

3239
### `policy-file`
3340

@@ -63,13 +70,16 @@ on:
6370

6471
jobs:
6572
acls:
73+
permissions:
74+
contents: read
75+
id-token: write # This is required for the Tailscale action to request a JWT from GitHub
6676
runs-on: ubuntu-latest
6777

6878
steps:
69-
- uses: actions/checkout@v4
79+
- uses: actions/checkout@v6
7080

7181
- name: Fetch version-cache.json
72-
uses: actions/cache@v4
82+
uses: actions/cache@v5
7383
with:
7484
path: ./version-cache.json
7585
key: version-cache.json-${{ github.run_id }}
@@ -81,7 +91,8 @@ jobs:
8191
id: deploy-acl
8292
uses: tailscale/gitops-acl-action@v1
8393
with:
84-
api-key: ${{ secrets.TS_API_KEY }}
94+
oauth-client-id: ${{ secrets.TS_OAUTH_ID }}
95+
audience: ${{ secrets.TS_AUDIENCE }}
8596
tailnet: ${{ secrets.TS_TAILNET }}
8697
action: apply
8798

@@ -90,23 +101,20 @@ jobs:
90101
id: test-acl
91102
uses: tailscale/gitops-acl-action@v1
92103
with:
93-
api-key: ${{ secrets.TS_API_KEY }}
104+
oauth-client-id: ${{ secrets.TS_OAUTH_ID }}
105+
audience: ${{ secrets.TS_AUDIENCE }}
94106
tailnet: ${{ secrets.TS_TAILNET }}
95107
action: test
96108
```
97109
98-
Generate a new API key [here](https://login.tailscale.com/admin/settings/keys).
99-
100-
Set a monthly calendar reminder to renew this key because Tailscale does not
101-
currently support API key renewal (this will be updated to support that when
102-
that feature is implemented).
110+
Generate a new federated identity. See [here](https://login.tailscale.com/admin/settings/keys) for instructions.
103111
104112
Then open the secrets settings for your repo and add two secrets:
105113
106-
* `TS_API_KEY`: Your Tailscale API key from the earlier step
114+
* `TS_OAUTH_ID`: Your federated identity's client ID
115+
* `TS_AUDIENCE`: Your federated identity's audience
107116
* `TS_TAILNET`: Your tailnet's name (it's next to the logo on the upper
108-
left-hand corner of the [admin
109-
panel](https://login.tailscale.com/admin/machines))
117+
left-hand corner of the [admin panel](https://login.tailscale.com/admin/machines))
110118

111119
Once you do that, commit the changes and push them to GitHub. You will have CI
112120
automatically test and push changes to your tailnet policy file to Tailscale.

action.yml

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ inputs:
88
description: "Tailscale API key"
99
required: false
1010
oauth-client-id:
11-
description: "Tailscale OAuth ID"
11+
description: "Tailscale OAuth or OIDC Federated Identity Client ID"
1212
required: false
1313
oauth-secret:
1414
description: "Tailscale OAuth Secret"
1515
required: false
16+
audience:
17+
description: "Tailscale OIDC Federated Identity Audience"
18+
required: false
1619
policy-file:
1720
description: "Path to policy file"
1821
required: true
@@ -24,29 +27,39 @@ runs:
2427
using: "composite"
2528
steps:
2629
- name: Check Auth Info Empty
27-
if: ${{ inputs['api-key'] == '' && inputs['oauth-secret'] == '' }}
30+
if: ${{ inputs['api-key'] == '' && inputs['oauth-secret'] == '' && inputs['oauth-client-id'] == ''}}
2831
shell: bash
2932
run: |
30-
echo "::error title=⛔ error hint::API Key or OAuth secret must be specified. Maybe you need to populate it in the Secrets for your workflow, see more in https://docs.github.com/en/actions/security-guides/encrypted-secrets and https://tailscale.com/s/oauth-clients"
33+
echo "::error title=⛔ error hint::API Key, OAuth secret, or OAuth client ID and audience must be specified. Maybe you need to populate it in the Secrets for your workflow, see more in https://docs.github.com/en/actions/security-guides/encrypted-secrets and https://tailscale.com/s/trust-credentials
3134
exit 1
3235
- name: Check Conflicting Auth Info
33-
if: ${{ inputs['api-key'] != '' && inputs['oauth-secret'] != '' }}
36+
if: ${{ (inputs['api-key'] != '' && (inputs['oauth-secret'] != '' || inputs['audience'] != '')) || (inputs['oauth-secret'] != '' && (inputs['api-key'] != '' || inputs['audience'] != '')) || (inputs['audience'] != '' && (inputs['api-key'] != '' || inputs['oauth-secret'] != '')) }}
3437
shell: bash
3538
run: |
36-
echo "::error title=⛔ error hint::only one of API Key or OAuth secret should be specified.
39+
echo "::error title=⛔ error hint::only one of API Key, OAuth secret, or OAuth client ID and audience should be specified."
3740
exit 1
3841
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
3942
with:
4043
go-version: 1.25.5
4144
cache: false
42-
45+
- name: Fetch ID token
46+
if: ${{ inputs['oauth-client-id'] != '' && inputs['audience'] != '' }}
47+
shell: bash
48+
id: fetch-id-token
49+
run: |
50+
ID_TOKEN=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${{ inputs.audience }}" | jq -r '.value')
51+
echo "::add-mask::ID_TOKEN"
52+
echo "id_token=$ID_TOKEN" >> $GITHUB_OUTPUT
4353
- name: Gitops pusher
4454
shell: bash
4555
env:
46-
# gitops-pusher will use OAUTH_ID and OAUTH_SECRET if non-empty,
56+
# gitops-pusher will use OAUTH_ID and OAUTH_SECRET or
57+
# OAUTH_ID and ID_TOKEN if non-empty,
4758
# otherwise it will use API_KEY.
4859
TS_OAUTH_ID: "${{ inputs.oauth-client-id }}"
4960
TS_OAUTH_SECRET: "${{ inputs.oauth-secret }}"
61+
TS_ID_TOKEN: "${{ steps.fetch-id-token.outputs.id_token }}"
5062
TS_API_KEY: "${{ inputs.api-key }}"
5163
TS_TAILNET: "${{ inputs.tailnet }}"
52-
run: go run tailscale.com/cmd/gitops-pusher@2078eb56f3ca310821aae3fa140aa3b0d3bda2dc "--policy-file=${{ inputs.policy-file }}" "${{ inputs.action }}"
64+
run: go run tailscale.com/cmd/gitops-pusher@4c37141ab780dbf6c037bd64fe48ab330441ad06 "--policy-file=${{ inputs.policy-file }}" "${{ inputs.action }}"
65+

0 commit comments

Comments
 (0)