Files
lmxopcua/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs
T

87 lines
3.6 KiB
C#

using Opc.Ua;
using Opc.Ua.Configuration;
using Serilog;
using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;
namespace ZB.MOM.WW.OtOpcUa.Client.Shared.Adapters;
/// <summary>
/// Production implementation that builds a real OPC UA ApplicationConfiguration.
/// </summary>
internal sealed class DefaultApplicationConfigurationFactory : IApplicationConfigurationFactory
{
private static readonly ILogger Logger = Log.ForContext<DefaultApplicationConfigurationFactory>();
/// <inheritdoc />
public async Task<ApplicationConfiguration> CreateAsync(ConnectionSettings settings, CancellationToken ct)
{
// Resolve the canonical PKI path lazily on first use so constructing a
// ConnectionSettings instance — including the throwaway copies the client
// service builds per failover attempt — does not touch the filesystem.
// Callers that supply an explicit path override the default.
var storePath = string.IsNullOrWhiteSpace(settings.CertificateStorePath)
? ClientStoragePaths.GetPkiPath()
: settings.CertificateStorePath;
var config = new ApplicationConfiguration(ClientTelemetry.Context)
{
ApplicationName = "OtOpcUaClient",
ApplicationUri = "urn:localhost:OtOpcUaClient",
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier
{
StoreType = CertificateStoreType.Directory,
StorePath = Path.Combine(storePath, "own"),
SubjectName = "CN=OtOpcUaClient"
},
TrustedIssuerCertificates = new CertificateTrustList
{
StoreType = CertificateStoreType.Directory,
StorePath = Path.Combine(storePath, "issuer")
},
TrustedPeerCertificates = new CertificateTrustList
{
StoreType = CertificateStoreType.Directory,
StorePath = Path.Combine(storePath, "trusted")
},
RejectedCertificateStore = new CertificateTrustList
{
StoreType = CertificateStoreType.Directory,
StorePath = Path.Combine(storePath, "rejected")
},
AutoAcceptUntrustedCertificates = settings.AutoAcceptCertificates
},
ClientConfiguration = new ClientConfiguration
{
DefaultSessionTimeout = settings.SessionTimeoutSeconds * 1000
}
};
try
{
await config.ValidateAsync(ApplicationType.Client, ct);
if (settings.SecurityMode != SecurityMode.None)
{
var app = new ApplicationInstance(ClientTelemetry.Context)
{
ApplicationName = "OtOpcUaClient",
ApplicationType = ApplicationType.Client,
ApplicationConfiguration = config
};
await app.CheckApplicationInstanceCertificatesAsync(false, lifeTimeInMonths: 2048, ct: ct);
}
}
catch
{
try { (config.CertificateManager as IDisposable)?.Dispose(); }
catch (Exception ex) { Logger.Warning(ex, "Disposing certificate manager after configuration failure"); }
throw;
}
Logger.Debug("ApplicationConfiguration created for {EndpointUrl}", settings.EndpointUrl);
return config;
}
}