Sign-in by customer: realm petrolyst, row rules, guest role (PD-21)

Keycloak import for realm petrolyst: two clients, petrolyst with MFA for
Superset and Traefik, petrolyst-app password only. It lists only
app.petrolyst.com and traefik.petrolyst.com, and no customer names, as this
repository is public. public.v_operator shows each customer's group. Dashboards
overview and site, role Petrolyst Guest, filtered by row. Superset refuses a
user with no mapped role. The realm travels with the release: each release's
compose files name their realm and secret file, and a rollback needs only its
target's secret. Not deployed.

Checks earlier on this content: tests/run.sh 109 of 109 and read-only, dashboards
import twice, column drift 0, compose config on old and new trees, the secret
check on a scratch folder, a rehearsal on a throwaway Keycloak 26.4. Never a real
deploy or rollback; shellcheck not installed today, clean when last run. Codex
inspected once; its fixes are not re-inspected, on the owner's word.

Bands: persistence, Superset. Rules: 1, 2, 3, 6, 14.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nasim SadatandClaude Opus 5.5 committed 2026-10-30 18:31:14 +01:00
1 parent ab553526f6
commit 78a498f1ce
20 files changed
+279 -78

No files matched your search

+6 -6
View File
@@ -15,7 +15,7 @@ and where it runs lives in `stacks/`, `traefik/`, `deploy/` and `host/`.
|---|---|---|
| `superset_config.py` | Keycloak sign-in, role mapping, proxy and cookie settings, Redis caches, theme and chart palettes | `/app/pythonpath/` |
| `petrolyst_security.py` | `PetrolystSecurityManager`: user info and roles from the Keycloak ID token, `/login/` straight to Keycloak, `/logout/` through Keycloak | `/app/pythonpath/` |
| `roles/` | `atoma_guest.py`: the role "ATOMA Guest" for the Petrolyst app's embedded dashboards, with exactly its permissions; run by hand (see "Embedding") | `/app/petrolyst-roles/` |
| `roles/` | `petrolyst_guest.py`: the role "Petrolyst Guest" for the Petrolyst app's embedded dashboards, with exactly its permissions; run by hand (see "Embedding") | `/app/petrolyst-roles/` |
| `assets/branding/` | logos (full colour and white): the wordmark alone for the navbar, and the stacked logo; favicons, app icons; ATOMA's logo, which the Petrolyst app shows in its map's corner (the server reads this file itself: `PETROLYST_OPERATOR_LOGO_FILE`) | `/app/superset/static/assets/branding/`, served at `/static/assets/branding/…` |
| `patches/` | runtime patches, `fix_*.py` with `--verify` (see its README); none at present | `/app/patches/petrolyst/`, applied during the build |
| `dashboards/` | exported dashboards and import scripts (see its README) | not in the image |
@@ -35,13 +35,13 @@ value.
|---|---|
| `superset_secret_key` | Flask `SECRET_KEY` |
| `superset_db_password` | password of user `superset` on the metadata database |
| `keycloak_petrolyst_client_secret` | client secret of Keycloak client `petrolyst` |
| `keycloak_petrolyst_client_secret` | client secret of Keycloak client `petrolyst`, realm `petrolyst`; on the server in `shared/keycloak_petrolyst_realm_client_secret` |
On the server they come from `/opt/petrolyst/secrets/` (see the deployment README).
## Sign-in and roles
- Provider: Keycloak realm `thedigitalbridge` at `iam.thedigitalbridge.io`, client `petrolyst`,
- Provider: Keycloak realm `petrolyst` at `iam.thedigitalbridge.io`, client `petrolyst`,
authorization code flow with PKCE S256. The realm URL can be overridden with
`KEYCLOAK_REALM_URL`.
- Roles come from the client roles of `petrolyst`, which a protocol mapper puts into the claim
@@ -68,14 +68,14 @@ stack** (`.local/fmdb-scratch`); `superset_config.py` here leaves it off, and lo
guest secret.
- The scratch stack's `superset_config_local.py` turns on `EMBEDDED_SUPERSET`, names the guest
role `GUEST_ROLE_NAME = "ATOMA Guest"`, reads the signing secret with
role `GUEST_ROLE_NAME = "Petrolyst Guest"`, reads the signing secret with
`_read_secret("superset_guest_token_secret")` and expects the audience `petrolyst-app`. The
Petrolyst server signs the guest passes itself with the same secret.
- `roles/atoma_guest.py` gives "ATOMA Guest" exactly what a dashboard needs to be read. Which
- `roles/petrolyst_guest.py` gives "Petrolyst Guest" exactly what a dashboard needs to be read. Which
dashboard a guest sees comes from the pass, not the role. It is not in `init.sh`; run it once,
and again whenever its permissions change:
docker exec <superset> /app/.venv/bin/python /app/petrolyst-roles/atoma_guest.py
docker exec <superset> /app/.venv/bin/python /app/petrolyst-roles/petrolyst_guest.py
- The app's dashboards and their embedding ids: `dashboards/README.md`.