예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }