Skip to content

Commit

Permalink
Install Trust Bundle in EdgeAgent and EdgeHub (#2120)
Browse files Browse the repository at this point in the history
* Changes to install Trust bundle

* Remove list allocation

* Add null check for logger.
  • Loading branch information
varunpuranik authored Dec 18, 2019
1 parent a003c3e commit 4f85dcc
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public static class Constants

public const string StorageMaxTotalWalSize = "RocksDB_MaxTotalWalSize";

public const string WorkloadApiVersion = "2019-01-30";

public static class Labels
{
public const string Version = "net.azure-devices.edge.version";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Service
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Autofac;
Expand Down Expand Up @@ -162,6 +164,10 @@ public static async Task<int> MainAsync(IConfiguration configuration)
apiVersion = configuration.GetValue<string>(Constants.EdgeletApiVersionVariableName);
builder.RegisterModule(new AgentModule(maxRestartCount, intensiveCareTime, coolOffTimeUnitInSeconds, usePersistentStorage, storagePath, Option.Some(new Uri(workloadUri)), Option.Some(apiVersion), moduleId, Option.Some(moduleGenerationId), enableNonPersistentStorageBackup, storageBackupPath, storageTotalMaxWalSize));
builder.RegisterModule(new EdgeletModule(iothubHostname, edgeDeviceHostName, deviceId, new Uri(managementUri), new Uri(workloadUri), apiVersion, dockerAuthConfig, upstreamProtocol, proxy, productInfo, closeOnIdleTimeout, idleTimeout));

IEnumerable<X509Certificate2> trustBundle = await CertificateHelper.GetTrustBundleFromEdgelet(new Uri(workloadUri), apiVersion, Constants.WorkloadApiVersion, moduleId, moduleGenerationId);
CertificateHelper.InstallCertificates(trustBundle, logger);

break;

case Constants.KubernetesMode:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Devices.Edge.Hub.Service
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Edge.Util;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

public class EdgeHubCertificates
{
Expand All @@ -26,7 +27,7 @@ public class EdgeHubCertificates

public IList<X509Certificate2> TrustBundle { get; }

public static async Task<EdgeHubCertificates> LoadAsync(IConfigurationRoot configuration)
public static async Task<EdgeHubCertificates> LoadAsync(IConfigurationRoot configuration, ILogger logger)
{
Preconditions.CheckNotNull(configuration, nameof(configuration));
EdgeHubCertificates result;
Expand All @@ -51,7 +52,6 @@ public static async Task<EdgeHubCertificates> LoadAsync(IConfigurationRoot confi
DateTime expiration = DateTime.UtcNow.AddDays(Constants.CertificateValidityDays);

certificates = await CertificateHelper.GetServerCertificatesFromEdgelet(workloadUri, edgeletApiVersion, Constants.WorkloadApiVersion, moduleId, generationId, edgeHubHostname, expiration);
InstallCertificates(certificates.CertificateChain);
IEnumerable<X509Certificate2> trustBundle = await CertificateHelper.GetTrustBundleFromEdgelet(workloadUri, edgeletApiVersion, Constants.WorkloadApiVersion, moduleId, generationId);

result = new EdgeHubCertificates(
Expand All @@ -67,8 +67,6 @@ public static async Task<EdgeHubCertificates> LoadAsync(IConfigurationRoot confi
(X509Certificate2 ServerCertificate, IEnumerable<X509Certificate2> CertificateChain) certificates;

certificates = CertificateHelper.GetServerCertificateAndChainFromFile(edgeHubDevCertPath, edgeHubDevPrivateKeyPath);
InstallCertificates(certificates.CertificateChain);

IEnumerable<X509Certificate2> trustBundle = CertificateHelper.ParseTrustedBundleFromFile(edgeHubDevTrustBundlePath);

result = new EdgeHubCertificates(
Expand All @@ -81,36 +79,17 @@ public static async Task<EdgeHubCertificates> LoadAsync(IConfigurationRoot confi
{
// If no connection string was set and we use iotedge devdiv style certificates for development
List<X509Certificate2> certificateChain = CertificateHelper.GetServerCACertificatesFromFile(edgeHubDockerCaChainCertPath)?.ToList();
InstallCertificates(certificateChain);
result = new EdgeHubCertificates(new X509Certificate2(edgeHubDockerCertPFXPath), certificateChain, new List<X509Certificate2>());
}
else
{
throw new InvalidOperationException("Edge Hub certificate files incorrectly configured");
}

return result;
}

static void InstallCertificates(IEnumerable<X509Certificate2> certificateChain)
{
string message;
if (certificateChain != null)
{
X509Certificate2[] certs = certificateChain.ToArray();
message = $"Found intermediate certificates: {string.Join(",", certs.Select(c => $"[{c.Subject}:{c.GetExpirationDateString()}]"))}";

CertificateHelper.InstallCerts(
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StoreName.CertificateAuthority : StoreName.Root,
StoreLocation.CurrentUser,
certs);
}
else
{
message = "Unable to find intermediate certificates.";
}
CertificateHelper.InstallCertificates(result.CertificateChain, logger);
CertificateHelper.InstallCertificates(result.TrustBundle, logger);

Console.WriteLine($"[{DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss.fff tt", CultureInfo.InvariantCulture)}] {message}");
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static async Task<int> MainAsync(IConfigurationRoot configuration)

ILogger logger = Logger.Factory.CreateLogger("EdgeHub");

EdgeHubCertificates certificates = await EdgeHubCertificates.LoadAsync(configuration);
EdgeHubCertificates certificates = await EdgeHubCertificates.LoadAsync(configuration, logger);
bool clientCertAuthEnabled = configuration.GetValue(Constants.ConfigKey.EdgeHubClientCertAuthEnabled, false);

string sslProtocolsConfig = configuration.GetValue(Constants.ConfigKey.SslProtocols, string.Empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Devices.Edge.Util
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
Expand Down Expand Up @@ -207,13 +208,18 @@ public static bool ValidateCertExpiry(X509Certificate2 certificate, ILogger logg
return true;
}

public static void InstallCerts(StoreName name, StoreLocation location, IEnumerable<X509Certificate2> certs)
public static void InstallCertificates(IEnumerable<X509Certificate2> certificateChain, ILogger logger)
{
List<X509Certificate2> certsList = Preconditions.CheckNotNull(certs, nameof(certs)).ToList();
using (var store = new X509Store(name, location))
X509Certificate2[] certs = Preconditions.CheckNotNull(certificateChain, nameof(certificateChain)).ToArray();
Preconditions.CheckNotNull(logger, nameof(logger));

StoreName storeName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StoreName.CertificateAuthority : StoreName.Root;

logger.LogInformation($"Installing certificates {string.Join(",", certs.Select(c => $"[{c.Subject}:{c.GetExpirationDateString()}]"))} to {storeName}");
using (var store = new X509Store(storeName, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadWrite);
foreach (X509Certificate2 cert in certsList)
foreach (X509Certificate2 cert in certs)
{
store.Add(cert);
}
Expand Down

0 comments on commit 4f85dcc

Please sign in to comment.