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

Commit e4c6636

Browse files
committed
Delay loading the dev cert #2422
1 parent 769dd46 commit e4c6636

File tree

7 files changed

+95
-68
lines changed

7 files changed

+95
-68
lines changed

build/dependencies.props

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,39 @@
77
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
88
<InternalAspNetCoreSdkPackageVersion>2.1.0-preview3-17001</InternalAspNetCoreSdkPackageVersion>
99
<LibuvPackageVersion>1.10.0</LibuvPackageVersion>
10-
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
11-
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
12-
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
13-
<MicrosoftAspNetCoreHostingPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreHostingPackageVersion>
14-
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
15-
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
16-
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreHttpPackageVersion>
17-
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreTestingPackageVersion>
18-
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview3-32037</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
19-
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
20-
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsBuffersSourcesPackageVersion>
21-
<MicrosoftExtensionsBuffersTestingSourcesPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsBuffersTestingSourcesPackageVersion>
22-
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsConfigurationBinderPackageVersion>
23-
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsConfigurationJsonPackageVersion>
24-
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsDependencyInjectionPackageVersion>
25-
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
26-
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsLoggingConsolePackageVersion>
27-
<MicrosoftExtensionsLoggingPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsLoggingPackageVersion>
28-
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsLoggingTestingPackageVersion>
29-
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview3-32037</MicrosoftExtensionsOptionsPackageVersion>
10+
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
11+
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
12+
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
13+
<MicrosoftAspNetCoreHostingPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreHostingPackageVersion>
14+
<MicrosoftAspNetCoreHttpAbstractionsPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>
15+
<MicrosoftAspNetCoreHttpFeaturesPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreHttpFeaturesPackageVersion>
16+
<MicrosoftAspNetCoreHttpPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreHttpPackageVersion>
17+
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreTestingPackageVersion>
18+
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.0-preview3-32119</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
19+
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
20+
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsBuffersSourcesPackageVersion>
21+
<MicrosoftExtensionsBuffersTestingSourcesPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsBuffersTestingSourcesPackageVersion>
22+
<MicrosoftExtensionsConfigurationBinderPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsConfigurationBinderPackageVersion>
23+
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsConfigurationJsonPackageVersion>
24+
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsDependencyInjectionPackageVersion>
25+
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
26+
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsLoggingConsolePackageVersion>
27+
<MicrosoftExtensionsLoggingPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsLoggingPackageVersion>
28+
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsLoggingTestingPackageVersion>
29+
<MicrosoftExtensionsOptionsPackageVersion>2.1.0-preview3-32119</MicrosoftExtensionsOptionsPackageVersion>
3030
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
31-
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview3-32037</MicrosoftNetHttpHeadersPackageVersion>
3231
<MicrosoftNETCoreApp21PackageVersion>2.1.0-preview3-26331-01</MicrosoftNETCoreApp21PackageVersion>
32+
<MicrosoftNetHttpHeadersPackageVersion>2.1.0-preview3-32119</MicrosoftNetHttpHeadersPackageVersion>
3333
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
3434
<MoqPackageVersion>4.7.49</MoqPackageVersion>
35+
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
3536
<SystemBuffersPackageVersion>4.5.0-preview3-26331-02</SystemBuffersPackageVersion>
3637
<SystemIOPipelinesPackageVersion>4.5.0-preview3-26331-02</SystemIOPipelinesPackageVersion>
3738
<SystemMemoryPackageVersion>4.5.0-preview3-26331-02</SystemMemoryPackageVersion>
3839
<SystemNumericsVectorsPackageVersion>4.5.0-preview3-26331-02</SystemNumericsVectorsPackageVersion>
3940
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.5.0-preview3-26331-02</SystemRuntimeCompilerServicesUnsafePackageVersion>
4041
<SystemSecurityCryptographyCngPackageVersion>4.5.0-preview3-26331-02</SystemSecurityCryptographyCngPackageVersion>
4142
<SystemThreadingTasksExtensionsPackageVersion>4.5.0-preview3-26331-02</SystemThreadingTasksExtensionsPackageVersion>
42-
<NewtonsoftJsonPackageVersion>11.0.1</NewtonsoftJsonPackageVersion>
4343
<XunitAnalyzersPackageVersion>0.8.0</XunitAnalyzersPackageVersion>
4444
<XunitPackageVersion>2.3.1</XunitPackageVersion>
4545
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>

