HistorianWcfTagClient: respect options.Transport for cert variant
Browse/metadata previously hardcoded the Windows transport binding + /Hist-Integrated endpoint regardless of options.Transport. That meant RemoteTcpCertificate clients (notably anything from Linux, where the Windows transport security isn't available in WCF) couldn't use these ops even when other reads worked. Made the binding+endpoint selection conditional: - LocalPipe / RemoteTcpIntegrated: keep existing /Hist-Integrated + Windows transport binding (the legacy Open2-V1 buffer carries its own auth blob and only validates against this transport). - RemoteTcpCertificate: switch to /HistCert + cert binding, propagating options.ServerDnsIdentity. Cert-binding callers also opt out of setting Windows credentials on the factory. Cert-validation override (HistorianWcfClientCredentialsHelper.Configure) now applies on both the history and retrieval factories. Confirmed locally: 178/178 tests pass on Windows. Linux verification still pending — gated tests don't exercise the path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using AVEVA.Historian.Client.Models;
|
||||
using AVEVA.Historian.Client.Wcf.Contracts;
|
||||
|
||||
@@ -281,17 +282,38 @@ internal static class HistorianWcfTagClient
|
||||
{
|
||||
ValidateSupportedAuth(options);
|
||||
|
||||
// The browse/metadata code uses the legacy Open2-V1 buffer, which carries
|
||||
// its own auth blob. That buffer is only valid against the WCF transport that
|
||||
// negotiates Windows security at the channel level (`/Hist-Integrated`) or
|
||||
// against the cert binding (which trusts the channel-level cert identity).
|
||||
// For LocalPipe and RemoteTcpIntegrated the original behaviour stays —
|
||||
// hit the Integrated endpoint with the Windows transport binding. Only
|
||||
// RemoteTcpCertificate gets the cert binding here, so browse/metadata
|
||||
// works from a Linux client over the cert transport.
|
||||
(Binding historyBinding, EndpointAddress historyEndpoint) = options.Transport switch
|
||||
{
|
||||
HistorianTransport.RemoteTcpCertificate => (
|
||||
HistorianWcfBindingFactory.CreateMdasNetTcpCertificateBinding(options.RequestTimeout),
|
||||
HistorianWcfBindingFactory.CreateEndpointAddress(options.Host, options.Port, HistorianWcfServiceNames.HistoryCertificate, options.ServerDnsIdentity)),
|
||||
_ => (
|
||||
HistorianWcfBindingFactory.CreateMdasNetTcpWindowsBinding(options.RequestTimeout),
|
||||
HistorianWcfBindingFactory.CreateEndpointAddress(options.Host, options.Port, HistorianWcfServiceNames.HistoryIntegrated)),
|
||||
};
|
||||
|
||||
ChannelFactory<IHistoryServiceContract2>? historyFactory = null;
|
||||
IHistoryServiceContract2? historyChannel = null;
|
||||
ChannelFactory<IRetrievalServiceContract2>? retrievalFactory = null;
|
||||
IRetrievalServiceContract2? retrievalChannel = null;
|
||||
ChannelFactory<IRetrievalServiceContract2>? retrievalFactory = null;
|
||||
IRetrievalServiceContract2? retrievalChannel = null;
|
||||
try
|
||||
{
|
||||
historyFactory = new ChannelFactory<IHistoryServiceContract2>(
|
||||
HistorianWcfBindingFactory.CreateMdasNetTcpWindowsBinding(options.RequestTimeout),
|
||||
HistorianWcfBindingFactory.CreateEndpointAddress(options.Host, options.Port, HistorianWcfServiceNames.HistoryIntegrated));
|
||||
historyFactory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
|
||||
ApplyWindowsCredential(historyFactory, options);
|
||||
historyFactory = new ChannelFactory<IHistoryServiceContract2>(historyBinding, historyEndpoint);
|
||||
HistorianWcfClientCredentialsHelper.Configure(historyFactory, options);
|
||||
if (options.Transport != HistorianTransport.RemoteTcpCertificate)
|
||||
{
|
||||
// Windows transport-security only applies to the integrated-auth binding.
|
||||
historyFactory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
|
||||
ApplyWindowsCredential(historyFactory, options);
|
||||
}
|
||||
historyFactory.Open();
|
||||
|
||||
historyChannel = historyFactory.CreateChannel();
|
||||
@@ -310,6 +332,7 @@ internal static class HistorianWcfTagClient
|
||||
retrievalFactory = new ChannelFactory<IRetrievalServiceContract2>(
|
||||
HistorianWcfBindingFactory.CreateMdasNetTcpBinding(options.RequestTimeout),
|
||||
HistorianWcfBindingFactory.CreateEndpointAddress(options.Host, options.Port, HistorianWcfServiceNames.Retrieval));
|
||||
HistorianWcfClientCredentialsHelper.Configure(retrievalFactory, options);
|
||||
retrievalFactory.Open();
|
||||
|
||||
retrievalChannel = retrievalFactory.CreateChannel();
|
||||
|
||||
Reference in New Issue
Block a user