Fail on startup for Http/2 HTTPS on Mac #11061 (#11120)

* Use automatic resx #11054
This commit is contained in:
Chris Ross 2019-06-13 15:42:45 -07:00 committed by GitHub
parent 3bf09d8d75
commit 82d2b4f4d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 2377 deletions

View File

@ -1,6 +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.InteropServices;
using System.Threading.Tasks;
using Templates.Test.Helpers;
using Xunit;
@ -37,16 +38,38 @@ namespace Templates.Test
using (var serverProcess = Project.StartBuiltProjectAsync())
{
Assert.False(
serverProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process));
// These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support.
// https://github.com/aspnet/AspNetCore/issues/11061
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Assert.True(serverProcess.Process.HasExited, "built");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on OSX due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process));
}
else
{
Assert.False(
serverProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built service", Project, serverProcess.Process));
}
}
using (var aspNetProcess = Project.StartPublishedProjectAsync())
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process));
// These templates are HTTPS + HTTP/2 only which is not supported on Mac due to missing ALPN support.
// https://github.com/aspnet/AspNetCore/issues/11061
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Assert.True(aspNetProcess.Process.HasExited, "published");
Assert.Contains("System.NotSupportedException: HTTP/2 over TLS is not supported on OSX due to missing ALPN support.",
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process));
}
else
{
Assert.False(
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published service", Project, aspNetProcess.Process));
}
}
}
}

View File

@ -605,4 +605,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
<data name="RequestTrailersNotAvailable" xml:space="preserve">
<value>The request trailers are not available yet. They may not be available until the full request body is read.</value>
</data>
<data name="HTTP2NoTlsOsx" xml:space="preserve">
<value>HTTP/2 over TLS is not supported on OSX due to missing ALPN support.</value>
</data>
</root>

View File

@ -5,17 +5,18 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal
{
@ -41,6 +42,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Https.Internal
throw new ArgumentNullException(nameof(options));
}
// This configuration will always fail per-request, preemptively fail it here. See HttpConnection.SelectProtocol().
if (options.HttpProtocols == HttpProtocols.Http2 && RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
throw new NotSupportedException(CoreStrings.HTTP2NoTlsOsx);
}
// capture the certificate now so it can't be switched after validation
_serverCertificate = options.ServerCertificate;
_serverCertificateSelector = options.ServerCertificateSelector;

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,8 @@
<PropertyGroup>
<KestrelRoot>$(MSBuildThisFileDirectory)</KestrelRoot>
<KestrelSharedSourceRoot>$(MSBuildThisFileDirectory)shared\</KestrelSharedSourceRoot>
<GenerateResxSource>true</GenerateResxSource>
<GenerateResxSourceEmitFormatMethods>true</GenerateResxSourceEmitFormatMethods>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsTestProject)' == 'true' ">

