Compare commits

...

4 Commits

Author SHA1 Message Date
Joseph Doherty fb20997dc9 Merge branch 'fix/pkcs-cve-pin' into main
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m47s
ci / java (push) Successful in 2m6s
ci / portable (push) Successful in 8m57s
Claude-Session: https://claude.ai/code/session_016J6isfcgqy4SB2RK3ZvFvT
2026-10-20 07:24:10 -04:00
Joseph Doherty a09fa0a4d6 fix: pin System.Security.Cryptography.Pkcs 10.0.13 (NU1903)
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m23s
ci / java (push) Successful in 2m19s
ci / portable (push) Successful in 10m44s
Microsoft.Data.SqlClient 6.0.2 pulls System.Security.Cryptography.Pkcs 9.0.4,
which carries GHSA-846f-f764-76mx (high) and GHSA-2fmv-rv2c-59x7 (moderate).
With TreatWarningsAsErrors the NU1902/NU1903 audit warnings failed restore.
10.0.13 patches both.

Claude-Session: https://claude.ai/code/session_016J6isfcgqy4SB2RK3ZvFvT
2026-10-20 07:07:59 -04:00
Joseph Doherty 91bbdbf154 Merge branch 'docs/managed-alarm-ack-live-result' into main
ci / nightly-windev (push) Has been skipped
ci / java (push) Successful in 2m14s
ci / windows-x86 (push) Successful in 2m23s
ci / portable (push) Failing after 2m32s
2026-10-18 15:15:58 -04:00
Joseph Doherty 8c095b9a56 Record the managed GUID alarm-ack live result
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m25s
ci / java (push) Successful in 2m18s
ci / portable (push) Failing after 2m39s
The 2026-10-18 live test on the dev rig showed the opt-in managed ack path
cannot work as built: AlarmClient.RegisterConsumer returns -65 alongside the
worker's wnwrap reader (the worker then silently falls back to wnwrap), the
managed client does not recognise the wnwrap GUID even standalone, and the
gateway's GUID arm sends empty identity fields. Replace the docs' claim that
the path works with the measured results and tell operators to leave
MXGATEWAY_USE_MANAGED_ALARM_ACK unset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:11:11 -04:00
3 changed files with 55 additions and 24 deletions
+46 -19
View File
@@ -793,27 +793,54 @@ in the codebase for the forward-compat shape, but the gateway-side
`AcknowledgeAlarmByName` when the public RPC supplies a recognizable `AcknowledgeAlarmByName` when the public RPC supplies a recognizable
`Provider!Group.Tag` reference. `Provider!Group.Tag` reference.
**Opt-in managed GUID ack.** Setting `MXGATEWAY_USE_MANAGED_ALARM_ACK=1` **Opt-in managed GUID ack — does not work on this rig (live-tested
in the gateway's environment (workers inherit it) routes GUID-keyed acks 2026-10-18).** Setting `MXGATEWAY_USE_MANAGED_ALARM_ACK=1` in the
through `aaAlarmManagedClient.AlarmClient.AlarmAckByGUID` instead of the gateway's environment (workers inherit it) makes the worker build an
wnwrap method. That managed method is implemented on this build and `AaManagedAlarmAckConsumer`, which drives
carries operator domain and full name natively. The worker reaches it by `aaAlarmManagedClient.AlarmClient` by reflection (its members are
reflection (`AaManagedAlarmAckConsumer`) because the members are non-public) and is meant to take GUID-keyed acks in place of the
non-public, and runs its own Initialize → Register → Subscribe lifecycle wnwrap method. The live test shows it cannot do that as built, so leave
against the alarm subscription expression. The path is deliberately the flag off.
conservative:
- If the DLL cannot load or the lifecycle returns a non-zero status, the The test raised `TestMachine_001.TestAlarm001` with a secured write,
worker drops back to the wnwrap ack path; alarm reads never fail read its GUID from the wnwrap XML snapshot (the public API exposes no
because of it. alarm GUIDs), and acknowledged it through the `AcknowledgeAlarm` RPC
- Subtag-mode acks (forced subtag, or failover currently on the standby) with the flag on:
stay on the subtag consumer: their GUIDs are synthetic and only it can
resolve them.
- By-name acks stay on wnwrap — `AlarmClient` has no by-name ack.
A zero return still means *accepted*, not *applied*; a secured | Step | Result |
(`MxSecurityOperate`) alarm needs an authenticated operator. The skip-gated |---|---|
`AlarmManagedGuidAckLiveSmokeTests` asserts the ack actually lands. | RPC ack by GUID, flag off (control) | `NotImplementedException`; `.Acked` stays `False` |
| RPC ack by GUID, flag on | Same `NotImplementedException`; `.Acked` `False`, `.AckMsg` empty |
| `AlarmClient.RegisterConsumer` in a process with a registered wnwrap consumer | `-65` — and wnwrap gets `-65` if the managed client registered first; a real `hWnd` does not help |
| Managed client alone in its own process, records loaded | `AlarmAckByGUID` → `-1`, `SelectByGUID` → `-1` for the wnwrap GUID in both byte orders, `AlarmAckSelected` → `-57` |
Three separate problems follow:
1. **The two libraries cannot share a process.** The worker always runs
a wnwrap reader, so the managed `RegisterConsumer` fails with `-65`.
The dispatcher is built to drop back to the wnwrap ack path on a
lifecycle failure (so alarm reads keep working), and it does so
silently — which is why the flag-on RPC is indistinguishable from the
control.
2. **The managed client does not recognise the wnwrap GUID.** `-1` from
`SelectByGUID` is "not found", not a security refusal, even with the
client holding records. Getting the client's own identifier for the
alarm is not reliable either: `GetHighPriAlarm` mostly throws the
FILETIME `ArgumentOutOfRangeException` described above. The
`MxSecurityOperate` question was therefore never reached.
3. **The gateway does not send the identity fields.** Its GUID arm fills
`OperatorNode`, `OperatorDomain` and `OperatorFullName` with empty
strings, so the domain and full name the managed method carries
would not arrive through the public RPC even if 1 and 2 were solved.
A working managed ack would need the client hosted out of process, a way
to resolve the alarm to the identifier the managed client uses, and the
identity fields plumbed through the gateway. Routing rules the worker
already applies stay correct and would carry over: subtag-mode acks
(synthetic GUIDs) stay on the subtag consumer, and by-name acks stay on
wnwrap because `AlarmClient` has no by-name ack. The skip-gated
`AlarmManagedGuidAckLiveSmokeTests` exercises the in-process
arrangement and hits problem 1.
### 5. STA / threading — resolved ### 5. STA / threading — resolved
+6 -5
View File
@@ -446,11 +446,12 @@ behavior.
The alarm monitor is independent of client sessions: `AcknowledgeAlarm` and The alarm monitor is independent of client sessions: `AcknowledgeAlarm` and
`StreamAlarms` are session-less RPCs served by the monitor. `StreamAlarms` are session-less RPCs served by the monitor.
GUID-keyed acknowledges can opt into AVEVA's managed alarm client by setting The worker also reads `MXGATEWAY_USE_MANAGED_ALARM_ACK` (inherited from the
the environment variable `MXGATEWAY_USE_MANAGED_ALARM_ACK=1` on the gateway gateway process). Setting it to `1` is meant to route GUID-keyed acknowledges
process (workers inherit it; under NSSM, add it to the service environment). through AVEVA's managed alarm client, but a live test (2026-10-18) showed the
It is off by default and has no `MxGateway:*` option because it is still path cannot work as built: the managed client fails to register alongside the
awaiting live confirmation on the rig. See worker's wnwrap reader and the worker silently falls back to wnwrap. Leave it
unset. It has no `MxGateway:*` option. See
[AlarmClientDiscovery](./AlarmClientDiscovery.md) ("Opt-in managed GUID ack"). [AlarmClientDiscovery](./AlarmClientDiscovery.md) ("Opt-in managed GUID ack").
### Alarm fallback options ### Alarm fallback options
@@ -32,6 +32,9 @@
native 2.1.11; 2.1.12 patches it. Bumping Sqlite does not clear it. --> native 2.1.11; 2.1.12 patches it. Bumping Sqlite does not clear it. -->
<PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.12" /> <PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.12" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<!-- Security pin: GHSA-846f-f764-76mx / GHSA-2fmv-rv2c-59x7. Microsoft.Data.SqlClient 6.0.2
pulls the vulnerable System.Security.Cryptography.Pkcs 9.0.4; 10.0.13 patches it. -->
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="10.0.13" />
<PackageReference Include="Polly.Core" Version="8.6.6" /> <PackageReference Include="Polly.Core" Version="8.6.6" />
</ItemGroup> </ItemGroup>