Show fwlink on HTTPS certificate errors (#83).
This commit is contained in:
parent
4d5e1076c9
commit
012d9990ef
|
|
@ -13,7 +13,7 @@ namespace AppSettings
|
||||||
{
|
{
|
||||||
using (WebHost.Start(context => context.Response.WriteAsync("Hello, World!")))
|
using (WebHost.Start(context => context.Response.WriteAsync("Hello, World!")))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Running application: Press any key to shutdown...");
|
Console.WriteLine("Running application: Press any key to shutdown.");
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore
|
namespace Microsoft.AspNetCore
|
||||||
{
|
{
|
||||||
|
|
@ -15,14 +16,17 @@ namespace Microsoft.AspNetCore
|
||||||
public class CertificateLoader
|
public class CertificateLoader
|
||||||
{
|
{
|
||||||
private readonly IConfiguration _certificatesConfiguration;
|
private readonly IConfiguration _certificatesConfiguration;
|
||||||
|
private readonly string _environmentName;
|
||||||
private readonly ICertificateFileLoader _certificateFileLoader;
|
private readonly ICertificateFileLoader _certificateFileLoader;
|
||||||
private readonly ICertificateStoreLoader _certificateStoreLoader;
|
private readonly ICertificateStoreLoader _certificateStoreLoader;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of <see cref="CertificateLoader"/>.
|
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CertificateLoader()
|
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
|
||||||
: this(null)
|
public CertificateLoader(IConfiguration certificatesConfiguration)
|
||||||
|
: this(certificatesConfiguration, null, null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,17 +34,35 @@ namespace Microsoft.AspNetCore
|
||||||
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
|
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
|
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
|
||||||
public CertificateLoader(IConfiguration certificatesConfiguration)
|
/// <param name="loggerFactory">An <see cref="ILoggerFactory"/> instance.</param>
|
||||||
: this(certificatesConfiguration, new CertificateFileLoader(), new CertificateStoreLoader())
|
public CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory)
|
||||||
|
: this(certificatesConfiguration, loggerFactory, null)
|
||||||
{
|
{
|
||||||
_certificatesConfiguration = certificatesConfiguration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CertificateLoader(IConfiguration certificatesConfiguration, ICertificateFileLoader certificateFileLoader, ICertificateStoreLoader certificateStoreLoader)
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
|
||||||
|
/// <param name="loggerFactory">An <see cref="ILoggerFactory"/> instance.</param>
|
||||||
|
/// <param name="environmentName">The name of the environment the application is running in.</param>
|
||||||
|
public CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory, string environmentName)
|
||||||
|
: this(certificatesConfiguration, loggerFactory, environmentName, new CertificateFileLoader(), new CertificateStoreLoader())
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal CertificateLoader(
|
||||||
|
IConfiguration certificatesConfiguration,
|
||||||
|
ILoggerFactory loggerFactory,
|
||||||
|
string environmentName,
|
||||||
|
ICertificateFileLoader certificateFileLoader,
|
||||||
|
ICertificateStoreLoader certificateStoreLoader)
|
||||||
|
{
|
||||||
|
_environmentName = environmentName;
|
||||||
_certificatesConfiguration = certificatesConfiguration;
|
_certificatesConfiguration = certificatesConfiguration;
|
||||||
_certificateFileLoader = certificateFileLoader;
|
_certificateFileLoader = certificateFileLoader;
|
||||||
_certificateStoreLoader = certificateStoreLoader;
|
_certificateStoreLoader = certificateStoreLoader;
|
||||||
|
_logger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.CertificateLoader");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -99,7 +121,8 @@ namespace Microsoft.AspNetCore
|
||||||
|
|
||||||
if (!certificateConfiguration.Exists())
|
if (!certificateConfiguration.Exists())
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"No certificate named {certificateName} found in configuration");
|
var environmentName = _environmentName != null ? $" ({_environmentName})" : "";
|
||||||
|
throw new KeyNotFoundException($"No certificate named '{certificateName}' found in configuration for the current environment{environmentName}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoadSingle(certificateConfiguration);
|
return LoadSingle(certificateConfiguration);
|
||||||
|
|
@ -116,10 +139,10 @@ namespace Microsoft.AspNetCore
|
||||||
certificateSource = new CertificateFileSource(_certificateFileLoader);
|
certificateSource = new CertificateFileSource(_certificateFileLoader);
|
||||||
break;
|
break;
|
||||||
case "store":
|
case "store":
|
||||||
certificateSource = new CertificateStoreSource(_certificateStoreLoader);
|
certificateSource = new CertificateStoreSource(_certificateStoreLoader, _logger);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException($"Invalid certificate source kind: {sourceKind}");
|
throw new InvalidOperationException($"Invalid certificate source kind '{sourceKind}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
certificateConfiguration.Bind(certificateSource);
|
certificateConfiguration.Bind(certificateSource);
|
||||||
|
|
@ -163,7 +186,7 @@ namespace Microsoft.AspNetCore
|
||||||
|
|
||||||
if (error != null)
|
if (error != null)
|
||||||
{
|
{
|
||||||
throw error;
|
throw new InvalidOperationException($"Unable to load certificate from file '{Path}'. Error details: '{error.Message}'.", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return certificate;
|
return certificate;
|
||||||
|
|
@ -188,10 +211,12 @@ namespace Microsoft.AspNetCore
|
||||||
private class CertificateStoreSource : CertificateSource
|
private class CertificateStoreSource : CertificateSource
|
||||||
{
|
{
|
||||||
private readonly ICertificateStoreLoader _certificateStoreLoader;
|
private readonly ICertificateStoreLoader _certificateStoreLoader;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public CertificateStoreSource(ICertificateStoreLoader certificateStoreLoader)
|
public CertificateStoreSource(ICertificateStoreLoader certificateStoreLoader, ILogger logger)
|
||||||
{
|
{
|
||||||
_certificateStoreLoader = certificateStoreLoader;
|
_certificateStoreLoader = certificateStoreLoader;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Subject { get; set; }
|
public string Subject { get; set; }
|
||||||
|
|
@ -203,10 +228,17 @@ namespace Microsoft.AspNetCore
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse(StoreLocation, ignoreCase: true, result: out StoreLocation storeLocation))
|
if (!Enum.TryParse(StoreLocation, ignoreCase: true, result: out StoreLocation storeLocation))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Invalid store location: {StoreLocation}");
|
throw new InvalidOperationException($"The certificate store location '{StoreLocation}' is invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _certificateStoreLoader.Load(Subject, StoreName, storeLocation, !AllowInvalid);
|
var certificate = _certificateStoreLoader.Load(Subject, StoreName, storeLocation, !AllowInvalid);
|
||||||
|
|
||||||
|
if (certificate == null)
|
||||||
|
{
|
||||||
|
_logger?.LogWarning($"Unable to find a matching certificate for subject '{Subject}' in store '{StoreName}' in '{StoreLocation}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return certificate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,29 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore
|
namespace Microsoft.AspNetCore
|
||||||
{
|
{
|
||||||
internal class KestrelServerOptionsSetup : IConfigureOptions<KestrelServerOptions>
|
internal class KestrelServerOptionsSetup : IConfigureOptions<KestrelServerOptions>
|
||||||
{
|
{
|
||||||
|
private readonly IHostingEnvironment _hostingEnvironment;
|
||||||
private readonly IConfiguration _configurationRoot;
|
private readonly IConfiguration _configurationRoot;
|
||||||
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
|
||||||
public KestrelServerOptionsSetup(IConfiguration configurationRoot)
|
public KestrelServerOptionsSetup(
|
||||||
|
IHostingEnvironment hostingEnvironment,
|
||||||
|
IConfiguration configurationRoot,
|
||||||
|
ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
|
_hostingEnvironment = hostingEnvironment;
|
||||||
_configurationRoot = configurationRoot;
|
_configurationRoot = configurationRoot;
|
||||||
|
_loggerFactory = loggerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(KestrelServerOptions options)
|
public void Configure(KestrelServerOptions options)
|
||||||
|
|
@ -27,7 +36,7 @@ namespace Microsoft.AspNetCore
|
||||||
|
|
||||||
private void BindConfiguration(KestrelServerOptions options)
|
private void BindConfiguration(KestrelServerOptions options)
|
||||||
{
|
{
|
||||||
var certificateLoader = new CertificateLoader(_configurationRoot.GetSection("Certificates"));
|
var certificateLoader = new CertificateLoader(_configurationRoot.GetSection("Certificates"), _loggerFactory, _hostingEnvironment.EnvironmentName);
|
||||||
|
|
||||||
foreach (var endPoint in _configurationRoot.GetSection("Kestrel:EndPoints").GetChildren())
|
foreach (var endPoint in _configurationRoot.GetSection("Kestrel:EndPoints").GetChildren())
|
||||||
{
|
{
|
||||||
|
|
@ -56,14 +65,22 @@ namespace Microsoft.AspNetCore
|
||||||
options.Listen(address, port, listenOptions =>
|
options.Listen(address, port, listenOptions =>
|
||||||
{
|
{
|
||||||
var certificateConfig = endPoint.GetSection("Certificate");
|
var certificateConfig = endPoint.GetSection("Certificate");
|
||||||
|
X509Certificate2 certificate;
|
||||||
|
|
||||||
if (certificateConfig.Exists())
|
if (certificateConfig.Exists())
|
||||||
{
|
{
|
||||||
var certificate = certificateLoader.Load(certificateConfig).FirstOrDefault();
|
try
|
||||||
|
|
||||||
if (certificate == null)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Unable to load certificate for endpoint '{endPoint.Key}'");
|
certificate = certificateLoader.Load(certificateConfig).FirstOrDefault();
|
||||||
|
|
||||||
|
if (certificate == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"No certificate found for endpoint '{endPoint.Key}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
listenOptions.UseHttps(certificate);
|
listenOptions.UseHttps(certificate);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Xunit;
|
using Microsoft.Extensions.Logging;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.FunctionalTests
|
namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
{
|
{
|
||||||
|
|
@ -35,6 +36,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
|
|
@ -45,31 +48,28 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Throws_SingleCertificateName_File_KeyNotFound()
|
public void Throws_SingleCertificateName_KeyNotFound()
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
["Certificates:Certificate1:Source"] = "File",
|
["TestConfig:Certificate"] = "Certificate1"
|
||||||
["Certificates:Certificate1:Path"] = "Certificate1.pfx",
|
|
||||||
["Certificates:Certificate1:Password"] = "Password1",
|
|
||||||
["TestConfig:Certificate"] = "Certificate2"
|
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var certificate = new X509Certificate2();
|
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
var exception = Assert.Throws<KeyNotFoundException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
Assert.Equal("No certificate named Certificate2 found in configuration", exception.Message);
|
Assert.Equal("No certificate named 'Certificate1' found in configuration for the current environment.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Throws_SingleCertificateName_File_FileNotFound()
|
public void Throws_SingleCertificateName_File_FileLoadError()
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -81,19 +81,20 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var exception = new Exception();
|
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Callback(() => throw exception);
|
.Callback(() => throw new Exception(nameof(Throws_SingleCertificateName_File_FileLoadError)));
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
|
Assert.Equal($"Unable to load certificate from file 'Certificate1.pfx'. Error details: '{nameof(Throws_SingleCertificateName_File_FileLoadError)}'.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -119,6 +120,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -127,30 +130,7 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
Assert.Same(certificate, loadedCertificates.ElementAt(0));
|
Assert.Same(certificate, loadedCertificates.ElementAt(0));
|
||||||
certificateStoreLoader.VerifyAll();
|
certificateStoreLoader.VerifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Throws_SingleCertificateName_Store_KeyNotFound()
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
["Certificates:Certificate1:Source"] = "Store",
|
|
||||||
["Certificates:Certificate1:Subject"] = "localhost",
|
|
||||||
["Certificates:Certificate1:StoreName"] = "My",
|
|
||||||
["Certificates:Certificate1:StoreLocation"] = "CurrentUser",
|
|
||||||
["TestConfig:Certificate"] = "Certificate2"
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
|
||||||
configuration.GetSection("Certificates"),
|
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
|
||||||
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
|
||||||
Assert.Equal("No certificate named Certificate2 found in configuration", exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ReturnsNull_SingleCertificateName_Store_NotFoundInStore()
|
public void ReturnsNull_SingleCertificateName_Store_NotFoundInStore()
|
||||||
{
|
{
|
||||||
|
|
@ -172,6 +152,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -209,6 +191,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
|
|
@ -220,12 +204,9 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("Certificate1;NotFound")]
|
[InlineData("Certificate1;Certificate2")]
|
||||||
[InlineData("Certificate1;Certificate2;NotFound")]
|
[InlineData("Certificate2;Certificate1")]
|
||||||
[InlineData("NotFound;Certificate1")]
|
public void Throws_MultipleCertificateNames_File_FileLoadError(string certificateNames)
|
||||||
[InlineData("NotFound;Certificate1;Certificate2")]
|
|
||||||
[InlineData("Certificate1;NotFound;Certificate2")]
|
|
||||||
public void Throws_MultipleCertificateNames_File_KeyNotFound(string certificateNames)
|
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -241,7 +222,6 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var certificate1 = new X509Certificate2();
|
var certificate1 = new X509Certificate2();
|
||||||
var certificate2 = new X509Certificate2();
|
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
|
|
@ -249,52 +229,17 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate1);
|
.Returns(certificate1);
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Returns(certificate2);
|
.Throws(new Exception(nameof(Throws_MultipleCertificateNames_File_FileLoadError)));
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
Assert.Equal("No certificate named NotFound found in configuration", exception.Message);
|
Assert.Equal($"Unable to load certificate from file 'Certificate2.pfx'. Error details: '{nameof(Throws_MultipleCertificateNames_File_FileLoadError)}'.", exception.Message);
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Certificate1;Certificate2")]
|
|
||||||
[InlineData("Certificate2;Certificate1")]
|
|
||||||
public void Throws_MultipleCertificateNames_File_FileNotFound(string certificateNames)
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
["Certificates:Certificate1:Source"] = "File",
|
|
||||||
["Certificates:Certificate1:Path"] = "Certificate1.pfx",
|
|
||||||
["Certificates:Certificate1:Password"] = "Password1",
|
|
||||||
["Certificates:Certificate2:Source"] = "File",
|
|
||||||
["Certificates:Certificate2:Path"] = "Certificate2.pfx",
|
|
||||||
["Certificates:Certificate2:Password"] = "Password2",
|
|
||||||
["TestConfig:Certificate"] = certificateNames
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var certificate1 = new X509Certificate2();
|
|
||||||
var exception = new Exception();
|
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
|
||||||
certificateFileLoader
|
|
||||||
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
|
||||||
.Returns(certificate1);
|
|
||||||
certificateFileLoader
|
|
||||||
.Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny<X509KeyStorageFlags>()))
|
|
||||||
.Throws(exception);
|
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
|
||||||
configuration.GetSection("Certificates"),
|
|
||||||
certificateFileLoader.Object,
|
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -328,6 +273,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -338,49 +285,6 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
certificateStoreLoader.VerifyAll();
|
certificateStoreLoader.VerifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Certificate1;NotFound")]
|
|
||||||
[InlineData("Certificate1;Certificate2;NotFound")]
|
|
||||||
[InlineData("NotFound;Certificate1")]
|
|
||||||
[InlineData("NotFound;Certificate1;Certificate2")]
|
|
||||||
[InlineData("Certificate1;NotFound;Certificate2")]
|
|
||||||
public void Throws_MultipleCertificateNames_Store_KeyNotFound(string certificateNames)
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
["Certificates:Certificate1:Source"] = "Store",
|
|
||||||
["Certificates:Certificate1:Subject"] = "localhost",
|
|
||||||
["Certificates:Certificate1:StoreName"] = "My",
|
|
||||||
["Certificates:Certificate1:StoreLocation"] = "CurrentUser",
|
|
||||||
["Certificates:Certificate2:Source"] = "Store",
|
|
||||||
["Certificates:Certificate2:Subject"] = "example.com",
|
|
||||||
["Certificates:Certificate2:StoreName"] = "Root",
|
|
||||||
["Certificates:Certificate2:StoreLocation"] = "LocalMachine",
|
|
||||||
["TestConfig:Certificate"] = certificateNames
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var certificate1 = new X509Certificate2();
|
|
||||||
var certificate2 = new X509Certificate2();
|
|
||||||
|
|
||||||
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
|
||||||
certificateStoreLoader
|
|
||||||
.Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny<bool>()))
|
|
||||||
.Returns(certificate1);
|
|
||||||
certificateStoreLoader
|
|
||||||
.Setup(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny<bool>()))
|
|
||||||
.Returns(certificate2);
|
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
|
||||||
configuration.GetSection("Certificates"),
|
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
|
||||||
certificateStoreLoader.Object);
|
|
||||||
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
|
||||||
Assert.Equal("No certificate named NotFound found in configuration", exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("Certificate1;Certificate2", 1)]
|
[InlineData("Certificate1;Certificate2", 1)]
|
||||||
[InlineData("Certificate2;Certificate1", 1)]
|
[InlineData("Certificate2;Certificate1", 1)]
|
||||||
|
|
@ -421,6 +325,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -460,6 +366,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -475,7 +383,7 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
[InlineData("Certificate1;Certificate2;NotFound")]
|
[InlineData("Certificate1;Certificate2;NotFound")]
|
||||||
[InlineData("Certificate1;NotFound;Certificate2")]
|
[InlineData("Certificate1;NotFound;Certificate2")]
|
||||||
[InlineData("NotFound;Certificate1;Certificate2")]
|
[InlineData("NotFound;Certificate1;Certificate2")]
|
||||||
public void Throws_MultipleCertificateNames_FileAndStore_KeyNotFound(string certificateNames)
|
public void Throws_MultipleCertificateNames_KeyNotFound(string certificateNames)
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -506,17 +414,19 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
var exception = Assert.Throws<KeyNotFoundException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
Assert.Equal("No certificate named NotFound found in configuration", exception.Message);
|
Assert.Equal("No certificate named 'NotFound' found in configuration for the current environment.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("Certificate1;Certificate2")]
|
[InlineData("Certificate1;Certificate2")]
|
||||||
[InlineData("Certificate2;Certificate1")]
|
[InlineData("Certificate2;Certificate1")]
|
||||||
public void Throws_MultipleCertificateNames_FileAndStore_FileNotFound(string certificateNames)
|
public void Throws_MultipleCertificateNames_FileAndStore_FileLoadError(string certificateNames)
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -532,13 +442,12 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var exception = new Exception();
|
|
||||||
var storeCertificate = new X509Certificate2();
|
var storeCertificate = new X509Certificate2();
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Throws(exception);
|
.Throws(new Exception(nameof(Throws_MultipleCertificateNames_FileAndStore_FileLoadError)));
|
||||||
|
|
||||||
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
||||||
certificateStoreLoader
|
certificateStoreLoader
|
||||||
|
|
@ -547,10 +456,13 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
|
Assert.Equal($"Unable to load certificate from file 'Certificate1.pfx'. Error details: '{nameof(Throws_MultipleCertificateNames_FileAndStore_FileLoadError)}'.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
|
|
@ -586,6 +498,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
configuration.GetSection("Certificates"),
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
|
|
@ -616,6 +530,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate);
|
.Returns(certificate);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
@ -627,7 +543,7 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Throws_SingleCertificateInline_FileNotFound()
|
public void Throws_SingleCertificateInline_FileLoadError()
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -638,19 +554,20 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var exception = new Exception();
|
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Throws(exception);
|
.Throws(new Exception(nameof(Throws_SingleCertificateInline_FileLoadError)));
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
|
Assert.Equal($"Unable to load certificate from file 'Certificate1.pfx'. Error details: '{nameof(Throws_SingleCertificateInline_FileLoadError)}'.", exception.Message);
|
||||||
certificateFileLoader.VerifyAll();
|
certificateFileLoader.VerifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -675,6 +592,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate);
|
.Returns(certificate);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -701,6 +620,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -737,6 +658,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate2);
|
.Returns(certificate2);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
@ -749,7 +672,7 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Throws_MultipleCertificatesInline_File_FileNotFound()
|
public void Throws_MultipleCertificatesInline_File_FileLoadError()
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -764,7 +687,6 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var certificate1 = new X509Certificate2();
|
var certificate1 = new X509Certificate2();
|
||||||
var exception = new Exception();
|
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
|
|
@ -772,14 +694,17 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate1);
|
.Returns(certificate1);
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Throws(exception);
|
.Throws(new Exception(nameof(Throws_MultipleCertificatesInline_File_FileLoadError)));
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
Mock.Of<ICertificateStoreLoader>());
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificates"))));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")));
|
||||||
|
Assert.Equal($"Unable to load certificate from file 'Certificate2.pfx'. Error details: '{nameof(Throws_MultipleCertificatesInline_File_FileLoadError)}'.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -811,6 +736,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate2);
|
.Returns(certificate2);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -851,6 +778,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate);
|
.Returns(certificate);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
Mock.Of<ICertificateFileLoader>(),
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -908,6 +837,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(storeCertificate2);
|
.Returns(storeCertificate2);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -922,7 +853,7 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Throws_MultipleCertificatesInline_FileAndStore_FileNotFound()
|
public void Throws_MultipleCertificatesInline_FileAndStore_FileLoadError()
|
||||||
{
|
{
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.AddInMemoryCollection(new Dictionary<string, string>
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
|
@ -937,13 +868,12 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var exception = new Exception();
|
|
||||||
var certificate = new X509Certificate2();
|
var certificate = new X509Certificate2();
|
||||||
|
|
||||||
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
var certificateFileLoader = new Mock<ICertificateFileLoader>();
|
||||||
certificateFileLoader
|
certificateFileLoader
|
||||||
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
.Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny<X509KeyStorageFlags>()))
|
||||||
.Throws(exception);
|
.Throws(new Exception(nameof(Throws_MultipleCertificatesInline_FileAndStore_FileLoadError)));
|
||||||
|
|
||||||
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
var certificateStoreLoader = new Mock<ICertificateStoreLoader>();
|
||||||
certificateStoreLoader
|
certificateStoreLoader
|
||||||
|
|
@ -951,11 +881,14 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns(certificate);
|
.Returns(certificate);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
||||||
Assert.Same(exception, Assert.Throws<Exception>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificates"))));
|
var exception = Assert.Throws<InvalidOperationException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")));
|
||||||
|
Assert.Equal($"Unable to load certificate from file 'Certificate1.pfx'. Error details: '{nameof(Throws_MultipleCertificatesInline_FileAndStore_FileLoadError)}'.", exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -987,6 +920,8 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
.Returns<X509Certificate>(null);
|
.Returns<X509Certificate>(null);
|
||||||
|
|
||||||
var certificateLoader = new CertificateLoader(
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
certificateFileLoader.Object,
|
certificateFileLoader.Object,
|
||||||
certificateStoreLoader.Object);
|
certificateStoreLoader.Object);
|
||||||
|
|
@ -995,5 +930,115 @@ namespace Microsoft.AspNetCore.FunctionalTests
|
||||||
Assert.Equal(1, loadedCertificates.Count());
|
Assert.Equal(1, loadedCertificates.Count());
|
||||||
Assert.Same(certificate, loadedCertificates.ElementAt(0));
|
Assert.Same(certificate, loadedCertificates.ElementAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("Development")]
|
||||||
|
[InlineData("Production")]
|
||||||
|
public void IncludesEnvironmentNameInExceptionWhenAvailable(string environmentName)
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["TestConfig:Certificate"] = "Certificate1"
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var certificateLoader = new CertificateLoader(
|
||||||
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
environmentName,
|
||||||
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
|
var exception = Assert.Throws<KeyNotFoundException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
|
Assert.Equal($"No certificate named 'Certificate1' found in configuration for the current environment ({environmentName}).", exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DoesNotIncludeEnvironmentNameInExceptionWhenNotAvailable()
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["TestConfig:Certificate"] = "Certificate1"
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var certificateLoader = new CertificateLoader(
|
||||||
|
configuration.GetSection("Certificates"),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
|
var exception = Assert.Throws<KeyNotFoundException>(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")));
|
||||||
|
Assert.Equal("No certificate named 'Certificate1' found in configuration for the current environment.", exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WarningLoggedWhenCertificateNotFoundInStore()
|
||||||
|
{
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.AddInMemoryCollection(new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["TestConfig:Certificates:Certificate1:Source"] = "Store",
|
||||||
|
["TestConfig:Certificates:Certificate1:Subject"] = "localhost",
|
||||||
|
["TestConfig:Certificates:Certificate1:StoreName"] = "My",
|
||||||
|
["TestConfig:Certificates:Certificate1:StoreLocation"] = "CurrentUser",
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var loggerFactory = new Mock<ILoggerFactory>();
|
||||||
|
var logger = new MockLogger();
|
||||||
|
|
||||||
|
loggerFactory
|
||||||
|
.Setup(factory => factory.CreateLogger("Microsoft.AspNetCore.CertificateLoader"))
|
||||||
|
.Returns(logger);
|
||||||
|
|
||||||
|
var certificateLoader = new CertificateLoader(
|
||||||
|
null,
|
||||||
|
loggerFactory.Object,
|
||||||
|
null,
|
||||||
|
Mock.Of<ICertificateFileLoader>(),
|
||||||
|
Mock.Of<ICertificateStoreLoader>());
|
||||||
|
|
||||||
|
var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates"));
|
||||||
|
Assert.Equal(0, loadedCertificates.Count());
|
||||||
|
Assert.Single(logger.LogMessages, logMessage =>
|
||||||
|
logMessage.LogLevel == LogLevel.Warning &&
|
||||||
|
logMessage.Message == "Unable to find a matching certificate for subject 'localhost' in store 'My' in 'CurrentUser'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockLogger : ILogger
|
||||||
|
{
|
||||||
|
private readonly List<LogMessage> _logMessages = new List<LogMessage>();
|
||||||
|
|
||||||
|
public IEnumerable<LogMessage> LogMessages => _logMessages;
|
||||||
|
|
||||||
|
public IDisposable BeginScope<TState>(TState state)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEnabled(LogLevel logLevel)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
||||||
|
{
|
||||||
|
_logMessages.Add(new LogMessage
|
||||||
|
{
|
||||||
|
LogLevel = logLevel,
|
||||||
|
Message = formatter(state, exception)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogMessage
|
||||||
|
{
|
||||||
|
public LogLevel LogLevel { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue