public async Task <X509CertificateCollection> KeyVaultSigningRequestAsync() { Skip.If(!_fixture.KeyVaultInitOk); X509CertificateCollection certCollection = new X509CertificateCollection(); string[] groups = await _keyVault.GetCertificateGroupIds(); foreach (string group in groups) { var certificateGroupConfiguration = await _keyVault.GetCertificateGroupConfiguration(group); ApplicationTestData randomApp = _fixture.RandomGenerator.RandomApplicationTestData(); X509Certificate2 csrCertificate = CertificateFactory.CreateCertificate( null, null, null, randomApp.ApplicationRecord.ApplicationUri, null, randomApp.Subject, randomApp.DomainNames.ToArray(), certificateGroupConfiguration.DefaultCertificateKeySize, DateTime.UtcNow.AddDays(-10), certificateGroupConfiguration.DefaultCertificateLifetime, certificateGroupConfiguration.DefaultCertificateHashSize ); byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, randomApp.DomainNames); X509Certificate2 newCert = await _keyVault.SigningRequestAsync( group, randomApp.ApplicationRecord.ApplicationUri, certificateRequest); // get issuer cert used for signing X509Certificate2Collection issuerCerts = await _keyVault.GetIssuerCACertificateChainAsync(group); #if WRITECERT // save cert for debugging using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreType.Directory)) { Assert.NotNull(store); store.Open("d:\\unittest"); await store.Add(newCert); foreach (var cert in issuerCerts) { await store.Add(cert); } } #endif Assert.NotNull(issuerCerts); Assert.True(issuerCerts.Count >= 1); X509TestUtils.VerifySignedApplicationCert(randomApp, newCert, issuerCerts); certCollection.Add(newCert); } return(certCollection); }
/// <summary> /// Saves the certificate in the rejected certificate store. /// </summary> private void SaveCertificate(X509Certificate2 certificate) { lock (m_lock) { if (m_rejectedCertificateStore != null) { Utils.Trace((int)Utils.TraceMasks.Error, "Writing rejected certificate to directory: {0}", m_rejectedCertificateStore); try { ICertificateStore store = m_rejectedCertificateStore.OpenStore(); try { store.Delete(certificate.Thumbprint); store.Add(certificate); } finally { store.Close(); } } catch (Exception e) { Utils.Trace(e, "Could not write certificate to directory: {0}", m_rejectedCertificateStore); } } } }
/// <summary> /// Updates the certificate authority certificate and CRL in the trusted list. /// </summary> private async Task UpdateAuthorityCertInTrustedList() { string trustedListStorePath = Configuration.TrustedListPath; if (!String.IsNullOrEmpty(Configuration.TrustedListPath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(trustedListStorePath)) { X509Certificate2Collection certs = await store.FindByThumbprint(Certificate.Thumbprint); if (certs.Count == 0) { await store.Add(Certificate); } // delete existing CRL in trusted list foreach (var crl in store.EnumerateCRLs(Certificate, false)) { if (crl.VerifySignature(Certificate, false)) { store.DeleteCRL(crl); } } // copy latest CRL to trusted list using (ICertificateStore storeAuthority = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath)) { foreach (var crl in storeAuthority.EnumerateCRLs(Certificate, true)) { store.AddCRL(crl); } } } } }
public async Task TestNoFileConfigAsServerX509Store() { #if NETCOREAPP2_1_OR_GREATER // this test fails on macOS, ignore if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { Assert.Ignore("X509Store trust lists not supported on mac OS."); } #endif var applicationInstance = new ApplicationInstance() { ApplicationName = ApplicationName }; Assert.NotNull(applicationInstance); ApplicationConfiguration config = await applicationInstance.Build(ApplicationUri, ProductUri) .AsServer(new string[] { "opc.tcp://localhost:51000" }) .AddUnsecurePolicyNone() .AddSignAndEncryptPolicies() .AddUserTokenPolicy(UserTokenType.UserName) .AsClient() .SetDefaultSessionTimeout(10000) .AddSecurityConfiguration(SubjectName, CertificateStoreType.X509Store) .Create().ConfigureAwait(false); Assert.NotNull(config); bool certOK = await applicationInstance.CheckApplicationInstanceCertificate(true, 0).ConfigureAwait(false); using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) { await store.Add(applicationInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate); } Assert.True(certOK); }
public async Task VerifyAppChainsOneTrusted() { var stopWatch = new Stopwatch(); stopWatch.Start(); // verify cert with issuer chain for (int v = 0; v < kCaChainCount; v++) { long start = stopWatch.ElapsedMilliseconds; TestContext.Out.WriteLine($"Chain Number {v}, Total Elapsed: {start}"); CleanupValidatorAndStores(); TestContext.Out.WriteLine($"Cleanup: {stopWatch.ElapsedMilliseconds-start}"); for (int i = 0; i < kCaChainCount; i++) { ICertificateStore store = i == v ? m_trustedStore : m_issuerStore; await store.Add(m_caChain[i]); store.AddCRL(m_crlChain[i]); } TestContext.Out.WriteLine($"AddChains: {stopWatch.ElapsedMilliseconds - start}"); var certValidator = InitValidatorWithStores(); TestContext.Out.WriteLine($"InitValidator: {stopWatch.ElapsedMilliseconds - start}"); foreach (var app in m_goodApplicationTestSet) { certValidator.Validate(new X509Certificate2(app.Certificate)); } TestContext.Out.WriteLine($"Validation: {stopWatch.ElapsedMilliseconds - start}"); } TestContext.Out.WriteLine($"Total: {stopWatch.ElapsedMilliseconds}"); }
private void PasteMI_Click(object sender, EventArgs e) { try { string xml = (string)ClipboardHack.GetData(DataFormats.Text); if (String.IsNullOrEmpty(xml)) { return; } // deserialize the data. CertificateIdentifier id = null; using (XmlTextReader reader = new XmlTextReader(new StringReader(xml))) { DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateIdentifier)); id = (CertificateIdentifier)serializer.ReadObject(reader, false); } if (id.Certificate != null) { using (ICertificateStore store = m_storeId.OpenStore()) { store.Add(id.Certificate); } AddItem(id.Certificate); } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
protected async Task UpdateGroupStore(string storePath, X509Certificate2Collection certs, IList <Opc.Ua.X509CRL> crls) { if (!String.IsNullOrEmpty(storePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { X509Certificate2Collection oldCertificates = await store.Enumerate(); foreach (var cert in oldCertificates) { await store.Delete(cert.Thumbprint); } foreach (var crl in store.EnumerateCRLs()) { store.DeleteCRL(crl); } foreach (var cert in certs) { await store.Add(cert); } foreach (var crl in crls) { store.AddCRL(crl); } } } }
/// <summary> /// Synchronous helper implementation of CheckApplicationInstanceCertificate for C++ Proxy /// </summary> public static void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration) { // create a default certificate id none specified. CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate; if (id == null) { id = new CertificateIdentifier(); id.StoreType = Utils.DefaultStoreType; id.StorePath = Utils.DefaultStorePath; id.SubjectName = configuration.ApplicationName; } // check for certificate with a private key. X509Certificate2 certificate = id.Find(true).Result; if (certificate != null) { return; } // construct the subject name from the List <string> hostNames = new List <string>(); hostNames.Add(Utils.GetHostName()); string commonName = Utils.Format("CN={0}", configuration.ApplicationName); string domainName = Utils.Format("DC={0}", hostNames[0]); string subjectName = Utils.Format("{0}, {1}", commonName, domainName); // create a new certificate with a new public key pair. certificate = CertificateFactory.CreateCertificate( configuration.ApplicationUri, configuration.ApplicationName, subjectName, hostNames) .CreateForRSA() .AddToStore( id.StoreType, id.StorePath); id.Certificate = certificate; // update and save the configuration file. configuration.SaveToFile(configuration.SourceFilePath); // add certificate to the trusted peer store so other applications will trust it. using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) { X509Certificate2Collection certificateCollection = store.FindByThumbprint(certificate.Thumbprint).Result; if (certificateCollection != null) { store.Add(certificateCollection[0]).Wait(); } } // tell the certificate validator about the new certificate. configuration.CertificateValidator.Update(configuration.SecurityConfiguration).Wait(); }
private ServiceResult AddCertificate( ISystemContext context, MethodState method, NodeId objectId, byte[] certificate, bool isTrustedCertificate) { HasSecureWriteAccess(context); lock (m_lock) { if (m_sessionId != null) { return StatusCodes.BadInvalidState; } if (certificate == null) { return StatusCodes.BadInvalidArgument; } X509Certificate2 cert = null; X509CRL crl = null; try { cert = new X509Certificate2(certificate); } catch { try { crl = new X509CRL(certificate); } catch { return StatusCodes.BadCertificateInvalid; } } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { if (cert != null) { store.Add(cert).Wait(); } if (crl != null) { store.AddCRL(crl); } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } return ServiceResult.Good; }
/// <summary> /// Handles a drop event. /// </summary> protected override void NodesTV_DragDrop(object sender, DragEventArgs e) { try { TreeNode node = NodesTV.GetNodeAt(PointToClient(new Point(e.X, e.Y))); if (node == null) { return; } ContainerInfo info = node.Tag as ContainerInfo; if (info == null) { return; } if (info.Type == ContainerInfoType.Store) { CertificateStoreIdentifier id = info.GetCertificateStore(); if (id == null) { return; } object[] certificates = e.Data.GetData(typeof(object[])) as object[]; if (certificates == null) { return; } using (ICertificateStore store = id.OpenStore()) { for (int ii = 0; ii < certificates.Length; ii++) { X509Certificate2 certificate = certificates[ii] as X509Certificate2; if (certificate != null) { store.Add(certificate); } } } NodesTV.SelectedNode = node; return; } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
public async Task TestNoFileConfigAsServerX509Store() { #if NETCOREAPP2_1_OR_GREATER // this test fails on macOS, ignore if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { Assert.Ignore("X509Store trust lists not supported on mac OS."); } #endif var applicationInstance = new ApplicationInstance() { ApplicationName = ApplicationName }; Assert.NotNull(applicationInstance); ApplicationConfiguration config = await applicationInstance.Build(ApplicationUri, ProductUri) .AsServer(new string[] { EndpointUrl }) .AddUnsecurePolicyNone() .AddSignAndEncryptPolicies() .AddUserTokenPolicy(UserTokenType.UserName) .AsClient() .SetDefaultSessionTimeout(10000) .AddSecurityConfiguration(SubjectName, CertificateStoreType.X509Store) .Create().ConfigureAwait(false); Assert.NotNull(config); var applicationCertificate = applicationInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate; bool deleteAfterUse = applicationCertificate.Certificate != null; bool certOK = await applicationInstance.CheckApplicationInstanceCertificate(true, 0).ConfigureAwait(false); Assert.True(certOK); using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) { // store public key in trusted store var rawData = applicationCertificate.Certificate.RawData; await store.Add(new X509Certificate2(rawData)); } if (deleteAfterUse) { var thumbprint = applicationCertificate.Certificate.Thumbprint; using (ICertificateStore store = applicationCertificate.OpenStore()) { bool success = await store.Delete(thumbprint); Assert.IsTrue(success); } using (ICertificateStore store = applicationInstance.ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) { bool success = await store.Delete(thumbprint); Assert.IsTrue(success); } } }
private ServiceResult AddCertificate( ISystemContext context, MethodState method, NodeId objectId, byte[] certificate, bool isTrustedCertificate) { HasSecureWriteAccess(context); ServiceResult result = StatusCodes.Good; lock (m_lock) { if (m_sessionId != null) { result = StatusCodes.BadInvalidState; } else if (certificate == null) { result = StatusCodes.BadInvalidArgument; } else { X509Certificate2 cert = null; try { cert = new X509Certificate2(certificate); } catch { // note: a previous version of the sample code accepted also CRL, // but the behaviour was not as specified and removed // https://mantis.opcfoundation.org/view.php?id=6342 result = StatusCodes.BadCertificateInvalid; } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { if (cert != null) { store.Add(cert).GetAwaiter().GetResult(); } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } } // report the TrustListUpdatedAuditEvent object[] inputParameters = new object[] { certificate, isTrustedCertificate }; m_node.ReportTrustListUpdatedAuditEvent(context, objectId, "Method/AddCertificate", method.NodeId, inputParameters, result.StatusCode); return(result); }
private void ImportMenuItem_Click(object sender, EventArgs e) { try { string directory = Environment.CurrentDirectory; if (m_certificateFile != null) { directory = m_certificateFile.DirectoryName; } OpenFileDialog dialog = new OpenFileDialog { CheckFileExists = true, CheckPathExists = true, DefaultExt = "*.der", Filter = "Certificate Files (*.der)|*.der|All Files (*.*)|*.*", Title = "Import Certificate", Multiselect = false, ValidateNames = true, FileName = m_certificateFile?.Name, InitialDirectory = directory, RestoreDirectory = true }; if (dialog.ShowDialog() != DialogResult.OK) { return; } m_certificateFile = new FileInfo(dialog.FileName); X509Certificate2 certificate = CertificateFactory.Load(new X509Certificate2(File.ReadAllBytes(dialog.FileName)), false); if (certificate != null) { if (!String.IsNullOrEmpty(m_trustedStorePath)) { using (ICertificateStore store = CreateStore(m_trustedStorePath)) { store.Add(certificate); } } } AddCertificate(certificate, Status.Trusted, null); NoDataWarningLabel.Visible = CertificatesTable.Rows.Count == 0; } catch (Exception ex) { Opc.Ua.Client.Controls.ExceptionDlg.Show(Text, ex); } }
public async Task VerifyAppChainsWithGoodAndInvalidChain() { // verify cert with issuer chain for (int v = 0; v < kCaChainCount; v++) { CleanupValidatorAndStores(); for (int i = 0; i < kCaChainCount; i++) { ICertificateStore store = i == v ? m_trustedStore : m_issuerStore; await store.Add(m_caChain[i]); store.AddCRL(m_crlChain[i]); await store.Add(m_caDupeChain[i]); store.AddCRL(m_crlDupeChain[i]); } var certValidator = InitValidatorWithStores(); foreach (var app in m_goodApplicationTestSet) { certValidator.Validate(new X509Certificate2(app.Certificate)); } } }
private void MoveCertificate(DataRow row, Status status) { Status oldStatus = (Status)row[4]; row[4] = status; SetIcon(row, status); string targetStorePath = null; switch (status) { case Status.Trusted: { targetStorePath = m_trustedStorePath; break; } case Status.Issuer: { targetStorePath = m_issuerStorePath; break; } case Status.Rejected: { targetStorePath = m_rejectedStorePath; break; } } string oldStorePath = null; switch (oldStatus) { case Status.Trusted: { oldStorePath = m_trustedStorePath; break; } case Status.Issuer: { oldStorePath = m_issuerStorePath; break; } case Status.Rejected: { oldStorePath = m_rejectedStorePath; break; } } X509Certificate2 certificate = (X509Certificate2)row[7]; if (oldStorePath != targetStorePath) { if (!String.IsNullOrEmpty(targetStorePath)) { using (ICertificateStore store = CreateStore(targetStorePath)) { store.Add(certificate); } } if (!String.IsNullOrEmpty(oldStorePath)) { using (ICertificateStore store = CreateStore(oldStorePath)) { store.Delete(certificate.Thumbprint); } } } }
/// <summary> /// Add to certificate store /// </summary> /// <param name="store"></param> /// <param name="certificates"></param> /// <param name="noCopy"></param> /// <returns></returns> public static void Add(this ICertificateStore store, IEnumerable <X509Certificate2> certificates, bool noCopy = false) { if (certificates == null) { throw new ArgumentNullException(nameof(certificates)); } foreach (var cert in certificates) { Try.Op(() => store.Delete(cert.Thumbprint)); store.Add(noCopy ? cert : new X509Certificate2(cert)); } }
/// <summary> /// Saves the certificate in the invalid certificate directory. /// </summary> private void SaveCertificate(X509Certificate2 certificate) { try { ICertificateStore store = m_rejectedCertificateStore.OpenStore(); try { store.Delete(certificate.Thumbprint); store.Add(certificate); } finally { store.Close(); } } catch (Exception e) { Utils.Trace(e, "Could not write certificate to directory: {0}", m_rejectedCertificateStore); } }
private ServiceResult AddCertificate( ISystemContext context, MethodState method, NodeId objectId, byte[] certificate, bool isTrustedCertificate) { HasSecureWriteAccess(context); lock (m_lock) { if (m_sessionId != null) { return(StatusCodes.BadInvalidState); } if (certificate == null) { return(StatusCodes.BadInvalidArgument); } X509Certificate2 cert = null; try { cert = new X509Certificate2(certificate); } catch { // note: a previous version of the sample code accepted also CRL, // but the behaviour was not as specified and removed // https://mantis.opcfoundation.org/view.php?id=6342 return(StatusCodes.BadCertificateInvalid); } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { if (cert != null) { store.Add(cert).Wait(); } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } return(ServiceResult.Good); }
private void PasteMI_Click(object sender, EventArgs e) { try { string xml = (string)ClipboardHack.GetData(DataFormats.Text); if (String.IsNullOrEmpty(xml)) { return; } // check if in the favorites list. ContainerInfo info = NodesTV.SelectedNode.Tag as ContainerInfo; // check if pasting into a store. if (info.Type == ContainerInfoType.Store) { CertificateIdentifier id = null; using (XmlTextReader reader = new XmlTextReader(new StringReader(xml))) { DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateIdentifier)); id = (CertificateIdentifier)serializer.ReadObject(reader, false); } if (id.Certificate != null) { CertificateStoreIdentifier storeId = info.GetCertificateStore(); using (ICertificateStore store = storeId.OpenStore()) { store.Add(id.Certificate); } } SelectNode(); return; } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
/// <summary> /// Adds an application certificate to a store. /// </summary> private static void AddApplicationCertificateToStore( CertificateStoreIdentifier csid, X509Certificate2 certificate, string oldThumbprint) { ICertificateStore store = csid.OpenStore(); try { // delete the old certificate. if (oldThumbprint != null) { store.Delete(oldThumbprint); } // delete certificates with the same application uri. if (store.FindByThumbprint(certificate.Thumbprint) != null) { return; } string applicationUri = Utils.GetApplicationUriFromCertficate(certificate); // delete any existing certificates. foreach (X509Certificate2 target in store.Enumerate()) { if (!Utils.CompareDistinguishedName(target.Subject, certificate.Subject)) { continue; } if (Utils.GetApplicationUriFromCertficate(target) == applicationUri) { store.Delete(target.Thumbprint); } } // add new certificate. store.Add(new X509Certificate2(certificate.RawData)); } finally { store.Close(); } }
/// <summary> /// Adds the certificate to the Trusted Certificate Store /// </summary> /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param> /// <param name="certificate">The certificate to register.</param> public static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate) { ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); try { // check if it already exists. X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (existingCertificates.Count > 0) { return; } List <string> subjectName = Utils.ParseDistinguishedName(certificate.Subject); // check for old certificate. X509Certificate2Collection certificates = await store.Enumerate(); for (int ii = 0; ii < certificates.Count; ii++) { if (Utils.CompareDistinguishedName(certificates[ii], subjectName)) { if (certificates[ii].Thumbprint == certificate.Thumbprint) { return; } await store.Delete(certificates[ii].Thumbprint); break; } } // add new certificate. X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); await store.Add(publicKey); } finally { store.Close(); } }
/// <summary> /// Updates the certificate authority certificate and CRL in the trusted list. /// </summary> protected async Task UpdateAuthorityCertInTrustedList() { string trustedListStorePath = Configuration.TrustedListPath; if (!String.IsNullOrEmpty(Configuration.TrustedListPath)) { using (ICertificateStore authorityStore = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath)) using (ICertificateStore trustedStore = CertificateStoreIdentifier.OpenStore(trustedListStorePath)) { X509Certificate2Collection certificates = await authorityStore.Enumerate(); foreach (var certificate in certificates) { if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName)) { X509Certificate2Collection certs = await trustedStore.FindByThumbprint(certificate.Thumbprint); if (certs.Count == 0) { await trustedStore.Add(new X509Certificate2(certificate.RawData)); } // delete existing CRL in trusted list foreach (var crl in trustedStore.EnumerateCRLs(certificate, false)) { if (crl.VerifySignature(certificate, false)) { trustedStore.DeleteCRL(crl); } } // copy latest CRL to trusted list foreach (var crl in authorityStore.EnumerateCRLs(certificate, true)) { trustedStore.AddCRL(crl); } } } } } }
private async Task <bool> UpdateStoreCertificates( CertificateTrustList trustList, X509Certificate2Collection updatedCerts) { bool result = true; ICertificateStore store = null; try { store = trustList.OpenStore(); var storeCerts = await store.Enumerate().ConfigureAwait(false); foreach (var cert in storeCerts) { if (!updatedCerts.Contains(cert)) { if (!store.Delete(cert.Thumbprint).Result) { result = false; } } else { updatedCerts.Remove(cert); } } foreach (var cert in updatedCerts) { await store.Add(cert).ConfigureAwait(false); } } catch { result = false; } finally { store?.Close(); } return(result); }
private async Task <bool> UpdateStoreCertificates( string storePath, X509Certificate2Collection updatedCerts) { bool result = true; try { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { var storeCerts = await store.Enumerate().ConfigureAwait(false); foreach (var cert in storeCerts) { if (!updatedCerts.Contains(cert)) { if (!await store.Delete(cert.Thumbprint).ConfigureAwait(false)) { result = false; } } else { updatedCerts.Remove(cert); } } foreach (var cert in updatedCerts) { await store.Add(cert).ConfigureAwait(false); } } } catch { result = false; } return(result); }
/// <summary> /// Extension to add a certificate to a <see cref="ICertificateStore"/>. /// </summary> /// <remarks> /// Saves also the private key, if available. /// If written to a Pfx file, the password is used for protection. /// </remarks> /// <param name="certificate">The certificate to store.</param> /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param> /// <param name="storePath">The store path (syntax depends on storeType).</param> /// <param name="password">The password to use to protect the certificate.</param> /// <returns></returns> public static X509Certificate2 AddToStore( this X509Certificate2 certificate, string storeType, string storePath, string password = null) { // add cert to the store. if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType)) { using (ICertificateStore store = Opc.Ua.CertificateStoreIdentifier.CreateStore(storeType)) { if (store == null) { throw new ArgumentException("Invalid store type"); } store.Open(storePath); store.Add(certificate, password).Wait(); store.Close(); } } return(certificate); }
private bool UpdateStoreCertificates( string storePath, X509Certificate2Collection updatedCerts) { bool result = true; try { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { var storeCerts = store.Enumerate().Result; foreach (var cert in storeCerts) { if (!updatedCerts.Contains(cert)) { if (!store.Delete(cert.Thumbprint).Result) { result = false; } } else { updatedCerts.Remove(cert); } } foreach (var cert in updatedCerts) { store.Add(cert).Wait(); } } } catch { result = false; } return(result); }
/// <summary> /// Adds the certificate to the Trusted Certificate Store /// </summary> /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param> /// <param name="certificate">The certificate to register.</param> private static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } string storePath = null; if (configuration != null && configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null) { storePath = configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath; } if (String.IsNullOrEmpty(storePath)) { Utils.Trace(Utils.TraceMasks.Information, "WARNING: Trusted peer store not specified."); return; } try { ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Utils.Trace("Could not open trusted peer store. StorePath={0}", storePath); return; } try { // check if it already exists. X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (existingCertificates.Count > 0) { return; } Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", storePath); List <string> subjectName = X509Utils.ParseDistinguishedName(certificate.Subject); // check for old certificate. X509Certificate2Collection certificates = await store.Enumerate(); for (int ii = 0; ii < certificates.Count; ii++) { if (X509Utils.CompareDistinguishedName(certificates[ii], subjectName)) { if (certificates[ii].Thumbprint == certificate.Thumbprint) { return; } await store.Delete(certificates[ii].Thumbprint); break; } } // add new certificate. X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); await store.Add(publicKey); } finally { store.Close(); } } catch (Exception e) { Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", storePath); } }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // validate new subject matches the previous subject if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = X509Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; if (updateCertificate != null) { try { using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore()) { Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate); appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey); var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait(); // keep only track of cert without private key var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData); updateCertificate.CertificateWithPrivateKey.Dispose(); updateCertificate.CertificateWithPrivateKey = certOnly; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer); issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } } catch (Exception ex) { Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex)); throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex); } } return(ServiceResult.Good); }
/// <summary> /// Creates a self signed application instance certificate. /// </summary> /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param> /// <param name="storePath">The store path (syntax depends on storeType).</param> /// <param name="password">The password to use to protect the certificate.</param> /// <param name="applicationUri">The application uri (created if not specified).</param> /// <param name="applicationName">Name of the application (optional if subjectName is specified).</param> /// <param name="subjectName">The subject used to create the certificate (optional if applicationName is specified).</param> /// <param name="domainNames">The domain names that can be used to access the server machine (defaults to local computer name if not specified).</param> /// <param name="keySize">Size of the key (1024, 2048 or 4096).</param> /// <param name="startTime">The start time.</param> /// <param name="lifetimeInMonths">The lifetime of the key in months.</param> /// <param name="hashSizeInBits">The hash size in bits.</param> /// <param name="isCA">if set to <c>true</c> then a CA certificate is created.</param> /// <param name="issuerCAKeyCert">The CA cert with the CA private key.</param> /// <returns>The certificate with a private key.</returns> public static X509Certificate2 CreateCertificate( string storeType, string storePath, string password, string applicationUri, string applicationName, string subjectName, IList <String> domainNames, ushort keySize, DateTime startTime, ushort lifetimeInMonths, ushort hashSizeInBits, bool isCA = false, X509Certificate2 issuerCAKeyCert = null, byte[] publicKey = null) { if (issuerCAKeyCert != null) { if (!issuerCAKeyCert.HasPrivateKey) { throw new NotSupportedException("Cannot sign with a CA certificate without a private key."); } } if (publicKey != null && issuerCAKeyCert == null) { throw new NotSupportedException("Cannot use a public key without a CA certificate with a private key."); } // set default values. X509Name subjectDN = SetSuitableDefaults( ref applicationUri, ref applicationName, ref subjectName, ref domainNames, ref keySize, ref lifetimeInMonths); using (var cfrg = new CertificateFactoryRandomGenerator()) { // cert generators SecureRandom random = new SecureRandom(cfrg); X509V3CertificateGenerator cg = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); cg.SetSerialNumber(serialNumber); // subject and issuer DN X509Name issuerDN = null; if (issuerCAKeyCert != null) { issuerDN = new CertificateFactoryX509Name(issuerCAKeyCert.Subject); } else { // self signed issuerDN = subjectDN; } cg.SetIssuerDN(issuerDN); cg.SetSubjectDN(subjectDN); // valid for cg.SetNotBefore(startTime); cg.SetNotAfter(startTime.AddMonths(lifetimeInMonths)); // set Private/Public Key AsymmetricKeyParameter subjectPublicKey; AsymmetricKeyParameter subjectPrivateKey; if (publicKey == null) { var keyGenerationParameters = new KeyGenerationParameters(random, keySize); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair(); subjectPublicKey = subjectKeyPair.Public; subjectPrivateKey = subjectKeyPair.Private; } else { // special case, if a cert is signed by CA, the private key of the cert is not needed subjectPublicKey = PublicKeyFactory.CreateKey(publicKey); subjectPrivateKey = null; } cg.SetPublicKey(subjectPublicKey); // add extensions // Subject key identifier cg.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey))); // Basic constraints cg.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCA)); // Authority Key identifier references the issuer cert or itself when self signed AsymmetricKeyParameter issuerPublicKey; BigInteger issuerSerialNumber; if (issuerCAKeyCert != null) { issuerPublicKey = GetPublicKeyParameter(issuerCAKeyCert); issuerSerialNumber = GetSerialNumber(issuerCAKeyCert); } else { issuerPublicKey = subjectPublicKey; issuerSerialNumber = serialNumber; } cg.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey), new GeneralNames(new GeneralName(issuerDN)), issuerSerialNumber)); if (!isCA) { // Key usage cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment | KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyCertSign | KeyUsage.KeyEncipherment)); // Extended Key usage cg.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(new List <DerObjectIdentifier>() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1"), // server auth new DerObjectIdentifier("1.3.6.1.5.5.7.3.2"), // client auth })); // subject alternate name List <GeneralName> generalNames = new List <GeneralName>(); generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri)); generalNames.AddRange(CreateSubjectAlternateNameDomains(domainNames)); cg.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(generalNames.ToArray())); } else { // Key usage CA cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign)); } // sign certificate AsymmetricKeyParameter signingKey; if (issuerCAKeyCert != null) { // signed by issuer signingKey = GetPrivateKeyParameter(issuerCAKeyCert); } else { // self signed signingKey = subjectPrivateKey; } ISignatureFactory signatureFactory = new Asn1SignatureFactory(GetRSAHashAlgorithm(hashSizeInBits), signingKey, random); Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory); // convert to X509Certificate2 X509Certificate2 certificate = null; if (subjectPrivateKey == null) { // create the cert without the private key certificate = new X509Certificate2(x509.GetEncoded()); } else { // note: this cert has a private key! certificate = CreateCertificateWithPrivateKey(x509, null, subjectPrivateKey, random); } Utils.Trace(Utils.TraceMasks.Security, "Created new certificate: {0}", certificate.Thumbprint); // add cert to the store. if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType)) { using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(storeType)) { if (store == null) { throw new ArgumentException("Invalid store type"); } store.Open(storePath); store.Add(certificate, password).Wait(); store.Close(); } } return(certificate); } }
/// <summary> /// Configures all OPC stack settings /// </summary> public async Task ConfigureAsync() { // Instead of using a Config.xml we configure everything programmatically. // // OPC UA Application configuration // PublisherOpcApplicationConfiguration = new ApplicationConfiguration(); // Passed in as command line argument PublisherOpcApplicationConfiguration.ApplicationName = ApplicationName; PublisherOpcApplicationConfiguration.ApplicationUri = $"urn:{Utils.GetHostName()}:{PublisherOpcApplicationConfiguration.ApplicationName}:microsoft:"; PublisherOpcApplicationConfiguration.ProductUri = "https://github.com/Azure/iot-edge-opc-publisher"; PublisherOpcApplicationConfiguration.ApplicationType = ApplicationType.ClientAndServer; // // Security configuration // PublisherOpcApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration(); // Application certificate PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType = OpcOwnCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath = OpcOwnCertStorePath; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = PublisherOpcApplicationConfiguration.ApplicationName; Logger.Information($"Application Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Logger.Information($"Application Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath}"); Logger.Information($"Application Certificate subject name is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName}"); // Use existing certificate, if it is there. X509Certificate2 certificate = await PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Find(true); if (certificate == null) { Logger.Information($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Logger.Information($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType, PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath, null, PublisherOpcApplicationConfiguration.ApplicationUri, PublisherOpcApplicationConfiguration.ApplicationName, PublisherOpcApplicationConfiguration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate can not be created! Cannot continue without it!"); } else { Logger.Information("Application certificate found in Application Certificate Store"); } PublisherOpcApplicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Logger.Information($"Application certificate is for Application URI '{PublisherOpcApplicationConfiguration.ApplicationUri}', Application '{PublisherOpcApplicationConfiguration.ApplicationName} and has Subject '{PublisherOpcApplicationConfiguration.ApplicationName}'"); // TrustedIssuerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = OpcIssuerCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = OpcIssuerCertStorePath; Logger.Information($"Trusted Issuer store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Logger.Information($"Trusted Issuer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // TrustedPeerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = OpcTrustedCertStoreType; if (string.IsNullOrEmpty(OpcTrustedCertStorePath)) { // Set default. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStoreType == X509Store ? OpcTrustedCertX509StorePathDefault : OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStorePath; } Logger.Information($"Trusted Peer Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Logger.Information($"Trusted Peer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // RejectedCertificateStore PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = OpcRejectedCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = OpcRejectedCertStorePath; Logger.Information($"Rejected certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Logger.Information($"Rejected Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); // AutoAcceptUntrustedCertificates // This is a security risk and should be set to true only for debugging purposes. PublisherOpcApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false; // RejectSHA1SignedCertificates // We allow SHA1 certificates for now as many OPC Servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Logger.Information($"Rejection of SHA1 signed certificates is {(PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // MinimunCertificatesKeySize // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Logger.Information($"Minimum certificate key size set to {PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize}"); // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store. if (TrustMyself) { // Ensure it is trusted try { ICertificateStore store = PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Logger.Information($"Can not open trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Logger.Information($"Adding publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); X509Certificate2Collection certCollection = await store.FindByThumbprint(publicKey.Thumbprint); if (certCollection.Count > 0) { Logger.Information($"A certificate with the same thumbprint is already in the trusted store."); } else { await store.Add(publicKey); } } finally { store.Close(); } } } catch (Exception e) { Logger.Error(e, $"Can not add publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Logger.Information("Publisher certificate is not added to trusted peer store."); } // // TransportConfigurations // PublisherOpcApplicationConfiguration.TransportQuotas = new TransportQuotas(); PublisherOpcApplicationConfiguration.TransportQuotas.MaxByteStringLength = 4 * 1024 * 1024; PublisherOpcApplicationConfiguration.TransportQuotas.MaxMessageSize = 4 * 1024 * 1024; // the maximum string length could be set to ajust for large number of nodes when reading the list of published nodes PublisherOpcApplicationConfiguration.TransportQuotas.MaxStringLength = OpcMaxStringLength; // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout = OpcOperationTimeout; Logger.Information($"OperationTimeout set to {PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout}"); // // ServerConfiguration // PublisherOpcApplicationConfiguration.ServerConfiguration = new ServerConfiguration(); // BaseAddresses if (PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Count == 0) { // We do not use the localhost replacement mechanism of the configuration loading, to immediately show the base address here PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Utils.GetHostName()}:{PublisherServerPort}{PublisherServerPath}"); } foreach (var endpoint in PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses) { Logger.Information($"Publisher server base address: {endpoint}"); } // SecurityPolicies // We do not allow security policy SecurityPolicies.None, but always high security ServerSecurityPolicy newPolicy = new ServerSecurityPolicy() { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }; PublisherOpcApplicationConfiguration.ServerConfiguration.SecurityPolicies.Add(newPolicy); Logger.Information($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added"); // MaxRegistrationInterval PublisherOpcApplicationConfiguration.ServerConfiguration.MaxRegistrationInterval = LdsRegistrationInterval; Logger.Information($"LDS(-ME) registration intervall set to {LdsRegistrationInterval} ms (0 means no registration)"); // // TraceConfiguration // // // TraceConfiguration // PublisherOpcApplicationConfiguration.TraceConfiguration = new TraceConfiguration(); PublisherOpcApplicationConfiguration.TraceConfiguration.TraceMasks = OpcStackTraceMask; PublisherOpcApplicationConfiguration.TraceConfiguration.ApplySettings(); Utils.Tracing.TraceEventHandler += new EventHandler <TraceEventArgs>(LoggerOpcUaTraceHandler); Logger.Information($"opcstacktracemask set to: 0x{OpcStackTraceMask:X}"); // add default client configuration PublisherOpcApplicationConfiguration.ClientConfiguration = new ClientConfiguration(); // validate the configuration now await PublisherOpcApplicationConfiguration.Validate(PublisherOpcApplicationConfiguration.ApplicationType); }