prole/scripts/k3d-knoe-pf.sh
chrisfu 93157b0a86 feat(knoe-auth): Phase 2 OIDC sandbox in k3d dev loop
Completes the Phase 2 OIDC laptop dev path. Source for the OIDC surface
(discovery, authorize, token, userinfo, JWKS controllers + signing /
session services) landed on `main` via the merge that brought
claude/crazy-bose-fec256 back. This commit makes Phase 2 actually
exercisable in the k3d dev loop without any GKE deploy.

What's new:

  authority/src/main/resources/application-k3d.yml
    Spring profile activated by `-Dspring-boot.run.profiles=k3d`.
    Enables OIDC (knoe.oidc.enabled=true), points the issuer at
    `http://localhost:8080`, sets Kerberos realm to KNOE.LOCAL, and
    aligns the datasource with the port-forwarded localhost:5432 DB.

  etc/gen_oidc_signing_key.sh  (executable)
    Idempotent RS256 PKCS#8 keypair generator. Outputs:
      etc/secrets/knoe-auth-oidc-key.pem  (PEM)
      etc/secrets/knoe-auth-oidc-key.b64  (single-line base64 of DER —
        directly consumable as KNOE_AUTH_OIDC_SIGNING_KEY by
        OidcTokenService.init())
    `etc/secrets/` is already gitignored. Set FORCE=1 to rotate.

What's wired:

  scripts/k3d-knoe-up.sh
    New §7 calls etc/gen_oidc_signing_key.sh after schema seed. Keypair
    persists across `make k3d-knoe-down && make k3d-knoe-up` cycles.

  scripts/k3d-knoe-pf.sh
    Output now includes the KNOE_AUTH_OIDC_SIGNING_KEY export line, the
    full `mvn spring-boot:run` invocation with -Dspring-boot.run.profiles=k3d,
    and the three OIDC endpoints to curl-test.

