···11+layout: blog.njk
22+type: blog
33+index: true
44+is_note: true
+61
lume/src/notes/recover-github-action-secret.mdx
···11+---
22+title: "How to recover a GitHub Actions secret"
33+date: 2023-11-02
44+tags:
55+ - github
66+ - actions
77+ - secrets
88+ - tailscale
99+---
1010+1111+Sometimes you fuck up and lose your only copy of a GitHub secret that you can't replace easily, such as a [Cachix](https://www.cachix.org/) signing key. However you lucked out and that key is actually saved in GitHub Actions secrets...which won't let you read the contents of that secret for understandable security reasons. Here's how you work around that.
1212+1313+First, make sure [Deno](https://deno.land) is installed and copy this program to `recover-secret.ts`.
1414+1515+```ts
1616+const port = 8080;
1717+1818+const handler = async (req: Request): Promise<Response> => {
1919+ const body = (await req.text());
2020+ console.log(body);
2121+2222+ return new Response()
2323+};
2424+2525+console.log(`HTTP server running. Access it at: http://localhost:${port}/`);
2626+Deno.serve({ port }, handler);
2727+```
2828+2929+Run it with `deno run -A recover-secret.ts`.
3030+3131+Next go to the [Tailscale admin console OAuth clients section](https://login.tailscale.com/admin/settings/oauth) and generate a new OAuth client that lets you create auth keys (you want the write on devices scope). Add a helpful description like "GitHub Actions secret recovery" and copy the client ID and secret to your password manager. Then add them as GitHub secrets named `TAILSCALE_CLIENT_ID` and `TAILSCALE_CLIENT_SECRET`.
3232+3333+Now create a new GitHub Actions workflow with the following contents:
3434+3535+```yaml
3636+on:
3737+ workflow_dispatch:
3838+3939+jobs:
4040+ recoversecret:
4141+ runs-on: ubuntu-latest
4242+ steps:
4343+ - name: Tailscale
4444+ uses: tailscale/github-action@v2
4545+ with:
4646+ oauth-client-id: ${{ secrets.TAILSCALE_CLIENT_ID }}
4747+ oauth-secret: ${{ secrets.TAILSCALE_CLIENT_SECRET }}
4848+ tags: tag:ci
4949+ version: 1.52.0
5050+ - name: "Recover secret"
5151+ run: |
5252+ echo ${SECRET} > ./output.txt
5353+ curl --data-binary @./output.txt ${TARGET}
5454+ env:
5555+ SECRET: ${{ secrets.CACHIX_SIGNING_KEY }}
5656+ TARGET: "http://kaine.shark-harmonic.ts.net:8080"
5757+```
5858+5959+Replace the contents of `TARGET` as facts and circumstances demand.
6060+6161+Now you can recover your secret by hitting the "Run workflow" button on the Actions tab of your repo. The secret will be in your terminal, and you can copy it to your password manager as a note.
+11
scripts/recover-secret.ts
···11+const port = 8080;
22+33+const handler = async (req: Request): Promise<Response> => {
44+ const body = (await req.text());
55+ console.log(body);
66+77+ return new Response()
88+};
99+1010+console.log(`HTTP server running. Access it at: http://localhost:${port}/`);
1111+Deno.serve({ port }, handler);