913 lines
38 KiB
C#
913 lines
38 KiB
C#
/* ========================================================================
|
|
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
|
|
*
|
|
* OPC Foundation MIT License 1.00
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use,
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* The complete license agreement can be found here:
|
|
* http://opcfoundation.org/License/MIT/1.00/
|
|
* ======================================================================*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading.Tasks;
|
|
using System.Xml;
|
|
|
|
namespace Opc.Ua.Configuration
|
|
{
|
|
/// <summary>
|
|
/// A class that builds a configuration for a UA application.
|
|
/// </summary>
|
|
public class ApplicationConfigurationBuilder :
|
|
IApplicationConfigurationBuilder
|
|
{
|
|
#region ctor
|
|
/// <summary>
|
|
/// Create the application instance builder.
|
|
/// </summary>
|
|
public ApplicationConfigurationBuilder(ApplicationInstance applicationInstance)
|
|
{
|
|
ApplicationInstance = applicationInstance;
|
|
}
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
/// <summary>
|
|
/// The application instance used to build the configuration.
|
|
/// </summary>
|
|
public ApplicationInstance ApplicationInstance { get; private set; }
|
|
/// <summary>
|
|
/// The application configuration.
|
|
/// </summary>
|
|
public ApplicationConfiguration ApplicationConfiguration => ApplicationInstance.ApplicationConfiguration;
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientSelected AsClient()
|
|
{
|
|
switch (ApplicationInstance.ApplicationType)
|
|
{
|
|
case ApplicationType.Client:
|
|
case ApplicationType.ClientAndServer:
|
|
break;
|
|
case ApplicationType.Server:
|
|
ApplicationInstance.ApplicationType =
|
|
m_typeSelected ? ApplicationType.ClientAndServer : ApplicationType.Client;
|
|
break;
|
|
default:
|
|
throw new ArgumentException("Invalid application type for client.");
|
|
}
|
|
|
|
m_typeSelected = true;
|
|
|
|
ApplicationConfiguration.ClientConfiguration = new ClientConfiguration();
|
|
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions AddSecurityConfiguration(
|
|
string subjectName,
|
|
string pkiRoot = null,
|
|
string appRoot = null,
|
|
string rejectedRoot = null
|
|
)
|
|
{
|
|
pkiRoot = DefaultPKIRoot(pkiRoot);
|
|
appRoot = appRoot == null ? pkiRoot : DefaultPKIRoot(appRoot);
|
|
rejectedRoot = rejectedRoot == null ? pkiRoot : DefaultPKIRoot(rejectedRoot);
|
|
var appStoreType = CertificateStoreIdentifier.DetermineStoreType(appRoot);
|
|
var pkiRootType = CertificateStoreIdentifier.DetermineStoreType(pkiRoot);
|
|
var rejectedRootType = CertificateStoreIdentifier.DetermineStoreType(rejectedRoot);
|
|
ApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration {
|
|
// app cert store
|
|
ApplicationCertificate = new CertificateIdentifier() {
|
|
StoreType = appStoreType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.Application, appRoot),
|
|
SubjectName = Utils.ReplaceDCLocalhost(subjectName)
|
|
},
|
|
// App trusted & issuer
|
|
TrustedPeerCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.Trusted, pkiRoot)
|
|
},
|
|
TrustedIssuerCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.Issuer, pkiRoot)
|
|
},
|
|
// Https trusted & issuer
|
|
TrustedHttpsCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.TrustedHttps, pkiRoot)
|
|
},
|
|
HttpsIssuerCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.IssuerHttps, pkiRoot)
|
|
},
|
|
// User trusted & issuer
|
|
TrustedUserCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.TrustedUser, pkiRoot)
|
|
},
|
|
UserIssuerCertificates = new CertificateTrustList() {
|
|
StoreType = pkiRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.IssuerUser, pkiRoot)
|
|
},
|
|
// rejected store
|
|
RejectedCertificateStore = new CertificateTrustList() {
|
|
StoreType = rejectedRootType,
|
|
StorePath = DefaultCertificateStorePath(TrustlistType.Rejected, rejectedRoot)
|
|
},
|
|
// ensure secure default settings
|
|
AutoAcceptUntrustedCertificates = false,
|
|
AddAppCertToTrustedStore = false,
|
|
RejectSHA1SignedCertificates = true,
|
|
RejectUnknownRevocationStatus = true,
|
|
SuppressNonceValidationErrors = false,
|
|
SendCertificateChain = false,
|
|
MinimumCertificateKeySize = CertificateFactory.DefaultKeySize
|
|
};
|
|
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public async Task<ApplicationConfiguration> Create()
|
|
{
|
|
// sanity checks
|
|
if (ApplicationInstance.ApplicationType == ApplicationType.Server ||
|
|
ApplicationInstance.ApplicationType == ApplicationType.ClientAndServer)
|
|
{
|
|
if (ApplicationConfiguration.ServerConfiguration == null) throw new ArgumentException("ApplicationType Server is not configured.");
|
|
}
|
|
if (ApplicationInstance.ApplicationType == ApplicationType.Client ||
|
|
ApplicationInstance.ApplicationType == ApplicationType.ClientAndServer)
|
|
{
|
|
if (ApplicationConfiguration.ClientConfiguration == null) throw new ArgumentException("ApplicationType Client is not configured.");
|
|
}
|
|
|
|
// ensure for a user token policy
|
|
if (ApplicationConfiguration.ServerConfiguration?.UserTokenPolicies.Count == 0)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous));
|
|
}
|
|
|
|
// ensure for secure transport profiles
|
|
if (ApplicationConfiguration.ServerConfiguration?.SecurityPolicies.Count == 0)
|
|
{
|
|
AddSecurityPolicies();
|
|
}
|
|
|
|
ApplicationConfiguration.TraceConfiguration?.ApplySettings();
|
|
|
|
await ApplicationConfiguration.Validate(ApplicationInstance.ApplicationType).ConfigureAwait(false);
|
|
|
|
await ApplicationConfiguration.CertificateValidator.
|
|
Update(ApplicationConfiguration.SecurityConfiguration).ConfigureAwait(false);
|
|
|
|
return ApplicationConfiguration;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AsServer(
|
|
string[] baseAddresses,
|
|
string[] alternateBaseAddresses = null)
|
|
{
|
|
switch (ApplicationInstance.ApplicationType)
|
|
{
|
|
case ApplicationType.Client:
|
|
ApplicationInstance.ApplicationType =
|
|
m_typeSelected ? ApplicationType.ClientAndServer : ApplicationType.Server;
|
|
break;
|
|
case ApplicationType.Server:
|
|
case ApplicationType.ClientAndServer: break;
|
|
default:
|
|
throw new ArgumentException("Invalid application type for server.");
|
|
}
|
|
|
|
m_typeSelected = true;
|
|
|
|
// configure a server
|
|
var serverConfiguration = new ServerConfiguration();
|
|
|
|
// by default disable LDS registration
|
|
serverConfiguration.MaxRegistrationInterval = 0;
|
|
|
|
// base addresses
|
|
foreach (var baseAddress in baseAddresses)
|
|
{
|
|
serverConfiguration.BaseAddresses.Add(Utils.ReplaceLocalhost(baseAddress));
|
|
}
|
|
|
|
// alternate base addresses
|
|
if (alternateBaseAddresses != null)
|
|
{
|
|
foreach (var alternateBaseAddress in alternateBaseAddresses)
|
|
{
|
|
serverConfiguration.AlternateBaseAddresses.Add(Utils.ReplaceLocalhost(alternateBaseAddress));
|
|
}
|
|
}
|
|
|
|
// add container for policies
|
|
serverConfiguration.SecurityPolicies = new ServerSecurityPolicyCollection();
|
|
|
|
// add user token policy container and Anonymous
|
|
serverConfiguration.UserTokenPolicies = new UserTokenPolicyCollection();
|
|
|
|
ApplicationConfiguration.ServerConfiguration = serverConfiguration;
|
|
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddUnsecurePolicyNone(bool addPolicy = true)
|
|
{
|
|
if (addPolicy)
|
|
{
|
|
AddSecurityPolicies(false, false, true);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddSignPolicies(bool addPolicies = true)
|
|
{
|
|
if (addPolicies)
|
|
{
|
|
AddSecurityPolicies(true, false, false);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddSignAndEncryptPolicies(bool addPolicies = true)
|
|
{
|
|
if (addPolicies)
|
|
{
|
|
AddSecurityPolicies(false, false, false);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddPolicy(MessageSecurityMode securityMode, string securityPolicy)
|
|
{
|
|
if (SecurityPolicies.GetDisplayName(securityPolicy) == null) throw new ArgumentException("Unknown security policy", nameof(securityPolicy));
|
|
if (securityMode == MessageSecurityMode.None || securityPolicy.Equals(SecurityPolicies.None)) throw new ArgumentException("Use AddUnsecurePolicyNone to add no security policy.");
|
|
InternalAddPolicy(ApplicationConfiguration.ServerConfiguration.SecurityPolicies, securityMode, securityPolicy);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddUserTokenPolicy(UserTokenType userTokenType)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(userTokenType));
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerSelected AddUserTokenPolicy(UserTokenPolicy userTokenPolicy)
|
|
{
|
|
if (userTokenPolicy == null) throw new ArgumentNullException(nameof(userTokenPolicy));
|
|
ApplicationConfiguration.ServerConfiguration.UserTokenPolicies.Add(userTokenPolicy);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetAutoAcceptUntrustedCertificates(bool autoAccept)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = autoAccept;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetAddAppCertToTrustedStore(bool addToTrustedStore)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.AddAppCertToTrustedStore = addToTrustedStore;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetRejectSHA1SignedCertificates(bool rejectSHA1Signed)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = rejectSHA1Signed;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetRejectUnknownRevocationStatus(bool rejectUnknownRevocationStatus)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.RejectUnknownRevocationStatus = rejectUnknownRevocationStatus;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetSuppressNonceValidationErrors(bool suppressNonceValidationErrors)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.SuppressNonceValidationErrors = suppressNonceValidationErrors;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetSendCertificateChain(bool sendCertificateChain)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.SendCertificateChain = sendCertificateChain;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions SetMinimumCertificateKeySize(ushort keySize)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = keySize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderSecurityOptions AddCertificatePasswordProvider(ICertificatePasswordProvider certificatePasswordProvider)
|
|
{
|
|
ApplicationConfiguration.SecurityConfiguration.CertificatePasswordProvider = certificatePasswordProvider;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotasSet SetTransportQuotas(TransportQuotas transportQuotas)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas = transportQuotas;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetOperationTimeout(int operationTimeout)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.OperationTimeout = operationTimeout;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetMaxStringLength(int maxStringLength)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.MaxStringLength = maxStringLength;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetMaxByteStringLength(int maxByteStringLength)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.MaxByteStringLength = maxByteStringLength;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetMaxArrayLength(int maxArrayLength)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.MaxArrayLength = maxArrayLength;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetMaxMessageSize(int maxMessageSize)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.MaxMessageSize = maxMessageSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetMaxBufferSize(int maxBufferSize)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.MaxBufferSize = maxBufferSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetChannelLifetime(int channelLifetime)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.ChannelLifetime = channelLifetime;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTransportQuotas SetSecurityTokenLifetime(int securityTokenLifetime)
|
|
{
|
|
ApplicationConfiguration.TransportQuotas.SecurityTokenLifetime = securityTokenLifetime;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMinRequestThreadCount(int minRequestThreadCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MinRequestThreadCount = minRequestThreadCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxRequestThreadCount(int maxRequestThreadCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxRequestThreadCount = maxRequestThreadCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxQueuedRequestCount(int maxQueuedRequestCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxQueuedRequestCount = maxQueuedRequestCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetDiagnosticsEnabled(bool diagnosticsEnabled)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.DiagnosticsEnabled = diagnosticsEnabled;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxSessionCount(int maxSessionCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxSessionCount = maxSessionCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMinSessionTimeout(int minSessionTimeout)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MinSessionTimeout = minSessionTimeout;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxSessionTimeout(int maxSessionTimeout)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxSessionTimeout = maxSessionTimeout;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxBrowseContinuationPoints(int maxBrowseContinuationPoints)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxBrowseContinuationPoints = maxBrowseContinuationPoints;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxQueryContinuationPoints(int maxQueryContinuationPoints)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxQueryContinuationPoints = maxQueryContinuationPoints;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxHistoryContinuationPoints(int maxHistoryContinuationPoints)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxHistoryContinuationPoints = maxHistoryContinuationPoints;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxRequestAge(int maxRequestAge)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxRequestAge = maxRequestAge;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMinPublishingInterval(int minPublishingInterval)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MinPublishingInterval = minPublishingInterval;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxPublishingInterval(int maxPublishingInterval)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxPublishingInterval = maxPublishingInterval;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetPublishingResolution(int publishingResolution)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.PublishingResolution = publishingResolution;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxSubscriptionLifetime(int maxSubscriptionLifetime)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxSubscriptionLifetime = maxSubscriptionLifetime;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxMessageQueueSize(int maxMessageQueueSize)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxMessageQueueSize = maxMessageQueueSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxNotificationQueueSize(int maxNotificationQueueSize)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxNotificationQueueSize = maxNotificationQueueSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxNotificationsPerPublish(int maxNotificationsPerPublish)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxNotificationsPerPublish = maxNotificationsPerPublish;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMinMetadataSamplingInterval(int minMetadataSamplingInterval)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MinMetadataSamplingInterval = minMetadataSamplingInterval;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetAvailableSamplingRates(SamplingRateGroupCollection availableSampleRates)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.AvailableSamplingRates = availableSampleRates;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetRegistrationEndpoint(EndpointDescription registrationEndpoint)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.RegistrationEndpoint = registrationEndpoint;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxRegistrationInterval(int maxRegistrationInterval)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxRegistrationInterval = maxRegistrationInterval;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetNodeManagerSaveFile(string nodeManagerSaveFile)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.NodeManagerSaveFile = nodeManagerSaveFile;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMinSubscriptionLifetime(int minSubscriptionLifetime)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MinSubscriptionLifetime = minSubscriptionLifetime;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxPublishRequestCount(int maxPublishRequestCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxPublishRequestCount = maxPublishRequestCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxSubscriptionCount(int maxSubscriptionCount)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxSubscriptionCount = maxSubscriptionCount;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxEventQueueSize(int maxEventQueueSize)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxEventQueueSize = maxEventQueueSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions AddServerProfile(string serverProfile)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.ServerProfileArray.Add(serverProfile);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetShutdownDelay(int shutdownDelay)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.ShutdownDelay = shutdownDelay;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions AddServerCapabilities(string serverCapability)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.ServerCapabilities.Add(serverCapability);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetSupportedPrivateKeyFormats(StringCollection supportedPrivateKeyFormats)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.SupportedPrivateKeyFormats = supportedPrivateKeyFormats;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMaxTrustListSize(int maxTrustListSize)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MaxTrustListSize = maxTrustListSize;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetMultiCastDnsEnabled(bool multiCastDnsEnabled)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.MultiCastDnsEnabled = multiCastDnsEnabled;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetReverseConnect(ReverseConnectServerConfiguration reverseConnectConfiguration)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.ReverseConnect = reverseConnectConfiguration;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderServerOptions SetOperationLimits(OperationLimits operationLimits)
|
|
{
|
|
ApplicationConfiguration.ServerConfiguration.OperationLimits = operationLimits;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientOptions SetDefaultSessionTimeout(int defaultSessionTimeout)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.DefaultSessionTimeout = defaultSessionTimeout;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientOptions AddWellKnownDiscoveryUrls(string wellKnownDiscoveryUrl)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.WellKnownDiscoveryUrls.Add(wellKnownDiscoveryUrl);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientOptions AddDiscoveryServer(EndpointDescription discoveryServer)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.DiscoveryServers.Add(discoveryServer);
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientOptions SetEndpointCacheFilePath(string endpointCacheFilePath)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.EndpointCacheFilePath = endpointCacheFilePath;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
IApplicationConfigurationBuilderClientOptions IApplicationConfigurationBuilderClientOptions.SetMinSubscriptionLifetime(int minSubscriptionLifetime)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.MinSubscriptionLifetime = minSubscriptionLifetime;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderClientOptions SetReverseConnect(ReverseConnectClientConfiguration reverseConnect)
|
|
{
|
|
ApplicationConfiguration.ClientConfiguration.ReverseConnect = reverseConnect;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTraceConfiguration SetOutputFilePath(string outputFilePath)
|
|
{
|
|
ApplicationConfiguration.TraceConfiguration.OutputFilePath = outputFilePath;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTraceConfiguration SetDeleteOnLoad(bool deleteOnLoad)
|
|
{
|
|
ApplicationConfiguration.TraceConfiguration.DeleteOnLoad = deleteOnLoad;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderTraceConfiguration SetTraceMasks(int traceMasks)
|
|
{
|
|
ApplicationConfiguration.TraceConfiguration.TraceMasks = traceMasks;
|
|
return this;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public IApplicationConfigurationBuilderExtension AddExtension<T>(XmlQualifiedName elementName, object value)
|
|
{
|
|
ApplicationConfiguration.UpdateExtension<T>(elementName, value);
|
|
return this;
|
|
}
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
/// <summary>
|
|
/// Internal enumeration of supported trust lists.
|
|
/// </summary>
|
|
private enum TrustlistType
|
|
{
|
|
Application,
|
|
Trusted,
|
|
Issuer,
|
|
TrustedHttps,
|
|
IssuerHttps,
|
|
TrustedUser,
|
|
IssuerUser,
|
|
Rejected
|
|
};
|
|
|
|
/// <summary>
|
|
/// Return the default PKI root path if root is unspecified, directory or X509Store.
|
|
/// </summary>
|
|
/// <param name="root">A real root path or the store type.</param>
|
|
private string DefaultPKIRoot(string root)
|
|
{
|
|
if (root == null ||
|
|
root.Equals(CertificateStoreType.Directory, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return CertificateStoreIdentifier.DefaultPKIRoot;
|
|
}
|
|
else if (root.Equals(CertificateStoreType.X509Store, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return CertificateStoreIdentifier.CurrentUser;
|
|
}
|
|
return root;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine the default store path for a given trust list type.
|
|
/// </summary>
|
|
/// <param name="trustListType">The trust list type.</param>
|
|
/// <param name="pkiRoot">A PKI root for which the store path is needed.</param>
|
|
private string DefaultCertificateStorePath(TrustlistType trustListType, string pkiRoot)
|
|
{
|
|
var pkiRootType = CertificateStoreIdentifier.DetermineStoreType(pkiRoot);
|
|
if (pkiRootType.Equals(CertificateStoreType.Directory, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
string leafPath = "";
|
|
// see https://reference.opcfoundation.org/v104/GDS/docs/F.1/
|
|
switch (trustListType)
|
|
{
|
|
case TrustlistType.Application: leafPath = "own"; break;
|
|
case TrustlistType.Trusted: leafPath = "trusted"; break;
|
|
case TrustlistType.Issuer: leafPath = "issuer"; break;
|
|
case TrustlistType.TrustedHttps: leafPath = "trustedHttps"; break;
|
|
case TrustlistType.IssuerHttps: leafPath = "issuerHttps"; break;
|
|
case TrustlistType.TrustedUser: leafPath = "trustedUser"; break;
|
|
case TrustlistType.IssuerUser: leafPath = "issuerUser"; break;
|
|
case TrustlistType.Rejected: leafPath = "rejected"; break;
|
|
}
|
|
// Caller may have already provided the leaf path, then no need to add.
|
|
int startIndex = pkiRoot.Length - leafPath.Length;
|
|
char lastChar = pkiRoot.Last();
|
|
if (lastChar == Path.DirectorySeparatorChar ||
|
|
lastChar == Path.AltDirectorySeparatorChar)
|
|
{
|
|
startIndex--;
|
|
}
|
|
if (startIndex > 0)
|
|
{
|
|
if (pkiRoot.Substring(startIndex, leafPath.Length).Equals(leafPath, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return pkiRoot;
|
|
}
|
|
}
|
|
return Path.Combine(pkiRoot, leafPath);
|
|
}
|
|
else if (pkiRootType.Equals(CertificateStoreType.X509Store, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
switch (trustListType)
|
|
{
|
|
case TrustlistType.Application:
|
|
#if !NETFRAMEWORK
|
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
|
|
pkiRoot.StartsWith(CertificateStoreIdentifier.CurrentUser, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return pkiRoot + "My";
|
|
}
|
|
#endif
|
|
return pkiRoot + "UA_MachineDefault";
|
|
case TrustlistType.Trusted:
|
|
return pkiRoot + "UA_Trusted";
|
|
case TrustlistType.Issuer:
|
|
return pkiRoot + "UA_Issuer";
|
|
case TrustlistType.TrustedHttps:
|
|
return pkiRoot + "UA_Trusted_Https";
|
|
case TrustlistType.IssuerHttps:
|
|
return pkiRoot + "UA_Issuer_Https";
|
|
case TrustlistType.TrustedUser:
|
|
return pkiRoot + "UA_Trusted_User";
|
|
case TrustlistType.IssuerUser:
|
|
return pkiRoot + "UA_Issuer_User";
|
|
case TrustlistType.Rejected:
|
|
return pkiRoot + "UA_Rejected";
|
|
}
|
|
}
|
|
throw new NotSupportedException("Unsupported store type.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add specified groups of security policies and security modes.
|
|
/// </summary>
|
|
/// <param name="includeSign">Include the Sign only policies.</param>
|
|
/// <param name="deprecated">Include the deprecated policies.</param>
|
|
/// <param name="policyNone">Include policy 'None'. (no security!)</param>
|
|
private void AddSecurityPolicies(bool includeSign = false, bool deprecated = false, bool policyNone = false)
|
|
{
|
|
// create list of supported policies
|
|
string[] defaultPolicyUris = SecurityPolicies.GetDefaultUris();
|
|
if (deprecated)
|
|
{
|
|
var names = SecurityPolicies.GetDisplayNames();
|
|
var deprecatedPolicyList = new List<string>();
|
|
foreach (var name in names)
|
|
{
|
|
var uri = SecurityPolicies.GetUri(name);
|
|
if (uri != null)
|
|
{
|
|
deprecatedPolicyList.Add(uri);
|
|
}
|
|
}
|
|
defaultPolicyUris = deprecatedPolicyList.ToArray();
|
|
}
|
|
|
|
foreach (MessageSecurityMode securityMode in typeof(MessageSecurityMode).GetEnumValues())
|
|
{
|
|
var policies = ApplicationConfiguration.ServerConfiguration.SecurityPolicies;
|
|
if (policyNone && securityMode == MessageSecurityMode.None)
|
|
{
|
|
InternalAddPolicy(policies, MessageSecurityMode.None, SecurityPolicies.None);
|
|
}
|
|
else if (securityMode >= MessageSecurityMode.SignAndEncrypt ||
|
|
(includeSign && securityMode == MessageSecurityMode.Sign))
|
|
{
|
|
foreach (var policyUri in defaultPolicyUris)
|
|
{
|
|
InternalAddPolicy(policies, securityMode, policyUri);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
#endregion
|
|
|
|
#region Private Fields
|
|
private bool m_typeSelected;
|
|
#endregion
|
|
}
|
|
}
|