Skip to content

Commit

Permalink
Hotfix/certificates (#423)
Browse files Browse the repository at this point in the history
* unifying opc ua certificates handling
* added PkiRoot config
* fixed tests in build pipeline
* consistently use the Dns.GetHostName()
* pki certificate stores everywhere
* cleanup IClientServicesConfig

Co-authored-by: Marc Schier <[email protected]>
  • Loading branch information
cristipogacean and marcschier authored May 8, 2020
1 parent 25103a9 commit d13faea
Show file tree
Hide file tree
Showing 32 changed files with 285 additions and 589 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/**/obj/**
/**/.vs
/**/bin/**
/**/pki/**
/**/csx/**
/**/ecf/**
/**/*.log
Expand Down Expand Up @@ -36,4 +37,3 @@
*.cache
CodeCoverage
coverage.cobertura.xml

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static bool IsNull(this VariantValue value) {
/// <returns></returns>
public static T GetValueOrDefault<T>(this Dictionary<string, VariantValue> dict,
string key, T defaultValue) {
if (dict != null && dict.TryGetValue(key, out var token)) {
if (dict != null && dict.TryGetValue(key, out var token) && token != null) {
try {
return token.ConvertTo<T>();
}
Expand All @@ -52,7 +52,7 @@ public static T GetValueOrDefault<T>(this Dictionary<string, VariantValue> dict,
/// <returns></returns>
public static T? GetValueOrDefault<T>(this Dictionary<string, VariantValue> dict,
string key, T? defaultValue) where T : struct {
if (dict != null && dict.TryGetValue(key, out var token)) {
if (dict != null && dict.TryGetValue(key, out var token) && token != null) {
try {
// Handle enumerations serialized as string
if (typeof(T).IsEnum &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Gateway.Server {
using Microsoft.Azure.IIoT.OpcUa.Twin;
using Microsoft.Azure.IIoT.OpcUa.History.Models;
using Microsoft.Azure.IIoT.OpcUa.History;
using Microsoft.Azure.IIoT.Auth.Server;
using Microsoft.Azure.IIoT.Auth;
using Microsoft.Azure.IIoT.Serializers;
using Serilog;
using Opc.Ua;
using Opc.Ua.Configuration;
Expand All @@ -27,10 +27,12 @@ namespace Microsoft.Azure.IIoT.OpcUa.Gateway.Server {
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Text;
using Microsoft.Azure.IIoT.Serializers;


/// <summary>
/// Gateway server controller implementation
Expand Down Expand Up @@ -1597,33 +1599,33 @@ internal void OnRequestComplete(RequestContextModel context) {
/// </summary>
private async Task InitAsync() {
var config = new ApplicationConfiguration {
ApplicationName = "Opc UA Gateway Server",
// TODO provide proper naming here
ApplicationName = "Microsoft.Azure.IIoT.Gateway",
ApplicationType = Opc.Ua.ApplicationType.ClientAndServer,
ApplicationUri =
$"urn:{Utils.GetHostName()}:Microsoft:OpcGatewayServer",
ProductUri = "http://opcfoundation.org/UA/SampleServer",
$"urn:{Dns.GetHostName()}:Microsoft:Azure.IIoT.Gateway",
ProductUri = "https://github.com/Azure/Industrial-IoT",

SecurityConfiguration = new SecurityConfiguration {
ApplicationCertificate = new CertificateIdentifier {
StoreType = "Directory",
StorePath =
"OPC Foundation/CertificateStores/MachineDefault",
SubjectName = "Opc UA Gateway Server"
StoreType = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
"X509Store" : "Directory",
StorePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
"CurrentUser\\UA_MachineDefault" :
"pki/own",
SubjectName = "Microsoft.Azure.IIoT.Gateway"
},
TrustedPeerCertificates = new CertificateTrustList {
StoreType = "Directory",
StorePath =
"OPC Foundation/CertificateStores/UA Applications",
StorePath = "pki/trusted",
},
TrustedIssuerCertificates = new CertificateTrustList {
StoreType = "Directory",
StorePath =
"OPC Foundation/CertificateStores/UA Certificate Authorities",
StorePath = "pki/issuers",
},
RejectedCertificateStore = new CertificateTrustList {
StoreType = "Directory",
StorePath =
"OPC Foundation/CertificateStores/RejectedCertificates",
StorePath = "pki/rejected"
},
AutoAcceptUntrustedCertificates = false
},
Expand Down Expand Up @@ -1686,8 +1688,7 @@ private async Task InitAsync() {

await config.CertificateValidator.Update(config.SecurityConfiguration);
// Use existing certificate, if it is there.
var cert = await config.SecurityConfiguration.ApplicationCertificate
.Find(true);
var cert = config.SecurityConfiguration.ApplicationCertificate.Certificate;
if (cert == null) {
// Create cert
#pragma warning disable IDE0067 // Dispose objects before losing scope
Expand All @@ -1702,12 +1703,11 @@ private async Task InitAsync() {
CertificateFactory.defaultHashSize,
false, null, null);
#pragma warning restore IDE0067 // Dispose objects before losing scope
}

if (cert != null) {

config.SecurityConfiguration.ApplicationCertificate.Certificate = cert;
config.ApplicationUri = Utils.GetApplicationUriFromCertificate(cert);
await config.CertificateValidator.UpdateCertificate(config.SecurityConfiguration);
}
config.ApplicationUri = Utils.GetApplicationUriFromCertificate(cert);

var application = new ApplicationInstance(config);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public interface IServerFactory {
/// </summary>
/// <returns></returns>
ApplicationConfiguration CreateServer(IEnumerable<int> ports,
out ServerBase server);
string pkiRootPath, out ServerBase server);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Protocol.Runtime {
/// <summary>
/// Default client configuration
/// </summary>
public class ClientServicesConfig2 : ConfigBase, IClientServicesConfig2, ISecurityConfig, ITransportQuotaConfig {
public class ClientServicesConfig : ConfigBase, IClientServicesConfig, ISecurityConfig, ITransportQuotaConfig {

/// <summary>
/// Configuration
Expand Down Expand Up @@ -49,6 +49,8 @@ public class ClientServicesConfig2 : ConfigBase, IClientServicesConfig2, ISecuri
public uint MaxKeepAliveCount =>
(uint)GetIntOrDefault(MaxKeepAliveCountKey, () => 5);

/// <inheritdoc/>
public string PkiRootPath => _security.PkiRootPath;

/// <inheritdoc/>
public CertificateInfo ApplicationCertificate => _security.ApplicationCertificate;
Expand Down Expand Up @@ -84,7 +86,7 @@ public class ClientServicesConfig2 : ConfigBase, IClientServicesConfig2, ISecuri
public int SecurityTokenLifetime => _transport.SecurityTokenLifetime;

/// <inheritdoc/>
public ClientServicesConfig2(IConfiguration configuration = null) : base(configuration) {
public ClientServicesConfig(IConfiguration configuration = null) : base(configuration) {
_security = new SecurityConfig(configuration);
_transport = new TransportQuotaConfig(configuration);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class SecurityConfig : ConfigBase, ISecurityConfig {
/// Configuration
/// </summary>
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public const string PkiRootPathKey = "PkiRootPath";
public const string ApplicationCertificateStorePathKey = "ApplicationCertificateStorePath";
public const string ApplicationCertificateStoreTypeKey = "ApplicationCertificateStoreType";
public const string ApplicationCertificateSubjectNameKey = "ApplicationCertificateSubjectName";
Expand All @@ -31,11 +32,15 @@ public class SecurityConfig : ConfigBase, ISecurityConfig {
public const string MinimumCertificateKeySizeKey = "MinimumCertificateKeySize";
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

/// <inheritdoc/>
public string PkiRootPath =>
GetStringOrDefault(PkiRootPathKey, () => "pki");

/// <inheritdoc/>
public CertificateInfo ApplicationCertificate => new CertificateInfo {
StorePath = GetStringOrDefault(ApplicationCertificateStorePathKey,
() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
"CurrentUser\\My" : "/pki/own"),
"CurrentUser\\UA_MachineDefault" : $"{PkiRootPath}/own"),
StoreType = GetStringOrDefault(ApplicationCertificateStoreTypeKey,
() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
"X509Store" : "Directory"),
Expand All @@ -45,19 +50,19 @@ public class SecurityConfig : ConfigBase, ISecurityConfig {

/// <inheritdoc/>
public CertificateStore TrustedIssuerCertificates => new CertificateStore {
StorePath = GetStringOrDefault(TrustedIssuerCertificatesPathKey, () => "/pki/trusted"),
StorePath = GetStringOrDefault(TrustedIssuerCertificatesPathKey, () => $"{PkiRootPath}/issuers"),
StoreType = GetStringOrDefault(TrustedIssuerCertificatesTypeKey, () => "Directory"),
};

/// <inheritdoc/>
public CertificateStore TrustedPeerCertificates => new CertificateStore {
StorePath = GetStringOrDefault(TrustedPeerCertificatesPathKey, () => "/pki/trusted"),
StorePath = GetStringOrDefault(TrustedPeerCertificatesPathKey, () => $"{PkiRootPath}/trusted"),
StoreType = GetStringOrDefault(TrustedPeerCertificatesTypeKey, () => "Directory"),
};

/// <inheritdoc/>
public CertificateStore RejectedCertificateStore => new CertificateStore {
StorePath = GetStringOrDefault(RejectedCertificateStorePathKey, () => "/pki/trusted"),
StorePath = GetStringOrDefault(RejectedCertificateStorePathKey, () => $"{PkiRootPath}/rejected"),
StoreType = GetStringOrDefault(RejectedCertificateStoreTypeKey, () => "Directory"),
};

Expand Down
Loading

0 comments on commit d13faea

Please sign in to comment.