Moving CertificateLoader from MetaPackages to Hosting.
This commit is contained in:
parent
0177ab8424
commit
44ccbee9ba
32
Hosting.sln
32
Hosting.sln
|
|
@ -1,6 +1,6 @@
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26510.0
|
VisualStudioVersion = 15.0.26524.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0497F39-AFFB-4819-A116-E39E361915AB}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0497F39-AFFB-4819-A116-E39E361915AB}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -34,6 +34,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin
|
||||||
EndProject
|
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}"
|
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
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Certificates.Configuration", "src\Microsoft.AspNetCore.Certificates.Configuration\Microsoft.AspNetCore.Certificates.Configuration.csproj", "{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}"
|
||||||
|
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
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -192,6 +196,30 @@ Global
|
||||||
{9C93A93B-270A-4785-8F41-46C38DC33825}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{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.ActiveCfg = Release|Any CPU
|
||||||
{9C93A93B-270A-4785-8F41-46C38DC33825}.Release|x86.Build.0 = Release|Any CPU
|
{9C93A93B-270A-4785-8F41-46C38DC33825}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4}.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
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -210,5 +238,7 @@ Global
|
||||||
{39D3B138-37DB-4D03-A5A0-3F2B02EFC671} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0}
|
{39D3B138-37DB-4D03-A5A0-3F2B02EFC671} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0}
|
||||||
{96BC7EEA-64D9-4DA5-8E87-1C18CBFE7D12} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
{96BC7EEA-64D9-4DA5-8E87-1C18CBFE7D12} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||||
{9C93A93B-270A-4785-8F41-46C38DC33825} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
{9C93A93B-270A-4785-8F41-46C38DC33825} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||||
|
{A911A891-EAC5-4AA1-B17E-B83A1BB1E8B4} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||||
|
{AB0B7394-278D-4838-A59C-276ED88D00CC} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A helper class to load certificates from files and certificate stores based on <seealso cref="IConfiguration"/> data.
|
||||||
|
/// </summary>
|
||||||
|
public class CertificateLoader
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _certificatesConfiguration;
|
||||||
|
private readonly string _environmentName;
|
||||||
|
private readonly ICertificateFileLoader _certificateFileLoader;
|
||||||
|
private readonly ICertificateStoreLoader _certificateStoreLoader;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
public CertificateLoader(IConfiguration certificatesConfiguration)
|
||||||
|
: this(certificatesConfiguration, null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
public CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory)
|
||||||
|
: this(certificatesConfiguration, loggerFactory, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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;
|
||||||
|
_certificateFileLoader = certificateFileLoader;
|
||||||
|
_certificateStoreLoader = certificateStoreLoader;
|
||||||
|
_logger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.CertificateLoader");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads one or more certificates based on the information found in a configuration section.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificateConfiguration">A configuration section containing either a string value referencing certificates
|
||||||
|
/// by name, or one or more inline certificate specifications.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>One or more loaded certificates.</returns>
|
||||||
|
public IEnumerable<X509Certificate2> Load(IConfigurationSection certificateConfiguration)
|
||||||
|
{
|
||||||
|
var certificateNames = certificateConfiguration.Value;
|
||||||
|
var certificates = new List<X509Certificate2>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads a certificate by name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="certificateName">The certificate name.</param>
|
||||||
|
/// <returns>The loaded certificate</returns>
|
||||||
|
/// <remarks>This method only works if the <see cref="CertificateLoader"/> instance was constructed with
|
||||||
|
/// a reference to an <see cref="IConfiguration"/> instance containing named certificates.
|
||||||
|
/// </remarks>
|
||||||
|
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<X509Certificate2> 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
|
||||||
|
?? TryLoad(X509KeyStorageFlags.EphemeralKeySet, out error)
|
||||||
|
#elif NETSTANDARD2_0
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Loads certificates from certificate stores.
|
||||||
|
/// </summary>
|
||||||
|
public class CertificateStoreLoader : ICertificateStoreLoader
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Load a ceritificate from the given store location.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="subject">The certificate subject name to match.</param>
|
||||||
|
/// <param name="storeName">The store to open.</param>
|
||||||
|
/// <param name="storeLocation">The store location to open.</param>
|
||||||
|
/// <param name="validOnly">Only load currently valid certs.</param>
|
||||||
|
/// <returns>The closest matching vertificate.</returns>
|
||||||
|
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<X509Certificate2>()
|
||||||
|
.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>
|
||||||
|
<PackageTags>aspnetcore;certificates</PackageTags>
|
||||||
|
<Description>Helpers for loading certificates from configuration.</Description>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="$(AspNetCoreVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(AspNetCoreVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
// 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("Microsoft.AspNetCore.Certificates.Configuration.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||||
|
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,32 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<Import Project="..\..\build\common.props" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
|
||||||
|
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netcoreapp2.0</TargetFrameworks>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Workaround for "Use executable flags in Microsoft.NET.Test.Sdk" (https://github.com/Microsoft/vstest/issues/792).
|
||||||
|
Remove when fixed.
|
||||||
|
-->
|
||||||
|
<HasRuntimeOutput>true</HasRuntimeOutput>
|
||||||
|
<RuntimeIdentifier Condition="'$(TargetFramework)' != 'netcoreapp2.0'">win7-x64</RuntimeIdentifier>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="testCert.pfx" CopyToOutputDirectory="PreserveNewest" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Certificates.Configuration\Microsoft.AspNetCore.Certificates.Configuration.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
|
||||||
|
<PackageReference Include="Moq" Version="$(MoqVersion)" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
|
||||||
|
<PackageReference Include="xunit" Version="$(XunitVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Binary file not shown.
Loading…
Reference in New Issue