Files
scadaproj/components/secrets/current-state/mxaccessgw/CURRENT-STATE.md
T
Joseph Doherty e347286f28 docs(components): normalize Secrets component + index the shared lib
Add components/secrets/ (SPEC, realized shared-contract, code-verified
current-state for OtOpcUa/mxaccessgw/ScadaBridge, GAPS adoption backlog) and
register the Secrets row in CLAUDE.md + components/README.md. The
ZB.MOM.WW.Secrets lib is built + published 0.1.2 + reference-consumer-proven
(HistorianGateway, live vs the wonder historian); per-app adoption is the
tracked follow-on.
2026-07-16 04:49:57 -04:00

3.5 KiB

MxAccessGateway — secrets current state

Descriptive baseline (code-verified) of how mxaccessgw handles secrets today, before adopting ZB.MOM.WW.Secrets. Paths are relative to ~/Desktop/MxAccessGateway.

Where each secret lives today

Secret Location today At-rest protection
gRPC inbound API keys Peppered HMAC-SHA256 hashes in SQLite gateway-auth.db (MxGateway:Authentication:SqlitePath, …Server/appsettings.json:17) via ZB.MOM.WW.Auth.ApiKeys (…/Security/Authentication/AuthStoreServiceCollectionExtensions.cs:70) Hashed (not reversible); plaintext key never stored
API-key pepper Read by config-key name MxGateway:ApiKeyPepper; value supplied out-of-band (env MxGateway__ApiKeyPepper), intentionally not in appsettings (AuthStoreServiceCollectionExtensions.cs:36,54-55) Runtime-supplied; no dedicated env reader (default config binding); flagged open item SEC-10
LDAP dashboard bind password Plaintext appsettings.json:29 ServiceAccountPassword: "serviceaccount123"; also a hardcoded default in Configuration/LdapOptions.cs:61 None
Galaxy-repository SQL connection string Plaintext appsettings.json:76 (currently Integrated Security=True, but the field is a raw connstr that would carry Password= in plaintext) None (redacted for display only, Dashboard/DashboardConnectionStringDisplay.cs:10-24)
TLS PFX Generated/persisted with a null password, ACL-protected on disk (Security/Tls/SelfSignedCertificateProvider.cs:153,193) Filesystem ACL, no password
MXAccess/Wonderware creds Not stored — pass-through runtime gRPC request payload forwarded to COM (Worker/MxAccess/MxAccessCommandExecutor.cs:318-325) N/A

Encryption-at-rest today

  • None for the secrets above. The only Data Protection use is short-lived SignalR hub bearer tokens (Dashboard/HubTokenService.cs:43-46) — and Data Protection is never explicitly configured (no AddDataProtection/PersistKeysTo/ProtectKeysWith/ SetApplicationName anywhere), so the key ring falls back to the ASP.NET default. Not applied to any credential.

Config expansion today

  • None. Stock WebApplication.CreateBuilder chain (GatewayApplication.cs:60); no ${...} expansion, no custom config post-processing before options binding. Secrets are read verbatim from resolved config values.

Adoption plan (toward SPEC)

  1. Highest value first: move the plaintext LDAP ServiceAccountPassword and the Galaxy connection-string password behind ${secret:ldap/mxgateway/bind} / ${secret:sql/mxgateway/galaxy} — pre-host SecretReferenceExpander before the existing GatewayOptionsValidator runs. Delete the hardcoded plaintext defaults in LdapOptions.
  2. Pepper: the pepper is already runtime-supplied by design — optionally source it via ${secret:apikey-pepper/mxgateway} to close SEC-10's "no dedicated env reader" gap while keeping it out of appsettings.
  3. Master key: env provider (ZB_SECRETS_MASTER_KEY) for the Windows/NSSM deployment, or DPAPI provider (Windows box) if a machine-bound key is preferred.
  4. UI: mount /admin/secrets in the existing Blazor dashboard; map the gateway's Administrator role onto secrets:manage/secrets:reveal.
  5. Keep bespoke: the peppered-HMAC API-key store (already best-practice — hashed, not encrypted-reversible) and the ACL-protected passwordless TLS PFX stay as-is; MXAccess pass-through creds are out of scope (never stored).