fix(TST-31): reconcile glauth.md with the shared GLAuth directory, fix propagated live-test credential
glauth.md's OPC-perm group table and pre-provisioned-users table described a directory that no longer exists: all five OPC-perm gids were off by 100 (5501-5505 vs actual 5601-5605), and the user table listed readonly/writeop/writetune/writeconfig/alarmack accounts that scadaproj's shared GLAuth (config.toml) never provisioned. The real per-role testers are opc-readonly/opc-writeop/opc-writetune/opc-writeconfig/opc-alarmack (renamed to avoid a cn= case-collision with their group), and every dev user's password is "password" per config.toml's own comment and passsha256 (not admin123). admin itself is no longer a member of any OPC-perm group in the shared directory (only GwAdmin + OtOpcUa-Admins) - multi-role is the actual "covers every gw capability" account now. The wrong admin123 default had propagated into MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_PASSWORD (docs/GatewayTesting.md) and the WorkerLiveMxAccessSmokeTests.cs literal/comment attributing the rig's GLAuth-bridged ArchestrA identity - both corrected to password. Also made the WriteSecured parity test log (never assert) whether AuthenticateUser succeeded or was rejected: MXAccess parity means a bad credential is a legitimate failure reply, so it must not fail the test, but a stale rig credential was silently degrading the nightly live smoke's WriteSecured leg from an authenticated round-trip to a bare failure-reply-shape check with no visible signal. Verified: dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx succeeds (IntegrationTests builds cleanly on macOS, net10.0, no COM/x86 dependency). Flips Batch B (TST-31) to Done in the cycle-3 remediation tracker.
This commit is contained in:
@@ -514,21 +514,37 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
|
||||
// AuthenticateUser resolves an ArchestrA user id for the WriteSecured call.
|
||||
// Credentials are env-overridable so the test honors the gateway's "do not
|
||||
// log secrets" rule and works against either MXAccess's own user store or
|
||||
// the LmxOpcUa-baseline GLAuth-bridged ArchestrA identity (admin/admin123).
|
||||
// the LmxOpcUa-baseline GLAuth-bridged ArchestrA identity (admin/password —
|
||||
// see glauth.md; the shared GLAuth's dev-user password is "password", not
|
||||
// the old per-box "admin123").
|
||||
MxCommandReply authReply = await fixture.Service.Invoke(
|
||||
CreateAuthenticateUserRequest(sessionId, serverHandle, verifyUser, verifyPassword),
|
||||
new TestServerCallContext()).ConfigureAwait(false);
|
||||
recordedOutput.WriteLine(
|
||||
$"AuthenticateUser status={authReply.ProtocolStatus.Code} hresult={authReply.Hresult} user_id={authReply.AuthenticateUser?.UserId}");
|
||||
|
||||
// AuthenticateUser is allowed to fail (the underlying provider may reject
|
||||
// the credential pair); we use the returned user id if non-zero and fall
|
||||
// back to 0 ("operator only" / no verifier) so the parity assertion holds.
|
||||
int currentUserId = authReply.ProtocolStatus.Code == ProtocolStatusCode.Ok
|
||||
// AuthenticateUser is allowed to fail — MXAccess parity means a rejected
|
||||
// credential is a legitimate reply, not a bug, so this must never be an
|
||||
// Assert. But a silent fall-through to "operator only" (currentUserId 0)
|
||||
// quietly demotes the rest of this test from an authenticated round-trip
|
||||
// to a bare failure-reply-shape check, which a stale rig credential (e.g.
|
||||
// TST-31) would otherwise hide indefinitely in nightly runs. Log the
|
||||
// outcome loudly — never the password (verifyUser only) — so that
|
||||
// degradation is visible in the test output even though it never fails
|
||||
// the test by itself.
|
||||
bool authenticateUserSucceeded = authReply.ProtocolStatus.Code == ProtocolStatusCode.Ok
|
||||
&& authReply.AuthenticateUser is not null
|
||||
&& authReply.AuthenticateUser.UserId != 0
|
||||
? authReply.AuthenticateUser.UserId
|
||||
: 0;
|
||||
&& authReply.AuthenticateUser.UserId != 0;
|
||||
recordedOutput.WriteLine(
|
||||
authenticateUserSucceeded
|
||||
? $"AuthenticateUser SUCCEEDED for user={verifyUser} user_id={authReply.AuthenticateUser!.UserId}"
|
||||
: $"AuthenticateUser FAILED (credential rejected or not recognized by the provider) "
|
||||
+ $"for user={verifyUser} status={authReply.ProtocolStatus.Code} hresult={authReply.Hresult} "
|
||||
+ $"diagnostic={authReply.DiagnosticMessage} -- WriteSecured below will run as an "
|
||||
+ $"unauthenticated (currentUserId=0) failure-reply-shape check only, not an "
|
||||
+ $"authenticated round-trip. If this is unexpected, verify "
|
||||
+ $"MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_USER/_PASSWORD against the rig's ArchestrA "
|
||||
+ $"identity (see glauth.md).");
|
||||
|
||||
int currentUserId = authenticateUserSucceeded ? authReply.AuthenticateUser!.UserId : 0;
|
||||
|
||||
MxCommandReply writeSecuredReply = await fixture.Service.Invoke(
|
||||
CreateWriteSecuredRequest(
|
||||
@@ -1429,7 +1445,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
|
||||
string verifyUser = Environment.GetEnvironmentVariable("MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_USER")
|
||||
?? "admin";
|
||||
string verifyPassword = Environment.GetEnvironmentVariable("MXGATEWAY_LIVE_MXACCESS_WRITE_SECURED_PASSWORD")
|
||||
?? "admin123";
|
||||
?? "password";
|
||||
return (verifyUser, verifyPassword);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user