/// <summary> /// Creates a new policy object. /// </summary> private static ServerSecurityPolicy CreatePolicy(string profileUri) { ServerSecurityPolicy policy = new ServerSecurityPolicy(); policy.SecurityPolicyUri = profileUri; if (profileUri != null) { switch (profileUri) { case SecurityPolicies.None: { policy.SecurityMode = MessageSecurityMode.None; policy.SecurityLevel = 0; break; } case SecurityPolicies.Basic128Rsa15: { policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy.SecurityLevel = 1; break; } case SecurityPolicies.Basic256: { policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy.SecurityLevel = 2; break; } } } return(policy); }
/// <summary> /// Creates a new policy object. /// Always uses sign and encrypt for all security policies except none /// </summary> private static ServerSecurityPolicy CreatePolicy(string profileUri) { ServerSecurityPolicy policy = new ServerSecurityPolicy(); policy.SecurityPolicyUri = profileUri; if (profileUri != null) { switch (profileUri) { case SecurityPolicies.None: { policy.SecurityMode = MessageSecurityMode.None; break; } case SecurityPolicies.Basic128Rsa15: case SecurityPolicies.Basic256: case SecurityPolicies.Basic256Sha256: case SecurityPolicies.Aes128_Sha256_RsaOaep: case SecurityPolicies.Aes256_Sha256_RsaPss: { policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; break; } } } return(policy); }
private ServerSecurityPolicy CreateSecurityPolicy(byte MessageMode, byte PolicyNumber) { try { ServerSecurityPolicy Policy = new ServerSecurityPolicy(); switch (MessageMode) { case 0: Policy.SecurityMode = MessageSecurityMode.None; break; case 1: Policy.SecurityMode = MessageSecurityMode.Sign; break; case 2: Policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; break; default: Policy.SecurityMode = MessageSecurityMode.Invalid; break; } switch (PolicyNumber) { case 0: Policy.SecurityPolicyUri = SecurityPolicies.None; break; case 1: Policy.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; break; case 2: Policy.SecurityPolicyUri = SecurityPolicies.Basic256; break; case 3: Policy.SecurityPolicyUri = SecurityPolicies.Basic256Sha256; break; } } catch (Exception exception) { ServerUtils.HandleException(this.Text, exception); } return(Policy); }
private void DeletePolicies(ApplicationConfiguration configuration, ServerSecurityPolicy polici) { try { int i = 0; foreach (ServerSecurityPolicy policy in configuration.ServerConfiguration.SecurityPolicies) { if (polici == policy) { configuration.ServerConfiguration.SecurityPolicies.Add(policy); } break; } } catch (Exception exception) { ServerUtils.HandleException(this.Text, exception); } }
private void CheckSecurity() { try { ServerSecurityPolicy policy = new ServerSecurityPolicy(); if (UA_SM_NoneCB.Checked) { policy = CreateSecurityPolicy(0, 0); Addpolicies(m_configuration, policy); } else { policy = CreateSecurityPolicy(0, 0); DeletePolicies(m_configuration, policy); }; if ((UA_SM_SignCB.Checked) && (Basic128Rsa15_CB.Checked)) { policy = CreateSecurityPolicy(1, 1); Addpolicies(m_configuration, policy); } else { policy = CreateSecurityPolicy(1, 1); DeletePolicies(m_configuration, policy); } if ((UA_SM_Sign_EnCB.Checked) && (Basic256Sha256_CB.Checked)) { policy = CreateSecurityPolicy(2, 3); Addpolicies(m_configuration, policy); } else { policy = CreateSecurityPolicy(2, 3); DeletePolicies(m_configuration, policy); } } catch (Exception exception) { ServerUtils.HandleException(this.Text, exception); } }
/// <summary> /// Add security policy if it doesn't exist yet. /// </summary> /// <param name="policies">The collection to which the policies are added.</param> /// <param name="securityMode">The message security mode.</param> /// <param name="policyUri">The security policy Uri.</param> private bool InternalAddPolicy(ServerSecurityPolicyCollection policies, MessageSecurityMode securityMode, string policyUri) { if (securityMode == MessageSecurityMode.Invalid) { throw new ArgumentException("Invalid security mode selected", nameof(securityMode)); } var newPolicy = new ServerSecurityPolicy() { SecurityMode = securityMode, SecurityPolicyUri = policyUri }; if (policies.Find(s => s.SecurityMode == newPolicy.SecurityMode && string.Equals(s.SecurityPolicyUri, newPolicy.SecurityPolicyUri, StringComparison.Ordinal) ) == null) { policies.Add(newPolicy); return(true); } return(false); }
/// <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); }
/// <summary> /// Creates a minimal application configuration for a server. /// </summary> /// <remarks> /// In many cases the application configuration will be loaded from an XML file. /// This example populates the configuration in code. /// </remarks> public static ApplicationConfiguration CreateServerConfiguration() { // The application configuration can be loaded from any file. // ApplicationConfiguration.Load() method loads configuration by looking up a file path in the App.config. // This approach allows applications to share configuration files and to update them. ApplicationConfiguration configuration = new ApplicationConfiguration(); // Step 1 - Specify the server identity. configuration.ApplicationName = "My Server Name"; configuration.ApplicationType = ApplicationType.Server; configuration.ApplicationUri = "http://localhost/VendorId/ApplicationId/InstanceId"; configuration.ProductUri = "http://VendorId/ProductId/VersionId"; configuration.SecurityConfiguration = new SecurityConfiguration(); // Step 2 - Specify the server's application instance certificate. // Application instance certificates must be placed in a windows certficate store because that is // the best way to protect the private key. Certificates in a store are identified with 4 parameters: // StoreLocation, StoreName, SubjectName and Thumbprint. // // In this example the following values are used: // // LocalMachine - use the machine wide certificate store. // Personal - use the store for individual certificates. // ApplicationName - use the application name as a search key. configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); configuration.SecurityConfiguration.ApplicationCertificate.StoreType = CertificateStoreType.Windows; configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "LocalMachine\\My"; configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = configuration.ApplicationName; // trust all applications installed on the same machine. configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = CertificateStoreType.Windows; configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "LocalMachine\\My"; // find the certificate in the store. X509Certificate2 serverCertificate = configuration.SecurityConfiguration.ApplicationCertificate.Find(true); // create a new certificate if one not found. if (serverCertificate == null) { // this code would normally be called as part of the installer - called here to illustrate. // create a new certificate an place it in the LocalMachine/Personal store. serverCertificate = CertificateFactory.CreateCertificate( configuration.SecurityConfiguration.ApplicationCertificate.StoreType, configuration.SecurityConfiguration.ApplicationCertificate.StorePath, configuration.ApplicationUri, configuration.ApplicationName, null, null, 1024, 300); Console.WriteLine("Created server certificate: {0}", serverCertificate.Subject); } // Step 4 - Specify the supported transport quotas. // The transport quotas are used to set limits on the contents of messages and are // used to protect against DOS attacks and rogue clients. They should be set to // reasonable values. configuration.TransportQuotas = new TransportQuotas(); configuration.TransportQuotas.OperationTimeout = 60000; configuration.ServerConfiguration = new ServerConfiguration(); // turn off registration with the discovery server. configuration.ServerConfiguration.MaxRegistrationInterval = 0; // Step 5 - Specify the based addresses - one per binding specified above. configuration.ServerConfiguration.BaseAddresses.Add(DefaultHttpUrl); configuration.ServerConfiguration.BaseAddresses.Add(DefaultTcpUrl); // Step 6 - Specify the security policies. // Security policies control what security must be used to connect to the server. // The SDK will automatically create EndpointDescriptions for each combination of // security policy and base address. // // Note that some bindings only allow one policy per URL so the SDK will append // text to the base addresses in order to ensure that each policy has a unique URL. // The first policy specified in the configuration is assigned the base address. // this policy requires signing and encryption. ServerSecurityPolicy policy1 = new ServerSecurityPolicy(); policy1.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy1.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; policy1.SecurityLevel = 1; configuration.ServerConfiguration.SecurityPolicies.Add(policy1); // this policy does not require any security. ServerSecurityPolicy policy2 = new ServerSecurityPolicy(); policy2.SecurityMode = MessageSecurityMode.None; policy2.SecurityPolicyUri = SecurityPolicies.None; policy2.SecurityLevel = 0; configuration.ServerConfiguration.SecurityPolicies.Add(policy2); // specify the supported user token types. configuration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous)); configuration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName)); // Step 6 - Validate the configuration. // This step checks if the configuration is consistent and assigns a few internal variables // that are used by the SDK. This is called automatically if the configuration is loaded from // a file using the ApplicationConfiguration.Load() method. configuration.Validate(ApplicationType.Server); return(configuration); }
internal void OnDeserializedMethod(StreamingContext context) { // Validate configuration and set reasonable defaults Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName()); Configuration.ApplicationType = ApplicationType.ClientAndServer; Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }; Configuration.ClientConfiguration = new ClientConfiguration(); Configuration.ServerConfiguration = new ServerConfiguration(); if (Configuration.SecurityConfiguration == null) { Configuration.SecurityConfiguration = new SecurityConfiguration(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.RejectedCertificateStore == null) { Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "CertificateStores/UA Applications"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = "CertificateStores/UA Certificate Authorities"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = "CertificateStores/Rejected Certificates"; } Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = "X509Store"; Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "CurrentUser\\UA_MachineDefault"; Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName; X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result; if (certificate == null) { certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.ApplicationName, new List <string>() { Configuration.ApplicationName } ); } if (certificate == null) { throw new Exception("Opc.Ua.Publisher.Module: OPC UA application certificate could not be created, cannot continue without it!"); } Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); // Ensure it is trusted try { ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Utils.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } else { try { Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); store.Add(publicKey).Wait(); } finally { store.Close(); } } } catch (Exception e) { Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } // patch our base address if (Configuration.ServerConfiguration.BaseAddresses.Count == 0) { Configuration.ServerConfiguration.BaseAddresses.Add("opc.tcp://" + Configuration.ApplicationName.ToLowerInvariant() + ":62222/UA/Publisher"); } // tighten security policy by removing security policy "none" foreach (ServerSecurityPolicy policy in Configuration.ServerConfiguration.SecurityPolicies) { if (policy.SecurityMode == MessageSecurityMode.None) { Configuration.ServerConfiguration.SecurityPolicies.Remove(policy); break; } } // turn off LDS registration Configuration.ServerConfiguration.MaxRegistrationInterval = 0; // add sign & encrypt policy ServerSecurityPolicy newPolicy = new ServerSecurityPolicy(); newPolicy.SecurityMode = MessageSecurityMode.SignAndEncrypt; newPolicy.SecurityLevel = 1; newPolicy.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy); // enable logging Configuration.TraceConfiguration = new TraceConfiguration(); Configuration.TraceConfiguration.DeleteOnLoad = true; Configuration.TraceConfiguration.TraceMasks = 519; Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt"; Configuration.TraceConfiguration.ApplySettings(); // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s Configuration.TransportQuotas.OperationTimeout = 120000; // validate the configuration now Configuration.Validate(Configuration.ApplicationType).Wait(); }
public ModuleConfiguration(string applicationName) { // set reasonable defaults Configuration = new ApplicationConfiguration(); Configuration.ApplicationName = applicationName; Configuration.ApplicationUri = "urn:" + Utils.GetHostName() + ":microsoft:" + Configuration.ApplicationName; Configuration.ApplicationType = ApplicationType.ClientAndServer; Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }; Configuration.ClientConfiguration = new ClientConfiguration(); Configuration.ServerConfiguration = new ServerConfiguration(); // enable logging Configuration.TraceConfiguration = new TraceConfiguration(); Configuration.TraceConfiguration.TraceMasks = Utils.TraceMasks.Error | Utils.TraceMasks.Security | Utils.TraceMasks.StackTrace | Utils.TraceMasks.StartStop; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_LOGP"))) { Configuration.TraceConfiguration.OutputFilePath = Environment.GetEnvironmentVariable("_GW_LOGP"); } else { Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt"; } Configuration.TraceConfiguration.ApplySettings(); if (Configuration.SecurityConfiguration == null) { Configuration.SecurityConfiguration = new SecurityConfiguration(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.RejectedCertificateStore == null) { Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "CertificateStores/UA Applications"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = "CertificateStores/UA Certificate Authorities"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = "CertificateStores/Rejected Certificates"; } Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = "X509Store"; Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "CurrentUser\\UA_MachineDefault"; Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName; X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result; if (certificate == null) { certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, null, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); } if (certificate == null) { throw new Exception("OPC UA application certificate could not be created, cannot continue without it!"); } Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); // Ensure it is trusted try { ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Program.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } else { try { Program.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); store.Add(publicKey).Wait(); } finally { store.Close(); } } } catch (Exception e) { Program.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } // patch our base address if (Configuration.ServerConfiguration.BaseAddresses.Count == 0) { Configuration.ServerConfiguration.BaseAddresses.Add("opc.tcp://" + Configuration.ApplicationName.ToLowerInvariant() + ":62222/UA/Publisher"); } // tighten security policy by removing security policy "none" foreach (ServerSecurityPolicy policy in Configuration.ServerConfiguration.SecurityPolicies) { if (policy.SecurityMode == MessageSecurityMode.None) { Configuration.ServerConfiguration.SecurityPolicies.Remove(policy); break; } } // turn off LDS registration Configuration.ServerConfiguration.MaxRegistrationInterval = 0; // add sign & encrypt policy ServerSecurityPolicy newPolicy = new ServerSecurityPolicy(); newPolicy.SecurityMode = MessageSecurityMode.SignAndEncrypt; newPolicy.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy); // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s Configuration.TransportQuotas.OperationTimeout = 120000; // allow SHA1 certificates for now as many OPC Servers still use them Configuration.SecurityConfiguration.RejectSHA1SignedCertificates = false; // allow 1024 minimum key size as many OPC Servers still use them Configuration.SecurityConfiguration.MinimumCertificateKeySize = 1024; // validate the configuration now Configuration.Validate(Configuration.ApplicationType).Wait(); }
public ModuleConfiguration(string applicationName) { // set reasonable defaults Configuration = new ApplicationConfiguration() { ApplicationName = applicationName }; Configuration.ApplicationUri = "urn:" + Utils.GetHostName() + ":microsoft:" + Configuration.ApplicationName; Configuration.ApplicationType = ApplicationType.ClientAndServer; Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }; Configuration.ClientConfiguration = new ClientConfiguration(); Configuration.ServerConfiguration = new ServerConfiguration(); // initialize stack tracing Configuration.TraceConfiguration = new TraceConfiguration() { TraceMasks = Program.OpcStackTraceMask }; Utils.SetTraceOutput(Utils.TraceOutput.FileOnly); if (string.IsNullOrEmpty(Program.LogFileName)) { if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_LOGP"))) { Configuration.TraceConfiguration.OutputFilePath = Environment.GetEnvironmentVariable("_GW_LOGP"); } else { Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt"; } } else { Configuration.TraceConfiguration.OutputFilePath = Program.LogFileName; } Configuration.TraceConfiguration.ApplySettings(); Trace($"Current directory is: {Directory.GetCurrentDirectory()}"); Trace($"Log file is: {Utils.GetAbsoluteFilePath(Configuration.TraceConfiguration.OutputFilePath, true, false, false, true)}"); Trace($"opcstacktracemask set to: 0x{Program.OpcStackTraceMask:X} ({Program.OpcStackTraceMask})"); Configuration.SecurityConfiguration = new SecurityConfiguration(); // Trusted cert store configuration. Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = Program.OpcTrustedCertStoreType; if (string.IsNullOrEmpty(Program.OpcTrustedCertStorePath)) { // Set default. Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Program.OpcTrustedCertStoreType == CertificateStoreType.X509Store ? Program.OpcTrustedCertX509StorePathDefault : Program.OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Program.OpcTrustedCertStorePath; } Trace($"Trusted Peer Certificate store type is: {Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Trace($"Trusted Peer Certificate store path is: {Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // Trusted issuer cert store configuration. Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = Program.OpcIssuerCertStoreType; Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = Program.OpcIssuerCertStorePath; Trace($"Trusted Issuer store type is: {Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Trace($"Trusted Issuer Certificate store path is: {Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // Rejected cert store configuration. Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = Program.OpcRejectedCertStoreType; Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = Program.OpcRejectedCertStorePath; Trace($"Rejected certificate store type is: {Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Trace($"Rejected Certificate store path is: {Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier() { StoreType = Program.OpcOwnCertStoreType, StorePath = Program.OpcOwnCertStorePath, SubjectName = Configuration.ApplicationName }; Trace($"Application Certificate store type is: {Configuration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Trace($"Application Certificate store path is: {Configuration.SecurityConfiguration.ApplicationCertificate.StorePath}"); // Use existing certificate, if it is there. X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result; if (certificate == null) { Trace($"Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Trace($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, null, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate could not be created! Cannot continue without it!"); // Trust myself if requested. if (Program.TrustMyself) { // Ensure it is trusted try { ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Trace($"Could not open trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Trace($"Adding publisher certificate to trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); store.Add(publicKey).Wait(); } finally { store.Close(); } } } catch (Exception e) { Trace(e, $"Could not add publisher certificate to trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Trace("Publisher certificate is not added to trusted peer store."); } } else { Trace("Application certificate found in Application Certificate Store"); } Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Trace($"Application certificate is for Application URI: {Configuration.ApplicationUri}"); // patch our base address if (Configuration.ServerConfiguration.BaseAddresses.Count == 0) { Configuration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Configuration.ApplicationName.ToLowerInvariant()}:{Program.PublisherServerPort}{Program.PublisherServerPath}"); } foreach (var endpoint in Configuration.ServerConfiguration.BaseAddresses) { Trace($"Publisher server Endpoint URL: {endpoint}"); } // Set LDS registration interval Configuration.ServerConfiguration.MaxRegistrationInterval = Program.LdsRegistrationInterval; Trace($"LDS(-ME) registration intervall set to {Program.LdsRegistrationInterval} ms (0 means no registration)"); // add sign & encrypt policy ServerSecurityPolicy newPolicy = new ServerSecurityPolicy() { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }; Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy); Trace($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added"); // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s Configuration.TransportQuotas.OperationTimeout = Program.OpcOperationTimeout; Trace($"OperationTimeout set to {Configuration.TransportQuotas.OperationTimeout}"); // allow SHA1 certificates for now as many OPC Servers still use them Configuration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Trace($"Rejection of SHA1 signed certificates is {(Configuration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // allow 1024 minimum key size as many OPC Servers still use them Configuration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Trace($"Minimum certificate key size set to {Configuration.SecurityConfiguration.MinimumCertificateKeySize}"); // validate the configuration now Configuration.Validate(Configuration.ApplicationType).Wait(); }
/// <summary> /// hardcoded application configuration of the collector server/client /// </summary> /// <returns>application configuration of the collector server/client</returns> public static ApplicationConfiguration getConfiguration() { //not fully implemented ApplicationConfiguration config = new ApplicationConfiguration(); config.ApplicationName = "Collector Server"; //config.ApplicationType = null; config.ApplicationUri = @"urn:localhost:UA:InformationModelServer"; //config.CertificateValidator = null; //config.ClientConfiguration = null; //config.DisableHiResClock = null; //config.DiscoveryServerConfiguration = null; #region Extensions List <XmlElement> config_extensions = new List <XmlElement>(); #endregion config.Extensions = new XmlElementCollection(); //config.MessageContext = null; config.ProductUri = @"http://opcfoundation.org/UA/InformationModelServer"; //config.Properties = null; //config.PropertiesLock = null; #region Security Configuration SecurityConfiguration config_security = new SecurityConfiguration(); CertificateIdentifier config_security_certificate = new CertificateIdentifier(); config_security_certificate.StoreType = "Directory"; config_security_certificate.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\own"; config_security_certificate.SubjectName = @"CN = Demo Server, C = US, S = Arizona, O = OPC Foundation, DC = localhost"; config_security.ApplicationCertificate = config_security_certificate; CertificateTrustList config_trustedIssuer = new CertificateTrustList(); config_trustedIssuer.StoreType = "Directory"; config_trustedIssuer.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\issuer"; config_security.TrustedIssuerCertificates = config_trustedIssuer; CertificateTrustList config_security_trustedPeer = new CertificateTrustList(); config_security_trustedPeer.StoreType = "Directory"; config_security_trustedPeer.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\trusted"; config_security.TrustedPeerCertificates = config_security_trustedPeer; CertificateStoreIdentifier config_security_rejected = new CertificateStoreIdentifier(); config_security_rejected.StoreType = "Directory"; config_security_rejected.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\rejected"; config_security.RejectedCertificateStore = config_security_rejected; #endregion config.SecurityConfiguration = config_security; //config_security.ApplicationCertificate = null; #region ServerConfiguration ServerConfiguration config_server = new ServerConfiguration(); List <string> config_server_baseAdress = new List <string>(); config_server_baseAdress.Add(@"https://*****:*****@"opc.tcp://localhost:51210/CollectorServer"); config_server.BaseAddresses = new StringCollection(config_server_baseAdress); List <ServerSecurityPolicy> config_server_policies = new List <ServerSecurityPolicy>(); ServerSecurityPolicy tmp_pol1 = new ServerSecurityPolicy(); tmp_pol1.SecurityMode = MessageSecurityMode.SignAndEncrypt; tmp_pol1.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"; config_server_policies.Add(tmp_pol1); ServerSecurityPolicy tmp_pol2 = new ServerSecurityPolicy(); tmp_pol2.SecurityMode = MessageSecurityMode.None; tmp_pol2.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#None"; config_server_policies.Add(tmp_pol2); ServerSecurityPolicy tmp_pol3 = new ServerSecurityPolicy(); tmp_pol3.SecurityMode = MessageSecurityMode.Sign; tmp_pol3.SecurityPolicyUri = @""; config_server_policies.Add(tmp_pol3); ServerSecurityPolicy tmp_pol4 = new ServerSecurityPolicy(); tmp_pol4.SecurityMode = MessageSecurityMode.SignAndEncrypt; tmp_pol4.SecurityPolicyUri = @""; ServerSecurityPolicyCollection config_server_policy = new ServerSecurityPolicyCollection(config_server_policies); config_server.SecurityPolicies = config_server_policy; List <UserTokenPolicy> config_server_userTokenPolicies = new List <UserTokenPolicy>(); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous)); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName)); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Certificate)); config_server.UserTokenPolicies = new UserTokenPolicyCollection(config_server_userTokenPolicies); config_server.DiagnosticsEnabled = false; config_server.MaxSessionCount = 100; config_server.MinSessionTimeout = 10000; config_server.MaxSessionTimeout = 3600000; config_server.MaxBrowseContinuationPoints = 10; config_server.MaxQueryContinuationPoints = 10; config_server.MaxHistoryContinuationPoints = 100; config_server.MaxRequestAge = 600000; config_server.MinPublishingInterval = 100; config_server.MaxPublishingInterval = 3600000; config_server.PublishingResolution = 50; config_server.MaxSubscriptionLifetime = 3600000; config_server.MaxMessageQueueSize = 10; config_server.MaxNotificationQueueSize = 100; config_server.MaxNotificationsPerPublish = 1000; config_server.MinMetadataSamplingInterval = 1000; List <SamplingRateGroup> config_server_samplingRateGroups = new List <SamplingRateGroup>(); config_server_samplingRateGroups.Add(new SamplingRateGroup(5, 5, 20)); config_server_samplingRateGroups.Add(new SamplingRateGroup(100, 100, 4)); config_server_samplingRateGroups.Add(new SamplingRateGroup(500, 250, 2)); config_server_samplingRateGroups.Add(new SamplingRateGroup(1000, 500, 20)); config_server.AvailableSamplingRates = new SamplingRateGroupCollection(config_server_samplingRateGroups); config_server.MaxRegistrationInterval = 30000; #endregion config.ServerConfiguration = config_server; //config.SourceFilePath = null; #region TraceConfiguration TraceConfiguration config_traceConfiguration = new TraceConfiguration(); config_traceConfiguration.OutputFilePath = @"Logs\Quickstarts.BoilerServer.log.txt"; config_traceConfiguration.DeleteOnLoad = true; config_traceConfiguration.TraceMasks = 515; #endregion config.TraceConfiguration = config_traceConfiguration; config.TransportConfigurations = new TransportConfigurationCollection(); #region TransportQuotas TransportQuotas config_transportQuotas = new TransportQuotas(); config_transportQuotas.OperationTimeout = 600000; config_transportQuotas.MaxStringLength = 1048576; config_transportQuotas.MaxByteStringLength = 1048576; config_transportQuotas.MaxArrayLength = 65535; config_transportQuotas.ChannelLifetime = 300000; config_transportQuotas.SecurityTokenLifetime = 3600000; #endregion config.TransportQuotas = config_transportQuotas; return(config); }
/// <summary> /// Creates a minimal application configuration for a server. /// </summary> /// <remarks> /// In many cases the application configuration will be loaded from an XML file. /// This example populates the configuration in code. /// </remarks> public static ApplicationConfiguration CreateServerConfiguration() { // The application configuration can be loaded from any file. // ApplicationConfiguration.Load() method loads configuration by looking up a file path in the App.config. // This approach allows applications to share configuration files and to update them. ApplicationConfiguration configuration = new ApplicationConfiguration(); // Step 1 - Specify the server identity. configuration.ApplicationName = "My Server Name"; configuration.ApplicationType = ApplicationType.Server; configuration.ApplicationUri = "http://localhost/VendorId/ApplicationId/InstanceId"; configuration.ProductUri = "http://VendorId/ProductId/VersionId"; configuration.SecurityConfiguration = new SecurityConfiguration(); // Step 2 - Specify the server's application instance certificate. // Application instance certificates must be placed in a windows certficate store because that is // the best way to protect the private key. Certificates in a store are identified with 4 parameters: // StoreLocation, StoreName, SubjectName and Thumbprint. // // In this example the following values are used: // // LocalMachine - use the machine wide certificate store. // Personal - use the store for individual certificates. // ApplicationName - use the application name as a search key. configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); configuration.SecurityConfiguration.ApplicationCertificate.StoreType = CertificateStoreType.Windows; configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "LocalMachine\\My"; configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = configuration.ApplicationName; // trust all applications installed on the same machine. configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = CertificateStoreType.Windows; configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "LocalMachine\\My"; // find the certificate in the store. X509Certificate2 serverCertificate = configuration.SecurityConfiguration.ApplicationCertificate.Find(true); // create a new certificate if one not found. if (serverCertificate == null) { // this code would normally be called as part of the installer - called here to illustrate. // create a new certificate an place it in the LocalMachine/Personal store. serverCertificate = CertificateFactory.CreateCertificate( configuration.SecurityConfiguration.ApplicationCertificate.StoreType, configuration.SecurityConfiguration.ApplicationCertificate.StorePath, configuration.ApplicationUri, configuration.ApplicationName, null, null, 1024, 300); Console.WriteLine("Created server certificate: {0}", serverCertificate.Subject); } // Step 4 - Specify the supported transport quotas. // The transport quotas are used to set limits on the contents of messages and are // used to protect against DOS attacks and rogue clients. They should be set to // reasonable values. configuration.TransportQuotas = new TransportQuotas(); configuration.TransportQuotas.OperationTimeout = 60000; configuration.ServerConfiguration = new ServerConfiguration(); // turn off registration with the discovery server. configuration.ServerConfiguration.MaxRegistrationInterval = 0; // Step 5 - Specify the based addresses - one per binding specified above. configuration.ServerConfiguration.BaseAddresses.Add(DefaultHttpUrl); configuration.ServerConfiguration.BaseAddresses.Add(DefaultTcpUrl); // Step 6 - Specify the security policies. // Security policies control what security must be used to connect to the server. // The SDK will automatically create EndpointDescriptions for each combination of // security policy and base address. // // Note that some bindings only allow one policy per URL so the SDK will append // text to the base addresses in order to ensure that each policy has a unique URL. // The first policy specified in the configuration is assigned the base address. // this policy requires signing and encryption. ServerSecurityPolicy policy1 = new ServerSecurityPolicy(); policy1.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy1.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; policy1.SecurityLevel = 1; configuration.ServerConfiguration.SecurityPolicies.Add(policy1); // this policy does not require any security. ServerSecurityPolicy policy2 = new ServerSecurityPolicy(); policy2.SecurityMode = MessageSecurityMode.None; policy2.SecurityPolicyUri = SecurityPolicies.None; policy2.SecurityLevel = 0; configuration.ServerConfiguration.SecurityPolicies.Add(policy2); // specify the supported user token types. configuration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous)); configuration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName)); // Step 6 - Validate the configuration. // This step checks if the configuration is consistent and assigns a few internal variables // that are used by the SDK. This is called automatically if the configuration is loaded from // a file using the ApplicationConfiguration.Load() method. configuration.Validate(ApplicationType.Server); return configuration; }
/// <inheritdoc/> /// <summary> /// Create a new service host for UA TCP. /// </summary> public List <EndpointDescription> CreateServiceHost( ServerBase serverBase, IDictionary <string, ServiceHost> hosts, ApplicationConfiguration configuration, IList <string> baseAddresses, ApplicationDescription serverDescription, List <ServerSecurityPolicy> securityPolicies, X509Certificate2 instanceCertificate, X509Certificate2Collection instanceCertificateChain) { // generate a unique host name. string hostName = "/Tcp"; if (hosts.ContainsKey(hostName)) { hostName += Utils.Format("/{0}", hosts.Count); } // build list of uris. List <Uri> uris = new List <Uri>(); EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection(); // create the endpoint configuration to use. EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration); string computerName = Utils.GetHostName(); for (int ii = 0; ii < baseAddresses.Count; ii++) { // UA TCP and HTTPS endpoints support multiple policies. if (!baseAddresses[ii].StartsWith(Utils.UriSchemeOpcTcp, StringComparison.Ordinal)) { continue; } UriBuilder uri = new UriBuilder(baseAddresses[ii]); if (String.Equals(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase)) { uri.Host = computerName; } ITransportListener listener = this.Create(); if (listener != null) { EndpointDescriptionCollection listenerEndpoints = new EndpointDescriptionCollection(); uris.Add(uri.Uri); foreach (ServerSecurityPolicy policy in securityPolicies) { // create the endpoint description. EndpointDescription description = new EndpointDescription(); description.EndpointUrl = uri.ToString(); description.Server = serverDescription; description.SecurityMode = policy.SecurityMode; description.SecurityPolicyUri = policy.SecurityPolicyUri; description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(policy.SecurityMode, policy.SecurityPolicyUri); description.UserIdentityTokens = serverBase.GetUserTokenPolicies(configuration, description); description.TransportProfileUri = Profiles.UaTcpTransport; bool requireEncryption = ServerBase.RequireEncryption(description); if (requireEncryption) { description.ServerCertificate = instanceCertificate.RawData; // check if complete chain should be sent. if (configuration.SecurityConfiguration.SendCertificateChain && instanceCertificateChain != null && instanceCertificateChain.Count > 0) { List <byte> serverCertificateChain = new List <byte>(); for (int i = 0; i < instanceCertificateChain.Count; i++) { serverCertificateChain.AddRange(instanceCertificateChain[i].RawData); } description.ServerCertificate = serverCertificateChain.ToArray(); } } listenerEndpoints.Add(description); } serverBase.CreateServiceHostEndpoint(uri.Uri, listenerEndpoints, endpointConfiguration, listener, configuration.CertificateValidator.GetChannelValidator() ); endpoints.AddRange(listenerEndpoints); } else { Utils.Trace(Utils.TraceMasks.Error, "Failed to create endpoint {0} because the transport profile is unsupported.", uri); } } hosts[hostName] = serverBase.CreateServiceHost(serverBase, uris.ToArray()); return(endpoints); }
/// <summary> /// Creates a new policy object. /// </summary> private static ServerSecurityPolicy CreatePolicy(string profileUri) { ServerSecurityPolicy policy = new ServerSecurityPolicy(); policy.SecurityPolicyUri = profileUri; if (profileUri != null) { switch (profileUri) { case SecurityPolicies.None: { policy.SecurityMode = MessageSecurityMode.None; policy.SecurityLevel = 0; break; } case SecurityPolicies.Basic128Rsa15: { policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy.SecurityLevel = 1; break; } case SecurityPolicies.Basic256: { policy.SecurityMode = MessageSecurityMode.SignAndEncrypt; policy.SecurityLevel = 2; break; } } } return policy; }
/// <inheritdoc/> /// <summary> /// Create a new service host for UA HTTPS. /// </summary> public List <EndpointDescription> CreateServiceHost( ServerBase serverBase, IDictionary <string, Task> hosts, ApplicationConfiguration configuration, IList <string> baseAddresses, ApplicationDescription serverDescription, List <ServerSecurityPolicy> securityPolicies, X509Certificate2 instanceCertificate, X509Certificate2Collection instanceCertificateChain ) { // generate a unique host name. string hostName = String.Empty; if (hosts.ContainsKey(hostName)) { hostName = "/Https"; } if (hosts.ContainsKey(hostName)) { hostName += Utils.Format("/{0}", hosts.Count); } // build list of uris. List <Uri> uris = new List <Uri>(); EndpointDescriptionCollection endpoints = new EndpointDescriptionCollection(); // create the endpoint configuration to use. EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(configuration); string computerName = Utils.GetHostName(); for (int ii = 0; ii < baseAddresses.Count; ii++) { if (!baseAddresses[ii].StartsWith(Utils.UriSchemeHttps, StringComparison.Ordinal)) { continue; } UriBuilder uri = new UriBuilder(baseAddresses[ii]); if (uri.Path[uri.Path.Length - 1] != '/') { uri.Path += "/"; } if (String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase) == 0) { uri.Host = computerName; } uris.Add(uri.Uri); if (uri.Scheme == Utils.UriSchemeHttps) { // Can only support one policy with HTTPS // So pick the first policy with security mode sign and encrypt ServerSecurityPolicy bestPolicy = null; foreach (ServerSecurityPolicy policy in securityPolicies) { if (policy.SecurityMode != MessageSecurityMode.SignAndEncrypt) { continue; } bestPolicy = policy; break; } // Pick the first policy from the list if no policies with sign and encrypt defined if (bestPolicy == null) { bestPolicy = securityPolicies[0]; } EndpointDescription description = new EndpointDescription(); description.EndpointUrl = uri.ToString(); description.Server = serverDescription; if (instanceCertificate != null) { description.ServerCertificate = instanceCertificate.RawData; // check if complete chain should be sent. if (configuration.SecurityConfiguration.SendCertificateChain && instanceCertificateChain != null && instanceCertificateChain.Count > 0) { List <byte> serverCertificateChain = new List <byte>(); for (int i = 0; i < instanceCertificateChain.Count; i++) { serverCertificateChain.AddRange(instanceCertificateChain[i].RawData); } description.ServerCertificate = serverCertificateChain.ToArray(); } } description.SecurityMode = bestPolicy.SecurityMode; description.SecurityPolicyUri = bestPolicy.SecurityPolicyUri; description.SecurityLevel = ServerSecurityPolicy.CalculateSecurityLevel(bestPolicy.SecurityMode, bestPolicy.SecurityPolicyUri); description.UserIdentityTokens = serverBase.GetUserTokenPolicies(configuration, description); description.TransportProfileUri = Profiles.HttpsBinaryTransport; ITransportListener listener = Create(); if (listener != null) { endpoints.Add(description); serverBase.CreateServiceHostEndpoint(uri.Uri, endpoints, endpointConfiguration, listener, configuration.CertificateValidator.GetChannelValidator()); } else { Utils.Trace(Utils.TraceMasks.Error, "Failed to create endpoint {0} because the transport profile is unsupported.", uri); } } } return(endpoints); }
public OpcStackConfiguration(string applicationName) { // Instead of using a Config.xml we configure everything programmatically. // // OPC UA Application configuration // Configuration = new ApplicationConfiguration(); // Passed in as command line argument Configuration.ApplicationName = applicationName; Configuration.ApplicationUri = $"urn:{Utils.GetHostName()}:{Configuration.ApplicationName}:microsoft:"; Configuration.ProductUri = "https://github.com/Azure/iot-edge-opc-publisher"; Configuration.ApplicationType = ApplicationType.ClientAndServer; // // Security configuration // Configuration.SecurityConfiguration = new SecurityConfiguration(); // Application certificate Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = Program.OpcOwnCertStoreType; Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = Program.OpcOwnCertStorePath; Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName; Trace($"Application Certificate store type is: {Configuration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Trace($"Application Certificate store path is: {Configuration.SecurityConfiguration.ApplicationCertificate.StorePath}"); Trace($"Application Certificate subject name is: {Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName}"); // Use existing certificate, if it is there. X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result; if (certificate == null) { Trace($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Trace($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, null, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate could not be created! Cannot continue without it!"); } else { Trace("Application certificate found in Application Certificate Store"); } Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Trace($"Application certificate is for Application URI '{Configuration.ApplicationUri}', Application '{Configuration.ApplicationName} and has Subject '{Configuration.ApplicationName}'"); // TrustedIssuerCertificates Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = Program.OpcIssuerCertStoreType; Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = Program.OpcIssuerCertStorePath; Trace($"Trusted Issuer store type is: {Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Trace($"Trusted Issuer Certificate store path is: {Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // TrustedPeerCertificates Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = Program.OpcTrustedCertStoreType; if (string.IsNullOrEmpty(Program.OpcTrustedCertStorePath)) { // Set default. Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Program.OpcTrustedCertStoreType == CertificateStoreType.X509Store ? Program.OpcTrustedCertX509StorePathDefault : Program.OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Program.OpcTrustedCertStorePath; } Trace($"Trusted Peer Certificate store type is: {Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Trace($"Trusted Peer Certificate store path is: {Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // RejectedCertificateStore Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = Program.OpcRejectedCertStoreType; Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = Program.OpcRejectedCertStorePath; Trace($"Rejected certificate store type is: {Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Trace($"Rejected Certificate store path is: {Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); // AutoAcceptUntrustedCertificates // This is a security risk and should be set to true only for debugging purposes. Configuration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false; // RejectSHA1SignedCertificates // We allow SHA1 certificates for now as many OPC Servers still use them Configuration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Trace($"Rejection of SHA1 signed certificates is {(Configuration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // MinimunCertificatesKeySize // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them Configuration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Trace($"Minimum certificate key size set to {Configuration.SecurityConfiguration.MinimumCertificateKeySize}"); // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store. if (Program.TrustMyself) { // Ensure it is trusted try { ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Trace($"Could not open trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Trace($"Adding publisher certificate to trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); store.Add(publicKey).Wait(); } finally { store.Close(); } } } catch (Exception e) { Trace(e, $"Could not add publisher certificate to trusted peer store. StorePath={Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Trace("Publisher certificate is not added to trusted peer store."); } // // TransportConfigurations // Configuration.TransportQuotas = new TransportQuotas(); // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s Configuration.TransportQuotas.OperationTimeout = Program.OpcOperationTimeout; Trace($"OperationTimeout set to {Configuration.TransportQuotas.OperationTimeout}"); // // ServerConfiguration // Configuration.ServerConfiguration = new ServerConfiguration(); // BaseAddresses if (Configuration.ServerConfiguration.BaseAddresses.Count == 0) { // We do not use the localhost replacement mechanism of the configuration loading, to immediately show the base address here Configuration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Utils.GetHostName()}:{Program.PublisherServerPort}{Program.PublisherServerPath}"); } foreach (var endpoint in Configuration.ServerConfiguration.BaseAddresses) { Trace($"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 }; Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy); Trace($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added"); // MaxRegistrationInterval Configuration.ServerConfiguration.MaxRegistrationInterval = Program.LdsRegistrationInterval; Trace($"LDS(-ME) registration intervall set to {Program.LdsRegistrationInterval} ms (0 means no registration)"); // // TraceConfiguration // Configuration.TraceConfiguration = new TraceConfiguration(); // Due to a bug in a stack we need to do console output ourselve. Utils.SetTraceOutput(Utils.TraceOutput.FileOnly); // OutputFilePath if (string.IsNullOrEmpty(Program.LogFileName)) { if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_LOGP"))) { Configuration.TraceConfiguration.OutputFilePath = Environment.GetEnvironmentVariable("_GW_LOGP"); } else { Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt"; } } else { Configuration.TraceConfiguration.OutputFilePath = Program.LogFileName; } // DeleteOnLoad Configuration.TraceConfiguration.DeleteOnLoad = false; // TraceMasks Configuration.TraceConfiguration.TraceMasks = Program.OpcStackTraceMask; // Apply the settings Configuration.TraceConfiguration.ApplySettings(); Trace($"Current directory is: {Directory.GetCurrentDirectory()}"); Trace($"Log file is: {Utils.GetAbsoluteFilePath(Configuration.TraceConfiguration.OutputFilePath, true, false, false, true)}"); Trace($"opcstacktracemask set to: 0x{Program.OpcStackTraceMask:X} ({Program.OpcStackTraceMask})"); Configuration.ClientConfiguration = new ClientConfiguration(); // validate the configuration now Configuration.Validate(Configuration.ApplicationType).Wait(); }