Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,43 @@ public GlobalDiscoveryServerClient(
/// </value>
public string EndpointUrl { get; set; }

/// <summary>
/// Gets the endpoint.
/// </summary>
/// <value>
/// The endpoint.
/// </value>
/// <exception cref="InvalidOperationException"></exception>
public ConfiguredEndpoint Endpoint
{
get
{
if (Session != null && Session.ConfiguredEndpoint != null)
{
return Session.ConfiguredEndpoint;
}

return m_endpoint;
}
set
{
if (Session != null)
{
throw new InvalidOperationException(
"Session must be closed before changing endpoint.");
}

if (value == null ||
m_endpoint == null ||
value.EndpointUrl != m_endpoint.EndpointUrl)
{
AdminCredentials = null;
}

m_endpoint = value;
}
}

/// <summary>
/// Gets or sets the preferred locales.
/// </summary>
Expand Down
199 changes: 104 additions & 95 deletions Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>$(AssemblyPrefix).Gds.Server.Common</AssemblyName>
<DefineConstants>$(DefineConstants);OPCUA_INCLUDE_ASYNC</DefineConstants>
<TargetFrameworks>$(LibTargetFrameworks)</TargetFrameworks>
<PackageId>$(PackagePrefix).Opc.Ua.Gds.Server.Common</PackageId>
<RootNamespace>Opc.Ua.Gds.Server</RootNamespace>
Expand All @@ -15,7 +16,7 @@
<PackageId>$(PackageId).Debug</PackageId>
</PropertyGroup>
<PropertyGroup Condition="'$(SignAssembly)' == 'true'">
<DefineConstants>$(DefineConstants);SIGNASSEMBLY</DefineConstants>
<DefineConstants>$(DefineConstants);SIGNASSEMBLY;OPCUA_INCLUDE_ASYNC</DefineConstants>
</PropertyGroup>
<!-- select ECC support -->
<Choose>
Expand Down
30 changes: 17 additions & 13 deletions Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ .. configuration.ServerConfiguration.SupportedPrivateKeyFormats
m_serverConfigurationNode.UpdateCertificate.OnCallAsync
= new UpdateCertificateMethodStateMethodAsyncCallHandler(
UpdateCertificateAsync);
m_serverConfigurationNode.CreateSigningRequest.OnCall =
new CreateSigningRequestMethodStateMethodCallHandler(CreateSigningRequest);
m_serverConfigurationNode.CreateSigningRequest.OnCallAsync =
new CreateSigningRequestMethodStateMethodAsyncCallHandler(CreateSigningRequestAsync);
m_serverConfigurationNode.ApplyChanges.OnCallMethod2
= new GenericMethodCalledEventHandler2(ApplyChanges);
m_serverConfigurationNode.GetRejectedList.OnCall
Expand Down Expand Up @@ -599,13 +599,12 @@ private async ValueTask<UpdateCertificateMethodStateResult> UpdateCertificateAsy
}
else
{
X509Certificate2 certWithPrivateKey = existingCertIdentifier
X509Certificate2 certWithPrivateKey = await existingCertIdentifier
.LoadPrivateKeyExAsync(
passwordProvider,
m_configuration.ApplicationUri,
cancellation)
.GetAwaiter()
.GetResult();
.ConfigureAwait(false);
exportableKey = X509Utils.CreateCopyWithPrivateKey(
certWithPrivateKey,
false);
Expand Down Expand Up @@ -774,7 +773,7 @@ await existingCertIdentifier.FindAsync(
};
}

