|
| 1 | +# tskeyservice |
| 2 | + |
| 3 | +This lightweight service exchanges OIDC token from trusted issuer for a short-lived, one-time use [Tailscale](https://tailscale.com) [Auth Token](https://tailscale.com/kb/1085/auth-keys/). |
| 4 | + |
| 5 | +## Why? |
| 6 | + |
| 7 | +The idea for this service was born when connecting a GitHub Action to my Tailscale network. |
| 8 | +While this is typically done by creating an ephemeral auth key, add it to the secrets of the workflow. |
| 9 | +Although such Tailscale auth keys have an expiration by default, I always try to avoid "static" secrets. |
| 10 | + |
| 11 | +## How? |
| 12 | + |
| 13 | +GitHub Actions has support for OpenID Connect (OIDC) tokens, allowing your workflows to exchange short-lived tokens from e.g. your cloud provider. |
| 14 | +This service is such an implementation and creates ephemeral, short-lived, one-time auth keys for your Tailscale network. |
| 15 | + |
| 16 | +## Configuration |
| 17 | + |
| 18 | +Configuration is done by settings environment variables: |
| 19 | + |
| 20 | +- TS_TAILNET: the name of your tailnet |
| 21 | +- TS_API_KEY: a Tailscale API key |
| 22 | +- TS_KEYS_ISSUER: a trusted OIDC Issuer url (e.g. https://token.actions.githubusercontent.com) |
| 23 | +- TS_KEYS_TAGS: comma-separated list of ACL tags |
| 24 | +- TS_KEY_BEXPR: a boolean expression to filter OIDC tokens (based on claims) when creating auth keys |
| 25 | + |
| 26 | +The last setting is quit important as it allows you to filter OIDC tokens and only creating auth keys when the token has some certain claims. |
| 27 | + |
| 28 | +Example: |
| 29 | + |
| 30 | +In case of GitHub Action, the issued token has a `repository` claim. |
| 31 | +The following expression will only create auth keys for a workflow from this repository: |
| 32 | + |
| 33 | +```shell |
| 34 | +export TS_KEY_BEXPR='repository == "jsiebens/tskeys-example"' |
| 35 | +``` |
| 36 | + |
| 37 | +The boolean expression is implemented using the [HashiCorp go-bexpr](https://github.com/hashicorp/go-bexpr) library |
| 38 | + |
| 39 | +## Deployment |
| 40 | + |
| 41 | +When using in GitHub Actions, this service should be publicly available. E.g. on Google Cloud Run of [fly.io](https://fly.io). |
| 42 | + |
| 43 | +A Docker image is available at `ghcr.io/jsiebens/tskeyservice` |
| 44 | + |
| 45 | +## Example workflow |
| 46 | + |
| 47 | +```yaml |
| 48 | +name: GitHub Action Sample |
| 49 | + |
| 50 | +on: |
| 51 | + workflow_dispatch: |
| 52 | + |
| 53 | +permissions: |
| 54 | + id-token: write |
| 55 | + |
| 56 | +jobs: |
| 57 | + sample: |
| 58 | + runs-on: ubuntu-latest |
| 59 | + steps: |
| 60 | + |
| 61 | + - name: Get Tailscale key |
| 62 | + shell: bash |
| 63 | + env: |
| 64 | + TSKEYSERVICE_URL: "<your tskeservice url e.g. https://tskeys.example.com/key>" |
| 65 | + run: | |
| 66 | + OIDC_TOKEN=$(curl -sLS "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=brink" -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" | jq -j '.value') |
| 67 | + TS_KEY=$(curl -sLS $TSKEYSERVICE_URL -H "User-Agent: actions/oidc-client" -H "Authorization: Bearer $OIDC_TOKEN" | jq -j '.key') |
| 68 | + echo "TAILSCALE_AUTHKEY=$TS_KEY" >> $GITHUB_ENV |
| 69 | + |
| 70 | + - name: Tailscale |
| 71 | + uses: tailscale/github-action@main |
| 72 | + with: |
| 73 | + authkey: ${{ env.TAILSCALE_AUTHKEY }} |
| 74 | +``` |
| 75 | +
|
| 76 | +## Alternatives |
| 77 | +
|
| 78 | +- [vault-plugin-tailscale](https://github.com/davidsbond/vault-plugin-tailscale) |
0 commit comments