test(c2): make WCF spike transport-selectable (integrated|certificate) + opt-in verbose
The first live run used the wrong port (32568 direct vs the 42568 WCF tunnel) and hardcoded RemoteTcpIntegrated; via the tunnel the error advanced from socket-RST to ProtocolException (binding/security mismatch). Add HISTORIAN_WCF_EVENT_TRANSPORT (certificate), _DNSID, _ALLOW_UNTRUSTED, and an opt-in _VERBOSE for live binding diagnosis. Default output stays sanitized; still Windows-only, never fails the suite. Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -48,17 +48,27 @@ public sealed class WcfEventReadSpikeTests
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_USER");
|
||||
string? password = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_PASSWORD");
|
||||
string? spn = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_SPN");
|
||||
bool integrated = string.IsNullOrEmpty(user);
|
||||
string? dnsId = Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_DNSID");
|
||||
bool certificate = string.Equals(
|
||||
Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_TRANSPORT"), "certificate", StringComparison.OrdinalIgnoreCase);
|
||||
bool allowUntrusted = string.Equals(
|
||||
Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_ALLOW_UNTRUSTED"), "1", StringComparison.Ordinal);
|
||||
// Certificate transport carries no Windows transport credential (cert-validated TLS channel);
|
||||
// integrated derives one from the logged-in identity unless an explicit DOMAIN\user is supplied.
|
||||
// App-level ValidateClientCredential still uses UserName/Password (or the process identity).
|
||||
bool integrated = !certificate && string.IsNullOrEmpty(user);
|
||||
|
||||
HistorianClientOptions options = new()
|
||||
{
|
||||
Host = host,
|
||||
Port = port,
|
||||
Transport = HistorianTransport.RemoteTcpIntegrated,
|
||||
Transport = certificate ? HistorianTransport.RemoteTcpCertificate : HistorianTransport.RemoteTcpIntegrated,
|
||||
IntegratedSecurity = integrated,
|
||||
UserName = user ?? string.Empty,
|
||||
Password = password ?? string.Empty,
|
||||
TargetSpn = string.IsNullOrWhiteSpace(spn) ? "NT SERVICE\\aahClientAccessPoint" : spn,
|
||||
ServerDnsIdentity = string.IsNullOrWhiteSpace(dnsId) ? null : dnsId,
|
||||
AllowUntrustedServerCertificate = allowUntrusted,
|
||||
};
|
||||
|
||||
HistorianWcfEventOrchestrator orchestrator = new(options);
|
||||
@@ -79,10 +89,16 @@ public sealed class WcfEventReadSpikeTests
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
outcome = $"threw {ex.GetType().Name}"; // message omitted — may carry host/credential text
|
||||
// Default: type name only (sanitized). Opt into messages for live binding/protocol debugging
|
||||
// via HISTORIAN_WCF_EVENT_VERBOSE=1 — binding/protocol errors may carry the endpoint host
|
||||
// (already known to the operator) but never credentials; still off by default.
|
||||
outcome = string.Equals(Environment.GetEnvironmentVariable("HISTORIAN_WCF_EVENT_VERBOSE"), "1", StringComparison.Ordinal)
|
||||
? $"threw {ex.GetType().FullName} :: {ex.Message} | inner={ex.InnerException?.GetType().FullName} :: {ex.InnerException?.Message}"
|
||||
: $"threw {ex.GetType().Name}";
|
||||
}
|
||||
|
||||
// Sanitized diagnostic dump — counts, native return codes, buffer lengths, sha256 ONLY.
|
||||
_output.WriteLine($"[C2 WCF spike] transport: {options.Transport} (integratedSec={integrated}, allowUntrusted={allowUntrusted})");
|
||||
_output.WriteLine($"[C2 WCF spike] outcome: {outcome}");
|
||||
_output.WriteLine($"[C2 WCF spike] events observed: {observed}");
|
||||
_output.WriteLine($"[C2 WCF spike] hasFirstEvent: {hasFirstEvent}");
|
||||
|
||||
Reference in New Issue
Block a user