private ServiceResult CreateSigningRequest(
private async ValueTask<CreateSigningRequestMethodStateResult> CreateSigningRequestAsync(
ISystemContext context,
MethodState method,
NodeId objectId,
Expand All @@ -783,7 +782,7 @@ private ServiceResult CreateSigningRequest(
string subjectName,
bool regeneratePrivateKey,
byte[] nonce,
ref byte[] certificateRequest)
CancellationToken cancellationToken)
{
HasApplicationSecureAdminAccess(context);

Expand Down Expand Up @@ -818,10 +817,11 @@ private ServiceResult CreateSigningRequest(
ICertificatePasswordProvider passwordProvider = m_configuration
.SecurityConfiguration
.CertificatePasswordProvider;
certWithPrivateKey = existingCertIdentifier
.LoadPrivateKeyExAsync(passwordProvider, m_configuration.ApplicationUri)
.GetAwaiter()
.GetResult();
certWithPrivateKey = await existingCertIdentifier
.LoadPrivateKeyExAsync(passwordProvider,
m_configuration.ApplicationUri,
cancellationToken)
.ConfigureAwait(false);

if (certWithPrivateKey == null)
{
Expand All @@ -833,11 +833,15 @@ private ServiceResult CreateSigningRequest(
Utils.TraceMasks.Security,
"Create signing request: ",
certWithPrivateKey);
certificateRequest = CertificateFactory.CreateSigningRequest(
byte[] certificateRequest = CertificateFactory.CreateSigningRequest(
certWithPrivateKey,
X509Utils.GetDomainsFromCertificate(certWithPrivateKey));

return ServiceResult.Good;
return new CreateSigningRequestMethodStateResult
{
ServiceResult = ServiceResult.Good,
CertificateRequest = certificateRequest
};
}

private X509Certificate2 GenerateTemporaryApplicationCertificate(
Expand Down
2 changes: 1 addition & 1 deletion Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1833,7 +1833,7 @@ private async Task WorkerLoopAsync(CancellationToken ct)
}

//process request from queue
if (m_queue.TryDequeue(out var request))
if (m_queue.TryDequeue(out IEndpointIncomingRequest request))
{
try
{
Expand Down
2 changes: 1 addition & 1 deletion Tests/Opc.Ua.Gds.Tests/ClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1733,7 +1733,7 @@ private async Task ConnectGDSAsync(
? m_gdsClient.AdminUser
: m_gdsClient.AppUser;
}
await m_gdsClient.GDSClient.ConnectAsync(m_gdsClient.GDSClient.EndpointUrl).ConfigureAwait(false);
await m_gdsClient.GDSClient.ConnectAsync().ConfigureAwait(false);
TestContext.Progress.WriteLine($"GDS Client({admin}) connected -- {memberName}");
}

Expand Down
45 changes: 42 additions & 3 deletions Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ await TestUtils
gdsClientConfiguration.GlobalDiscoveryServerUrl,
port)
};

await SetEndpointAsync(SecurityPolicies.Aes256_Sha256_RsaPss)
.ConfigureAwait(false);

if (string.IsNullOrEmpty(gdsClientConfiguration.AppUserName))
{
AppUser = new UserIdentity(new AnonymousIdentityToken());
Expand Down Expand Up @@ -278,7 +282,7 @@ private async Task ApplyNewApplicationInstanceCertificateAsync(
private async Task<(byte[] certificate, byte[] privateKey)> FinishKeyPairAsync(
ApplicationTestData ownApplicationTestData)
{
GDSClient.ConnectAsync(GDSClient.EndpointUrl).GetAwaiter().GetResult();
GDSClient.ConnectAsync().GetAwaiter().GetResult();
//get cert
(byte[] certificate, byte[] privateKey, _) = await GDSClient.FinishRequestAsync(
ownApplicationTestData.ApplicationRecord.ApplicationId,
Expand All @@ -290,7 +294,7 @@ private async Task ApplyNewApplicationInstanceCertificateAsync(

private async Task<NodeId> StartNewKeyPairAsync(ApplicationTestData ownApplicationTestData)
{
await GDSClient.ConnectAsync(GDSClient.EndpointUrl).ConfigureAwait(false);
await GDSClient.ConnectAsync().ConfigureAwait(false);
//request new Cert
NodeId req_id = await GDSClient.StartNewKeyPairRequestAsync(
ownApplicationTestData.ApplicationRecord.ApplicationId,
Expand All @@ -307,7 +311,7 @@ private async Task<NodeId> StartNewKeyPairAsync(ApplicationTestData ownApplicati

private async Task<NodeId> RegisterAsync(ApplicationTestData ownApplicationTestData)
{
await GDSClient.ConnectAsync(GDSClient.EndpointUrl).ConfigureAwait(false);
await GDSClient.ConnectAsync().ConfigureAwait(false);
NodeId id = await GDSClient.RegisterApplicationAsync(ownApplicationTestData.ApplicationRecord).ConfigureAwait(false);
await GDSClient.DisconnectAsync().ConfigureAwait(false);
return id;
Expand Down Expand Up @@ -348,6 +352,41 @@ private ApplicationTestData GetOwnApplicationData()
};
}

/// <summary>
/// Sets the GDSClient's endpoint by SecurityPolicy URI.
/// </summary>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public async Task SetEndpointAsync(string securityPolicyUri)
{
if (Configuration == null)
{
throw new InvalidOperationException("Client configuration must be loaded before setting endpoint.");
}
if (GDSClient == null)
{
throw new InvalidOperationException("GDSClient must be initialized before setting endpoint.");
}
var endpointConfiguration = EndpointConfiguration.Create(Configuration);
var discoveryClient = DiscoveryClient.Create(new Uri(GDSClient.EndpointUrl), endpointConfiguration);
EndpointDescriptionCollection endpoints = await discoveryClient.GetEndpointsAsync(null).ConfigureAwait(false);
await discoveryClient.CloseAsync().ConfigureAwait(false);
EndpointDescription selectedEndpoint = null;
foreach (EndpointDescription ep in endpoints)
{
if (ep.SecurityPolicyUri == securityPolicyUri)
{
selectedEndpoint = ep;
break;
}
}
if (selectedEndpoint == null)
{
throw new ArgumentException($"No endpoint found for SecurityPolicyUri '{securityPolicyUri}'.");
}
GDSClient.Endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration);
}

private ApplicationInstance m_application;
private readonly string m_storeType;
}
Expand Down
2 changes: 2 additions & 0 deletions Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ private static async Task<ApplicationConfiguration> LoadAsync(
"urn:localhost:opcfoundation.org:GlobalDiscoveryTestServer",
"http://opcfoundation.org/UA/GlobalDiscoveryTestServer")
.AsServer(baseAddresses)
.AddEccSignAndEncryptPolicies()
.AddSignAndEncryptPolicies()
.AddUserTokenPolicy(UserTokenType.Anonymous)
.AddUserTokenPolicy(UserTokenType.UserName)
.SetDiagnosticsEnabled(true)
Expand Down
24 changes: 24 additions & 0 deletions Tests/Opc.Ua.Gds.Tests/Opc.Ua.GlobalDiscoveryTestClient.Config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,30 @@
<SubjectName>CN=Global Discovery Test Client, O=OPC Foundation, DC=localhost</SubjectName>
<CertificateTypeString>RsaSha256</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Global Discovery Test Client, O=OPC Foundation, DC=localhost</SubjectName>
<CertificateTypeString>NistP256</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Global Discovery Test Client, O=OPC Foundation, DC=localhost</SubjectName>
<CertificateTypeString>NistP384</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Global Discovery Test Client, O=OPC Foundation, DC=localhost</SubjectName>
<CertificateTypeString>BrainpoolP256r1</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Global Discovery Test Client, O=OPC Foundation, DC=localhost</SubjectName>
<CertificateTypeString>BrainpoolP384r1</CertificateTypeString>
</CertificateIdentifier>
</ApplicationCertificates>
<TrustedIssuerCertificates>
<StoreType>Directory</StoreType>
Expand Down
23 changes: 21 additions & 2 deletions Tests/Opc.Ua.Gds.Tests/Opc.Ua.GlobalDiscoveryTestServer.Config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,34 @@
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri></SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP256</SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP384</SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#ECC_brainpoolP256r1</SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#ECC_brainpoolP384r1</SecurityPolicyUri>
</ServerSecurityPolicy>
</SecurityPolicies>
<UserTokenPolicies>
<ua:UserTokenPolicy>
<ua:TokenType>Anonymous_0</ua:TokenType>
<ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#None</ua:SecurityPolicyUri>

</ua:UserTokenPolicy>
<ua:UserTokenPolicy>
<ua:TokenType>UserName_1</ua:TokenType>
<ua:SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</ua:SecurityPolicyUri>
</ua:UserTokenPolicy>
</UserTokenPolicies>
<DiagnosticsEnabled>true</DiagnosticsEnabled>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,30 @@
<SubjectName>CN=Server Configuration Push Test Client, O=OPC Foundation</SubjectName>
<CertificateTypeString>RsaSha256</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Server Configuration Push Test Client, O=OPC Foundation</SubjectName>
<CertificateTypeString>NistP256</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Server Configuration Push Test Client, O=OPC Foundation</SubjectName>
<CertificateTypeString>NistP384</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Server Configuration Push Test Client, O=OPC Foundation</SubjectName>
<CertificateTypeString>BrainpoolP256r1</CertificateTypeString>
</CertificateIdentifier>
<CertificateIdentifier>
<StoreType>Directory</StoreType>
<StorePath>%LocalApplicationData%/OPC/pki/own</StorePath>
<SubjectName>CN=Server Configuration Push Test Client, O=OPC Foundation</SubjectName>
<CertificateTypeString>BrainpoolP384r1</CertificateTypeString>
</CertificateIdentifier>
</ApplicationCertificates>
<TrustedIssuerCertificates>
<StoreType>Directory</StoreType>
Expand Down
Loading
Loading