Skip to content
This repository was archived by the owner on Nov 21, 2018. It is now read-only.

Commit 012d999

Browse files
author
Cesar Blum Silveira
authored
Show fwlink on HTTPS certificate errors (#83).
1 parent 4d5e107 commit 012d999

File tree

4 files changed

+261
-167
lines changed

4 files changed

+261
-167
lines changed

samples/AppSettings/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public static void Main(string[] args)
1313
{
1414
using (WebHost.Start(context => context.Response.WriteAsync("Hello, World!")))
1515
{
16-
Console.WriteLine("Running application: Press any key to shutdown...");
16+
Console.WriteLine("Running application: Press any key to shutdown.");
1717
Console.ReadKey();
1818
}
1919
}

src/Microsoft.AspNetCore/CertificateLoader.cs

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Security.Cryptography.X509Certificates;
88
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Logging;
910

1011
namespace Microsoft.AspNetCore
1112
{
@@ -15,32 +16,53 @@ namespace Microsoft.AspNetCore
1516
public class CertificateLoader
1617
{
1718
private readonly IConfiguration _certificatesConfiguration;
19+
private readonly string _environmentName;
1820
private readonly ICertificateFileLoader _certificateFileLoader;
1921
private readonly ICertificateStoreLoader _certificateStoreLoader;
22+
private readonly ILogger _logger;
2023

2124
/// <summary>
22-
/// Creates a new instance of <see cref="CertificateLoader"/>.
25+
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
2326
/// </summary>
24-
public CertificateLoader()
25-
: this(null)
27+
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
28+
public CertificateLoader(IConfiguration certificatesConfiguration)
29+
: this(certificatesConfiguration, null, null)
2630
{
2731
}
2832

2933
/// <summary>
3034
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
3135
/// </summary>
3236
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
33-
public CertificateLoader(IConfiguration certificatesConfiguration)
34-
: this(certificatesConfiguration, new CertificateFileLoader(), new CertificateStoreLoader())
37+
/// <param name="loggerFactory">An <see cref="ILoggerFactory"/> instance.</param>
38+
public CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory)
39+
: this(certificatesConfiguration, loggerFactory, null)
3540
{
36-
_certificatesConfiguration = certificatesConfiguration;
3741
}
3842

39-
internal CertificateLoader(IConfiguration certificatesConfiguration, ICertificateFileLoader certificateFileLoader, ICertificateStoreLoader certificateStoreLoader)
43+
/// <summary>
44+
/// Creates a new instance of <see cref="CertificateLoader"/> that can load certificate references from configuration.
45+
/// </summary>
46+
/// <param name="certificatesConfiguration">An <see cref="IConfiguration"/> with information about certificates.</param>
47+
/// <param name="loggerFactory">An <see cref="ILoggerFactory"/> instance.</param>
48+
/// <param name="environmentName">The name of the environment the application is running in.</param>
49+
public CertificateLoader(IConfiguration certificatesConfiguration, ILoggerFactory loggerFactory, string environmentName)
50+
: this(certificatesConfiguration, loggerFactory, environmentName, new CertificateFileLoader(), new CertificateStoreLoader())
4051
{
52+
}
53+
54+
internal CertificateLoader(
55+
IConfiguration certificatesConfiguration,
56+
ILoggerFactory loggerFactory,
57+
string environmentName,
58+
ICertificateFileLoader certificateFileLoader,
59+
ICertificateStoreLoader certificateStoreLoader)
60+
{
61+
_environmentName = environmentName;
4162
_certificatesConfiguration = certificatesConfiguration;
4263
_certificateFileLoader = certificateFileLoader;
4364
_certificateStoreLoader = certificateStoreLoader;
65+
_logger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.CertificateLoader");
4466
}
4567

4668
/// <summary>
@@ -99,7 +121,8 @@ private X509Certificate2 LoadSingle(string certificateName)
99121

100122
if (!certificateConfiguration.Exists())
101123
{
102-
throw new InvalidOperationException($"No certificate named {certificateName} found in configuration");
124+
var environmentName = _environmentName != null ? $" ({_environmentName})" : "";
125+
throw new KeyNotFoundException($"No certificate named '{certificateName}' found in configuration for the current environment{environmentName}.");
103126
}
104127

105128
return LoadSingle(certificateConfiguration);
@@ -116,10 +139,10 @@ private X509Certificate2 LoadSingle(IConfigurationSection certificateConfigurati
116139
certificateSource = new CertificateFileSource(_certificateFileLoader);
117140
break;
118141
case "store":
119-
certificateSource = new CertificateStoreSource(_certificateStoreLoader);
142+
certificateSource = new CertificateStoreSource(_certificateStoreLoader, _logger);
120143
break;
121144
default:
122-
throw new InvalidOperationException($"Invalid certificate source kind: {sourceKind}");
145+
throw new InvalidOperationException($"Invalid certificate source kind '{sourceKind}'.");
123146
}
124147

125148
certificateConfiguration.Bind(certificateSource);
@@ -163,7 +186,7 @@ public override X509Certificate2 Load()
163186

164187
if (error != null)
165188
{
166-
throw error;
189+
throw new InvalidOperationException($"Unable to load certificate from file '{Path}'. Error details: '{error.Message}'.", error);
167190
}
168191

169192
return certificate;
@@ -188,10 +211,12 @@ private X509Certificate2 TryLoad(X509KeyStorageFlags flags, out Exception except
188211
private class CertificateStoreSource : CertificateSource
189212
{
190213
private readonly ICertificateStoreLoader _certificateStoreLoader;
214+
private readonly ILogger _logger;
191215

192-
public CertificateStoreSource(ICertificateStoreLoader certificateStoreLoader)
216+
public CertificateStoreSource(ICertificateStoreLoader certificateStoreLoader, ILogger logger)
193217
{
194218
_certificateStoreLoader = certificateStoreLoader;
219+
_logger = logger;
195220
}
196221

197222
public string Subject { get; set; }
@@ -203,10 +228,17 @@ public override X509Certificate2 Load()
203228
{
204229
if (!Enum.TryParse(StoreLocation, ignoreCase: true, result: out StoreLocation storeLocation))
205230
{
206-
throw new InvalidOperationException($"Invalid store location: {StoreLocation}");
231+
throw new InvalidOperationException($"The certificate store location '{StoreLocation}' is invalid.");
232+
}
233+
234+
var certificate = _certificateStoreLoader.Load(Subject, StoreName, storeLocation, !AllowInvalid);
235+
236+
if (certificate == null)
237+
{
238+
_logger?.LogWarning($"Unable to find a matching certificate for subject '{Subject}' in store '{StoreName}' in '{StoreLocation}'.");
207239
}
208240

209-
return _certificateStoreLoader.Load(Subject, StoreName, storeLocation, !AllowInvalid);
241+
return certificate;
210242
}
211243
}
212244
}

src/Microsoft.AspNetCore/KestrelServerOptionsSetup.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,29 @@
44
using System;
55
using System.Linq;
66
using System.Net;
7+
using System.Security.Cryptography.X509Certificates;
78
using Microsoft.AspNetCore.Hosting;
89
using Microsoft.AspNetCore.Server.Kestrel.Core;
910
using Microsoft.Extensions.Configuration;
11+
using Microsoft.Extensions.Logging;
1012
using Microsoft.Extensions.Options;
1113

1214
namespace Microsoft.AspNetCore
1315
{
1416
internal class KestrelServerOptionsSetup : IConfigureOptions<KestrelServerOptions>
1517
{
18+
private readonly IHostingEnvironment _hostingEnvironment;
1619
private readonly IConfiguration _configurationRoot;
20+
private readonly ILoggerFactory _loggerFactory;
1721

18-
public KestrelServerOptionsSetup(IConfiguration configurationRoot)
22+
public KestrelServerOptionsSetup(
23+
IHostingEnvironment hostingEnvironment,
24+
IConfiguration configurationRoot,
25+
ILoggerFactory loggerFactory)
1926
{
27+
_hostingEnvironment = hostingEnvironment;
2028
_configurationRoot = configurationRoot;
29+
_loggerFactory = loggerFactory;
2130
}
2231

2332
public void Configure(KestrelServerOptions options)
@@ -27,7 +36,7 @@ public void Configure(KestrelServerOptions options)
2736

2837
private void BindConfiguration(KestrelServerOptions options)
2938
{
30-
var certificateLoader = new CertificateLoader(_configurationRoot.GetSection("Certificates"));
39+
var certificateLoader = new CertificateLoader(_configurationRoot.GetSection("Certificates"), _loggerFactory, _hostingEnvironment.EnvironmentName);
3140

3241
foreach (var endPoint in _configurationRoot.GetSection("Kestrel:EndPoints").GetChildren())
3342
{
@@ -56,14 +65,22 @@ private void BindEndPoint(
5665
options.Listen(address, port, listenOptions =>
5766
{
5867
var certificateConfig = endPoint.GetSection("Certificate");
68+
X509Certificate2 certificate;
5969

6070
if (certificateConfig.Exists())
6171
{
62-
var certificate = certificateLoader.Load(certificateConfig).FirstOrDefault();
72+
try
73+
{
74+
certificate = certificateLoader.Load(certificateConfig).FirstOrDefault();
6375

64-
if (certificate == null)
76+
if (certificate == null)
77+
{
78+
throw new InvalidOperationException($"No certificate found for endpoint '{endPoint.Key}'.");
79+
}
80+
}
81+
catch (Exception ex)
6582
{
66-
throw new InvalidOperationException($"Unable to load certificate for endpoint '{endPoint.Key}'");
83+
throw new InvalidOperationException("Unable to configure HTTPS endpoint. For information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.", ex);
6784
}
6885

6986
listenOptions.UseHttps(certificate);

0 commit comments

Comments
 (0)