docs(glauth): repoint glauth.md at the shared GLAuth on 10.100.0.35
No more per-box C:\publish\glauth NSSM service — dev/test LDAP is the shared zb-shared-glauth on 10.100.0.35:3893 (dc=zb,dc=local). Provisioning now via scadaproj/infra/glauth/config.toml. Old localhost/NSSM procedures kept as retired reference; test users multi-role/gw-viewer.
This commit is contained in:
@@ -100,7 +100,7 @@ When source code changes, build and test the affected component before reporting
|
||||
## Design Sources To Consult Before Non-Trivial Changes
|
||||
|
||||
- `gateway.md` — top-level architecture, command/event surface, IPC envelope, STA thread model, fault handling.
|
||||
- `glauth.md` — local LDAP server (GLAuth on `localhost:3893`, base DN `dc=zb,dc=local`) used for dev authn. Pre-provisioned users (`admin/admin123`, `readonly/readonly123`, etc.) and the role→capability mapping live there.
|
||||
- `glauth.md` — shared GLAuth LDAP server (`10.100.0.35:3893`, base DN `dc=zb,dc=local`, source of truth `scadaproj/infra/glauth/`) used for dev authn. Dashboard test users (`multi-role`/`password` = Administrator, `gw-viewer`/`password` = Viewer) and the role→capability mapping live there.
|
||||
- `docs/DesignDecisions.md` — v1 choices (MXAccess COM target `LMXProxyServerClass` from `C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll`, API-key-in-SQLite auth, fail-fast event backpressure, etc.).
|
||||
- `docs/GatewayProcessDesign.md`, `docs/MxAccessWorkerInstanceDesign.md`, `docs/WorkerFrameProtocol.md`, `docs/WorkerProcessLauncher.md` — detailed component designs.
|
||||
- `docs/GatewayConfiguration.md` — full `MxGateway:*` options bound by `GatewayOptions` and validated at startup by `GatewayOptionsValidator`.
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
# GLAuth — LDAP authn reference for mxaccessgw
|
||||
|
||||
GLAuth is a lightweight LDAP server installed on this dev box at
|
||||
`C:\publish\glauth\` and run as a Windows service via NSSM. It already
|
||||
backs the LmxOpcUa OPC UA server's UserName-token authn and the LmxOpcUa
|
||||
Admin UI's cookie login; this doc captures everything mxaccessgw needs
|
||||
to consume the same directory so a single set of dev credentials covers
|
||||
both stacks.
|
||||
> **UPDATED 2026-06-04 — mxaccessgw no longer uses a per-box GLAuth at `C:\publish\glauth`.
|
||||
> Dev/test LDAP is now the SHARED GLAuth on `10.100.0.35:3893` (`dc=zb,dc=local`);
|
||||
> the single source of truth is `scadaproj/infra/glauth/` (`config.toml` + `README`).
|
||||
> The localhost/NSSM/`glauth.cfg` procedures below are RETIRED, kept for reference/rollback.**
|
||||
|
||||
The authoritative copy of LmxOpcUa's reference lives at
|
||||
`C:\publish\glauth\auth.md`. This doc is a redistilled view tailored to
|
||||
mxaccessgw — what users + groups are already provisioned, how to bind
|
||||
against them, and what's needed to add a gw-specific role.
|
||||
GLAuth is a lightweight LDAP server. It already backs all three sister apps (MxAccessGateway,
|
||||
OtOpcUa, ScadaBridge) through a **shared container** (`zb-shared-glauth`) running on the Linux
|
||||
docker host at **`10.100.0.35:3893`**. This doc captures everything mxaccessgw needs to consume
|
||||
that directory so a single set of dev credentials covers all stacks.
|
||||
|
||||
~~GLAuth is installed on this dev box at `C:\publish\glauth\` and run as a Windows service via
|
||||
NSSM.~~ *(RETIRED — the per-box Windows service has been stopped and set to Manual startup;
|
||||
kept only as a rollback option. Do not edit or restart it for new work.)*
|
||||
|
||||
The single source of truth for the shared GLAuth is
|
||||
**`~/Desktop/scadaproj/infra/glauth/config.toml`** (deploy/verify runbook:
|
||||
`scadaproj/infra/glauth/README.md`). This doc is a redistilled view tailored to mxaccessgw —
|
||||
what users + groups are provisioned, how to bind against them, and what's needed to add a
|
||||
gw-specific role.
|
||||
|
||||
## Connection details
|
||||
|
||||
| Setting | Value |
|
||||
|---|---|
|
||||
| Protocol | LDAP (unencrypted) |
|
||||
| Host | `localhost` |
|
||||
| Host | **`10.100.0.35`** (shared docker host — ~~`localhost`~~ retired) |
|
||||
| Port | `3893` |
|
||||
| LDAPS | disabled in dev (set `[ldaps]` block to enable) |
|
||||
| LDAPS | disabled in dev (`Transport=None`, `AllowInsecure=true`) |
|
||||
| Base DN | `dc=zb,dc=local` |
|
||||
| Bind DN format | `cn={username},dc=zb,dc=local` |
|
||||
| Service account DN | `cn=serviceaccount,dc=zb,dc=local` / `serviceaccount123` |
|
||||
| Group OU | `ou=<groupname>,ou=groups,dc=zb,dc=local` |
|
||||
| Failed-bind throttle | 3 fails → 10-minute IP lockout (per `[behaviors]`) |
|
||||
|
||||
@@ -59,13 +68,13 @@ For mxaccessgw dev, `admin` covers every gw-side capability test;
|
||||
`readonly` is the right "negative" case for proving Browse-OK /
|
||||
Write-denied.
|
||||
|
||||
The gateway dashboard adds one role beyond this LmxOpcUa taxonomy:
|
||||
`GwAdmin`. `LdapOptions.RequiredGroup` defaults to `GwAdmin`, so the
|
||||
dashboard login and `DashboardLdapLiveTests` require `admin` to be a
|
||||
member of a `GwAdmin` group. `GwAdmin` is **not** in the baseline
|
||||
GLAuth config — it must be provisioned before dashboard authn or the
|
||||
LDAP live tests work. See [Provisioning the GwAdmin
|
||||
group](#provisioning-the-gwadmin-group) below.
|
||||
The gateway dashboard uses two gateway-specific groups beyond the LmxOpcUa taxonomy:
|
||||
`GwAdmin` (gid 5610 → role `Administrator`) and `GwReader` (gid 5611 → role `Viewer`).
|
||||
These are already provisioned in the shared `scadaproj/infra/glauth/config.toml`.
|
||||
The dashboard test users are **`multi-role`/`password`** (Administrator) and
|
||||
**`gw-viewer`/`password`** (Viewer). `LdapOptions.RequiredGroup` defaults to `GwAdmin`.
|
||||
See [Provisioning the GwAdmin group](#provisioning-the-gwadmin-group) below for the
|
||||
(now-retired) per-box procedure and for the shared-config equivalent.
|
||||
|
||||
> **Dashboard role value (Task 1.7):** the LDAP `GwAdmin` group now maps to
|
||||
> the canonical dashboard role **`Administrator`** (was `Admin`); `GwReader`
|
||||
@@ -118,7 +127,7 @@ record:
|
||||
```yaml
|
||||
ldap:
|
||||
enabled: true
|
||||
server: localhost
|
||||
server: 10.100.0.35 # shared GLAuth on docker host (was localhost)
|
||||
port: 3893
|
||||
useTls: false
|
||||
allowInsecureLdap: true # dev only
|
||||
@@ -143,13 +152,29 @@ look that up in `groupToRole`.
|
||||
|
||||
## Provisioning the GwAdmin group
|
||||
|
||||
> **UPDATED 2026-06-04 — RETIRED per-box procedure.** `GwAdmin` (gid 5610) and `GwReader`
|
||||
> (gid 5611) are already present in the shared GLAuth. To add or modify users/groups,
|
||||
> edit **`~/Desktop/scadaproj/infra/glauth/config.toml`** on host `10.100.0.35` and run:
|
||||
>
|
||||
> ```bash
|
||||
> cd ~/Desktop/scadaproj/infra/glauth
|
||||
> docker compose up -d --force-recreate
|
||||
> ```
|
||||
>
|
||||
> The per-box `C:\publish\glauth\glauth.cfg` + NSSM procedure below is kept for
|
||||
> rollback reference only — do not use it for new provisioning.
|
||||
|
||||
`GwAdmin` is the gateway-specific dashboard-admin role. It is the
|
||||
default `LdapOptions.RequiredGroup`, so the dashboard cookie login and
|
||||
`DashboardLdapLiveTests` (`MXGATEWAY_RUN_LIVE_LDAP_TESTS=1`) reject
|
||||
`admin` until a `GwAdmin` group exists and `admin` is a member.
|
||||
GLAuth's baseline config ships only the five LmxOpcUa role groups, so
|
||||
`GwAdmin` must be added to GLAuth rather than run from a separate LDAP
|
||||
server:
|
||||
logins unless the user is a member of `GwAdmin`.
|
||||
The `GwAdmin` (gid 5610) and `GwReader` (gid 5611) groups already exist in the shared
|
||||
config at `scadaproj/infra/glauth/config.toml`. Dashboard test users are
|
||||
`multi-role`/`password` (Administrator) and `gw-viewer`/`password` (Viewer).
|
||||
|
||||
---
|
||||
|
||||
**RETIRED — per-box provisioning (reference/rollback only):**
|
||||
|
||||
1. Edit `C:\publish\glauth\glauth.cfg`
|
||||
2. Append the group:
|
||||
@@ -199,15 +224,16 @@ echo -n "yourpassword" | openssl dgst -sha256
|
||||
|
||||
## Quick verification
|
||||
|
||||
From mxaccessgw's dev box, prove the directory is reachable:
|
||||
From mxaccessgw's dev box, prove the shared directory is reachable:
|
||||
|
||||
```powershell
|
||||
# Plain bind via PowerShell + System.DirectoryServices.Protocols
|
||||
$ldap = New-Object System.DirectoryServices.Protocols.LdapConnection("localhost:3893")
|
||||
# (shared GLAuth on 10.100.0.35 — was localhost, now the docker host)
|
||||
$ldap = New-Object System.DirectoryServices.Protocols.LdapConnection("10.100.0.35:3893")
|
||||
$ldap.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic
|
||||
$ldap.SessionOptions.ProtocolVersion = 3
|
||||
$ldap.SessionOptions.SecureSocketLayer = $false
|
||||
$cred = New-Object System.Net.NetworkCredential("cn=admin,dc=zb,dc=local","admin123")
|
||||
$cred = New-Object System.Net.NetworkCredential("cn=multi-role,dc=zb,dc=local","password")
|
||||
$ldap.Bind($cred)
|
||||
"Bind OK"
|
||||
```
|
||||
@@ -215,17 +241,32 @@ $ldap.Bind($cred)
|
||||
Or via `ldapsearch` if you have OpenLDAP CLI tools:
|
||||
|
||||
```bash
|
||||
ldapsearch -x -H ldap://localhost:3893 \
|
||||
-D "cn=admin,dc=zb,dc=local" -w admin123 \
|
||||
-b "dc=zb,dc=local" "(uid=admin)"
|
||||
ldapsearch -x -H ldap://10.100.0.35:3893 \
|
||||
-D "cn=serviceaccount,dc=zb,dc=local" -w serviceaccount123 \
|
||||
-b "dc=zb,dc=local" "(uid=multi-role)"
|
||||
```
|
||||
|
||||
The response should list `admin`'s entry with `memberOf` populated for
|
||||
all five role groups — plus `GwAdmin` once the gateway-specific group
|
||||
is provisioned.
|
||||
The response should list `multi-role`'s entry with `memberOf` including
|
||||
`ou=GwAdmin,ou=groups,dc=zb,dc=local`.
|
||||
|
||||
## Service management
|
||||
|
||||
> **RETIRED — per-box NSSM service (reference/rollback only).** The shared GLAuth is
|
||||
> managed via `docker compose` on `10.100.0.35` (`scadaproj/infra/glauth/`). The
|
||||
> Windows NSSM `GLAuth` service on the dev box has been stopped and set to
|
||||
> `StartupType=Manual`; only restart it if you need to roll back to a local directory.
|
||||
>
|
||||
> **Active (shared) management:**
|
||||
> ```bash
|
||||
> ssh 10.100.0.35
|
||||
> cd ~/Desktop/scadaproj/infra/glauth
|
||||
> docker compose ps # check container status
|
||||
> docker compose up -d --force-recreate # apply config.toml changes
|
||||
> docker compose logs -f # tail logs
|
||||
> ```
|
||||
|
||||
**RETIRED — per-box NSSM commands (rollback reference):**
|
||||
|
||||
```powershell
|
||||
# Status / start / stop / restart
|
||||
nssm status GLAuth
|
||||
@@ -259,7 +300,7 @@ applies to mxaccessgw verbatim. Keys that change:
|
||||
|
||||
| Field | GLAuth dev value | AD production value |
|
||||
|---|---|---|
|
||||
| `Server` | `localhost` | a domain controller FQDN, or the domain itself |
|
||||
| `Server` | `10.100.0.35` (shared docker host) | a domain controller FQDN, or the domain itself |
|
||||
| `Port` | `3893` | `636` (LDAPS) — AD increasingly rejects plain bind under LDAP-signing enforcement |
|
||||
| `UseTls` | `false` | `true` |
|
||||
| `AllowInsecureLdap` | `true` | `false` |
|
||||
@@ -275,12 +316,12 @@ add a `tokenGroups` query as an enhancement.
|
||||
|
||||
## Security notes for production
|
||||
|
||||
- **Plaintext passwords in `glauth.cfg` are dev-only.** The config is
|
||||
unencrypted on disk; anyone with read access to `C:\publish\glauth\`
|
||||
can SHA256-rainbow-table the entries. Treat the dev creds as
|
||||
throwaway. Production LDAP is Active Directory.
|
||||
- **Plaintext passwords in `config.toml` are dev-only.** The shared config is in
|
||||
`scadaproj/infra/glauth/config.toml` (unencrypted); restrict filesystem access on
|
||||
`10.100.0.35` accordingly. Treat the dev creds as throwaway. Production LDAP is Active
|
||||
Directory. *(The retired per-box `C:\publish\glauth\glauth.cfg` has the same caveat.)*
|
||||
- The 3-fail / 10-minute lockout is per source IP, not per user — a
|
||||
shared NAT can lock out a whole office. Tunable in `[behaviors]`.
|
||||
- LDAPS isn't enabled in dev; binding sends passwords cleartext on the
|
||||
wire. Fine for `localhost`, never expose port 3893 off-box without
|
||||
enabling TLS first.
|
||||
wire. The shared GLAuth listens only on the LAN (`10.100.0.35`); never
|
||||
expose port 3893 externally without enabling TLS first.
|
||||
|
||||
Reference in New Issue
Block a user