From a7a96a5c35c5cdd5d11bff429f63e19cdac92e25 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Sat, 30 Dec 2017 12:26:26 -0800 Subject: [PATCH] [Fixes #1301] Remove Microsoft.AspNetCore.Certificates.Configuration.Sources --- Hosting.sln | 15 - NuGetPackageVerifier.json | 1 - .../CertificateFileLoader.cs | 15 - .../CertificateLoader.cs | 249 ---- .../CertificateStoreLoader.cs | 67 -- .../ICertificateFileLoader.cs | 12 - .../ICertificateStoreLoader.cs | 12 - .../CertificateLoaderTests.cs | 1044 ----------------- ...re.Certificates.Configuration.Tests.csproj | 27 - .../Properties/AssemblyInfo.cs | 6 - .../testCert.pfx | Bin 2483 -> 0 bytes 11 files changed, 1448 deletions(-) delete mode 100644 shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateFileLoader.cs delete mode 100644 shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateLoader.cs delete mode 100644 shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateStoreLoader.cs delete mode 100644 shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateFileLoader.cs delete mode 100644 shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateStoreLoader.cs delete mode 100644 test/Microsoft.AspNetCore.Certificates.Configuration.Tests/CertificateLoaderTests.cs delete mode 100644 test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Microsoft.AspNetCore.Certificates.Configuration.Tests.csproj delete mode 100644 test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Properties/AssemblyInfo.cs delete mode 100644 test/Microsoft.AspNetCore.Certificates.Configuration.Tests/testCert.pfx diff --git a/Hosting.sln b/Hosting.sln index be21836dc4..2fdc130573 100644 --- a/Hosting.sln +++ b/Hosting.sln @@ -36,8 +36,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.WindowsServices", "src\Microsoft.AspNetCore.Hosting.WindowsServices\Microsoft.AspNetCore.Hosting.WindowsServices.csproj", "{9C93A93B-270A-4785-8F41-46C38DC33825}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Certificates.Configuration.Tests", "test\Microsoft.AspNetCore.Certificates.Configuration.Tests\Microsoft.AspNetCore.Certificates.Configuration.Tests.csproj", "{AB0B7394-278D-4838-A59C-276ED88D00CC}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{FA7D2012-C1B4-4AF7-9ADD-381B2004EA16}" ProjectSection(SolutionItems) = preProject test\TestAssets\Directory.Build.props = test\TestAssets\Directory.Build.props @@ -201,18 +199,6 @@ Global {9C93A93B-270A-4785-8F41-46C38DC33825}.Release|Mixed Platforms.Build.0 = Release|Any CPU {9C93A93B-270A-4785-8F41-46C38DC33825}.Release|x86.ActiveCfg = Release|Any CPU {9C93A93B-270A-4785-8F41-46C38DC33825}.Release|x86.Build.0 = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|x86.ActiveCfg = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Debug|x86.Build.0 = Debug|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|Any CPU.Build.0 = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|x86.ActiveCfg = Release|Any CPU - {AB0B7394-278D-4838-A59C-276ED88D00CC}.Release|x86.Build.0 = Release|Any CPU {EDFF02F0-A8A4-4EB1-A179-94D7500FB266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EDFF02F0-A8A4-4EB1-A179-94D7500FB266}.Debug|Any CPU.Build.0 = Debug|Any CPU {EDFF02F0-A8A4-4EB1-A179-94D7500FB266}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -337,7 +323,6 @@ Global {FC578F4E-171C-4F82-B301-3ABF6318D082} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0} {96BC7EEA-64D9-4DA5-8E87-1C18CBFE7D12} = {E0497F39-AFFB-4819-A116-E39E361915AB} {9C93A93B-270A-4785-8F41-46C38DC33825} = {E0497F39-AFFB-4819-A116-E39E361915AB} - {AB0B7394-278D-4838-A59C-276ED88D00CC} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0} {FA7D2012-C1B4-4AF7-9ADD-381B2004EA16} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0} {EDFF02F0-A8A4-4EB1-A179-94D7500FB266} = {FA7D2012-C1B4-4AF7-9ADD-381B2004EA16} {58194285-5891-464A-A96B-0FE043029E8A} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0} diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json index a637ea3343..7e6fb60925 100644 --- a/NuGetPackageVerifier.json +++ b/NuGetPackageVerifier.json @@ -4,7 +4,6 @@ // Don't run any rules for packages that don't ship. ], "packages": { - "Microsoft.AspNetCore.Certificates.Configuration.Sources": {}, "Microsoft.AspNetCore.Hosting.WebHostBuilderFactory.Sources": {}, "Microsoft.AspNetCore.Server.IntegrationTesting": {} } diff --git a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateFileLoader.cs b/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateFileLoader.cs deleted file mode 100644 index bcaa93d3e3..0000000000 --- a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateFileLoader.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNetCore.Certificates.Configuration -{ - internal class CertificateFileLoader : ICertificateFileLoader - { - public X509Certificate2 Load(string path, string password, X509KeyStorageFlags flags) - { - return new X509Certificate2(path, password, flags); - } - } -} diff --git a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateLoader.cs b/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateLoader.cs deleted file mode 100644 index b2a396dc2a..0000000000 --- a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateLoader.cs +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Certificates.Configuration -{ - /// - /// A helper class to load certificates from files and certificate stores based on data. - /// - internal class CertificateLoader - { - private readonly IConfiguration _certificatesConfiguration; - private readonly string _environmentName; - private readonly ICertificateFileLoader _certificateFileLoader; - private readonly ICertificateStoreLoader _certificateStoreLoader; - private readonly ILogger _logger; - - /// - /// Creates a new instance of that can load certificate references from configuration. - /// - /// An with information about certificates. - internal CertificateLoader(IConfiguration certificatesConfiguration) - : this(certificatesConfiguration, null, null) - { - } - - /// - /// Creates a new instance of that can load certificate references from configuration. - /// - /// An with information about certificates. - /// An instance. - internal CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory) - : this(certificatesConfiguration, loggerFactory, null) - { - } - - /// - /// Creates a new instance of that can load certificate references from configuration. - /// - /// An with information about certificates. - /// An instance. - /// The name of the environment the application is running in. - internal 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; - _certificateFileLoader = certificateFileLoader; - _certificateStoreLoader = certificateStoreLoader; - _logger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.CertificateLoader"); - } - - /// - /// Loads one or more certificates based on the information found in a configuration section. - /// - /// A configuration section containing either a string value referencing certificates - /// by name, or one or more inline certificate specifications. - /// - /// One or more loaded certificates. - internal IEnumerable Load(IConfigurationSection certificateConfiguration) - { - var certificateNames = certificateConfiguration.Value; - var certificates = new List(); - - if (certificateNames != null) - { - foreach (var certificateName in certificateNames.Split(';')) - { - var certificate = LoadSingle(certificateName); - if (certificate != null) - { - certificates.Add(certificate); - } - } - } - else - { - if (certificateConfiguration["Source"] != null) - { - var certificate = LoadSingle(certificateConfiguration); - if (certificate != null) - { - certificates.Add(certificate); - } - } - else - { - certificates.AddRange(LoadMultiple(certificateConfiguration)); - } - } - - return certificates; - } - - /// - /// Loads a certificate by name. - /// - /// The certificate name. - /// The loaded certificate - /// This method only works if the instance was constructed with - /// a reference to an instance containing named certificates. - /// - private X509Certificate2 LoadSingle(string certificateName) - { - var certificateConfiguration = _certificatesConfiguration?.GetSection(certificateName); - - if (!certificateConfiguration.Exists()) - { - var environmentName = _environmentName != null ? $" ({_environmentName})" : ""; - throw new KeyNotFoundException($"No certificate named '{certificateName}' found in configuration for the current environment{environmentName}."); - } - - return LoadSingle(certificateConfiguration); - } - - private X509Certificate2 LoadSingle(IConfigurationSection certificateConfiguration) - { - var sourceKind = certificateConfiguration["Source"]; - - CertificateSource certificateSource; - switch (sourceKind.ToLowerInvariant()) - { - case "file": - certificateSource = new CertificateFileSource(_certificateFileLoader); - break; - case "store": - certificateSource = new CertificateStoreSource(_certificateStoreLoader, _logger); - break; - default: - throw new InvalidOperationException($"Invalid certificate source kind '{sourceKind}'."); - } - - certificateConfiguration.Bind(certificateSource); - - return certificateSource.Load(); - } - - private IEnumerable LoadMultiple(IConfigurationSection certificatesConfiguration) - => certificatesConfiguration.GetChildren() - .Select(LoadSingle) - .Where(c => c != null); - - private abstract class CertificateSource - { - public string Source { get; set; } - - public abstract X509Certificate2 Load(); - } - - private class CertificateFileSource : CertificateSource - { - private ICertificateFileLoader _certificateFileLoader; - - public CertificateFileSource(ICertificateFileLoader certificateFileLoader) - { - _certificateFileLoader = certificateFileLoader; - } - - public string Path { get; set; } - - public string Password { get; set; } - - public override X509Certificate2 Load() - { - var certificate = TryLoad(X509KeyStorageFlags.DefaultKeySet, out var error) - ?? TryLoad(X509KeyStorageFlags.UserKeySet, out error) -#if NETCOREAPP2_0 || NETCOREAPP2_1 - ?? TryLoad(X509KeyStorageFlags.EphemeralKeySet, out error) -#elif NETSTANDARD2_0 -#elif NET461 -#else -#error target frameworks need to be updated -#endif - ; - - if (error != null) - { - throw new InvalidOperationException($"Unable to load certificate from file '{Path}'. Error details: '{error.Message}'.", error); - } - - return certificate; - } - - private X509Certificate2 TryLoad(X509KeyStorageFlags flags, out Exception exception) - { - try - { - var loadedCertificate = _certificateFileLoader.Load(Path, Password, flags); - exception = null; - return loadedCertificate; - } - catch (Exception e) - { - exception = e; - return null; - } - } - } - - private class CertificateStoreSource : CertificateSource - { - private readonly ICertificateStoreLoader _certificateStoreLoader; - private readonly ILogger _logger; - - public CertificateStoreSource(ICertificateStoreLoader certificateStoreLoader, ILogger logger) - { - _certificateStoreLoader = certificateStoreLoader; - _logger = logger; - } - - public string Subject { get; set; } - public string StoreName { get; set; } - public string StoreLocation { get; set; } - public bool AllowInvalid { get; set; } - - public override X509Certificate2 Load() - { - if (!Enum.TryParse(StoreLocation, ignoreCase: true, result: out StoreLocation storeLocation)) - { - throw new InvalidOperationException($"The certificate store location '{StoreLocation}' is invalid."); - } - - 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; - } - } - } -} diff --git a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateStoreLoader.cs b/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateStoreLoader.cs deleted file mode 100644 index c5af4e3fb6..0000000000 --- a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/CertificateStoreLoader.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNetCore.Certificates.Configuration -{ - /// - /// Loads certificates from certificate stores. - /// - internal class CertificateStoreLoader : ICertificateStoreLoader - { - /// - /// Load a ceritificate from the given store location. - /// - /// The certificate subject name to match. - /// The store to open. - /// The store location to open. - /// Only load currently valid certs. - /// The closest matching vertificate. - public X509Certificate2 Load(string subject, string storeName, StoreLocation storeLocation, bool validOnly) - { - using (var store = new X509Store(storeName, storeLocation)) - { - X509Certificate2Collection storeCertificates = null; - X509Certificate2Collection foundCertificates = null; - X509Certificate2 foundCertificate = null; - - try - { - store.Open(OpenFlags.ReadOnly); - storeCertificates = store.Certificates; - foundCertificates = storeCertificates.Find(X509FindType.FindBySubjectDistinguishedName, subject, validOnly); - foundCertificate = foundCertificates - .OfType() - .OrderByDescending(certificate => certificate.NotAfter) - .FirstOrDefault(); - - return foundCertificate; - } - finally - { - if (foundCertificate != null) - { - storeCertificates.Remove(foundCertificate); - foundCertificates.Remove(foundCertificate); - } - - DisposeCertificates(storeCertificates); - DisposeCertificates(foundCertificates); - } - } - } - - private void DisposeCertificates(X509Certificate2Collection certificates) - { - if (certificates != null) - { - foreach (var certificate in certificates) - { - certificate.Dispose(); - } - } - } - } -} diff --git a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateFileLoader.cs b/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateFileLoader.cs deleted file mode 100644 index 2a820eea39..0000000000 --- a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateFileLoader.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNetCore.Certificates.Configuration -{ - internal interface ICertificateFileLoader - { - X509Certificate2 Load(string path, string password, X509KeyStorageFlags flags); - } -} diff --git a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateStoreLoader.cs b/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateStoreLoader.cs deleted file mode 100644 index 2a7c334759..0000000000 --- a/shared/Microsoft.AspNetCore.Certificates.Configuration.Sources/ICertificateStoreLoader.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNetCore.Certificates.Configuration -{ - internal interface ICertificateStoreLoader - { - X509Certificate2 Load(string subject, string storeName, StoreLocation storeLocation, bool validOnly); - } -} diff --git a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/CertificateLoaderTests.cs b/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/CertificateLoaderTests.cs deleted file mode 100644 index 8bd889bbe0..0000000000 --- a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/CertificateLoaderTests.cs +++ /dev/null @@ -1,1044 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Moq; -using Xunit; - -namespace Microsoft.AspNetCore.Certificates.Configuration.Tests -{ - public class CertificateLoaderTests - { - [Fact] - public void Loads_SingleCertificateName_File() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateFileLoader.VerifyAll(); - } - - [Fact] - public void Throws_SingleCertificateName_KeyNotFound() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - Mock.Of()); - - var exception = Assert.Throws(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))); - Assert.Equal("No certificate named 'Certificate1' found in configuration for the current environment.", exception.Message); - } - - [Fact] - public void Throws_SingleCertificateName_File_FileLoadError() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Callback(() => throw new Exception(nameof(Throws_SingleCertificateName_File_FileLoadError))); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var exception = Assert.Throws(() => 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] - public void Loads_SingleCertificateName_Store() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "Store", - ["Certificates:Certificate1:Subject"] = "localhost", - ["Certificates:Certificate1:StoreName"] = "My", - ["Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void ReturnsNull_SingleCertificateName_Store_NotFoundInStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "Store", - ["Certificates:Certificate1:Subject"] = "localhost", - ["Certificates:Certificate1:StoreName"] = "My", - ["Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(null); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Empty(loadedCertificates); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void Loads_MultipleCertificateNames_File() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["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"] = "Certificate1;Certificate2" - }) - .Build(); - - var certificate1 = new X509Certificate2(); - var certificate2 = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate1); - certificateFileLoader - .Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny())) - .Returns(certificate2); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Equal(2, loadedCertificates.Count()); - Assert.Same(certificate1, loadedCertificates.ElementAt(0)); - Assert.Same(certificate2, loadedCertificates.ElementAt(1)); - certificateFileLoader.VerifyAll(); - } - - [Theory] - [InlineData("Certificate1;Certificate2")] - [InlineData("Certificate2;Certificate1")] - public void Throws_MultipleCertificateNames_File_FileLoadError(string certificateNames) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["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 certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate1); - certificateFileLoader - .Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny())) - .Throws(new Exception(nameof(Throws_MultipleCertificateNames_File_FileLoadError))); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var exception = Assert.Throws(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))); - Assert.Equal($"Unable to load certificate from file 'Certificate2.pfx'. Error details: '{nameof(Throws_MultipleCertificateNames_File_FileLoadError)}'.", exception.Message); - } - - [Fact] - public void Loads_MultipleCertificateNames_Store() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["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"] = "Certificate1;Certificate2" - }) - .Build(); - - var certificate1 = new X509Certificate2(); - var certificate2 = new X509Certificate2(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate1); - certificateStoreLoader - .Setup(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny())) - .Returns(certificate2); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Equal(2, loadedCertificates.Count()); - Assert.Same(certificate1, loadedCertificates.ElementAt(0)); - Assert.Same(certificate2, loadedCertificates.ElementAt(1)); - certificateStoreLoader.VerifyAll(); - } - - [Theory] - [InlineData("Certificate1;Certificate2", 1)] - [InlineData("Certificate2;Certificate1", 1)] - [InlineData("Certificate1;Certificate2;Certificate3", 1)] - [InlineData("Certificate2;Certificate3", 0)] - [InlineData("Certificate2;Certificate3;Certificate1", 1)] - public void ReturnsNull_MultipleCertificateNames_Store_NotFoundInStore(string certificateNames, int expectedFoundCertificates) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["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", - ["Certificates:Certificate3:Source"] = "Store", - ["Certificates:Certificate3:Subject"] = "notfound.com", - ["Certificates:Certificate3:StoreName"] = "Root", - ["Certificates:Certificate3:StoreLocation"] = "LocalMachine", - ["TestConfig:Certificate"] = certificateNames - }) - .Build(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(new X509Certificate2()); - certificateStoreLoader - .Setup(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny())) - .Returns(null); - certificateStoreLoader - .Setup(loader => loader.Load("notfound.com", "Root", StoreLocation.LocalMachine, It.IsAny())) - .Returns(null); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Equal(expectedFoundCertificates, loadedCertificates.Count()); - } - - [Fact] - public void Loads_MultipleCertificateNames_FileAndStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["Certificates:Certificate2:Source"] = "Store", - ["Certificates:Certificate2:Subject"] = "localhost", - ["Certificates:Certificate2:StoreName"] = "My", - ["Certificates:Certificate2:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = "Certificate1;Certificate2" - }) - .Build(); - - var fileCertificate = new X509Certificate2(); - var storeCertificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(fileCertificate); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(storeCertificate); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Equal(2, loadedCertificates.Count()); - Assert.Same(fileCertificate, loadedCertificates.ElementAt(0)); - Assert.Same(storeCertificate, loadedCertificates.ElementAt(1)); - certificateFileLoader.VerifyAll(); - certificateStoreLoader.VerifyAll(); - } - - [Theory] - [InlineData("Certificate1;Certificate2;NotFound")] - [InlineData("Certificate1;NotFound;Certificate2")] - [InlineData("NotFound;Certificate1;Certificate2")] - public void Throws_MultipleCertificateNames_KeyNotFound(string certificateNames) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["Certificates:Certificate2:Source"] = "Store", - ["Certificates:Certificate2:Subject"] = "localhost", - ["Certificates:Certificate2:StoreName"] = "My", - ["Certificates:Certificate2:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = certificateNames - }) - .Build(); - - var fileCertificate = new X509Certificate2(); - var storeCertificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(fileCertificate); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(storeCertificate); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var exception = Assert.Throws(() => certificateLoader.Load(configuration.GetSection("TestConfig:Certificate"))); - Assert.Equal("No certificate named 'NotFound' found in configuration for the current environment.", exception.Message); - } - - [Theory] - [InlineData("Certificate1;Certificate2")] - [InlineData("Certificate2;Certificate1")] - public void Throws_MultipleCertificateNames_FileAndStore_FileLoadError(string certificateNames) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["Certificates:Certificate2:Source"] = "Store", - ["Certificates:Certificate2:Subject"] = "localhost", - ["Certificates:Certificate2:StoreName"] = "My", - ["Certificates:Certificate2:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = certificateNames - }) - .Build(); - - var storeCertificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Throws(new Exception(nameof(Throws_MultipleCertificateNames_FileAndStore_FileLoadError))); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(storeCertificate); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var exception = Assert.Throws(() => 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] - [InlineData("Certificate1;Certificate2")] - [InlineData("Certificate2;Certificate1")] - public void ReturnsNull_MultipleCertificateNames_FileAndStore_NotFoundInStore(string certificateNames) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["Certificates:Certificate1:Source"] = "File", - ["Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["Certificates:Certificate1:Password"] = "Password1", - ["Certificates:Certificate2:Source"] = "Store", - ["Certificates:Certificate2:Subject"] = "localhost", - ["Certificates:Certificate2:StoreName"] = "My", - ["Certificates:Certificate2:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificate"] = certificateNames, - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(null); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateFileLoader.VerifyAll(); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void Loads_SingleCertificateInline_File() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate:Source"] = "File", - ["TestConfig:Certificate:Path"] = "Certificate1.pfx", - ["TestConfig:Certificate:Password"] = "Password1" - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateFileLoader.VerifyAll(); - } - - [Fact] - public void Throws_SingleCertificateInline_FileLoadError() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate:Source"] = "File", - ["TestConfig:Certificate:Path"] = "Certificate1.pfx", - ["TestConfig:Certificate:Password"] = "Password1" - }) - .Build(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Throws(new Exception(nameof(Throws_SingleCertificateInline_FileLoadError))); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var exception = Assert.Throws(() => 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(); - } - - [Fact] - public void Loads_SingleCertificateInline_Store() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate:Source"] = "Store", - ["TestConfig:Certificate:Subject"] = "localhost", - ["TestConfig:Certificate:StoreName"] = "My", - ["TestConfig:Certificate:StoreLocation"] = "CurrentUser", - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void ReturnsNull_SingleCertificateInline_Store_NotFoundInStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate:Source"] = "Store", - ["TestConfig:Certificate:Subject"] = "localhost", - ["TestConfig:Certificate:StoreName"] = "My", - ["TestConfig:Certificate:StoreLocation"] = "CurrentUser", - }) - .Build(); - - var certificateStoreLoader = new Mock(); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificate")); - Assert.Empty(loadedCertificates); - certificateStoreLoader.Verify(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())); - } - - [Fact] - public void Loads_MultipleCertificatesInline_File() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "File", - ["TestConfig:Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["TestConfig:Certificates:Certificate1:Password"] = "Password1", - ["TestConfig:Certificates:Certificate2:Source"] = "File", - ["TestConfig:Certificates:Certificate2:Path"] = "Certificate2.pfx", - ["TestConfig:Certificates:Certificate2:Password"] = "Password2", - }) - .Build(); - - var certificate1 = new X509Certificate2(); - var certificate2 = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate1); - certificateFileLoader - .Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny())) - .Returns(certificate2); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Equal(2, loadedCertificates.Count()); - Assert.Same(certificate1, loadedCertificates.ElementAt(0)); - Assert.Same(certificate2, loadedCertificates.ElementAt(1)); - certificateFileLoader.VerifyAll(); - } - - [Fact] - public void Throws_MultipleCertificatesInline_File_FileLoadError() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "File", - ["TestConfig:Certificates:Certificate1:Path"] = "Certificate1.pfx", - ["TestConfig:Certificates:Certificate1:Password"] = "Password1", - ["TestConfig:Certificates:Certificate2:Source"] = "File", - ["TestConfig:Certificates:Certificate2:Path"] = "Certificate2.pfx", - ["TestConfig:Certificates:Certificate2:Password"] = "Password2", - }) - .Build(); - - var certificate1 = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate1); - certificateFileLoader - .Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny())) - .Throws(new Exception(nameof(Throws_MultipleCertificatesInline_File_FileLoadError))); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - Mock.Of()); - - var exception = Assert.Throws(() => 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] - public void Loads_MultipleCertificatesInline_Store() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "Store", - ["TestConfig:Certificates:Certificate1:Subject"] = "localhost", - ["TestConfig:Certificates:Certificate1:StoreName"] = "My", - ["TestConfig:Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificates:Certificate2:Source"] = "Store", - ["TestConfig:Certificates:Certificate2:Subject"] = "example.com", - ["TestConfig:Certificates:Certificate2:StoreName"] = "Root", - ["TestConfig:Certificates:Certificate2:StoreLocation"] = "LocalMachine" - }) - .Build(); - - var certificate1 = new X509Certificate2(); - var certificate2 = new X509Certificate2(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate1); - certificateStoreLoader - .Setup(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny())) - .Returns(certificate2); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Equal(2, loadedCertificates.Count()); - Assert.Same(certificate1, loadedCertificates.ElementAt(0)); - Assert.Same(certificate2, loadedCertificates.ElementAt(1)); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void ReturnsNull_MultipleCertificatesInline_Store_NotFoundInStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "Store", - ["TestConfig:Certificates:Certificate1:Subject"] = "notfound.com", - ["TestConfig:Certificates:Certificate1:StoreName"] = "Root", - ["TestConfig:Certificates:Certificate1:StoreLocation"] = "LocalMachine", - ["TestConfig:Certificates:Certificate2:Source"] = "Store", - ["TestConfig:Certificates:Certificate2:Subject"] = "localhost", - ["TestConfig:Certificates:Certificate2:StoreName"] = "My", - ["TestConfig:Certificates:Certificate2:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificates:Certificate3:Source"] = "Store", - ["TestConfig:Certificates:Certificate3:Subject"] = "example.com", - ["TestConfig:Certificates:Certificate3:StoreName"] = "Root", - ["TestConfig:Certificates:Certificate3:StoreLocation"] = "LocalMachine" - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - Mock.Of(), - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - certificateStoreLoader.Verify(loader => loader.Load("notfound.com", "Root", StoreLocation.LocalMachine, It.IsAny())); - certificateStoreLoader.Verify(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())); - certificateStoreLoader.Verify(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny())); - } - - [Fact] - public void Loads_MultipleCertificatesInline_FileAndStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "Store", - ["TestConfig:Certificates:Certificate1:Subject"] = "localhost", - ["TestConfig:Certificates:Certificate1:StoreName"] = "My", - ["TestConfig:Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificates:Certificate2:Source"] = "File", - ["TestConfig:Certificates:Certificate2:Path"] = "Certificate1.pfx", - ["TestConfig:Certificates:Certificate2:Password"] = "Password1", - ["TestConfig:Certificates:Certificate3:Source"] = "Store", - ["TestConfig:Certificates:Certificate3:Subject"] = "example.com", - ["TestConfig:Certificates:Certificate3:StoreName"] = "Root", - ["TestConfig:Certificates:Certificate3:StoreLocation"] = "LocalMachine", - ["TestConfig:Certificates:Certificate4:Source"] = "File", - ["TestConfig:Certificates:Certificate4:Path"] = "Certificate2.pfx", - ["TestConfig:Certificates:Certificate4:Password"] = "Password2", - }) - .Build(); - - var fileCertificate1 = new X509Certificate2(); - var fileCertificate2 = new X509Certificate2(); - var storeCertificate1 = new X509Certificate2(); - var storeCertificate2 = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(fileCertificate1); - certificateFileLoader - .Setup(loader => loader.Load("Certificate2.pfx", "Password2", It.IsAny())) - .Returns(fileCertificate2); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(storeCertificate1); - certificateStoreLoader - .Setup(loader => loader.Load("example.com", "Root", StoreLocation.LocalMachine, It.IsAny())) - .Returns(storeCertificate2); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Equal(4, loadedCertificates.Count()); - Assert.Same(storeCertificate1, loadedCertificates.ElementAt(0)); - Assert.Same(fileCertificate1, loadedCertificates.ElementAt(1)); - Assert.Same(storeCertificate2, loadedCertificates.ElementAt(2)); - Assert.Same(fileCertificate2, loadedCertificates.ElementAt(3)); - certificateStoreLoader.VerifyAll(); - } - - [Fact] - public void Throws_MultipleCertificatesInline_FileAndStore_FileLoadError() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "Store", - ["TestConfig:Certificates:Certificate1:Subject"] = "localhost", - ["TestConfig:Certificates:Certificate1:StoreName"] = "My", - ["TestConfig:Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificates:Certificate2:Source"] = "File", - ["TestConfig:Certificates:Certificate2:Path"] = "Certificate1.pfx", - ["TestConfig:Certificates:Certificate2:Password"] = "Password1", - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Throws(new Exception(nameof(Throws_MultipleCertificatesInline_FileAndStore_FileLoadError))); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(certificate); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var exception = Assert.Throws(() => 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] - public void ReturnsNull_MultipleCertificatesInline_FileAndStore_NotFoundInStore() - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificates:Certificate1:Source"] = "Store", - ["TestConfig:Certificates:Certificate1:Subject"] = "localhost", - ["TestConfig:Certificates:Certificate1:StoreName"] = "My", - ["TestConfig:Certificates:Certificate1:StoreLocation"] = "CurrentUser", - ["TestConfig:Certificates:Certificate2:Source"] = "File", - ["TestConfig:Certificates:Certificate2:Path"] = "Certificate1.pfx", - ["TestConfig:Certificates:Certificate2:Password"] = "Password1", - }) - .Build(); - - var certificate = new X509Certificate2(); - - var certificateFileLoader = new Mock(); - certificateFileLoader - .Setup(loader => loader.Load("Certificate1.pfx", "Password1", It.IsAny())) - .Returns(certificate); - - var certificateStoreLoader = new Mock(); - certificateStoreLoader - .Setup(loader => loader.Load("localhost", "My", StoreLocation.CurrentUser, It.IsAny())) - .Returns(null); - - var certificateLoader = new CertificateLoader( - null, - null, - null, - certificateFileLoader.Object, - certificateStoreLoader.Object); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Single(loadedCertificates); - Assert.Same(certificate, loadedCertificates.ElementAt(0)); - } - - [Theory] - [InlineData("Development")] - [InlineData("Production")] - public void IncludesEnvironmentNameInExceptionWhenAvailable(string environmentName) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(new Dictionary - { - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - environmentName, - Mock.Of(), - Mock.Of()); - - var exception = Assert.Throws(() => 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 - { - ["TestConfig:Certificate"] = "Certificate1" - }) - .Build(); - - var certificateLoader = new CertificateLoader( - configuration.GetSection("Certificates"), - null, - null, - Mock.Of(), - Mock.Of()); - - var exception = Assert.Throws(() => 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 - { - ["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(); - var logger = new MockLogger(); - - loggerFactory - .Setup(factory => factory.CreateLogger("Microsoft.AspNetCore.CertificateLoader")) - .Returns(logger); - - var certificateLoader = new CertificateLoader( - null, - loggerFactory.Object, - null, - Mock.Of(), - Mock.Of()); - - var loadedCertificates = certificateLoader.Load(configuration.GetSection("TestConfig:Certificates")); - Assert.Empty(loadedCertificates); - 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 _logMessages = new List(); - - public IEnumerable LogMessages => _logMessages; - - public IDisposable BeginScope(TState state) - { - throw new NotImplementedException(); - } - - public bool IsEnabled(LogLevel logLevel) - { - throw new NotImplementedException(); - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - _logMessages.Add(new LogMessage - { - LogLevel = logLevel, - Message = formatter(state, exception) - }); - } - - public class LogMessage - { - public LogLevel LogLevel { get; set; } - public string Message { get; set; } - } - } - } -} diff --git a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Microsoft.AspNetCore.Certificates.Configuration.Tests.csproj b/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Microsoft.AspNetCore.Certificates.Configuration.Tests.csproj deleted file mode 100644 index 394a66c9c2..0000000000 --- a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Microsoft.AspNetCore.Certificates.Configuration.Tests.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - - $(StandardTestTfms) - - - true - win7-x64 - - - - - - - - - - - - - - - - diff --git a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Properties/AssemblyInfo.cs b/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 3337ebeac2..0000000000 --- a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/testCert.pfx b/test/Microsoft.AspNetCore.Certificates.Configuration.Tests/testCert.pfx deleted file mode 100644 index 7118908c2d730670c16e9f8b2c532a262c951989..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2483 zcmaKuc|27A8pqF>IWr86E&Q@(n=B)p$ug!;QVB6xij*z;uPLG!yCz#DQB)+9G$9m9 zQU)=DWXU?*EZIwG!+0d++P@yZ4Xhoagg?p6B~|Ue7tN=Ny=UD?x#1n1MTq z#c9MHh+D#gd|(a(cN}8i91v^=GcdgW3SmA$49p~gM-dys3jVWdg8+!iVL)pz1LDE5 zSb=|GAn(@R=(Ux!MfS9@}sFu-xDd zIt2+mqSq$glwy_6UNs<2?(qERU!gJ;5j}Pp&6trxG=wi)=@k(w2+fJVnc+qvXVzy(>Om4;L|^)R`t*3nTpAmEmTl(#i!RV#a0t#u6>Q9mY`-Nmcs7$XjXT7 zUmCD`O~_j7!%R#I?cG-7C^hcH)@l?WC1vyw$FFu_(r)jhOq6p}W8sG7NO{YTy8tG4 zrb$tTkag*G?(7lfoGx$4YWui>{{@}-FB2ub=}RX{1zx?j)s-##J9|G7E1@-;7Nuln z9MQoX7FJ76+D#XXT@ZZmLZCufIdf3@OigG6m8I7!GT=7VD|>?6e!z9=eT}*E_tSn6 zl+clHCZ-kcIR#gen#LjMJW8>0QtViaQB#FhqsCb0YPYr3;jRITl@V9Aph24D?r2d` zetCyyCg<*O-u+M& zW^ptmT|}p$VAOZpmbQ1{5fK-6ytEvre#Po}6c2URn`viQAF2+e?Z~PK2&pd>7=7)I zTCYm)@3PFRu_6a6Kb)IpCzQ%e3l%O#SDA+$Pq{Dk{HCqi7z>qd{nVpebffL7h{c4( zmhXn~G+C27S3(IfC)q2KON=YwqHXEo%zc40DgWLzF{%RIdr@RcLu90qMSHf!Y}JaqP<={8_Rfe;ddR5= zKEo;^Yip&^m((#{czE{kUga3-@`*;&EwO}Jt>QdURP2P>ob^j-A!qld-0S_pm)kjs zkNo48oZnMt){W~o8g^f;4#?lRLr-T@f}wH1o~-Iq=NEVtTVEZ`vrW~!>2yh%;Bc~H zHl&OK>n@d`*e19*9#v>zZpU?I);f7}IPIfSSk#N|ujE492Itg)l!)TJ19@FE^x|p= zH16NC7OfK&|6_!AnWfTIf^YPOa&`|nbk3VR0vql6&s@y1V3QOU%(`Re+kJgrz?r9!{^wOQ4W-eng23gc}f(LxIs zH_Ls~5izbjcRQH#WH6s6hR;zn>j_R8aJ$A)6xNneu8UI-vWV8Z@HZu&WwvG5q{1ZS zdZeVf{Pv5-u281~y;aJe*x%Uv0@biMZ$vPbKj}O`(SOWQc~kJX` zXR&d4DtAe@2RH$^ z0os5*;0eIUeJi3Uh`A%44x(XzjClG8BO~-r_A}odiRuHo2-86#`mhrgN5p~<$RLY? zq(kynfFA5{v#p+EA1 z5aoe1763EQHorRm`C&ktKn(OQ1n)$Q{GZz&jRb`eDEMpl<0O#+)DMV(T7nsIzCG{QuM->B9g7Lrl2SE&gW`M!~(un|y0fIn=b^6_$ z9{zEzgYI~39xn0ZP*9qBL%fg7rg$ttt&TOmvfNNO<6FT0ZavM$Y4CYLQGIcIYv9Y& zBGPUh&QTfW;V2!)oIra@s&d968y-y}Y|ww(R$GzWS*V&)k@W0>Slem{|HdTCjm;_5 zwY*A8W3nUbemE^_f0ng$tbd<`sr?TO-_&VCw+F#7P@LkIl$1PzTBoPY1b88EIO>UO zP-NK7+g2yD3U6g3i|iA6+su>54sf_Sk0F=)1|9odnCM4u2Rs z=&Y?-V&VquSN%3FJ2~ZGweP~iLs|w=l@9yu$tj@}Dp?e-2JUsqOoswdXb=E%&0te_ zA2M+{5Hf-dqD7=yw*r@A*xkn(1IS~nfP}k}e?4Bt|9g(eph4hFX_|S6nj1&Sz9z^= zRw~<&-9d@FzTn6S*RVE{Wj5lgLJr9HLB8S9CgOm*>XA8*y4`JE;^s$=bqD#U4;e5C&x&ggKIAVL zrQ)Yd8|{>7Z(6*B&7&4&9(*vDOfHMuR-Dk1IZia*XM^EZUD^{?cWG>J>KrtElc*{K zaVl(7SN2cH4I6Q$bZOpJ8e5LKaG7p;?tJ~#+9QrTYU@f#5`Vo7cEX!szCT}iX-K^2 w#3o+=C+lQz2J+SOEzVX(eJ)e7=eicC{rr9U2VGDcdH?_b