11name : Delete Inactive Tailnet Nodes
22
33permissions :
4+ id-token : write # Required for OIDC token
45 contents : read # Required for checkout
56
67on :
1819 description : " Dry run mode (only list devices, don't delete)"
1920 type : boolean
2021 default : true
21- oauth_client_id :
22- description : " OAuth Client ID for the Tailnet "
22+ audience :
23+ description : " Audience for the OIDC token "
2324 required : true
24- default : " "
25- oauth_client_secret :
26- description : " OAuth Client Secret for the Tailnet "
25+ default : " api.tailscale.com/kxF3d4zoso11CNTRL "
26+ client_id :
27+ description : " Client ID for the Tailscale OIDC JWT exchange "
2728 required : true
28- default : " "
29- tailnet_name :
30- description : " Tailnet name to operate on (e.g., 'example.com')"
31- required : true
32- default : " "
29+ default : " TbqNGJkY5611CNTRL/kxF3d4zoso11CNTRL"
3330
3431jobs :
3532 delete-inactive-nodes :
@@ -43,23 +40,33 @@ jobs:
4340 sudo apt-get update
4441 sudo apt-get install -y jq curl
4542
46- - name : Get access token using OAuth
43+ - name : Get OIDC token from GitHub Actions
44+ id : get_oidc_token
45+ run : |
46+ JWT=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${{ inputs.audience }}" | jq -r '.value')
47+ echo "::add-mask::$JWT"
48+ echo "jwt=$JWT" >> $GITHUB_OUTPUT
49+
50+ - name : Exchange OIDC token for access token
4751 id : get_access_token
4852 run : |
49- echo "Getting access token for tailnet ..."
50- ACCESS_TOKEN=$(./tailscale/scripts/get-access -token.sh "${{ inputs.oauth_client_id }}" "${{ inputs.oauth_client_secret }}")
53+ echo "Exchanging OIDC token with Tailscale ..."
54+ ACCESS_TOKEN=$(./tailscale/scripts/exchange-oidc -token.sh "${{ inputs.client_id }}" "${{ steps.get_oidc_token.outputs.jwt }}")
5155 echo "::add-mask::$ACCESS_TOKEN"
5256 echo "access_token=$ACCESS_TOKEN" >> $GITHUB_OUTPUT
5357 echo "Successfully obtained access token"
5458
5559 - name : Get all devices in tailnet
5660 id : get_devices
5761 run : |
58- echo "Fetching devices from tailnet: ${{ inputs.tailnet_name }}"
62+ # Extract tailnet from the client_id (format: clientid/tailnet)
63+ TAILNET=$(echo "${{ inputs.client_id }}" | cut -d'/' -f2)
64+ echo "Fetching devices from tailnet: $TAILNET"
65+ echo "tailnet=$TAILNET" >> $GITHUB_OUTPUT
5966
6067 # Make API call with proper error handling
6168 RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" \
62- https://api.tailscale.com/api/v2/tailnet/"${{ inputs.tailnet_name }} "/devices \
69+ https://api.tailscale.com/api/v2/tailnet/"$TAILNET "/devices \
6370 --header "Authorization: Bearer ${{ steps.get_access_token.outputs.access_token }}")
6471
6572 HTTP_STATUS=$(echo "$RESPONSE" | tail -n 1 | cut -d: -f2)
@@ -236,4 +243,5 @@ jobs:
236243 if : inputs.dry_run == false && steps.filter_devices.outputs.devices_count != '0'
237244 run : |
238245 echo "Fetching updated device list..."
239- ./tailscale/scripts/list-devices.sh "${{ steps.get_access_token.outputs.access_token }}" "${{ inputs.tailnet_name }}" table || true
246+ TAILNET=$(echo "${{ inputs.client_id }}" | cut -d'/' -f2)
247+ ./tailscale/scripts/list-devices.sh "${{ steps.get_access_token.outputs.access_token }}" "$TAILNET" table || true
0 commit comments