/// <summary> /// set a new application instance certificate /// </summary> /// <param name="newCertificate"></param> private async Task SetOwnCertificateAsync(X509Certificate2 newCertificate) { if (newCertificate == null || !newCertificate.HasPrivateKey) { throw new ArgumentException("Empty or invalid certificate"); } // attempt to replace the old certificate from the various trust lists var oldCertificate = _opcApplicationConfig.SecurityConfiguration .ApplicationCertificate.Certificate; if (oldCertificate?.Thumbprint != newCertificate.Thumbprint) { return; } _logger.Information( "Setting new application certificate {Thumbprint}, {Subject}...", newCertificate.Thumbprint, newCertificate.SubjectName.Name); // copy the certificate, public key only into the trusted certificates list using (var publicKey = new X509Certificate2(newCertificate.RawData)) { var trustList = _opcApplicationConfig.SecurityConfiguration.TrustedPeerCertificates; if (oldCertificate != null) { trustList.Remove(oldCertificate.YieldReturn()); } trustList.Add(newCertificate.YieldReturn()); } // add the certificate to the own store try { var applicationCertificate = _opcApplicationConfig.SecurityConfiguration .ApplicationCertificate; _logger.Information( "Adding own certificate to configured certificate store"); // Remove old and add new if (oldCertificate != null) { applicationCertificate.RemoveFromStore(oldCertificate); } applicationCertificate.AddToStore(newCertificate, true); } catch (Exception ex) { _logger.Warning(ex, "Failed adding own certificate into configured certificate store."); } // // Work around windows issue and persist application certificate also on // directory if configured. This is needed for container persistence. // if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _configuration.AppCertStoreType == CertificateStoreType.Directory) { var applicationCertificate = new CertificateIdentifier { StoreType = CertificateStoreType.Directory, StorePath = _configuration.OwnCertPath, SubjectName = newCertificate.SubjectName.Name }; try { _logger.Information( "Persisting own certificate into directory certificate store..."); // Remove old and add new if (oldCertificate != null) { applicationCertificate.RemoveFromStore(oldCertificate); } applicationCertificate.AddToStore(newCertificate, true); } catch (Exception ex) { _logger.Warning(ex, "Failed adding own certificate to directory certificate store."); } } _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate .Certificate = newCertificate; await _opcApplicationConfig.CertificateValidator.UpdateCertificate( _opcApplicationConfig.SecurityConfiguration); }
/// <summary> /// Initialize the OPC UA Application's security configuration /// </summary> /// <returns></returns> private async Task InitApplicationSecurityAsync() { // update certificates validator _opcApplicationConfig.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(VerifyCertificate); await _opcApplicationConfig.CertificateValidator .Update(_opcApplicationConfig).ConfigureAwait(false); // lookup for an existing certificate in the configured store var ownCertificate = await _opcApplicationConfig.SecurityConfiguration .ApplicationCertificate.Find(true).ConfigureAwait(false); if (ownCertificate == null) { // // Work around windows issue and lookup application certificate also on // directory if configured. This is needed for container persistence. // if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _configuration.AppCertStoreType == CertificateStoreType.Directory) { // Use x509 store instead of directory for private cert. var ownCertificateIdentifier = new CertificateIdentifier { StoreType = _configuration.AppCertStoreType, StorePath = _configuration.OwnCertPath, SubjectName = _opcApplicationConfig.SecurityConfiguration .ApplicationCertificate.SubjectName }; ownCertificate = await ownCertificateIdentifier.Find(true) .ConfigureAwait(false); if ((ownCertificate != null) && !ownCertificate.Verify()) { try { _logger.Warning("Found malformed own certificate {Thumbprint}, " + "{Subject} in the store - deleting it...", ownCertificate.Thumbprint, ownCertificate.Subject); ownCertificateIdentifier.RemoveFromStore(ownCertificate); } catch (Exception ex) { _logger.Information(ex, "Failed to remove malformed own certificate"); } ownCertificate = null; } } } if (ownCertificate == null) { _logger.Information("Application own certificate not found. " + "Creating a new self-signed certificate with default settings..."); ownCertificate = CertificateFactory.CreateCertificate( _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.StoreType, _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.StorePath, null, _opcApplicationConfig.ApplicationUri, _opcApplicationConfig.ApplicationName, _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null); _opcApplicationConfig.SecurityConfiguration.ApplicationCertificate.Certificate = ownCertificate; _logger.Information( "New application certificate with {Thumbprint}, {Subject} created", ownCertificate.Thumbprint, ownCertificate.SubjectName.Name); } else { _logger.Information("Application certificate with {Thumbprint}, {Subject} " + "found in the certificate store", ownCertificate.Thumbprint, ownCertificate.SubjectName.Name); } // Set the Certificate as the newly created certificate await SetOwnCertificateAsync(ownCertificate); if (_opcApplicationConfig.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _logger.Warning( "WARNING: Automatically accepting certificates. This is a security risk."); } }