src/Kestrel.Core/Internal/KestrelServerOptionsSetup.cs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Linq;
6-
using System.Security.Cryptography.X509Certificates;
7-
using Microsoft.AspNetCore.Certificates.Generation;
8-
using Microsoft.AspNetCore.Server.Kestrel.Internal;
9-
using Microsoft.Extensions.DependencyInjection;
10-
using Microsoft.Extensions.Logging;
115
using Microsoft.Extensions.Options;
126

137
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
@@ -24,33 +18,6 @@ public KestrelServerOptionsSetup(IServiceProvider services)
2418
public void Configure(KestrelServerOptions options)
2519
{
2620
options.ApplicationServices = _services;
27-
UseDefaultDeveloperCertificate(options);
28-
}
29-
30-
private void UseDefaultDeveloperCertificate(KestrelServerOptions options)
31-
{
32-
var logger = options.ApplicationServices.GetRequiredService<ILogger<KestrelServer>>();
33-
X509Certificate2 certificate = null;
34-
try
35-
{
36-
var certificateManager = new CertificateManager();
37-
certificate = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true)
38-
.FirstOrDefault();
39-
}
40-
catch
41-
{
42-
logger.UnableToLocateDevelopmentCertificate();
43-
}
44-
45-
if (certificate != null)
46-
{
47-
logger.LocatedDevelopmentCertificate(certificate);
48-
options.DefaultCertificate = certificate;
49-
}
50-
else
51-
{
52-
logger.UnableToLocateDevelopmentCertificate();
53-
}
5421
}
5522
}
5623
}

src/Kestrel.Core/KestrelConfigurationLoader.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ public void Load()
225225
// Specified
226226
httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name)
227227
?? httpsOptions.ServerCertificate;
228+
229+
// Fallback
230+
Options.ApplyDefaultCert(httpsOptions);
228231
}
229232

230233
if (EndpointConfigurations.TryGetValue(endpoint.Name, out var configureEndpoint))

src/Kestrel.Core/KestrelServerOptions.cs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Net;
78
using System.Security.Cryptography.X509Certificates;
9+
using Microsoft.AspNetCore.Certificates.Generation;
810
using Microsoft.AspNetCore.Http;
911
using Microsoft.AspNetCore.Server.Kestrel.Https;
12+
using Microsoft.AspNetCore.Server.Kestrel.Internal;
1013
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
1114
using Microsoft.Extensions.Configuration;
15+
using Microsoft.Extensions.DependencyInjection;
16+
using Microsoft.Extensions.Logging;
1217

1318
namespace Microsoft.AspNetCore.Server.Kestrel.Core
1419
{
@@ -75,10 +80,15 @@ public class KestrelServerOptions
7580
private Action<HttpsConnectionAdapterOptions> HttpsDefaults { get; set; } = _ => { };
7681

7782
/// <summary>
78-
/// The default server certificate for https endpoints. This is applied before HttpsDefaults.
83+
/// The default server certificate for https endpoints. This is applied lazily after HttpsDefaults and user options.
7984
/// </summary>
8085
internal X509Certificate2 DefaultCertificate { get; set; }
8186

87+
/// <summary>
88+
/// Has the default dev certificate load been attempted?
89+
/// </summary>
90+
internal bool IsDevCertLoaded { get; set; }
91+
8292
/// <summary>
8393
/// Specifies a configuration Action to run for each newly created endpoint. Calling this again will replace
8494
/// the prior action.
@@ -105,10 +115,50 @@ public void ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions> configu
105115

106116
internal void ApplyHttpsDefaults(HttpsConnectionAdapterOptions httpsOptions)
107117
{
108-
httpsOptions.ServerCertificate = DefaultCertificate;
109118
HttpsDefaults(httpsOptions);
110119
}
111120

121+
internal void ApplyDefaultCert(HttpsConnectionAdapterOptions httpsOptions)
122+
{
123+
// TODO SNI: Also check for the server cert selector
124+
if (httpsOptions.ServerCertificate != null)
125+
{
126+
return;
127+
}
128+
129+
EnsureDefaultCert();
130+
131+
httpsOptions.ServerCertificate = DefaultCertificate;
132+
}
133+
134+
private void EnsureDefaultCert()
135+
{
136+
if (DefaultCertificate == null && !IsDevCertLoaded)
137+
{
138+
IsDevCertLoaded = true; // Only try once
139+
var logger = ApplicationServices.GetRequiredService<ILogger<KestrelServer>>();
140+
try
141+
{
142+
var certificateManager = new CertificateManager();
143+
DefaultCertificate = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true)
144+
.FirstOrDefault();
145+
146+
if (DefaultCertificate != null)
147+
{
148+
logger.LocatedDevelopmentCertificate(DefaultCertificate);
149+
}
150+
else
151+
{
152+
logger.UnableToLocateDevelopmentCertificate();
153+
}
154+
}
155+
catch
156+
{
157+
logger.UnableToLocateDevelopmentCertificate();
158+
}
159+
}
160+
}
161+
112162
/// <summary>
113163
/// Creates a configuration loader for setting up Kestrel.
114164
/// </summary>

