Files
scadaproj/infra/glauth-redundant
Joseph Doherty 58f605609d feat(infra): redundant GLAuth pair for FallbackServers failover drills
Two local glauth containers (zb-ldap-primary :3893 / zb-ldap-backup :3894)
simulating the NAM two-DC topology, so the primary can be killed during a
drill without touching the shared 10.100.0.35 instance. Drill recipe +
verified-PASS record (HistorianGateway, 2026-08-13) in the README.
2026-08-13 08:28:05 -04:00
..

Redundant LDAP test pair (primary + backup "DC")

Two GLAuth containers on the dev Mac that simulate the NAM two-DC topology (uswap-vdc-nam1/nam2) for exercising ZB.MOM.WW.Auth.Ldap 0.2.x FallbackServers sticky failover. Deliberately local — the shared zb-shared-glauth on 10.100.0.35:3893 serves every other dev stack and must never be stopped for a drill.

container host port from a container
primary zb-ldap-primary 3893 host.docker.internal:3893
backup zb-ldap-backup 3894 host.docker.internal:3894

Both mount the same config.toml — identical directory contents, like a real replicated pair. It is a copy of ../glauth/config.toml with one difference: the serviceaccount password here is the well-known local value serviceaccount123 (the shared instance's is rotated out-of-band, SEC-36). Same users otherwise (multi-role/password, etc.).

docker compose up -d          # start the pair

Consumer wiring (any of the four apps)

Ldap__Server: host.docker.internal        # primary
Ldap__Port: "3893"
Ldap__FallbackServers__0: host.docker.internal:3894
Ldap__Transport: None
Ldap__AllowInsecure: "true"

First wired consumer: HistorianGateway/docker/docker-compose.yml (Auth pin 0.2.1, dashboard login enabled). Note its Production-env container needs Serilog__WriteTo__0__Name: Console or it logs nothing — the drill's failover lines would be invisible.

Failover drill (verified PASS 2026-08-13 against HistorianGateway)

  1. login → served by primary, no warnings
  2. docker stop zb-ldap-primary → login OK; app logs WRN LDAP endpoint …:3893 failed system-side at connect + INF LDAP sticky preference moved to …:3894
  3. docker start zb-ldap-primary → login OK, still served by the backup (sticky by design — verified by bind counts: primary got zero new binds)
  4. docker stop zb-ldap-backup → login OK; warn on :3894, sticky moves back to :3893

The sticky preference lives in the app's singleton LdapAuthService, so an app restart resets it to the configured primary.