View File

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -133,7 +134,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
serverOptions.ConfigureEndpointDefaults(opt =>
{
opt.Protocols = HttpProtocols.Http2;
opt.Protocols = HttpProtocols.Http1;
});
serverOptions.ConfigureHttpsDefaults(opt =>
@ -155,12 +156,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
Assert.True(opt.IsHttps);
Assert.NotNull(opt.HttpsOptions.ServerCertificate);
Assert.Equal(ClientCertificateMode.RequireCertificate, opt.HttpsOptions.ClientCertificateMode);
Assert.Equal(HttpProtocols.Http2, opt.ListenOptions.Protocols);
Assert.Equal(HttpProtocols.Http1, opt.ListenOptions.Protocols);
})
.LocalhostEndpoint(5002, opt =>
{
ran2 = true;
Assert.Equal(HttpProtocols.Http2, opt.Protocols);
Assert.Equal(HttpProtocols.Http1, opt.Protocols);
})
.Load();
@ -316,11 +317,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
}
}
[Theory]
[ConditionalTheory]
[InlineData("http1", HttpProtocols.Http1)]
// [InlineData("http2", HttpProtocols.Http2)] // Not supported due to missing ALPN support. https://github.com/dotnet/corefx/issues/33016
[InlineData("http1AndHttp2", HttpProtocols.Http1AndHttp2)] // Gracefully falls back to HTTP/1
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.Windows)]
public void DefaultConfigSectionCanSetProtocols_Mac(string input, HttpProtocols expected)
=> DefaultConfigSectionCanSetProtocols(input, expected);
[ConditionalTheory]
[InlineData("http1", HttpProtocols.Http1)]
[InlineData("http2", HttpProtocols.Http2)]
[InlineData("http1AndHttp2", HttpProtocols.Http1AndHttp2)]
public void DefaultConfigSectionCanSetProtocols(string input, HttpProtocols expected)
[OSSkipCondition(OperatingSystems.MacOSX)]
public void DefaultConfigSectionCanSetProtocols_NonMac(string input, HttpProtocols expected)
=> DefaultConfigSectionCanSetProtocols(input, expected);
private void DefaultConfigSectionCanSetProtocols(string input, HttpProtocols expected)
{
var serverOptions = CreateServerOptions();
var ranDefault = false;
@ -371,11 +384,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
Assert.True(ran3);
}
[Theory]
[ConditionalTheory]
[InlineData("http1", HttpProtocols.Http1)]
// [InlineData("http2", HttpProtocols.Http2)] // Not supported due to missing ALPN support. https://github.com/dotnet/corefx/issues/33016
[InlineData("http1AndHttp2", HttpProtocols.Http1AndHttp2)] // Gracefully falls back to HTTP/1
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.Windows)]
public void EndpointConfigSectionCanSetProtocols_Mac(string input, HttpProtocols expected) =>
EndpointConfigSectionCanSetProtocols(input, expected);
[ConditionalTheory]
[InlineData("http1", HttpProtocols.Http1)]
[InlineData("http2", HttpProtocols.Http2)]
[InlineData("http1AndHttp2", HttpProtocols.Http1AndHttp2)]
public void EndpointConfigSectionCanSetProtocols(string input, HttpProtocols expected)
[OSSkipCondition(OperatingSystems.MacOSX)]
public void EndpointConfigSectionCanSetProtocols_NonMac(string input, HttpProtocols expected) =>
EndpointConfigSectionCanSetProtocols(input, expected);
private void EndpointConfigSectionCanSetProtocols(string input, HttpProtocols expected)
{
var serverOptions = CreateServerOptions();
var ranDefault = false;

View File

@ -1,58 +0,0 @@
// <auto-generated />
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
{
using System.Globalization;
using System.Reflection;
using System.Resources;
internal static class SocketsStrings
{
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketsStrings", typeof(SocketsStrings).GetTypeInfo().Assembly);
/// <summary>
/// Only ListenType.IPEndPoint is supported by the Socket Transport. https://go.microsoft.com/fwlink/?linkid=874850
/// </summary>
internal static string OnlyIPEndPointsSupported
{
get => GetString("OnlyIPEndPointsSupported");
}
/// <summary>
/// Only ListenType.IPEndPoint is supported by the Socket Transport. https://go.microsoft.com/fwlink/?linkid=874850
/// </summary>
internal static string FormatOnlyIPEndPointsSupported()
=> GetString("OnlyIPEndPointsSupported");
/// <summary>
/// Transport is already bound.
/// </summary>
internal static string TransportAlreadyBound
{
get => GetString("TransportAlreadyBound");
}
/// <summary>
/// Transport is already bound.
/// </summary>
internal static string FormatTransportAlreadyBound()
=> GetString("TransportAlreadyBound");
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
System.Diagnostics.Debug.Assert(value != null);
if (formatterNames != null)
{
for (var i = 0; i < formatterNames.Length; i++)
{
value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}");
}
}
return value;
}
}
}

View File

@ -19,9 +19,6 @@ using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
{
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492")]
[SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/10428", Queues = "Debian.8.Amd64.Open")] // Debian 8 uses OpenSSL 1.0.1 which does not support HTTP/2
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10)]
public class HandshakeTests : LoggedTest
{
private static X509Certificate2 _x509Certificate2 = TestResources.GetTestCertificate();
@ -40,6 +37,30 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.Windows)]
// Mac SslStream is missing ALPN support: https://github.com/dotnet/corefx/issues/30492
public void TlsAndHttp2NotSupportedOnMac()
{
var ex = Assert.Throws<NotSupportedException>(() => new TestServer(context =>
{
throw new NotImplementedException();
}, new TestServiceContext(LoggerFactory),
kestrelOptions =>
{
kestrelOptions.Listen(IPAddress.Loopback, 0, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
listenOptions.UseHttps(_x509Certificate2);
});
}));
Assert.Equal("HTTP/2 over TLS is not supported on OSX due to missing ALPN support.", ex.Message);
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492")]
[SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/10428", Queues = "Debian.8.Amd64.Open")] // Debian 8 uses OpenSSL 1.0.1 which does not support HTTP/2
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10)]
public async Task TlsAlpnHandshakeSelectsHttp2From1and2()
{
using (var server = new TestServer(context =>
@ -68,6 +89,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492")]
[SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/10428", Queues = "Debian.8.Amd64.Open")] // Debian 8 uses OpenSSL 1.0.1 which does not support HTTP/2
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10)]
public async Task TlsAlpnHandshakeSelectsHttp2()
{
using (var server = new TestServer(context =>