Files
scadaproj/components/auth/GAPS.md
T

5.5 KiB
Raw Blame History

Auth — gaps & adoption backlog

Divergence of each project from spec/SPEC.md, and the ordered backlog to reach the shared ZB.MOM.WW.Auth library. Status legend: gap · 🟡 partial · matches.

Divergence vs spec

§1 LDAP config schema

Spec key OtOpcUa MxAccessGateway ScadaBridge
Section nesting 🟡 Authentication:Ldap (nested) MxGateway:Ldap (nested) flat ScadaBridge:Security:Ldap*
Transport enum UseTls bool UseTls bool LdapTransport enum
AllowInsecure 🟡 AllowInsecureLdap 🟡 AllowInsecureLdap 🟡 AllowInsecureLdap (rename)
UserNameAttribute UserNameAttribute UserNameAttribute LdapUserIdAttribute
GroupAttribute memberOf memberOf 🟡 LdapGroupAttribute (rename)
dev SearchBase dc=lmxopcua,dc=local dc=lmxopcua,dc=local dc=scadabridge,dc=local

Gap A1: adopt the Transport enum in OtOpcUa + gateway (replace UseTls). → Gap A2: ScadaBridge: nest keys + rename LdapUserIdAttributeUserNameAttribute, LdapGroupAttributeGroupAttribute. → Gap A3: unify the dev base DN (dc=lmxopcua vs dc=scadabridge) — pick one shared GLAuth base.

All three do bind-then-search; ScadaBridge has the most complete hygiene (RFC-4514 + filter escaping, per-op timeout, fail-closed on group lookup, username trim, service-account-bind distinction). 🟡 OtOpcUa/gateway: confirm each has filter escaping + fail-closed-on-group-lookup parity. → Gap B1: make ScadaBridge's hygiene the shared baseline; backfill any missing checks.

§3 group→role mapping

Mechanism split: OtOpcUa + gateway map in config (GroupToRole); ScadaBridge maps in the database (LdapGroupMapping). → Gap C1: IGroupRoleMapper<CanonicalRole> must support both backings; ship a config-backed and a DB/delegate-backed mapper.

Role vocabulary now standardized to the canonical six (spec/CANONICAL-ROLES.md); native enforcement stays per-project. → Gap C2: implement the canonical → native expansion in each project. ⚠ Removing Auditor collapses ScadaBridge AuditReadOnly→Viewer and Audit→Administrator, losing its auditor/admin separation-of-duties (accepted). OtOpcUa lacks a first-class Deployer (publish ⊂ FleetAdmin); ScadaBridge has no Operator/Engineer; mxaccessgw no Designer/Deployer — each project assigns only the applicable subset.

§4 API-key contract

OtOpcUa MxAccessGateway ScadaBridge
Has API keys n/a (OPC UA transport security) mxgw_…, SQLite, scopes + constraints 🟡 X-API-Key, per-method approval (Inbound API only)
Peppered HMAC-SHA256
Constant-time compare
Token format <prefix>_<id>_<secret> raw X-API-Key (no keyId/prefix structure)
Audit log append-only 🟡 (verify)

Gap D1: extract mxaccessgw's pipeline as ZB.MOM.WW.Auth.ApiKeys. → Gap D2: ScadaBridge Inbound API adopts it; reconcile token format and model "per-method approval" as the opaque constraint policy.

Cookie names differ (MxGatewayDashboard vs ZB.MOM.WW.ScadaBridge.Auth vs OtOpcUa control-plane cookie); claim-type conventions differ. → Gap E1: define canonical claim types + cookie defaults in ZB.MOM.WW.Auth.AspNetCore; each app keeps its own cookie name but shares attributes/claims.

§6 dev / secrets

All never-log-secrets and pepper-external. 🟡 escape-hatch flag names vary. Covered by A3 (base DN) + E.

Adoption backlog (ordered)

# Item Projects Priority Effort Risk Notes
1 Extract ZB.MOM.WW.Auth.Ldap from ScadaBridge's hardened impl all 3 High M Med security-sensitive; needs strong tests before cutover
2 Extract ZB.MOM.WW.Auth.ApiKeys from mxaccessgw Model A gw, SB High M Med gateway adopts first (it's the source), then SB
3 IGroupRoleMapper<TRole> seam + config & DB mappers (Gap C1) all 3 High S Low unblocks per-project role retention
4 Config migration to §1 schema (Gaps A1A2) all 3 Med S Low mechanical; do with #1
5 ZB.MOM.WW.Auth.AspNetCore claims/cookie conventions (Gap E1) all 3 (UIs) Med S Low incl. OtOpcUa Blazor Admin UI control-plane
6 Unify dev GLAuth base DN (Gap A3) all 3 Low S Low dev-only; touches fixtures/infra
7 Decide shared JWT/refresh helper vs per-project SB (+?) Low S Low only if a 2nd project wants the same
8 Adopt canonical roles: canonical → native mapping per project (Gap C2) all 3 Med M Med governance (assign canonical role per LDAP group org-wide) + each project's expansion; SB audit roles collapse

Sequencing: #3 first (cheap, unblocks), then #1 and #2 in parallel (independent libraries), then #4#5 alongside cutover, then #6#7 as cleanup. Each extraction lands behind tests in the source project before any consumer migrates. This stays consistent with the repos' loose coupling: adoption is opt-in per project, one consumer version-bump at a time.

Decisions still open

  • Shared dev base DN value (A3).
  • Whether constraints stay opaque object? or get a small IConstraintPolicy (shared-contract Q3).
  • Shared JWT/refresh helper or not (#7).