docs(security): credential-reference namespaces + migration note (#815)
docs/security.md gains the canonical table of per-driver namespaces, the five
enforcement seams, the out-of-scope cases (appsettings ${secret:}, Sql
connectionStringRef) and the migration steps for existing configs. Galaxy,
OpcUaClient, Heidenhain, Configuration and driver-specs docs, the Galaxy
options XML docs, the drivers rule file and the docker-dev compose comment
point at it. docker-dev's env:GALAXY_MXGW_API_KEY stays valid (allowed legacy
prefix), so no rig change is needed.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,7 @@ Project root files:
|
||||
|
||||
`DriverConfig` JSON binds to `Config/GalaxyDriverOptions.cs`. The four sections are:
|
||||
|
||||
- **`Gateway`** — endpoint, API key secret ref, TLS knobs, connect/call/stream timeouts. `StreamTimeoutSeconds = 0` keeps the long-lived `StreamEvents` RPC open for the driver's lifetime.
|
||||
- **`Gateway`** — endpoint, API key secret ref (`secret:galaxy/<name>` · `secret:otopcua/galaxy/<name>` · `env:OTOPCUA_GALAXY_<NAME>` · legacy `env:GALAXY_MXGW_<NAME>` · `dev:KEY` · literal; anything else, incl. `file:`, is refused — #815, [`docs/security.md`](../security.md) §"Credential references are namespaced per driver"), TLS knobs, connect/call/stream timeouts. `StreamTimeoutSeconds = 0` keeps the long-lived `StreamEvents` RPC open for the driver's lifetime.
|
||||
- **`MxAccess`** — `ClientName` (must be unique per OtOpcUa instance — redundancy pairs enforce uniqueness at install time), `PublishingIntervalMs` (forwarded as `buffered_update_interval_ms` on subscribe), `WriteUserId` for ArchestrA secured-write, `EventPumpChannelCapacity` (default 50_000 — one second of headroom at 50k tags / 1Hz; tune via the `galaxy.events.dropped` metric).
|
||||
- **`Repository`** — `DiscoverPageSize`, `WatchDeployEvents`.
|
||||
- **`Reconnect`** — `InitialBackoffMs`, `MaxBackoffMs`, `ReplayOnSessionLost` (calls the gateway's `ReplaySubscriptions` RPC after reconnect rather than re-issuing subscribe-bulk for every tag).
|
||||
@@ -103,8 +103,10 @@ Galaxy password, so `GalaxyAckCredentialResolver` picks the account per acknowle
|
||||
not silently downgraded to the fallback.
|
||||
2. **The driver's fallback account** — `AlarmAck.FallbackUser` / `FallbackDomain` /
|
||||
`FallbackPasswordSecretRef` in `DriverConfig`, used by keys without an identity and by anonymous
|
||||
sessions. The password ref must be `secret:NAME` / `${secret:NAME}` (production), `env:NAME`,
|
||||
`file:PATH` or `dev:VALUE`; a bare literal is refused so a password never sits in DriverConfig.
|
||||
sessions. The password ref must be `secret:galaxy/NAME` / `secret:otopcua/galaxy/NAME` (or the `${secret:…}`
|
||||
spelling; production), `env:OTOPCUA_GALAXY_NAME` / `env:GALAXY_MXGW_NAME`, or `dev:VALUE`; a bare literal, a
|
||||
`file:` reference or a reference outside the Galaxy namespace is refused (#815) — the password is sent to the
|
||||
authored gateway endpoint, so it must not be able to name another subsystem's secret.
|
||||
3. **Neither** → the driver throws `DriverOperationRefusedException`; **nothing is sent to the
|
||||
gateway**. The refusal is excluded from the resilience breaker (it says nothing about gateway
|
||||
health). How the client learns of it (#760):
|
||||
|
||||
@@ -91,7 +91,11 @@ Host at their own machine. Anything outside the namespace is refused by **every*
|
||||
(`HeidenhainCredentials`, fail-closed independently of earlier validation), the AdminUI **save path**
|
||||
(`RawTreeService` create/update driver + device refuse the config server-side via `DriverConfigSaveGate`, and the
|
||||
driver/device modals disable Save while it is invalid — so a literal never reaches the config database), and the
|
||||
deploy gate `HeidenhainCredentialPersisted`. Messages never echo the value.
|
||||
deploy gate `HeidenhainCredentialPersisted`. Messages never echo the value. Since #815 the parser and resolver are
|
||||
the shared `CredentialReferences` / `DriverCredentialPolicy` (`Core.Abstractions`) that Galaxy and OpcUaClient use
|
||||
too, and Test Connect / live browse also refuse an out-of-namespace reference before any probe or browser runs; a
|
||||
prefix in another casing (`SECRET:`) is refused, and `${secret:heidenhain/<name>}` is accepted as a spelling of
|
||||
`secret:heidenhain/<name>`.
|
||||
|
||||
Resolved **at each login**, never held in options or session state. Fail-closed: an absent secret or unset
|
||||
variable fails the login rather than sending the reference text. An unusable **INSPECT** credential fails the
|
||||
|
||||
@@ -81,6 +81,12 @@ for every field (security policy/mode, auth type, session timeout, keep-alive,
|
||||
browse root, node/depth caps). `ReconnectPeriod` was **deleted** (#676 — unused since #670 removed the SDK reconnect
|
||||
handler, and the AdminUI no longer shows it); stored configs that still carry `reconnectPeriod` keep parsing in the
|
||||
factory, the Test-Connect probe and the browse picker (unknown keys are skipped), and the form drops it on the next save.
|
||||
**Credentials (#815).** `Password` / `UserCertificatePassword` are a literal, `secret:opcuaclient/<name>` (the node's
|
||||
secret store) or `env:OTOPCUA_OPCUACLIENT_<NAME>`. They are resolved on the node and sent to the configured endpoint,
|
||||
so any other `secret:`/`env:` reference (and `file:`) is refused at save, deploy (`CredentialReferenceOutOfScope`), Test
|
||||
Connect, browse and again at session open, before anything is read. Migrate an existing `secret:<name>` by re-creating
|
||||
the secret as `opcuaclient/<name>`. See [`docs/security.md`](../security.md) §"Credential references are namespaced per driver".
|
||||
|
||||
`ProbeTimeoutSeconds` (default 15, AdminUI "Probe timeout") caps the Test-Connect probe's deadline — it can shorten
|
||||
the budget the host hands the probe, never extend it (review 2026-10-21 O-4; it used to be authored and consumed by nothing).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user