Complete identity smoke path: id_token claims, registration entry, cutover docs
Prefer verified KeyCape id_token claims when /userinfo returns 401; soft-fail userinfo. Add CSOC-WP-0003 registration entry (disabled until NetKingdom URL), AAL step-up hooks, smoke/cutover evidence for tegwick OIDC without MFA.
This commit is contained in:
parent
3bc16b581b
commit
29a9ff735e
14 changed files with 513 additions and 41 deletions
|
|
@ -1,11 +1,30 @@
|
|||
# Deploy notes (stub — CSOC-WP-0002-T08)
|
||||
# Deploy notes
|
||||
|
||||
## Shape
|
||||
|
||||
Standalone service: commit-SHA images → registry
|
||||
`gitea.coulomb.social/coulomb/coulomb-social` → `railiance-apps` values →
|
||||
`forgejo.coulomb.social/coulomb/coulomb-social` → `railiance-apps` Helm values →
|
||||
railiance01 (same lane as `vergabe-teilnahme`).
|
||||
|
||||
Chart/values/ingress live in **`railiance-apps`**
|
||||
(`helm/coulomb-social-values.yaml`, `docs/coulomb-social.md`).
|
||||
|
||||
## Current cluster status (2026-08-09)
|
||||
|
||||
| Item | State |
|
||||
|------|--------|
|
||||
| Namespace | `coulomb-social` Active |
|
||||
| Deployment | 1/1 Ready, image `:7067145` |
|
||||
| Service | ClusterIP :80 |
|
||||
| Ingress | `coulomb.social` → Traefik, cert-manager annotation |
|
||||
| Env secret | `coulomb-social-env` (`SECRET_KEY`, `DATABASE_URL`, `USER_ENGINE_PROXY_SECRET`) |
|
||||
| OIDC | enabled; issuer `https://kc.coulomb.social`; public client |
|
||||
| Public DNS | **still Cloudflare / Bubble** |
|
||||
| TLS secret | **pending** HTTP-01 until DNS points at the cluster |
|
||||
|
||||
In-cluster smoke (with `Host: coulomb.social`): `/healthz` ok, landing 200,
|
||||
`/auth/login/` → KeyCape authorize. Full browser session needs cutover.
|
||||
|
||||
## Runtime secrets (names only)
|
||||
|
||||
K8s Secret `coulomb-social-env` in namespace `coulomb-social` (chart `envFrom`):
|
||||
|
|
@ -26,24 +45,82 @@ make coulomb-social-env-secret
|
|||
./scripts/create-env-secret.sh
|
||||
```
|
||||
|
||||
Script: `railiance-apps/tools/create-coulomb-social-env-secret.sh`
|
||||
OIDC is a **public** client — no client secret.
|
||||
|
||||
Non-secret env (OIDC, ALLOWED_HOSTS, user-engine URL) lives in Helm values.
|
||||
|
||||
## Health
|
||||
|
||||
- `GET /healthz` → `{"status":"ok"}`
|
||||
- `GET /healthz` → `{"status":"ok","service":"coulomb-social"}`
|
||||
- Probes use `Host: coulomb.social` (`probes.hostHeader`)
|
||||
|
||||
## Build
|
||||
## Build / deploy
|
||||
|
||||
```bash
|
||||
SHA=$(git rev-parse --short HEAD)
|
||||
docker build -t forgejo.coulomb.social/coulomb/coulomb-social:$SHA .
|
||||
# push, then:
|
||||
# COULOMB_SOCIAL_IMAGE_TAG=$SHA make coulomb-social-deploy # in railiance-apps
|
||||
```
|
||||
|
||||
Runtime env (no secrets in image): `SECRET_KEY`, `DATABASE_URL`,
|
||||
`OIDC_*`, `USER_ENGINE_*`, `DEFAULT_TENANT_ID`, `ALLOWED_HOSTS`.
|
||||
## Cutover checklist (DNS → live Railiance)
|
||||
|
||||
## Status
|
||||
**Goal:** `https://coulomb.social` serves this app (identity shell), not Bubble.
|
||||
|
||||
- Dockerfile present (gunicorn, non-root, `/healthz` check).
|
||||
- railiance-apps Helm values / cluster Service **not** yet landed.
|
||||
- Local `make run` + `make test` remain the default verification path.
|
||||
### Preconditions
|
||||
|
||||
1. [x] Image + Helm release healthy
|
||||
2. [x] KeyCape client `coulomb-social` with prod redirect `https://coulomb.social/auth/callback/`
|
||||
3. [x] In-cluster OIDC start redirect works
|
||||
4. [ ] Local browser OIDC + MFA completed once (proves IdP + user-engine path)
|
||||
5. [ ] Operator accepts brief public outage / Bubble freeze during DNS switch
|
||||
6. [ ] Optional: export Bubble data if still needed (CSOC-WP-0001) — not required for identity-only cutover
|
||||
|
||||
### DNS switch
|
||||
|
||||
1. In Cloudflare (or DNS host): lower TTL on `coulomb.social` if possible (e.g. 300s) ahead of time.
|
||||
2. Point apex (and `www` if used) **A** to **`92.205.62.239`** (railiance01 ingress).
|
||||
- Prefer DNS-only (grey cloud) first so LE HTTP-01 and Traefik see real traffic; re-enable proxy only if you understand TLS termination path.
|
||||
3. Wait for propagation: `dig +short coulomb.social A` → `92.205.62.239`.
|
||||
4. cert-manager should finish HTTP-01; confirm:
|
||||
|
||||
```bash
|
||||
kubectl -n coulomb-social get certificate coulomb-social-tls
|
||||
# READY=True
|
||||
```
|
||||
|
||||
5. Smoke public HTTPS:
|
||||
|
||||
```bash
|
||||
curl -fsS https://coulomb.social/healthz
|
||||
curl -sI https://coulomb.social/auth/login/ | grep -i location
|
||||
# Location: https://kc.coulomb.social/authorize?...
|
||||
```
|
||||
|
||||
6. **Browser:** Sign in → Authelia MFA → land on `/app/` with principal.
|
||||
7. Sign out; confirm `/app/` requires login.
|
||||
8. Second login: same member row / user-engine user_id.
|
||||
|
||||
### Rollback
|
||||
|
||||
- Point DNS A (or Cloudflare origin) back to Bubble/Cloudflare target.
|
||||
- Cluster release can stay; it only receives traffic when DNS aims at the node.
|
||||
|
||||
### After cutover residuals
|
||||
|
||||
| Item | Note |
|
||||
|------|------|
|
||||
| Bubble freeze | Stop editing live Bubble as source of truth |
|
||||
| Content/UI | CSOC-WP-0001 + design extract — not required for identity shell |
|
||||
| flex-auth Service | leave `FLEX_AUTH_BASE_URL` unset (local vocabulary) until PDP exists |
|
||||
| apps-pg backup/HA | business-app contract |
|
||||
| OpenBao CCR | replace kubectl-sourced env secret when ready |
|
||||
| Image CI | Forgejo/Gitea pipeline for SHA tags |
|
||||
|
||||
## Local verification (no cutover)
|
||||
|
||||
```bash
|
||||
make test
|
||||
make run # offline identity
|
||||
# or OIDC vars from docs/identity/oidc-client.md
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,23 +1,101 @@
|
|||
# Identity smoke checklist
|
||||
|
||||
## Offline (dev claims)
|
||||
Evidence updated: **2026-08-09**.
|
||||
|
||||
1. `uv sync && uv run manage.py migrate && uv run manage.py runserver 8008`
|
||||
2. Open `/` → **Sign in**
|
||||
3. Dev form → submit subject `smoke-1`
|
||||
4. Land on `/app/` with display name and subject shown
|
||||
5. **Sign out** → back to landing; `/app/` redirects to login
|
||||
6. Sign in again with same subject → single `Member` row (idempotent)
|
||||
## Offline (dev claims) — **passed**
|
||||
|
||||
## With platform OIDC
|
||||
```bash
|
||||
uv sync && uv run manage.py migrate && make run
|
||||
# OIDC_ENABLED=false (default), DEBUG=true
|
||||
```
|
||||
|
||||
1. Set `OIDC_ENABLED=true` and issuer/client/redirect env vars
|
||||
2. Register redirect URI at the issuer (no wildcards)
|
||||
3. `/auth/login/` redirects to IdP; callback creates/links Member
|
||||
4. Logout clears app session
|
||||
| Step | Result |
|
||||
|------|--------|
|
||||
| Open `/` → **Sign in** | → `/auth/dev-login/` |
|
||||
| Dev form subject `smoke-1` | 302 → `/app/` |
|
||||
| Shell shows display name + subject | OK |
|
||||
| **Sign out** | session cleared |
|
||||
| `/app/` after logout | 302 → login |
|
||||
| Second login same subject | single `Member` row (idempotent) |
|
||||
| `make test` | **15 passed** |
|
||||
|
||||
Automated POST probe (2026-08-09):
|
||||
|
||||
```text
|
||||
dev_login_post → /app/ 200 with subject smoke-1
|
||||
logout → app 302 to /auth/login/?next=/app/
|
||||
```
|
||||
|
||||
## Cluster in-cluster (port-forward) — **passed (start of OIDC)**
|
||||
|
||||
DNS for `coulomb.social` still points at Cloudflare/Bubble; TLS ACME is
|
||||
blocked until cutover. Smoke via:
|
||||
|
||||
```bash
|
||||
kubectl -n coulomb-social port-forward svc/coulomb-social 18088:80
|
||||
curl -H 'Host: coulomb.social' http://127.0.0.1:18088/healthz
|
||||
# {"status": "ok", "service": "coulomb-social"}
|
||||
```
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Image | `forgejo.coulomb.social/coulomb/coulomb-social:7067145` |
|
||||
| `OIDC_ENABLED` | `true` (values) |
|
||||
| `GET /healthz` + Host | 200 JSON ok |
|
||||
| `GET /` + Host | 200 landing shell |
|
||||
| `GET /auth/login/` + Host | **302** → `https://kc.coulomb.social/authorize?...` with `client_id=coulomb-social`, `redirect_uri=https://coulomb.social/auth/callback/`, PKCE S256 |
|
||||
| Session cookie | `HttpOnly; Secure; SameSite=Lax` (prod settings) |
|
||||
|
||||
Full browser login against the **cluster** redirect URI requires public HTTPS
|
||||
on `coulomb.social` (Secure cookie + callback host). Use **local OIDC** below
|
||||
before DNS cutover, or complete browser MFA after cutover.
|
||||
|
||||
## Platform OIDC (local redirect) — **ready for human MFA**
|
||||
|
||||
Client registration and authorize handoff verified; **human Authelia + MFA**
|
||||
is the remaining interactive step.
|
||||
|
||||
```bash
|
||||
export OIDC_ENABLED=true
|
||||
export OIDC_ISSUER=https://kc.coulomb.social
|
||||
export OIDC_CLIENT_ID=coulomb-social
|
||||
export OIDC_REDIRECT_URI=http://127.0.0.1:8008/auth/callback/
|
||||
export OIDC_SCOPES="openid profile email groups"
|
||||
# optional live user-engine (else stub):
|
||||
# export USER_ENGINE_BASE_URL=https://users.92-205-62-239.nip.io
|
||||
# export USER_ENGINE_PROXY_SECRET="$(kubectl -n user-engine get secret user-engine-runtime \
|
||||
# -o jsonpath='{.data.proxy-secret}' | base64 -d)"
|
||||
make run
|
||||
```
|
||||
|
||||
| Step | Expected |
|
||||
|------|----------|
|
||||
| Open http://127.0.0.1:8008/ → Sign in | redirect KeyCape → Authelia |
|
||||
| Complete MFA | callback → `/app/` with subject / display name |
|
||||
| Sign out | landing; `/app/` requires login |
|
||||
| Second login | same Member / user_engine user_id |
|
||||
|
||||
Authorize probe (no browser) 2026-08-09:
|
||||
|
||||
| redirect_uri | KeyCape |
|
||||
|--------------|---------|
|
||||
| `http://127.0.0.1:8008/auth/callback/` | **302** → Authelia OIDC |
|
||||
| `https://coulomb.social/auth/callback/` | **302** → Authelia OIDC |
|
||||
|
||||
Unregistered redirects still fail with `invalid_profile_usage` (T03).
|
||||
|
||||
## Automated
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
||||
|
||||
## Blockers for production hostname smoke
|
||||
|
||||
| Blocker | Detail |
|
||||
|---------|--------|
|
||||
| Public DNS | `coulomb.social` → Cloudflare `104.*` (Bubble), not `92.205.62.239` |
|
||||
| TLS cert | `certificate/coulomb-social-tls` **not Ready**; HTTP-01 challenge gets **404** from public edge (LE never reaches cluster solver) |
|
||||
| Secure cookies | prod `SESSION_COOKIE_SECURE=True` — need HTTPS after cutover |
|
||||
|
||||
See cutover steps in `docs/deploy.md`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue