activity-core/docs/ops-sso-access.md
tegwick fee89c4ea1
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Finish ACTIVITY-WP-0025 after NK-WP-0021 group allowlist.
Close T06: LLDAP activity-core-operators and Authelia domain rules are live
in net-kingdom. Mark the workplan finished, update G10/runbook/SSO design
with membership pointers, and clear residual handoff notes.
2026-07-22 17:47:57 +02:00

107 lines
3.4 KiB
Markdown

# Ops console + Temporal UI — SSO access design (ACTIVITY-WP-0025)
## Audience
Founders / platform operators who already have Authelia accounts under
`coulomb.social` SSO (LLDAP → Authelia → KeyCape MFA path).
## Hostnames (locked)
| Host | Backend | Purpose |
| --- | --- | --- |
| `activity.coulomb.social` | `actcore-api:8010` | Ops console `/ops/ui`, JSON `/ops/*`, existing API |
| `temporal.coulomb.social` | `actcore-temporal-ui:8080` | Temporal Web UI (clean short name) |
Both resolve to the railiance01 Traefik LB (`92.205.62.239`) — same pattern as
`forgejo.coulomb.social`. **DNS A records + Let's Encrypt certs are live**
(verified 2026-07-22); Certificate objects `actcore-ops-tls` /
`actcore-temporal-ui-tls` are Ready.
## Auth edge (fleet pattern)
| Component | Location |
| --- | --- |
| Ingress controller | Traefik (`ingressClassName: traefik`) |
| TLS | cert-manager `ClusterIssuer/letsencrypt-prod` |
| Login portal | Authelia `https://auth.coulomb.social` |
| IAM / MFA | KeyCape `https://kc.coulomb.social` (post-password) |
| Forward auth | Traefik Middleware `forwardAuth` → Authelia `/api/verify` |
**Not** oauth2-proxy — the live railiance01 stack already runs Authelia in
namespace `sso`. Reuse it.
### Middleware
`Middleware/authelia-forwardauth` in `activity-core` calls:
```text
http://authelia.sso.svc.cluster.local:9091/api/verify?rd=https://auth.coulomb.social/
```
Response headers trusted into the app:
- `Remote-User`
- `Remote-Groups`
- `Remote-Name`
- `Remote-Email`
### Access control policy
Authelia `default_policy: one_factor` for the fleet; **restricted hosts** use
domain rules (NK-WP-0021, finished):
| Host | Rule |
| --- | --- |
| `activity.coulomb.social` | allow `group:activity-core-operators`, else deny |
| `temporal.coulomb.social` | allow `group:activity-core-operators`, else deny |
Membership: `net-kingdom/sso-mfa/k8s/lldap/OPERATOR-GROUPS.md`
(`./manage-group-members.sh add <uid> activity-core-operators`).
Intakes NK-IN-0001/0002 closed → promoted to **NK-WP-0021**.
## Mutation identity
Priority for ops mutations (`POST /ops/...`):
1. SSO principal from Authelia headers (preferred)
2. Shared `ACTIVITY_CORE_OPERATOR_TOKEN` (break-glass)
3. Else 401/403 fail-closed
## DNS (operator)
Expected records (live as of 2026-07-22):
```text
activity.coulomb.social A 92.205.62.239
temporal.coulomb.social A 92.205.62.239
```
**Important:** do **not** leave a stale **AAAA** (IPv6) record for either host
pointing at parking (e.g. IONOS `2001:8d8:100f:f000::200` / `217.160.0.253`).
Cluster resolvers prefer AAAA; cert-manager HTTP-01 self-check then hits the
wrong host. Either remove AAAA or set it to the railiance01 public IPv6.
## Break-glass
Port-forward remains documented in `docs/runbook.md` if Ingress/SSO is down.
## Manifests
- `k8s/railiance/30-authelia-middleware.yaml`
- `k8s/railiance/31-ingress-ops-sso.yaml`
- `k8s/railiance/32-ingress-temporal-sso.yaml`
Apply after DNS:
```bash
export KUBECONFIG=~/.kube/config-hosteurope
kubectl apply -f k8s/railiance/30-authelia-middleware.yaml
kubectl apply -f k8s/railiance/31-ingress-ops-sso.yaml
kubectl apply -f k8s/railiance/32-ingress-temporal-sso.yaml
# set public Temporal URL on API after cert Ready:
kubectl -n activity-core set env deploy/actcore-api \
ACTIVITY_CORE_TEMPORAL_UI_URL=https://temporal.coulomb.social
kubectl -n activity-core set env deploy/actcore-temporal-ui \
TEMPORAL_CORS_ORIGINS=https://temporal.coulomb.social
```