@@ -12,23 +12,90 @@ namespace Microsoft.AspNetCore
12
12
/// <summary>
13
13
/// A helper class to load certificates from files and certificate stores based on <seealso cref="IConfiguration"/> data.
14
14
/// </summary>
15
- public static class CertificateLoader
15
+ public class CertificateLoader
16
16
{
17
+ private readonly IConfiguration _certificatesConfiguration ;
18
+
19
+ /// <summary>
20
+ /// Creates a new instance of <see cref="KestrelServerOptionsSetup"/>.
21
+ /// </summary>
22
+ public CertificateLoader ( )
23
+ {
24
+ }
25
+
26
+ /// <summary>
27
+ /// Creates a new instance of <see cref="KestrelServerOptionsSetup"/> that can load certificates by name.
28
+ /// </summary>
29
+ /// <param name="certificatesConfig">An <see cref="IConfiguration"/> instance with information about certificates.</param>
30
+ public CertificateLoader ( IConfiguration certificatesConfig )
31
+ {
32
+ _certificatesConfiguration = certificatesConfig ;
33
+ }
34
+
35
+ /// <summary>
36
+ /// Loads one or more certificates based on the information found in a configuration section.
37
+ /// </summary>
38
+ /// <param name="certificateConfiguration">A configuration section containing either a string value referencing certificates
39
+ /// by name, or one or more inline certificate specifications.
40
+ /// </param>
41
+ /// <returns>One or more loaded certificates.</returns>
42
+ public IEnumerable < X509Certificate2 > Load ( IConfigurationSection certificateConfiguration )
43
+ {
44
+ var certificateNames = certificateConfiguration . Value ;
45
+
46
+ List < X509Certificate2 > certificates = new List < X509Certificate2 > ( ) ;
47
+
48
+ if ( certificateNames != null )
49
+ {
50
+ foreach ( var certificateName in certificateNames . Split ( ' ' ) )
51
+ {
52
+ certificates . Add ( Load ( certificateName ) ) ;
53
+ }
54
+ }
55
+ else
56
+ {
57
+ if ( certificateConfiguration [ "Source" ] != null )
58
+ {
59
+ certificates . Add ( LoadSingle ( certificateConfiguration ) ) ;
60
+ }
61
+ else
62
+ {
63
+ certificates . AddRange ( LoadMultiple ( certificateConfiguration ) ) ;
64
+ }
65
+ }
66
+
67
+ return certificates ;
68
+ }
69
+
17
70
/// <summary>
18
- /// Loads one or more certificates from a single source .
71
+ /// Loads a certificate by name .
19
72
/// </summary>
20
- /// <param name="certificateConfiguration">An <seealso cref="IConfiguration"/> with information about a certificate source.</param>
21
- /// <param name="password">The certificate password, in case it's being loaded from a file.</param>
22
- /// <returns>The loaded certificates.</returns>
23
- public static X509Certificate2 Load ( IConfiguration certificateConfiguration , string password )
73
+ /// <param name="certificateName">The certificate name.</param>
74
+ /// <returns>The loaded certificate</returns>
75
+ /// <remarks>This method only works if the <see cref="CertificateLoader"/> instance was constructed with
76
+ /// a reference to an <see cref="IConfiguration"/> instance containing named certificates.
77
+ /// </remarks>
78
+ public X509Certificate2 Load ( string certificateName )
24
79
{
25
- var sourceKind = certificateConfiguration . GetValue < string > ( "Source" ) ;
80
+ var certificateConfiguration = _certificatesConfiguration ? . GetSection ( certificateName ) ;
81
+
82
+ if ( certificateConfiguration == null )
83
+ {
84
+ throw new InvalidOperationException ( $ "No certificate named { certificateName } found in configuration") ;
85
+ }
86
+
87
+ return LoadSingle ( certificateConfiguration ) ;
88
+ }
89
+
90
+ private X509Certificate2 LoadSingle ( IConfigurationSection certificateConfiguration )
91
+ {
92
+ var sourceKind = certificateConfiguration [ "Source" ] ;
26
93
27
94
CertificateSource certificateSource ;
28
95
switch ( sourceKind . ToLowerInvariant ( ) )
29
96
{
30
97
case "file" :
31
- certificateSource = new CertificateFileSource ( password ) ;
98
+ certificateSource = new CertificateFileSource ( ) ;
32
99
break ;
33
100
case "store" :
34
101
certificateSource = new CertificateStoreSource ( ) ;
@@ -38,23 +105,12 @@ public static X509Certificate2 Load(IConfiguration certificateConfiguration, str
38
105
}
39
106
40
107
certificateConfiguration . Bind ( certificateSource ) ;
108
+
41
109
return certificateSource . Load ( ) ;
42
110
}
43
111
44
- /// <summary>
45
- /// Loads all certificates specified in an <seealso cref="IConfiguration"/>.
46
- /// </summary>
47
- /// <param name="configurationRoot">The root <seealso cref="IConfiguration"/>.</param>
48
- /// <returns>
49
- /// A dictionary mapping certificate names to loaded certificates.
50
- /// </returns>
51
- public static Dictionary < string , X509Certificate2 > LoadAll ( IConfiguration configurationRoot )
52
- {
53
- return configurationRoot . GetSection ( "Certificates" ) . GetChildren ( )
54
- . ToDictionary (
55
- certificateSource => certificateSource . Key ,
56
- certificateSource => Load ( certificateSource , certificateSource [ "Password" ] ) ) ;
57
- }
112
+ private IEnumerable < X509Certificate2 > LoadMultiple ( IConfigurationSection certificatesConfiguration )
113
+ => certificatesConfiguration . GetChildren ( ) . Select ( LoadSingle ) ;
58
114
59
115
private abstract class CertificateSource
60
116
{
@@ -65,15 +121,10 @@ private abstract class CertificateSource
65
121
66
122
private class CertificateFileSource : CertificateSource
67
123
{
68
- private readonly string _password ;
69
-
70
- public CertificateFileSource ( string password )
71
- {
72
- _password = password ;
73
- }
74
-
75
124
public string Path { get ; set ; }
76
125
126
+ public string Password { get ; set ; }
127
+
77
128
public override X509Certificate2 Load ( )
78
129
{
79
130
var certificate = TryLoad ( X509KeyStorageFlags . DefaultKeySet , out var error )
@@ -95,7 +146,7 @@ private X509Certificate2 TryLoad(X509KeyStorageFlags flags, out Exception except
95
146
{
96
147
try
97
148
{
98
- var loadedCertificate = new X509Certificate2 ( Path , _password , flags ) ;
149
+ var loadedCertificate = new X509Certificate2 ( Path , Password , flags ) ;
99
150
exception = null ;
100
151
return loadedCertificate ;
101
152
}
0 commit comments