Files
scadaproj/ZB.MOM.WW.Auth/README.md
T
Joseph Doherty 544a6ddb77 Fix all baseline code-review findings across the six shared libraries
Resolves the 35 findings from the 2026-06-01 baseline (commit 26ba1c7),
test-first for every behavioral change. +51 tests (331 -> 382 passing, 0 failed).

- Telemetry-001 (HIGH): RedactionEnricher now honours property removal, so a
  redactor that drops a key actually scrubs the secret from the event.
- Auth: LDAP validator ValidateOnStart; API-key verify no longer fails on a
  best-effort MarkUsed write or a corrupt scopes column (fail-closed); LDAP cert
  validation hook; KeyPrefix persistence aligned; README algorithm corrected.
- Health: Akka checks return Degraded (not throw) when the cluster isn't up yet;
  GrpcDependencyHealthCheck catch-all; null 'description' rendered; composite
  endpoint builder; XML docs shipped.
- Audit: CompositeAuditWriter no longer re-throws OperationCanceledException;
  TruncatingAuditRedactor over-redact scrubs Target + safe negative max; options
  record; XML docs shipped.
- Configuration: TryAddEnumerable idempotent registration; consistent port
  quoting; strict invariant port parsing; XML docs + README packaged.
- Theme: mobile toggle is now CSS-only (no Bootstrap JS); token/CSS hygiene;
  XML docs on the public parameter surface.

Shared-contract/spec docs updated where the code was the source of truth
(observability service.instance.id, MapZbMetrics, redactor reach). All changes
additive/back-compatible at v0.1.0. code-reviews bookkeeping follows separately.
2026-06-01 11:22:14 -04:00

3.9 KiB

ZB.MOM.WW.Auth

Authentication and authorisation libraries for the ZB.MOM.WW SCADA family (OtOpcUa, MxAccessGateway, ScadaBridge). These are libraries, not a service — each package is linked directly into the consuming application at build time. There is no central authentication process or network hop; auth logic runs in-process alongside the application.


Packages

Package Description Key Dependencies
ZB.MOM.WW.Auth.Abstractions Auth contracts, canonical role constants, and shared types (LdapOptions, LdapAuthResult, ILdapAuthService, IApiKeyStore). No runtime dependencies beyond the BCL.
ZB.MOM.WW.Auth.Ldap LDAP authentication service: bind-then-search-then-bind against GLAuth or Active Directory; RFC 4514-aware group extraction; fail-closed. Abstractions, Novell.Directory.Ldap.NETStandard
ZB.MOM.WW.Auth.ApiKeys SQLite-backed API-key store with pepper-keyed HMAC-SHA256 secret hashing, rotation, and audit log. DI wiring is AddZbApiKeyAuth; an opt-in MigrationHostedService runs schema migrations on startup. Abstractions, Microsoft.Data.Sqlite
ZB.MOM.WW.Auth.AspNetCore ASP.NET Core wiring for the LDAP provider only: AddZbLdapAuth (binds + start-time-validates LdapOptions, registers ILdapAuthService), plus ZbCookieDefaults.Apply (hardened cookie helper the consumer calls itself) and ZbClaimTypes constants. It does not wire API keys or cookie middleware — API-key DI is AddZbApiKeyAuth in the ApiKeys package. Abstractions, Ldap, Microsoft.AspNetCore.App

Consumer Matrix

Consumer Abstractions Ldap ApiKeys AspNetCore
OtOpcUa yes yes yes
MxAccessGateway yes yes yes yes
ScadaBridge yes yes yes yes

ApiKeys is NOT used by OtOpcUa (that app authenticates human operators via LDAP + cookies only; machine-to-machine access is out of scope).


Versioning

All four packages are versioned lockstep from Directory.Build.props. The current release is 0.1.0. A single version bump in Directory.Build.props bumps all four packages simultaneously — consumers should reference the same version for all ZB.MOM.WW.Auth packages.


Running the opt-in LDAP integration test

The GLAuth integration test (GLAuthIntegrationTests) is skipped by default and does not affect the normal test run. To exercise it against a live GLAuth instance:

  1. Start the GLAuth Docker stack from the sibling repo:

    cd ~/Desktop/ScadaBridge/infra/glauth
    docker compose up -d
    
  2. Set the required environment variables and run the test:

    export ZB_LDAP_IT=1
    export ZB_LDAP_SVC_DN="cn=svc,dc=lmxopcua,dc=local"
    export ZB_LDAP_SVC_PW="svcpass"
    export ZB_LDAP_USER="alice"
    export ZB_LDAP_PW="alicepass"
    
    dotnet test tests/ZB.MOM.WW.Auth.Ldap.Tests \
      --filter "FullyQualifiedName~GLAuthIntegrationTests"
    

All other variables (ZB_LDAP_SERVER, ZB_LDAP_PORT, ZB_LDAP_BASE, ZB_LDAP_USERATTR) default to sensible GLAuth values and are optional. The test also probes TCP reachability before attempting auth and skips if the server is not contactable.


Publishing packages

Use build/push.sh to pack and push to the Gitea NuGet feed:

export GITEA_NUGET_SOURCE="https://gitea.dohertylan.com/api/packages/dohertj2/nuget/index.json"
export GITEA_NUGET_KEY="your-gitea-token"
./build/push.sh

The script runs dotnet pack -c Release then dotnet nuget push --skip-duplicate.


Design documentation

Full design docs live in the components/auth folder of the SCADA project notes:

  • ~/Desktop/scadaproj/components/auth/spec/SPEC.md — overall auth specification
  • ~/Desktop/scadaproj/components/auth/spec/CANONICAL-ROLES.md — role taxonomy
  • ~/Desktop/scadaproj/components/auth/shared-contract/ — shared contract types