diff --git a/README.md b/README.md index e50010a..3635bc7 100644 --- a/README.md +++ b/README.md @@ -297,33 +297,192 @@ Detailed setup docs, cluster procedures, and host-specific notes should live in --- +## prole.org deployment + +This repository is the **prole.org fork** of the upstream knoe-db platform. It runs a production k3s cluster on a three-node ARM64 LAN (myrddin / gandalf / merlin) with Samba AD providing Kerberos identity for single sign-on across all platform services. + +### Live services + +| Service | URL | Auth | +|---|---|---| +| Supabase Studio | `https://db.prole.org` | SPNEGO → OIDC → Studio | +| Gitea | `https://git.prole.org` | SPNEGO (auto) or Gitea login | +| PostgreSQL | `pg.prole.org:5432` | mTLS + CNPG cert | +| SSH (Gitea) | `git.prole.org:3022` | SSH key | + +### Cluster nodes + +| Host | Role | IP | +|---|---|---| +| `myrddin.prole.org` | k3s server, Samba AD DC, container registry | 10.0.0.3 | +| `gandalf.prole.org` | k3s agent | 10.0.0.5 | +| `merlin.prole.org` | k3s agent | 10.0.0.6 | + +Kubectl context: `prole-service-cluster` (kubeconfig at `knoe-k3s.kubeconfig`). + +### Key namespaces + +| Namespace | Contents | +|---|---| +| `knoe-system` | knoe-auth, Kong API gateway, KDC, Redis, Traefik | +| `gitea` | Gitea, gitea-spnego-proxy | +| `knoe-db` | CloudNativePG cluster | +| `supabase` | Supabase Studio, Kong (supabase), oauth2-proxy | + +--- + +## Identity & SSO + +All platform services use a unified Kerberos SSO stack. The flow from browser to service is: + +``` +Browser (Chrome, Safari, curl --negotiate) + │ kinit-obtained TGT from PROLE.ORG KDC (myrddin.prole.org) + ▼ +Traefik (TLS termination, *.prole.org wildcard cert via ACME) + │ + ▼ +Kong API gateway (knoe-system/knoe-svc-kong) + │ routes by Host header + ├── db.prole.org ──► oauth2-proxy ──► knoe-auth (OIDC) ──► Supabase Studio + └── git.prole.org ──► gitea-spnego-proxy (port 4000) ──► Gitea (port 3000) +``` + +### Kerberos realm + +- **Realm:** `PROLE.ORG` +- **KDC / AD DC:** `myrddin.prole.org` (Samba 4, `10.0.0.3`) +- **Cross-realm trust:** `PROLE.ORG ↔ KNOE.LOCAL` (in-cluster MIT KDC for knoe-auth internal use) +- **Encryption:** AES256 + AES128 only (`msDS-SupportedEncryptionTypes=24`); RC4 disabled on all service accounts + +### knoe-auth (OIDC provider — `api.prole.org/auth`) + +knoe-auth is a Spring Boot 3 / JDK 21 OIDC authorization server that validates Kerberos SPNEGO tokens and issues OIDC tokens for downstream services. + +**Key implementation details:** + +| Detail | Value | +|---|---| +| Deployment | `knoe-system/knoe-auth` | +| SPNEGO endpoint | `https://api.prole.org/auth/spnego` | +| Keytab secret | `knoe-system/knoe-auth-keytab` (`HTTP/api.prole.org@PROLE.ORG`, AES-only) | +| JDK Subject API | `Subject.callAs()` — **not** `Subject.doAs()` (removed in JDK 21) | +| RC4 | Hard-removed in JDK 21 JGSS — keytab and AD account must be AES-only | +| krb5.conf | Mounted via ConfigMap; `permitted_enctypes = aes256 aes128` (cannot re-enable RC4 here) | + +Keytab provisioning (`etc/init_knoe_users.sh`): +```bash +# On myrddin — set AES-only, reset password, export and rekey keytab +sudo ldbmodify -H /var/lib/samba/private/sam.ldb <AuthServerAllowlist +*.prole.org +AuthNegotiateDelegateAllowlist +*.prole.org +``` + +Deploy to a Mac workstation: +```bash +make workstation +# or: ansible-playbook infrastructure/playbooks/workstation_kerberos.yml --ask-become-pass +``` + +### git.prole.org SPNEGO (Gitea) + +``` +Browser/curl → Kong → gitea-spnego-proxy (:4000) → Gitea (:3000) + │ + ├─ No Authorization header → 401 + WWW-Authenticate: Negotiate + ├─ Authorization: Negotiate → SPNEGO validate → X-WEBAUTH-USER → Gitea auto-login + └─ Authorization: Basic/token → pass-through → Gitea auth +``` + +**Component:** `gitea/spnego-proxy/` — Go binary using `gokrb5/v8`, built for `linux/arm64`. + +| Detail | Value | +|---|---| +| Image | `myrddin.prole.org:5000/gitea-spnego-proxy:latest` | +| Keytab secret | `gitea/gitea-krb5-keytab` (`HTTP/git.prole.org@PROLE.ORG`, AES-only, KVNO 4) | +| AD account | `CN=gitea-http,CN=Users,DC=prole,DC=org` (`msDS-SupportedEncryptionTypes=24`) | +| Rebuild | Build on myrddin (native arm64); `docker build` then `docker push localhost:5000/...` | + +Keytab rotation: +```bash +ansible-playbook infrastructure/playbooks/gitea_spnego_keytab.yml -e force_keytab_reset=true +``` + +Manual rebuild (if source changed): +```bash +# Transfer source and build on myrddin (all nodes are arm64) +tar -czf /tmp/src.tar.gz gitea/spnego-proxy/ && scp /tmp/src.tar.gz myrddin:/tmp/ +ssh myrddin "mkdir -p /tmp/spnego-build && tar -xzf /tmp/src.tar.gz -C /tmp/spnego-build && \ + sudo docker build -t localhost:5000/gitea-spnego-proxy:latest /tmp/spnego-build/gitea/spnego-proxy/ && \ + sudo docker push localhost:5000/gitea-spnego-proxy:latest" +kubectl --context=prole-service-cluster -n gitea rollout restart deployment/gitea-spnego-proxy +``` + +Smoke test: +```bash +curl -s -o /dev/null -w "%{http_code}\n" https://git.prole.org/ # → 401 (challenge) +curl -s -o /dev/null -w "%{http_code}\n" --negotiate -u : https://git.prole.org/ # → 200 (authed) +``` + +--- + ## Status -Knoe is an actively evolving platform stack aimed at practical self-hosted, edge, and cloud operation. +**As of 2026-05-28** the following work has shipped on the prole.org fork: -**As of 2026-05-23** the following work has shipped: -- `fix(cfg)` — `_validate_cfg_values` prevents MagicMock reprs from leaking into `conf/*.cfg` (`ef20c8a`) -- `feat(env)` — `gke_` kubecontext prefix auto-detected as `prod`; `status.py` context helpers (`da0fd2c`) -- `refactor(mock_val)` — `prole_*` shell lib and cfg tooling renamed to `knoe_*` namespace (`11064cb`) -- `feat(mock_val)` — init scripts rewritten; 10+ new service init scripts added (`3f96f66`) -- `feat(mock_val)` — diagnostics, utilities, certs, and operational scripts added (`3943d1b`) -- `feat(scripts)` — upstream knoe-db sync script + procedure doc (`decb9a5`) -- `feat(infrastructure)` — Pi-hole DNS flush Ansible playbook (`3ada16c`) -- `docs` — shipped briefs moved to `docs/completed/`; `conf/service/knoe.cfg` added (`73dce03`) -- `feat(mock_val)` — `common_core_lib` mode-aware config path helper (`d806905`) -- `fix(conf)` — MagicMock contamination removed from `conf/k3d.cfg` and `conf/k3s.cfg` (`568f03b`) -- `docs(branches)` — upstream knoe-db/20260523 review doc, branch index, and Junie integration brief (`0e822ea`) -- `feat(pg-knoe-auth)` — upstream PostgreSQL JWT auth extension imported; compiled in `knoe-db` image (`57886f9`) -- `docs(branches)` — Task 1 marked complete in branch index (`e5cf9b1`) +**Identity / SSO (May 2026)** +- `feat(gitea)` — SPNEGO Kerberos SSO for `git.prole.org`; proxy issues `WWW-Authenticate: Negotiate` challenge; `gitea_spnego_keytab.yml` Ansible playbook for full provisioning lifecycle (`5077e13`) +- `fix(ansible)` — workstation install script + `make workstation` target for Chrome SPNEGO policy on personal Macs (`b245593`) +- `fix(spnego)` — `Subject.callAs()`, AES-only keytab, and `krb5.conf` sync for JDK 21 knoe-auth (`c1d2a91`) +- `feat(oidc)` — knoe-auth routing through Kong; Flyway schema baseline for clean OIDC DB (`9523045`) +- `feat(prole)` — knoe-auth bootstrap on k3s; tenant onboarding; cluster stabilisation (`cf33342`) -Working tree is clean. Upstream sync tooling is operational; `upstream/knoe-db/20260523` review is in progress (Task 1 ✅). +**Infrastructure (earlier)** +- `fix(cfg)` — `_validate_cfg_values` prevents MagicMock reprs from leaking into `conf/*.cfg` +- `feat(env)` — `gke_` kubecontext prefix auto-detected as `prod`; `status.py` context helpers +- `refactor(mock_val)` — `prole_*` shell lib and cfg tooling renamed to `knoe_*` namespace +- `feat(mock_val)` — init scripts rewritten; 10+ new service init scripts added +- `feat(scripts)` — upstream knoe-db sync script + procedure doc +- `feat(pg-knoe-auth)` — upstream PostgreSQL JWT auth extension imported; compiled in `knoe-db` image -Expect the architecture to continue being refined toward: -- cleaner bootstrapping -- better shard isolation -- smoother rejoin/reset behavior for cluster nodes -- clearer service boundaries -- improved onboarding and operations documentation +Working tree is clean. Browser SPNEGO SSO is live on `db.prole.org` and `git.prole.org`. --- @@ -347,6 +506,21 @@ Upstream changes are pulled into a dated review branch (`upstream/knoe-db/YYYYMM See [`docs/upstream-knoe-db-sync.md`](docs/upstream-knoe-db-sync.md) for the full review-and-merge procedure. +### Fork-specific files + +Files added or substantially modified in the prole.org fork (not present or not relevant upstream): + +| Path | Purpose | +|---|---| +| `infrastructure/` | Ansible roles, playbooks, and inventory for the prole.org cluster | +| `infrastructure/playbooks/gitea_spnego_keytab.yml` | Gitea SPNEGO keytab provisioning | +| `infrastructure/playbooks/workstation_kerberos.yml` | Chrome SPNEGO policy + krb5.conf for macOS workstations | +| `infrastructure/playbooks/kerberos_trust_setup.yml` | PROLE.ORG ↔ KNOE.LOCAL cross-realm trust | +| `infrastructure/bin/install_workstation.sh` | Wrapper for workstation Ansible (adds `--ask-become-pass`) | +| `gitea/spnego-proxy/` | Go SPNEGO reverse proxy for `git.prole.org` | +| `deploy/opentofu/k3s/manifests/knoe/gitea-spnego-proxy.yaml` | k8s deployment for the SPNEGO proxy | +| `conf/k3s.cfg` | prole.org k3s cluster configuration | + --- ## License