#!/usr/bin/env bash # init_oauth2_proxy.sh # # Bootstrap the oauth2-proxy gate in front of Supabase Studio at # db.0.knoe.dev. Gates access via Google Workspace OIDC (knoey.com) so any # @knoey.com identity (chrisfu, ron) can sign in and share the Studio # session. Outside-domain users are rejected at this layer. # # Usage: # ./etc/init_oauth2_proxy.sh # # Env vars (resolved from etc/secrets/* if not set in the shell): # OAUTH2_PROXY_CLIENT_ID ← from etc/secrets/oauth2-proxy-client-id # OAUTH2_PROXY_CLIENT_SECRET ← from etc/secrets/oauth2-proxy-client-secret # OAUTH2_PROXY_COOKIE_SECRET ← from etc/secrets/oauth2-proxy-cookie-secret # # Optional: # APP_CLUSTER_KUBECONTEXT (default: $KUBECONTEXT then ambient) # NAMESPACE (default: supabase) # # Pre-reqs: # - OAuth 2.0 client created at GCP Console (see the secret template # deploy/gcp/gke/oauth2-proxy-google-oidc-secret.example.yaml for the # exact authorized redirect URI + consent screen settings). # - cookie_secret generated with: openssl rand -base64 32 # - Three values saved into etc/secrets/oauth2-proxy-{client-id,client-secret,cookie-secret} # (chmod 0600 each; etc/secrets/ is gitignored except for .keep). # # After this script runs and the oauth2-proxy Deployment is Ready, two # manual steps complete the wiring (NOT done by this script — see the plan # in docs/plans/ for the full sequence): # # 1. Patch the supabase-kong Ingress to route db.0.knoe.dev through # oauth2-proxy:80 instead of supabase-kong:8000: # # kubectl --context=$APP_CLUSTER_KUBECONTEXT -n supabase patch ingress \ # supabase-kong --type=json -p '[ # {"op": "replace", # "path": "/spec/rules/1/http/paths/0/backend/service/name", # "value": "oauth2-proxy"}, # {"op": "replace", # "path": "/spec/rules/1/http/paths/0/backend/service/port/number", # "value": 80} # ]' # (verify the index by checking which rule has host=db.0.knoe.dev first; # index may shift on future Helm reconciles) # # 2. Remove the basic-auth plugin from the dashboard route in the # supabase-kong configmap (oauth2-proxy is the gate now; double-auth is # friction). Then rollout-restart supabase-kong. # # When knoe-auth Round 1 ships an OIDC OP at https://api.knoe.dev/auth, change # `--provider=google` to `--provider=oidc --oidc-issuer-url=https://api.knoe.dev/auth` # in deploy/gcp/gke/oauth2-proxy-deployment.yaml and re-run this script. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" GKE_MANIFEST_DIR="$REPO_ROOT/deploy/gcp/gke" NAMESPACE="${NAMESPACE:-supabase}" KCTX="${APP_CLUSTER_KUBECONTEXT:-${KUBECONTEXT:-}}" if [[ -n "$KCTX" ]]; then KCTX_FLAG=(--context="$KCTX") else KCTX_FLAG=() fi log() { printf "[%s] %s\n" "$(date +%H:%M:%S)" "$*"; } die() { log "ERROR: $*" >&2; exit 1; } resolve_secret() { # Resolve a value from env (preferred) or etc/secrets/. local var="$1" file="$2" val="${!1:-}" if [[ -z "$val" && -f "$REPO_ROOT/etc/secrets/$file" ]]; then val="$(cat "$REPO_ROOT/etc/secrets/$file")" fi if [[ -z "$val" ]]; then die "missing $var (set the env var, or save the value into etc/secrets/$file)" fi printf '%s' "$val" } for tool in kubectl envsubst; do command -v "$tool" >/dev/null 2>&1 || die "required tool not found: $tool" done OAUTH2_PROXY_CLIENT_ID="$(resolve_secret OAUTH2_PROXY_CLIENT_ID oauth2-proxy-client-id)" OAUTH2_PROXY_CLIENT_SECRET="$(resolve_secret OAUTH2_PROXY_CLIENT_SECRET oauth2-proxy-client-secret)" OAUTH2_PROXY_COOKIE_SECRET="$(resolve_secret OAUTH2_PROXY_COOKIE_SECRET oauth2-proxy-cookie-secret)" export OAUTH2_PROXY_CLIENT_ID OAUTH2_PROXY_CLIENT_SECRET OAUTH2_PROXY_COOKIE_SECRET SECRET_TMPL="$GKE_MANIFEST_DIR/oauth2-proxy-google-oidc-secret.example.yaml" DEPLOY_MANIFEST="$GKE_MANIFEST_DIR/oauth2-proxy-deployment.yaml" [[ -f "$SECRET_TMPL" ]] || die "missing manifest: $SECRET_TMPL" [[ -f "$DEPLOY_MANIFEST" ]] || die "missing manifest: $DEPLOY_MANIFEST" log "==> oauth2-proxy bootstrap" log " namespace : $NAMESPACE" log " kubectx : ${KCTX:-}" log "Applying oauth2-proxy-google-oidc secret ..." envsubst '${OAUTH2_PROXY_CLIENT_ID} ${OAUTH2_PROXY_CLIENT_SECRET} ${OAUTH2_PROXY_COOKIE_SECRET}' \ < "$SECRET_TMPL" \ | kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" apply -f - log "Applying oauth2-proxy ServiceAccount + BackendConfig + Service + Deployment ..." kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" apply -f "$DEPLOY_MANIFEST" log "Waiting for oauth2-proxy Deployment to become Ready (timeout 180s) ..." kubectl "${KCTX_FLAG[@]}" -n "$NAMESPACE" rollout status deployment/oauth2-proxy --timeout=180s log "==> oauth2-proxy bootstrap complete." echo "" echo " Next steps (NOT performed by this script):" echo " 1. Patch the supabase-kong Ingress so db.0.knoe.dev routes to" echo " oauth2-proxy:80 instead of supabase-kong:8000." echo " 2. Remove the basic-auth plugin from the dashboard route in the" echo " supabase-kong configmap, then rollout-restart supabase-kong." echo " 3. In a browser, sign in to https://db.0.knoe.dev/ with a" echo " @knoey.com Google account. Try a non-knoey account too — should" echo " receive 403 from oauth2-proxy." echo "" echo " See the active plan in ~/.claude/plans/ for the exact patch commands."