Files
scadaproj/ZB.MOM.WW.SPHistorianClient/tests/ZB.MOM.WW.SPHistorianClient.Tests/HistorianWcfCertOptionTests.cs
T

98 lines
4.1 KiB
C#

using System.IdentityModel.Selectors;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using ZB.MOM.WW.SPHistorianClient;
using ZB.MOM.WW.SPHistorianClient.Wcf;
using ZB.MOM.WW.SPHistorianClient.Wcf.Contracts;
namespace ZB.MOM.WW.SPHistorianClient.Tests;
public sealed class HistorianWcfCertOptionTests
{
private static HistorianClientOptions BaseOptions(bool allowUntrusted = false, string? dnsIdentity = null) =>
new()
{
Host = "10.0.0.1",
Port = HistorianClientOptions.DefaultPort,
Transport = HistorianTransport.RemoteTcpCertificate,
IntegratedSecurity = false,
UserName = "user",
Password = "pass",
AllowUntrustedServerCertificate = allowUntrusted,
ServerDnsIdentity = dnsIdentity,
};
[Fact]
public void ClientCredentialsHelper_Disabled_LeavesValidationModeAtDefault()
{
Binding binding = HistorianWcfBindingFactory.CreateMdasNetTcpBinding(TimeSpan.FromSeconds(5));
ChannelFactory<IHistoryServiceContract2> factory = new(binding, new EndpointAddress("net.tcp://10.0.0.1:32568/Hist"));
try
{
HistorianWcfClientCredentialsHelper.Configure(factory, BaseOptions(allowUntrusted: false));
X509ServiceCertificateAuthentication auth = factory.Credentials.ServiceCertificate.SslCertificateAuthentication
?? factory.Credentials.ServiceCertificate.Authentication;
// Default validation mode is ChainTrust — explicitly NOT None / Custom.
Assert.NotEqual(X509CertificateValidationMode.None, auth.CertificateValidationMode);
Assert.Null(auth.CustomCertificateValidator);
}
finally
{
factory.Abort();
}
}
[Fact]
public void ClientCredentialsHelper_Enabled_InstallsAcceptAnyValidator()
{
Binding binding = HistorianWcfBindingFactory.CreateMdasNetTcpBinding(TimeSpan.FromSeconds(5));
ChannelFactory<IHistoryServiceContract2> factory = new(binding, new EndpointAddress("net.tcp://10.0.0.1:32568/Hist"));
try
{
HistorianWcfClientCredentialsHelper.Configure(factory, BaseOptions(allowUntrusted: true));
X509ServiceCertificateAuthentication auth = factory.Credentials.ServiceCertificate.SslCertificateAuthentication;
Assert.NotNull(auth);
Assert.Equal(X509CertificateValidationMode.Custom, auth.CertificateValidationMode);
Assert.Equal(X509RevocationMode.NoCheck, auth.RevocationMode);
Assert.NotNull(auth.CustomCertificateValidator);
Assert.IsAssignableFrom<X509CertificateValidator>(auth.CustomCertificateValidator);
}
finally
{
factory.Abort();
}
}
[Fact]
public void CreateEndpointAddress_WithoutDnsIdentity_HasNullIdentity()
{
EndpointAddress address = HistorianWcfBindingFactory.CreateEndpointAddress("10.0.0.1", 32568, "Hist");
Assert.Null(address.Identity);
}
[Fact]
public void CreateEndpointAddress_WithDnsIdentity_AttachesDnsEndpointIdentity()
{
EndpointAddress address = HistorianWcfBindingFactory.CreateEndpointAddress("10.0.0.1", 32568, "HistCert", "localhost");
Assert.NotNull(address.Identity);
DnsEndpointIdentity dns = Assert.IsType<DnsEndpointIdentity>(address.Identity);
Assert.Equal("localhost", dns.IdentityClaim.Resource);
}
[Fact]
public void CreateBindingPair_RemoteTcpCertificate_PropagatesServerDnsIdentity()
{
HistorianClientOptions options = BaseOptions(dnsIdentity: "localhost");
var (_, historyEndpoint, _, retrievalEndpoint) = HistorianWcfBindingFactory.CreateBindingPair(options);
DnsEndpointIdentity historyIdentity = Assert.IsType<DnsEndpointIdentity>(historyEndpoint.Identity);
Assert.Equal("localhost", historyIdentity.IdentityClaim.Resource);
// The Retrieval endpoint uses plain MdasNetTcp without TLS — no DNS identity needed.
Assert.Null(retrievalEndpoint.Identity);
}
}