| 1 | #!/usr/bin/env bash |
| 2 | # Generate the Worker's own secrets once (never rotated automatically): |
| 3 | # MASTER_KEY root key for encrypting Actions secrets |
| 4 | # OIDC_PRIVATE_KEY ES256 key that signs workflow OIDC id tokens |
| 5 | # Values are created on the runner and sent straight to Cloudflare; they are never printed. |
| 6 | set -euo pipefail |
| 7 | APP="$(cd "$(dirname "$0")/../apps/diffinery" && pwd)" |
| 8 | WRANGLER=(pnpm --dir "$APP" exec wrangler) |
| 9 | |
| 10 | # Fail closed: if listing fails we must not mistake "unknown" for "missing" and |
| 11 | # overwrite MASTER_KEY, which would make every stored Actions secret unreadable. |
| 12 | LIST="$("${WRANGLER[@]}" secret list -c wrangler.deploy.jsonc --format json)" |
| 13 | EXISTING="$(jq -er '.[].name' <<<"$LIST" || true)" |
| 14 | jq -e 'type == "array"' >/dev/null <<<"$LIST" || { echo "unexpected output from wrangler secret list" >&2; exit 1; } |
| 15 | |
| 16 | if ! grep -qx MASTER_KEY <<<"$EXISTING"; then |
| 17 | openssl rand -base64 32 | tr -d '\n' | "${WRANGLER[@]}" secret put MASTER_KEY -c wrangler.deploy.jsonc >/dev/null |
| 18 | echo "set MASTER_KEY" |
| 19 | fi |
| 20 | if ! grep -qx OIDC_PRIVATE_KEY <<<"$EXISTING"; then |
| 21 | node --input-type=module -e ' |
| 22 | const { subtle } = globalThis.crypto; |
| 23 | const k = await subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, ["sign", "verify"]); |
| 24 | const jwk = await subtle.exportKey("jwk", k.privateKey); |
| 25 | jwk.kid = "diffinery-" + new Date().toISOString().slice(0, 10); |
| 26 | process.stdout.write(JSON.stringify(jwk)); |
| 27 | ' | "${WRANGLER[@]}" secret put OIDC_PRIVATE_KEY -c wrangler.deploy.jsonc >/dev/null |
| 28 | echo "set OIDC_PRIVATE_KEY" |
| 29 | fi |