# 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).