src/Kestrel.Core/ListenOptionsHttpsExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ public static ListenOptions UseHttps(this ListenOptions listenOptions, Action<Ht
178178
var options = new HttpsConnectionAdapterOptions();
179179
listenOptions.KestrelServerOptions.ApplyHttpsDefaults(options);
180180
configureOptions(options);
181+
listenOptions.KestrelServerOptions.ApplyDefaultCert(options);
181182

182183
if (options.ServerCertificate == null)
183184
{
@@ -191,6 +192,7 @@ internal static bool TryUseHttps(this ListenOptions listenOptions)
191192
{
192193
var options = new HttpsConnectionAdapterOptions();
193194
listenOptions.KestrelServerOptions.ApplyHttpsDefaults(options);
195+
listenOptions.KestrelServerOptions.ApplyDefaultCert(options);
194196

195197
if (options.ServerCertificate == null)
196198
{

test/Kestrel.Core.Tests/KestrelServerTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ public void StartWithHttpsAddressConfiguresHttpsEndpoints()
6565
[Fact]
6666
public void KestrelServerThrowsUsefulExceptionIfDefaultHttpsProviderNotAdded()
6767
{
68-
using (var server = CreateServer(CreateServerOptions(), throwOnCriticalErrors: false))
68+
var options = CreateServerOptions();
69+
options.IsDevCertLoaded = true; // Prevent the system default from being loaded
70+
using (var server = CreateServer(options, throwOnCriticalErrors: false))
6971
{
7072
server.Features.Get<IServerAddressesFeature>().Addresses.Add("https://127.0.0.1:0");
7173

test/Kestrel.FunctionalTests/HttpsTests.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,38 +47,41 @@ public void UseHttpsDefaultsToDefaultCert()
4747
options.UseHttps();
4848
});
4949

50+
Assert.False(serverOptions.IsDevCertLoaded);
51+
5052
serverOptions.ListenLocalhost(5001, options =>
5153
{
5254
options.UseHttps(opt =>
5355
{
54-
Assert.Equal(defaultCert, opt.ServerCertificate);
56+
// The default cert is applied after UseHttps.
57+
Assert.Null(opt.ServerCertificate);
5558
});
5659
});
60+
Assert.False(serverOptions.IsDevCertLoaded);
5761
}
5862

5963
[Fact]
60-
public void ConfigureHttpsDefaultsOverridesDefaultCert()
64+
public void ConfigureHttpsDefaultsNeverLoadsDefaultCert()
6165
{
6266
var serverOptions = CreateServerOptions();
63-
var defaultCert = new X509Certificate2(TestResources.TestCertificatePath, "testPassword");
64-
serverOptions.DefaultCertificate = defaultCert;
67+
var testCert = new X509Certificate2(TestResources.TestCertificatePath, "testPassword");
6568
serverOptions.ConfigureHttpsDefaults(options =>
6669
{
67-
Assert.Equal(defaultCert, options.ServerCertificate);
68-
options.ServerCertificate = null;
70+
Assert.Null(options.ServerCertificate);
71+
options.ServerCertificate = testCert;
6972
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
7073
});
7174
serverOptions.ListenLocalhost(5000, options =>
7275
{
7376
options.UseHttps(opt =>
7477
{
75-
Assert.Null(opt.ServerCertificate);
78+
Assert.Equal(testCert, opt.ServerCertificate);
7679
Assert.Equal(ClientCertificateMode.RequireCertificate, opt.ClientCertificateMode);
77-
78-
// So UseHttps won't throw
79-
opt.ServerCertificate = defaultCert;
8080
});
8181
});
82+
// Never lazy loaded
83+
Assert.False(serverOptions.IsDevCertLoaded);
84+
Assert.Null(serverOptions.DefaultCertificate);
8285
}
8386

8487
[Fact]

0 commit comments

Comments
 (0)