/// <summary> /// Create session manager /// </summary> /// <param name="clientConfig"></param> /// <param name="identity"></param> /// <param name="logger"></param> public DefaultSessionManager(IClientServicesConfig clientConfig, IIdentity identity, ILogger logger) { _clientConfig = clientConfig; _logger = logger; _identity = identity; _lock = new SemaphoreSlim(1, 1); }
/// <summary> /// Create client host services /// </summary> /// <param name="clientConfig"></param> /// <param name="logger"></param> /// <param name="maxOpTimeout"></param> public ClientServices(ILogger logger, IClientServicesConfig clientConfig, TimeSpan?maxOpTimeout = null) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _clientConfig = clientConfig ?? throw new ArgumentNullException(nameof(clientConfig)); _maxOpTimeout = maxOpTimeout; _appConfig = _clientConfig.ToApplicationConfigurationAsync(true, VerifyCertificate).Result; // Create discovery config and client certificate _timer = new Timer(_ => OnTimer(), null, kEvictionCheck, Timeout.InfiniteTimeSpan); }
/// <summary> /// Create client host services /// </summary> /// <param name="clientConfig"></param> /// <param name="logger"></param> /// <param name="identity"></param> /// <param name="maxOpTimeout"></param> public ClientServices(ILogger logger, IClientServicesConfig clientConfig, IIdentity identity = null, TimeSpan?maxOpTimeout = null) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _clientConfig = clientConfig ?? throw new ArgumentNullException(nameof(clientConfig)); _identity = identity; _maxOpTimeout = maxOpTimeout; // Create discovery config and client certificate _timer = new Timer(_ => OnTimer(), null, kEvictionCheck, Timeout.InfiniteTimeSpan); }
/// <summary> /// Create converter /// </summary> /// <param name="logger"></param> /// <param name="serializer"></param> /// <param name="engineConfig"></param> /// <param name="clientConfig"></param> /// <param name="cryptoProvider"></param> public PublishedNodesJobConverter( ILogger logger, IJsonSerializer serializer, IEngineConfiguration engineConfig, IClientServicesConfig clientConfig, ISecureElement cryptoProvider = null) { _engineConfig = engineConfig ?? throw new ArgumentNullException(nameof(engineConfig)); _clientConfig = clientConfig ?? throw new ArgumentNullException(nameof(clientConfig)); _cryptoProvider = cryptoProvider; _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); }
/// <summary> /// Create session manager /// </summary> /// <param name="clientConfig"></param> /// <param name="identity"></param> /// <param name="logger"></param> public DefaultSessionManager(IClientServicesConfig clientConfig, IIdentity identity, ILogger logger) { _clientConfig = clientConfig; _logger = logger; _identity = identity; _applicationConfiguration = _clientConfig. ToApplicationConfigurationAsync(_identity, true, OnValidate).Result; _endpointConfiguration = _clientConfig.ToEndpointConfiguration(); _lock = new SemaphoreSlim(1, 1); _cts = new CancellationTokenSource(); _runner = Task.Run(() => RunAsync(_cts.Token)); }
/// <summary> /// Create client host services /// </summary> /// <param name="logger"></param> /// <param name="configuration"></param> /// <param name="maxOpTimeout"></param> public ClientServices(ILogger logger, IClientServicesConfig configuration, TimeSpan?maxOpTimeout = null) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _maxOpTimeout = maxOpTimeout; // Create discovery config and client certificate _opcApplicationConfig = CreateApplicationConfiguration( TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(2)); InitApplicationSecurityAsync().Wait(); _timer = new Timer(_ => OnTimer(), null, kEvictionCheck, Timeout.InfiniteTimeSpan); }
/// <summary> /// Create application configuration /// </summary> /// <param name="opcConfig"></param> /// <param name="identity"></param> /// <param name="createSelfSignedCertIfNone"></param> /// <param name="handler"></param> /// <returns></returns> public static async Task <ApplicationConfiguration> ToApplicationConfigurationAsync( this IClientServicesConfig opcConfig, IIdentity identity, bool createSelfSignedCertIfNone, CertificateValidationEventHandler handler) { if (string.IsNullOrWhiteSpace(opcConfig.ApplicationName)) { throw new ArgumentNullException(nameof(opcConfig.ApplicationName)); } // wait with the configuration until network is up for (var retry = 0; retry < 3; retry++) { if (NetworkInterface.GetIsNetworkAvailable()) { break; } else { await Task.Delay(3000); } } var applicationConfiguration = new ApplicationConfiguration { ApplicationName = opcConfig.ApplicationName, ProductUri = opcConfig.ProductUri, ApplicationType = ApplicationType.Client, TransportQuotas = opcConfig.ToTransportQuotas(), CertificateValidator = new CertificateValidator(), ClientConfiguration = new ClientConfiguration(), ServerConfiguration = new ServerConfiguration() }; try { await Retry.WithLinearBackoff(null, new CancellationToken(), async() => { // try to resolve the hostname var hostname = !string.IsNullOrWhiteSpace(identity?.Gateway) ? identity.Gateway : !string.IsNullOrWhiteSpace(identity?.DeviceId) ? identity.DeviceId : Utils.GetHostName(); var alternateBaseAddresses = new List <string>(); try { alternateBaseAddresses.Add($"urn://{hostname}"); var hostEntry = Dns.GetHostEntry(hostname); if (hostEntry != null) { alternateBaseAddresses.Add($"urn://{hostEntry.HostName}"); foreach (var alias in hostEntry.Aliases) { alternateBaseAddresses.Add($"urn://{alias}"); } foreach (var ip in hostEntry.AddressList) { // only ad IPV4 addresses switch (ip.AddressFamily) { case AddressFamily.InterNetwork: alternateBaseAddresses.Add($"urn://{ip}"); break; default: break; } } } } catch { } applicationConfiguration.ApplicationUri = opcConfig.ApplicationUri.Replace("urn:localhost", $"urn:{hostname}"); applicationConfiguration.SecurityConfiguration = opcConfig.ToSecurityConfiguration(hostname); applicationConfiguration.ServerConfiguration.AlternateBaseAddresses = alternateBaseAddresses.ToArray(); await applicationConfiguration.Validate(applicationConfiguration.ApplicationType); var application = new ApplicationInstance(applicationConfiguration); var hasAppCertificate = await application.CheckApplicationInstanceCertificate(true, CertificateFactory.DefaultKeySize); if (!hasAppCertificate) { throw new InvalidConfigurationException("OPC UA application certificate invalid"); } applicationConfiguration.CertificateValidator.CertificateValidation += handler; await applicationConfiguration.CertificateValidator .Update(applicationConfiguration.SecurityConfiguration); }, e => true, 5); } catch (Exception e) { throw new InvalidConfigurationException("OPC UA configuration not valid", e); } return(applicationConfiguration); }
/// <summary> /// Create configuration /// </summary> /// <param name="application"></param> /// <param name="configuration"></param> public SecurityConfig(IClientServicesConfig application, IConfiguration configuration) : base(configuration) { _application = application ?? throw new ArgumentNullException(nameof(application)); }
/// <summary> /// Create application configuration /// </summary> /// <param name="opcConfig"></param> /// <param name="handler"></param> /// <param name="createSelfSignedCertIfNone"></param> /// <returns></returns> public static async Task <ApplicationConfiguration> ToApplicationConfigurationAsync( this IClientServicesConfig opcConfig, bool createSelfSignedCertIfNone, CertificateValidationEventHandler handler) { if (string.IsNullOrWhiteSpace(opcConfig.ApplicationName)) { throw new ArgumentNullException(nameof(opcConfig.ApplicationName)); } var applicationConfiguration = new ApplicationConfiguration { ApplicationName = opcConfig.ApplicationName, ApplicationUri = opcConfig.ApplicationUri, ProductUri = opcConfig.ProductUri, ApplicationType = ApplicationType.Client, TransportQuotas = opcConfig.ToTransportQuotas(), SecurityConfiguration = opcConfig.ToSecurityConfiguration(), ClientConfiguration = new ClientConfiguration(), CertificateValidator = new CertificateValidator() }; applicationConfiguration.CertificateValidator.CertificateValidation += handler; var configuredSubject = applicationConfiguration.SecurityConfiguration .ApplicationCertificate.SubjectName; applicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = applicationConfiguration.ApplicationName; await applicationConfiguration.CertificateValidator .Update(applicationConfiguration.SecurityConfiguration); // use existing certificate, if present var certificate = applicationConfiguration.SecurityConfiguration .ApplicationCertificate.Certificate; // create a self signed certificate if there is none if (certificate == null && createSelfSignedCertIfNone) { certificate = CertificateFactory.CreateCertificate( applicationConfiguration.SecurityConfiguration .ApplicationCertificate.StoreType, applicationConfiguration.SecurityConfiguration .ApplicationCertificate.StorePath, null, applicationConfiguration.ApplicationUri, applicationConfiguration.ApplicationName, configuredSubject, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize ); if (certificate == null) { throw new Exception( "OPC UA application certificate can not be created! Cannot continue without it!"); } applicationConfiguration.SecurityConfiguration .ApplicationCertificate.Certificate = certificate; try { // copy the certificate *public key only* into the trusted certificates list using (ICertificateStore trustedStore = applicationConfiguration .SecurityConfiguration.TrustedPeerCertificates.OpenStore()) { using (var publicKey = new X509Certificate2(certificate.RawData)) { trustedStore.Add(publicKey.YieldReturn()); } } } catch { } // update security information await applicationConfiguration.CertificateValidator.UpdateCertificate( applicationConfiguration.SecurityConfiguration); } applicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); return(applicationConfiguration); }
/// <summary> /// Build the opc ua stack application configuration /// </summary> public static async Task <ApplicationConfiguration> BuildApplicationConfigurationAsync( this IClientServicesConfig opcConfig, IIdentity identity, CertificateValidationEventHandler handler, ILogger logger) { if (string.IsNullOrWhiteSpace(opcConfig.ApplicationName)) { throw new ArgumentNullException(nameof(opcConfig.ApplicationName)); } // wait with the configuration until network is up for (var retry = 0; retry < 3; retry++) { if (NetworkInterface.GetIsNetworkAvailable()) { break; } else { await Task.Delay(3000); } } var appInstance = new ApplicationInstance { ApplicationName = opcConfig.ApplicationName, ApplicationType = ApplicationType.Client, }; try { await Retry.WithLinearBackoff(null, new CancellationToken(), async() => { // try to resolve the hostname var hostname = !string.IsNullOrWhiteSpace(identity?.Gateway) ? identity.Gateway : !string.IsNullOrWhiteSpace(identity?.DeviceId) ? identity.DeviceId : Utils.GetHostName(); var appBuilder = appInstance .Build( opcConfig.ApplicationUri.Replace("urn:localhost", $"urn:{hostname}"), opcConfig.ProductUri) .SetTransportQuotas(opcConfig.ToTransportQuotas()) .AsClient(); var appConfig = await opcConfig .BuildSecurityConfiguration( appBuilder, appInstance.ApplicationConfiguration, hostname) .ConfigureAwait(false); appConfig.CertificateValidator.CertificateValidation += handler; var ownCertificate = appConfig.SecurityConfiguration.ApplicationCertificate.Certificate; if (ownCertificate == null) { logger.Information("No application own certificate found. Creating a self-signed " + "own certificate valid since yesterday for {defaultLifeTime} months, with a " + "{defaultKeySize} bit key and {defaultHashSize} bit hash.", CertificateFactory.DefaultLifeTime, CertificateFactory.DefaultKeySize, CertificateFactory.DefaultHashSize); } else { logger.Information("Own certificate Subject '{subject}' (thumbprint: {thumbprint}) loaded.", ownCertificate.Subject, ownCertificate.Thumbprint); } var hasAppCertificate = await appInstance .CheckApplicationInstanceCertificate( true, CertificateFactory.DefaultKeySize, CertificateFactory.DefaultLifeTime) .ConfigureAwait(false); if (!hasAppCertificate || appConfig.SecurityConfiguration.ApplicationCertificate.Certificate == null) { logger.Error("Failed to load or create application own certificate."); throw new InvalidConfigurationException("OPC UA application own certificate invalid"); } if (ownCertificate == null) { ownCertificate = appConfig.SecurityConfiguration.ApplicationCertificate.Certificate; logger.Information("Own certificate Subject '{subject}' (thumbprint: {thumbprint}) created.", ownCertificate.Subject, ownCertificate.Thumbprint); } await ShowCertificateStoreInformationAsync(appConfig, logger) .ConfigureAwait(false); }, e => true, 5); } catch (Exception e) { throw new InvalidConfigurationException("OPC UA configuration not valid", e); } return(appInstance.ApplicationConfiguration); }