Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

45 lines · 2.5 KB · executableRaw History
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 (rotated by hand, with
4# MASTER_KEY_PREV, which this script never touches; see
5# apps/diffinery/docs/self-hosting/configuration.md, "Rotating MASTER_KEY")
6# OIDC_PRIVATE_KEY ES256 key that signs workflow OIDC id tokens
7# and, when missing, sets TURNSTILE_SECRET from the Turnstile widget whose site key was deployed
8# (scripts/turnstile.sh, through bootstrap and render-config).
9# Values are created on the runner (or read from Cloudflare's API) and sent straight to Cloudflare;
10# they are never printed.
11set -euo pipefail
12ROOT="$(cd "$(dirname "$0")/.." && pwd)"
13APP="$ROOT/apps/diffinery"
14WRANGLER=(pnpm --dir "$APP" exec wrangler)
15
16# Fail closed: if listing fails we must not mistake "unknown" for "missing" and
17# overwrite MASTER_KEY, which would make every stored Actions secret unreadable.
18LIST="$("${WRANGLER[@]}" secret list -c wrangler.deploy.jsonc --format json)"
19EXISTING="$(jq -er '.[].name' <<<"$LIST" || true)"
20jq -e 'type == "array"' >/dev/null <<<"$LIST" || { echo "unexpected output from wrangler secret list" >&2; exit 1; }
21
22if ! grep -qx MASTER_KEY <<<"$EXISTING"; then
23 openssl rand -base64 32 | tr -d '\n' | "${WRANGLER[@]}" secret put MASTER_KEY -c wrangler.deploy.jsonc >/dev/null
24 echo "set MASTER_KEY"
25fi
26if ! grep -qx OIDC_PRIVATE_KEY <<<"$EXISTING"; then
27 node --input-type=module -e '
28 const { subtle } = globalThis.crypto;
29 const k = await subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, ["sign", "verify"]);
30 const jwk = await subtle.exportKey("jwk", k.privateKey);
31 jwk.kid = "diffinery-" + new Date().toISOString().slice(0, 10);
32 process.stdout.write(JSON.stringify(jwk));
33 ' | "${WRANGLER[@]}" secret put OIDC_PRIVATE_KEY -c wrangler.deploy.jsonc >/dev/null
34 echo "set OIDC_PRIVATE_KEY"
35fi
36# Without the Turnstile permission this warns (scripts/turnstile.sh names it) and the deploy goes on:
37# people who aren't signed in can't send security reports until it's set.
38SITE_KEY="$(tail -n +2 "$APP/wrangler.deploy.jsonc" | jq -r '.vars.TURNSTILE_SITE_KEY // empty')"
39if [[ -n "$SITE_KEY" ]] && ! grep -qx TURNSTILE_SECRET <<<"$EXISTING"; then
40 if "$ROOT/scripts/turnstile.sh" secret "$SITE_KEY" -c wrangler.deploy.jsonc; then
41 echo "set TURNSTILE_SECRET"
42 else
43 echo "::warning::TURNSTILE_SECRET is not set, so only people who are signed in can send security reports. The next deploy tries again." >&2
44 fi
45fi