What's documented:

  docs/local-dev-knoe-auth.md
    "Daily loop" Terminal B: now exports KNOE_AUTH_OIDC_SIGNING_KEY,
    runs with `-Dspring-boot.run.profiles=k3d`, and the verify section
    includes /jwks.json. IntelliJ run config: adds Active Profiles: k3d
    and a note about pasting the b64 directly (no shell expansion in
    the env-var field).

  docs/knoe-system.md
    Phase 2 status row split: "k3d setup" → Shipped, "GKE deploy" →
    Pending. The "Open work items" Phase 2 entry rewritten to flag
    that the GKE deploy is the remaining thread (gated on queue #3 for
    the image rebuild as `knoe-auth:latest`).

  docs/TODO.md
    Promoted "Phase 2 OIDC provider — GKE deploy" into §In progress
    (replacing the empty "(none)" placeholder). Done section updated
    with two entries: the k3d Phase 1 dev loop (Junie's c3...) and
    this Phase 2 OIDC k3d sandbox.

End-to-end loop the engineer can run:

  make k3d-knoe-up                                     # one-time, ~5 min
  make k3d-knoe-pf &                                   # port-forwards
  export KRB5_CONFIG=$PWD/etc/krb5.local.conf
  export KNOE_AUTH_OIDC_SIGNING_KEY=$(cat etc/secrets/knoe-auth-oidc-key.b64)
  mvn -pl authority spring-boot:run \
    -Dspring-boot.run.jvmArguments="-Djava.security.krb5.conf=$PWD/etc/krb5.local.conf" \
    -Dspring-boot.run.profiles=k3d
  # then:
  curl -s http://localhost:8080/.well-known/openid-configuration | jq .issuer
  # → "http://localhost:8080"
  curl -s http://localhost:8080/jwks.json | jq '.keys[0].kty'
  # → "RSA"

Verified locally: keypair generator round-trips through openssl pkey -inform DER
(produces valid 2048-bit RSA keys); idempotent (existing key kept by default,
FORCE=1 rotates); bash -n clean on all 5 touched scripts.

Out of scope (TODO §In progress captures it):
  - GKE deploy of Phase 2 (image rebuild + K8s Secret + deployment env vars)
  - SPNEGO E2E from host browsers (k3d-mirror Phase 2)
  - knoe-auth-as-pod in k3d (k3d-mirror Phase 3)
  - OidcCodeService DB persistence (separate track)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 11:55:50 -07:00

106 lines
5.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# scripts/k3d-knoe-pf.sh
# Open port-forwards for the k3d-knoe dev cluster and print connection info.
#
# Forwards:
# localhost:5432 → service/knoe-db-rw (CNPG primary, namespace knoe-db-0)
# localhost:88 → service/knoe-kdc:88 (Kerberos KDC, namespace knoe-system)
# localhost:464 → service/knoe-kdc:464 (kpasswd, namespace knoe-system)
#
# Usage:
# make k3d-knoe-pf # foreground; ^C to stop
# make k3d-knoe-pf & # background (for scripts)
#
# Prerequisites: kubectl, k3d cluster running (make k3d-knoe-up)
set -euo pipefail
CLUSTER_NAME="${K3D_CLUSTER_NAME:-k3d-knoe}"
CTX="k3d-${CLUSTER_NAME}"
DB_NS="knoe-db-0"
SYS_NS="knoe-system"
log() { echo "[k3d-knoe-pf] $*"; }
kube() { kubectl --context="$CTX" "$@"; }
# ── Verify cluster is reachable ───────────────────────────────────────────────
if ! kube cluster-info >/dev/null 2>&1; then
echo "[k3d-knoe-pf] ERROR: Cannot reach cluster context '$CTX'." >&2
echo " Run: make k3d-knoe-up" >&2
exit 1
fi
# ── Retrieve DB password for display ─────────────────────────────────────────
DB_PASSWORD=$(kube -n "$DB_NS" get secret knoe-db-user \
-o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "knoe-dev-password")
# ── Print connection info ─────────────────────────────────────────────────────
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ k3d-knoe port-forwards │"
echo "├─────────────────────────────────────────────────────────────────┤"
echo "│ DB: localhost:5432 (CNPG primary, knoe-db-0) │"
echo "│ KDC: localhost:88 (Kerberos KDC, knoe-system) │"
echo "│ kpasswd: localhost:464 (kpasswd, knoe-system) │"
echo "├─────────────────────────────────────────────────────────────────┤"
echo "│ JDBC URL: │"
echo "│ jdbc:postgresql://localhost:5432/knoe-db?sslmode=require │"
echo "│ │"
echo "│ Export these before running knoe-auth: │"
echo "│ export KRB5_CONFIG=\$PWD/etc/krb5.local.conf │"
echo "│ export KNOE_DB_PASSWORD=${DB_PASSWORD}"
echo "│ export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/knoe-db?sslmode=require │"
echo "│ export SPRING_DATASOURCE_USERNAME=knoe │"
echo "│ export SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD}"
echo "│ # Phase 2 OIDC signing key (from etc/gen_oidc_signing_key.sh):│"
echo "│ export KNOE_AUTH_OIDC_SIGNING_KEY=\$(cat etc/secrets/knoe-auth-oidc-key.b64)│"
echo "├─────────────────────────────────────────────────────────────────┤"
echo "│ Run knoe-auth with the k3d profile (enables OIDC + dev defaults):│"
echo "│ mvn -pl authority spring-boot:run \\ │"
echo "│ -Dspring-boot.run.jvmArguments=\"-Djava.security.krb5.conf=\$PWD/etc/krb5.local.conf\" \\│"
echo "│ -Dspring-boot.run.profiles=k3d │"
echo "├─────────────────────────────────────────────────────────────────┤"
echo "│ Phase 2 OIDC endpoints (after knoe-auth is up): │"
echo "│ GET http://localhost:8080/.well-known/openid-configuration │"
echo "│ GET http://localhost:8080/jwks.json │"
echo "│ POST http://localhost:8080/token │"
echo "├─────────────────────────────────────────────────────────────────┤"
echo "│ Press ^C to stop all port-forwards │"
echo "└─────────────────────────────────────────────────────────────────┘"
echo ""
# ── Start port-forwards ───────────────────────────────────────────────────────
PF_PIDS=()
cleanup() {
log "Stopping port-forwards..."
for pid in "${PF_PIDS[@]:-}"; do
kill "$pid" 2>/dev/null || true
done
log "Done."
}
trap cleanup EXIT INT TERM
log "Starting port-forward: localhost:5432 → knoe-db-rw:5432 (knoe-db-0)..."
kube -n "$DB_NS" port-forward service/knoe-db-rw 5432:5432 &
PF_PIDS+=($!)
# Brief pause so the DB forward is established before KDC
sleep 1
log "Starting port-forward: localhost:88 → knoe-kdc:88 (knoe-system)..."
kube -n "$SYS_NS" port-forward service/knoe-kdc 88:88 &
PF_PIDS+=($!)
log "Starting port-forward: localhost:464 → knoe-kdc:464 (knoe-system)..."
kube -n "$SYS_NS" port-forward service/knoe-kdc 464:464 &
PF_PIDS+=($!)
log "All port-forwards running. Waiting (^C to stop)..."
wait