docs(audit): apply per-cluster judgment fixes across living docs

Resolve audit findings: correct WorkerEnvelope proto/route/metric/session
facts; rewrite auth (ZB.MOM.WW.Auth migration), dashboard (ZB.MOM.WW.Theme),
and StyleGuide (foreign-project copy-paste); document alarm subsystem, Ldap
options, and gateway alarm broker; fix client CLI flags and package paths.
This commit is contained in:
Joseph Doherty
2026-06-03 16:01:28 -04:00
parent f84e0c3474
commit e541339c07
29 changed files with 1102 additions and 432 deletions
+71 -50
View File
@@ -59,13 +59,17 @@ 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 adds one group beyond this LmxOpcUa taxonomy:
`GwAdmin`. There is no `RequiredGroup` option — dashboard authorization
is driven entirely by `MxGateway:Dashboard:GroupToRole`, which maps an
LDAP group to a dashboard role. A user whose groups produce no mapped
role is rejected at login. So for the dashboard to admit `admin`, a
group named in `GroupToRole` (by convention `GwAdmin``Administrator`)
must exist and `admin` must belong to it. `GwAdmin` is **not** in the
baseline GLAuth config — it must be provisioned before dashboard authn
or the `DashboardLdapLiveTests` (`MXGATEWAY_RUN_LIVE_LDAP_TESTS=1`)
work. See [Provisioning the GwAdmin group](#provisioning-the-gwadmin-group)
below.
> **Dashboard role value (Task 1.7):** the LDAP `GwAdmin` group now maps to
> the canonical dashboard role **`Administrator`** (was `Admin`); `GwReader`
@@ -112,43 +116,58 @@ to avoid re-deriving the LDAP escape-string handling.
## Suggested mxgw configuration shape
A YAML/JSON section for mxaccessgw that mirrors LmxOpcUa's `LdapOptions`
record:
The gateway binds the `MxGateway:Ldap` section onto `LdapOptions`. The
field names are PascalCase config keys (shown here as YAML; JSON
`appsettings` and env-var overrides use the same names). Note the keys
that changed from the older LmxOpcUa shape: `Transport` (an enum,
replacing the boolean `UseTls`), `AllowInsecure` (replacing
`AllowInsecureLdap`), and `UserNameAttribute` which defaults to `cn`:
```yaml
ldap:
enabled: true
server: localhost
port: 3893
useTls: false
allowInsecureLdap: true # dev only
searchBase: "dc=zb,dc=local"
serviceAccountDn: "cn=serviceaccount,dc=zb,dc=local"
serviceAccountPassword: "serviceaccount123"
userNameAttribute: "uid" # GLAuth populates this; AD uses sAMAccountName
displayNameAttribute: "cn"
groupAttribute: "memberOf"
groupToRole:
ReadOnly: "Browse"
WriteOperate: "Write"
WriteTune: "WriteSecured"
WriteConfigure: "WriteSecured"
AlarmAck: "AlarmAck"
MxGateway:
Ldap:
Enabled: true
Server: localhost
Port: 3893
Transport: None # None | StartTls | Ldaps (dev: None)
AllowInsecure: true # dev only
SearchBase: "dc=zb,dc=local"
ServiceAccountDn: "cn=serviceaccount,dc=zb,dc=local"
ServiceAccountPassword: "serviceaccount123"
UserNameAttribute: "cn" # GLAuth keys users by cn; AD uses sAMAccountName
DisplayNameAttribute: "cn"
GroupAttribute: "memberOf"
Dashboard:
GroupToRole:
GwAdmin: "Administrator"
GwReader: "Viewer"
```
`groupAttribute` returns full DNs like
`ou=ReadOnly,ou=groups,dc=zb,dc=local` — the authenticator
should strip the leading `ou=` (or `cn=` against AD) RDN value and
look that up in `groupToRole`.
`Transport` is an `LdapTransport` enum (`None`, `StartTls`, `Ldaps`); it
replaces the old boolean `UseTls` (`true``Ldaps`, `false` = `None`).
`UserNameAttribute` defaults to `cn` because GLAuth keys users by `cn`
(`backend.nameformat = "cn"`); only AD needs `sAMAccountName`. The
group-to-role mapping lives under `MxGateway:Dashboard:GroupToRole`, not
in the LDAP section, and its values must be dashboard roles
(`Administrator` or `Viewer`).
The shared `ZB.MOM.WW.Auth.Ldap` provider performs the runtime bind and
search; it returns each group already stripped to its short RDN value
(e.g. `GwAdmin` from `ou=GwAdmin,ou=groups,dc=zb,dc=local`) before the
gateway looks it up in `GroupToRole`. Keep `GroupToRole` keys as short
group names — a full-DN key will never match the short name the provider
returns.
## Provisioning the GwAdmin group
`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
`GwAdmin` is the gateway-specific dashboard-admin group, mapped to the
`Administrator` role through `MxGateway:Dashboard:GroupToRole`. Because
dashboard login rejects any user who resolves to no role, the dashboard
cookie login and `DashboardLdapLiveTests`
(`MXGATEWAY_RUN_LIVE_LDAP_TESTS=1`) reject `admin` until a `GwAdmin`
group exists, `admin` is a member, and `GroupToRole` maps `GwAdmin` to a
role. 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:
1. Edit `C:\publish\glauth\glauth.cfg`
@@ -178,10 +197,11 @@ server:
4. `nssm restart GLAuth`
After the restart, `admin`'s `memberOf` includes
`ou=GwAdmin,ou=groups,dc=zb,dc=local`, which the authenticator
strips to `GwAdmin` and matches against `RequiredGroup`. The same
pattern applies to any future permission that doesn't fit the existing
five roles.
`ou=GwAdmin,ou=groups,dc=zb,dc=local`. The shared LDAP provider strips
that to the short RDN `GwAdmin`, which the gateway looks up in
`MxGateway:Dashboard:GroupToRole` to resolve the dashboard role. The same
pattern applies to any future group that doesn't fit the existing five
roles — add the group, add the member, and add a `GroupToRole` entry.
Generate `passsha256` from a plaintext password:
@@ -254,24 +274,25 @@ Get-Content C:\publish\glauth\logs\stderr.log -Tail 20 -Wait
## Active Directory migration cheat-sheet
LmxOpcUa's `LdapOptions` xml-doc captures the AD overrides; same set
applies to mxaccessgw verbatim. Keys that change:
These `MxGateway:Ldap` keys change when pointing the gateway at AD
instead of dev GLAuth:
| Field | GLAuth dev value | AD production value |
|---|---|---|
| `Server` | `localhost` | 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` |
| `Transport` | `None` | `Ldaps` (or `StartTls`) |
| `AllowInsecure` | `true` | `false` |
| `SearchBase` | `dc=zb,dc=local` | `DC=corp,DC=example,DC=com` |
| `ServiceAccountDn` | `cn=serviceaccount,dc=zb,dc=local` | `CN=MxGwSvc,OU=Service Accounts,DC=corp,...` |
| `UserNameAttribute` | `uid` | `sAMAccountName` (or `userPrincipalName`) |
| `UserNameAttribute` | `cn` | `sAMAccountName` (or `userPrincipalName`) |
| `GroupAttribute` | `memberOf` (unchanged) | `memberOf` (unchanged) |
`memberOf` returns full DNs; the authenticator strips the leading
`CN=` value and uses it as the lookup key in `groupToRole`. Nested
groups are **not** auto-expanded; either flatten in the directory or
add a `tokenGroups` query as an enhancement.
`memberOf` returns full DNs; the shared LDAP provider strips each to its
leading RDN value (`CN=`/`OU=`) and the gateway uses that as the lookup
key in `MxGateway:Dashboard:GroupToRole`. Nested groups are **not**
auto-expanded; either flatten in the directory or add a `tokenGroups`
query as an enhancement.
## Security notes for production