prole/docs/completed/phase2-oidc-gke-deploy.md
chrisfu 73dce037f3 docs: reorganise briefs into docs/completed/; add conf/service/knoe.cfg
docs/completed/ — new directory; 9 shipped Junie briefs moved from
docs/plans/junie/ (02-k3s-prole-rename, 03-image-rename, 06-patch-garage,
07-init-cnpg-gke-sa-wiring, 13-podmonitor, 15-remove-dead-dashboard,
k3d-knoe-auth-dev-loop, phase2-oidc-gke-deploy, todo-1-cfg-save-path-bug).
docs/completed/README.md summarises all shipped work with dates/refs.

docs/plans/junie/README.md — updated to 2026-05-23; active/pending tables
reflect current state; shipped section now points to docs/completed/.

conf/service/knoe.cfg — new unattended deploy config for the service/k3s
environment (used by ./deploy.sh).

Co-authored-by: Junie <junie@jetbrains.com>
2026-05-23 21:32:01 -07:00

5.7 KiB

Brief: Phase 2 OIDC — GKE deploy

Status: Active
Filed: 2026-05-02
Author: Junie
Depends on: Queue #3 (image rename knoe-authorityknoe-auth) — shipped 2026-05-02


1. Context

knoe-auth Phase 2 adds an OIDC provider surface to the existing Kerberos enrollment service. The k3d dev sandbox shipped 2026-05-02 (commit 93157b0): application-k3d.yml profile, etc/gen_oidc_signing_key.sh keypair generator, and all OIDC endpoints (/.well-known/openid-configuration, /jwks.json, /authorize, /token, /userinfo) are exercisable locally.

This brief covers the remaining work to ship Phase 2 in production on GKE:

  1. Generate a production RS256 keypair and store it in 1Password (consistent with the existing secret pattern in etc/init_knoe_auth.sh).
  2. Wire the signing key into the knoe-auth-oidc K8s Secret in knoe-system.
  3. Enable OIDC in the GKE deployment (KNOE_AUTH_OIDC_ENABLED=true, issuer URL, signing key).
  4. Add a Kong route so https://api.knoe.dev/auth proxies to knoe-auth (the /auth/v1/* routes already go to GoTrue — knoe-auth needs /auth without the /v1 prefix).
  5. Rollout and verify externally.

Design reference: docs/knoe-auth-phase-2.md.


2. Deliverables

2.1 Production RS256 keypair

Generate once on the engineer's laptop (same tool as k3d):

./etc/gen_oidc_signing_key.sh   # writes etc/secrets/knoe-auth-oidc-key.{pem,b64}

Store the base64 PKCS#8 private key (knoe-auth-oidc-key.b64) in 1Password as item knoe-auth-oidc-signing-key field signing_key. This follows the same pattern as knoe-google-oidc / knoe-kdc-master used by op_secret() in init_knoe_auth.sh.

Do not commit the key. etc/secrets/ is gitignored.

2.2 init_knoe_auth.sh — new create_oidc_signing_key_secret function

Add a function (GKE path only) alongside create_google_oidc_secret():

create_oidc_signing_key_secret() {
  if kube -n "$NAMESPACE" get secret knoe-auth-oidc >/dev/null 2>&1; then
    info "knoe-auth-oidc already exists — skipping."
    return
  fi
  info "Creating knoe-auth-oidc secret..."
  local signing_key
  signing_key=$(op_secret "knoe-auth-oidc-signing-key" "signing_key")
  kube -n "$NAMESPACE" create secret generic knoe-auth-oidc \
    --from-literal=signing-key="$signing_key"
  info "knoe-auth-oidc created."
}

Call it from the schema subcommand block (GKE path), after create_google_oidc_secret.

Note: the existing knoe-auth-oidc-secret.example.yaml also has client-id and client-secret fields (for knoe-auth acting as an OIDC client). Those are not needed for Phase 2 (knoe-auth is the provider, not a client). The secret only needs signing-key for now; the example file can stay as-is.

2.3 deploy/gcp/gke/knoe-auth-deployment.yaml — enable OIDC

Change the three OIDC env vars (already present, currently disabled):

- name: KNOE_AUTH_OIDC_ENABLED
  value: "true"                          # was: "${KNOE_AUTH_OIDC_ENABLED:-false}"
- name: KNOE_AUTH_OIDC_ISSUER
  value: "https://api.knoe.dev/auth"     # was: empty / placeholder

The KNOE_AUTH_OIDC_SIGNING_KEY env var already reads from knoe-auth-oidc secret (signing-key key) — no change needed there.

2.4 Kong route for /auth → knoe-auth

In supabase/helm/knoe-supabase/templates/kong/config.yaml, add a new service + route block before the existing GoTrue /auth/v1 block (Kong matches longest prefix first, so order matters):

_format_version: "2.1"
services:
  # ── knoe-auth OIDC provider (/auth — no /v1 prefix) ─────────────────────
  - name: knoe-auth
    url: http://knoe-auth.knoe-system.svc.cluster.local:8080
    routes:
      - name: knoe-auth-oidc
        strip_path: false
        paths:
          - /auth
        # Note: /auth/v1/* is handled by GoTrue below; Kong routes by longest
        # prefix so /auth/v1/... hits GoTrue, /auth/... hits knoe-auth.

Verify with helm template that both routes render and that /auth/v1/ still resolves to GoTrue.

2.5 docs/knoe-system.md update

  • §2 WIP table: flip Phase 2 OIDC GKE deploy from PendingShipped.
  • §7 Open work items: remove the Phase 2 GKE pending bullet; update pg_oauth note to say "OIDC issuer now reachable — pg_oauth can resume".

3. Out of scope

  • pg_oauth wiring (separate brief; resumes after this lands).
  • Round 1.5 OpenBao transit-key encryption.
  • JWKS key rotation (future operational concern).
  • knoe-auth acting as an OIDC client (the client-id/client-secret fields in the oidc secret example are for a future phase).

4. Definition of done

  • kubectl -n knoe-system get secret knoe-auth-oidc exists with signing-key field
  • kubectl rollout status deployment/knoe-auth -n knoe-system → success
  • curl -fsS https://api.knoe.dev/auth/.well-known/openid-configuration | jq .issuer"https://api.knoe.dev/auth"
  • curl -fsS https://api.knoe.dev/auth/jwks.json | jq '.keys[0].kty'"RSA"
  • curl -fsS https://api.knoe.dev/auth/v1/ still routes to GoTrue (not knoe-auth)
  • docs/knoe-system.md Phase 2 GKE status → Shipped
  • docs/TODO.md Phase 2 OIDC GKE deploy moved from In progress → Done

5. Commit shape

feat(auth): Phase 2 OIDC GKE deploy

- init_knoe_auth.sh: add create_oidc_signing_key_secret (GKE path)
- deploy/gcp/gke/knoe-auth-deployment.yaml: enable OIDC (ENABLED=true, ISSUER set)
- supabase/helm/knoe-supabase/templates/kong/config.yaml: add /auth route → knoe-auth
- docs/knoe-system.md: Phase 2 GKE status → Shipped
- docs/TODO.md: Phase 2 OIDC GKE deploy → Done

Depends on: queue #3 (knoe-auth image rename, shipped 2026-05-02).
Unblocks: pg_oauth resume.