9.0 KiB
Shared GLAuth Standardization — Design
Status: IMPLEMENTED + verified 2026-06-04 (all 18 plan tasks). See
shared-glauth-on-35memory. Plan:2026-06-04-shared-glauth-standardization.md. Scope: dev/test only. Production stays on real corporate AD (out of scope).
Goal
Consolidate the three sister projects (OtOpcUa, MxAccessGateway, ScadaBridge) onto one shared
GLAuth dev directory running on the shared Docker host 10.100.0.35:3893, replacing the
three separate LDAP setups in use today. This is the natural endpoint of the Auth-component
normalization: all three already use the shared ZB.MOM.WW.Auth.Ldap library (search-then-bind)
and already default to the same base DN dc=zb,dc=local.
Decisions (locked during brainstorming)
| Decision | Choice |
|---|---|
| Environments | Dev/test only (prod → real AD, untouched) |
| Consolidation depth | Full — every dev instance points at 35 |
| Transport | Plaintext (Transport=None, AllowInsecure=true) — trusted lab subnet |
| Source of truth | scadaproj/infra/glauth/ (app-neutral, next to the other shared ZB.MOM.WW.* components) — Approach A |
Architecture
scadaproj/infra/glauth/ ← single source of truth (git)
├── config.toml (merged dc=zb,dc=local directory)
├── docker-compose.yml (one `glauth` service, :3893)
└── README.md
│ deploy on 10.100.0.35: docker compose up -d
▼
GLAuth @ 10.100.0.35:3893 · datastore=config · baseDN dc=zb,dc=local · ldaps=false
▲ ▲
plaintext bind │ (None + AllowInsecure) │
┌──────────────┴───────────┐ ┌─────────┴─────────────────────┐
Mac / OrbStack │ windev (10.100.0.48)
• ScadaBridge :9000/:9100 │ • MxGateway (MxAccessGw svc)
• OtOpcUa docker-dev │ • OtOpcUa (OtOpcUa svc)
(un-stubbed)
- One
glauthcontainer on10.100.0.35:3893,datastore=config,baseDN=dc=zb,dc=local, ldaps disabled. - Every dev consumer:
Server=10.100.0.35,Port=3893,Transport=None,AllowInsecure=true,SearchBase=dc=zb,dc=local. - Retired: the
scadabridge-ldapcontainer (ScadaBridgeinfra/docker-compose.yml) and the windev-local glauth (C:\publish\glauth). - Consequences: windev gains a runtime dependency on 35 for new logins (existing cookie sessions unaffected); deploying to 35 needs working access (see Prerequisites).
The merged directory
One dc=zb,dc=local directory; group families partitioned into non-overlapping gid ranges (today
both existing GLAuth files reuse 5501–5505 — the collision to fix). Each app maps only its own family
and ignores the rest, so the families coexist with zero conflict.
Groups
| Family | Used by | Groups (gidnumber) |
|---|---|---|
SCADA-* (55xx) |
ScadaBridge roles (DB-mapped) | Admins 5501, Designers 5502, Deploy-All 5503, Deploy-SiteA 5504, Viewers 5505 |
| OPC-perm (560x) | OtOpcUa + MxGateway OPC-UA write model | ReadOnly 5601, WriteOperate 5602, WriteTune 5603, WriteConfigure 5604, AlarmAck 5605 |
Gw* (561x) |
MxGateway dashboard (config-mapped) | GwAdmin 5610, GwReader 5611 |
OtOpcUa-* (57xx) |
OtOpcUa AdminUI (DB-mapped) | Admins 5701, Designers 5702, Viewers 5703 |
SCADA-* keeps its canonical 55xx numbers (already deployed). The OPC/Gw groups move off the old
5501–5505/5510 into 56xx to clear the clash.
Users (all password password; uid ranges 50xx ScadaBridge / 51xx MxGateway / 52xx OtOpcUa)
serviceaccount(5999,cn=serviceaccount,dc=zb,dc=local,search *capability) — the single bind account every app uses. Passwordserviceaccount123. ScadaBridge moves to it fromcn=admin/password.multi-role(5005) — member of every group → all roles in all three apps (canonical cross-app QA login).admin(5001) —SCADA-Admins+GwAdmin+OtOpcUa-Admins→ Administrator everywhere.- Per-role testers:
designer/deployer/site-deployer(ScadaBridge);gwreader(MxGateway Viewer);otdesigner/otviewer(OtOpcUa);readonly/writeop/writetune/writeconfig/alarmack(OPC perms).
Per-app config changes
Each consumer changes only its LDAP Server (+ a few keys). Shared service account
cn=serviceaccount,dc=zb,dc=local / serviceaccount123.
- ScadaBridge (
docker/+docker-env2/, central-node-a & -bappsettings.Central.json):Ldap:Serverscadabridge-ldap→10.100.0.35;ServiceAccountDncn=admin→cn=serviceaccount,ServiceAccountPassword→serviceaccount123. Rest unchanged (SCADA-*DB mappings already seeded). Retire theldapservice ininfra/docker-compose.yml; sequenced-recreate central nodes. - OtOpcUa docker-dev (
docker-dev/docker-compose.yml, all host containers) — the un-stub: dropSecurity__Ldap__DevStubMode=true; addServer=10.100.0.35,Port=3893,Transport=None,AllowInsecure=true,SearchBase=dc=zb,dc=local,ServiceAccountDn=cn=serviceaccount,…,ServiceAccountPassword=serviceaccount123. Seed OtOpcUa DB mappingsOtOpcUa-Admins→Administrator,OtOpcUa-Designers→Designer,OtOpcUa-Viewers→Viewer(system-wide). - MxGateway (windev
C:\publish\mxaccessgw\Server\appsettings.json):Ldap:Serverlocalhost→10.100.0.35;SearchBasedc=lmxopcua→dc=zb,dc=local;ServiceAccountDn→…dc=zb,dc=local.Transport=None/AllowInsecure=truealready migrated;GroupToRole(GwAdmin/GwReader) unchanged. RestartMxAccessGw(+ dependentOtOpcUasvc). - OtOpcUa (windev service): locate its deployed overlay; repoint
Server→10.100.0.35,SearchBase→dc=zb,dc=local, service account, and switch dev transportLdaps→None+AllowInsecure. - Then stop/disable the windev-local
glauthservice.
Rollout & rollback
Incremental; the old glauths stay up until the very end, so every step is reversible by pointing
Server back.
- Stand up the shared glauth on 35 → verify via
ldapsearch(bindserviceaccount;multi-rolememberOfspans all families). Nothing repointed yet. - Prove reachability from an OrbStack container to
10.100.0.35:3893(the linchpin) before any app edit. - ScadaBridge
:9000→ recreate → browser-verifymulti-role= 4 roles. Then:9100. - OtOpcUa docker-dev → un-stub + repoint + seed → recreate → verify.
- windev MxGateway (backup appsettings) → restart → verify. Then windev OtOpcUa overlay.
- Only once all green: stop/disable
scadabridge-ldap+ the windev-local glauth.
Rollback per consumer: revert the one-line Server change (git revert on the Mac; .bak restore on
windev) and recreate/restart. Remove the shared glauth = docker compose down on 35.
Testing & verification
- LDAP layer:
ldapsearchbindserviceaccount; confirm each test user +multi-role'smemberOfacross all four families; bind each user to confirmpassword. - Per-app browser (macbook Chrome): ScadaBridge
:9000/:9100multi-role→ 4 roles (via/auth/token); OtOpcUa:9200→ seeded roles; MxGateway10.100.0.48:5130→ Administrator; windev OtOpcUa → AdminUI. - Role-gating spot-checks:
gwreader→MxGateway Viewer-only;designer→ScadaBridge design-only;otviewer→OtOpcUa read-only. - Negative: wrong password rejected everywhere; a user in no family of an app → denied there.
Prerequisites & open items (resolve in the plan)
- Access to
10.100.0.35— SSH from this Mac is currently refused (Permission denied/connection reset) and the windev→35 jump is administratively prohibited. Either re-authorize this Mac's key on 35, or the user runs the finaldocker compose up -d. Artifacts are portable either way. - OtOpcUa group key shape — confirm OtOpcUa maps on the short RDN (
OtOpcUa-Admins) the shared lib returns vs the full-DN itsLdapGroupRoleMappingentity comment shows, before seeding. - OrbStack→LAN reachability — verify ScadaBridge/OtOpcUa containers can reach
10.100.0.35:3893early (likely fine; it's the linchpin).log()if any consumer can't reach 35 rather than silently failing. - windev OtOpcUa config path — discovery step (less is known about this deployment than MxGateway).
Notes
scadaprojis a plain-files umbrella that is also a local git repo;infra/glauth/lives here as the canonical source. Per-app config edits land on afeat/*branch per repo (merge on the user's go). windev edits are deployment-only with.bakbackups (like the GroupToRole / LDAP-key migrations done 2026-06-04); repo templates optionally aligned.- Related memory:
multi-role-cross-app-test-user,mxgateway-windev-deploy,scadabridge-local-deploy-gotchas,auth-audit-normalization-in-progress.