This commit is contained in:
parent
23595db0d2
commit
a77e68f1c5
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Authentication;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||
|
|
@ -12,6 +14,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
private const string ProtocolsKey = "Protocols";
|
||||
private const string CertificatesKey = "Certificates";
|
||||
private const string CertificateKey = "Certificate";
|
||||
private const string SslProtocolsKey = "SslProtocols";
|
||||
private const string EndpointDefaultsKey = "EndpointDefaults";
|
||||
private const string EndpointsKey = "Endpoints";
|
||||
private const string UrlKey = "Url";
|
||||
|
|
@ -49,13 +52,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
|
||||
// "EndpointDefaults": {
|
||||
// "Protocols": "Http1AndHttp2",
|
||||
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||
// }
|
||||
private EndpointDefaults ReadEndpointDefaults()
|
||||
{
|
||||
var configSection = _configuration.GetSection(EndpointDefaultsKey);
|
||||
return new EndpointDefaults
|
||||
{
|
||||
Protocols = ParseProtocols(configSection[ProtocolsKey])
|
||||
Protocols = ParseProtocols(configSection[ProtocolsKey]),
|
||||
SslProtocols = ParseSslProcotols(configSection.GetSection(SslProtocolsKey))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
// "EndpointName": {
|
||||
// "Url": "https://*:5463",
|
||||
// "Protocols": "Http1AndHttp2",
|
||||
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||
// "Certificate": {
|
||||
// "Path": "testCert.pfx",
|
||||
// "Password": "testPassword"
|
||||
|
|
@ -88,6 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
Protocols = ParseProtocols(endpointConfig[ProtocolsKey]),
|
||||
ConfigSection = endpointConfig,
|
||||
Certificate = new CertificateConfig(endpointConfig.GetSection(CertificateKey)),
|
||||
SslProtocols = ParseSslProcotols(endpointConfig.GetSection(SslProtocolsKey))
|
||||
};
|
||||
|
||||
endpoints.Add(endpoint);
|
||||
|
|
@ -105,19 +112,37 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static SslProtocols? ParseSslProcotols(IConfigurationSection sslProtocols)
|
||||
{
|
||||
var stringProtocols = sslProtocols.Get<string[]>();
|
||||
|
||||
return stringProtocols?.Aggregate(SslProtocols.None, (acc, current) =>
|
||||
{
|
||||
if (Enum.TryParse(current, ignoreCase: true, out SslProtocols parsed))
|
||||
{
|
||||
return acc | parsed;
|
||||
}
|
||||
|
||||
return acc;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// "EndpointDefaults": {
|
||||
// "Protocols": "Http1AndHttp2",
|
||||
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||
// }
|
||||
internal class EndpointDefaults
|
||||
{
|
||||
public HttpProtocols? Protocols { get; set; }
|
||||
public SslProtocols? SslProtocols { get; set; }
|
||||
}
|
||||
|
||||
// "EndpointName": {
|
||||
// "Url": "https://*:5463",
|
||||
// "Protocols": "Http1AndHttp2",
|
||||
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||
// "Certificate": {
|
||||
// "Path": "testCert.pfx",
|
||||
// "Password": "testPassword"
|
||||
|
|
@ -131,6 +156,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
public string Name { get; set; }
|
||||
public string Url { get; set; }
|
||||
public HttpProtocols? Protocols { get; set; }
|
||||
public SslProtocols? SslProtocols { get; set; }
|
||||
public CertificateConfig Certificate { get; set; }
|
||||
|
||||
// Compare config sections because it's accessible to app developers via an Action<EndpointConfiguration> callback.
|
||||
|
|
@ -154,6 +180,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
|||
Url == other.Url &&
|
||||
(Protocols ?? ListenOptions.DefaultHttpProtocols) == (other.Protocols ?? ListenOptions.DefaultHttpProtocols) &&
|
||||
Certificate == other.Certificate &&
|
||||
(SslProtocols ?? System.Security.Authentication.SslProtocols.None) == (other.SslProtocols ?? System.Security.Authentication.SslProtocols.None) &&
|
||||
_configSectionClone == other._configSectionClone;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Name, Url, Protocols ?? ListenOptions.DefaultHttpProtocols, Certificate, _configSectionClone);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.AspNetCore.Certificates.Generation;
|
||||
|
|
@ -279,9 +280,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
var httpsOptions = new HttpsConnectionAdapterOptions();
|
||||
if (https)
|
||||
{
|
||||
httpsOptions.SslProtocols = ConfigurationReader.EndpointDefaults.SslProtocols ?? SslProtocols.None;
|
||||
|
||||
// Defaults
|
||||
Options.ApplyHttpsDefaults(httpsOptions);
|
||||
|
||||
if (endpoint.SslProtocols.HasValue)
|
||||
{
|
||||
httpsOptions.SslProtocols = endpoint.SslProtocols.Value;
|
||||
}
|
||||
|
||||
// Specified
|
||||
httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name)
|
||||
?? httpsOptions.ServerCertificate;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Authentication;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Xunit;
|
||||
|
|
@ -173,5 +174,84 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
|||
Assert.Equal("cetlocation", cert4.Location);
|
||||
Assert.True(cert4.AllowInvalid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointWithSingleSslProtocolSet_ReturnsCorrectValue()
|
||||
{
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "http://*:5001"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:0", "Tls11"),
|
||||
}).Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.Endpoints.First();
|
||||
Assert.Equal(SslProtocols.Tls11, endpoint.SslProtocols);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointWithMultipleSslProtocolsSet_ReturnsCorrectValue()
|
||||
{
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "http://*:5001"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:0", "Tls11"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:1", "Tls12"),
|
||||
}).Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.Endpoints.First();
|
||||
Assert.Equal(SslProtocols.Tls11|SslProtocols.Tls12, endpoint.SslProtocols);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointWithSslProtocolSet_ReadsCaseInsensitive()
|
||||
{
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "http://*:5001"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:0", "TLS11"),
|
||||
}).Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.Endpoints.First();
|
||||
Assert.Equal(SslProtocols.Tls11, endpoint.SslProtocols);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointWithNoSslProtocolSettings_ReturnsNull()
|
||||
{
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "http://*:5001"),
|
||||
}).Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.Endpoints.First();
|
||||
Assert.Null(endpoint.SslProtocols);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointDefaultsWithSingleSslProtocolSet_ReturnsCorrectValue()
|
||||
{
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("EndpointDefaults:SslProtocols:0", "Tls11"),
|
||||
}).Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.EndpointDefaults;
|
||||
Assert.Equal(SslProtocols.Tls11, endpoint.SslProtocols);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadEndpointDefaultsWithNoSslProtocolSettings_ReturnsCorrectValue()
|
||||
{
|
||||
var config = new ConfigurationBuilder().Build();
|
||||
var reader = new ConfigurationReader(config);
|
||||
|
||||
var endpoint = reader.EndpointDefaults;
|
||||
Assert.Null(endpoint.SslProtocols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
|
|
@ -18,7 +19,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
||||
{
|
||||
public class KestrelConfigurationBuilderTests
|
||||
public class KestrelConfigurationLoaderTests
|
||||
{
|
||||
private KestrelServerOptions CreateServerOptions()
|
||||
{
|
||||
|
|
@ -456,6 +457,136 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
|||
Assert.True(ran3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndpointConfigureSection_CanSetSslProtocol()
|
||||
{
|
||||
var serverOptions = CreateServerOptions();
|
||||
var ranDefault = false;
|
||||
|
||||
serverOptions.ConfigureHttpsDefaults(opt =>
|
||||
{
|
||||
opt.ServerCertificate = TestResources.GetTestCertificate();
|
||||
|
||||
// Kestrel default
|
||||
Assert.Equal(SslProtocols.None, opt.SslProtocols);
|
||||
ranDefault = true;
|
||||
});
|
||||
|
||||
var ran1 = false;
|
||||
var ran2 = false;
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:0", "Tls11"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
|
||||
}).Build();
|
||||
serverOptions.Configure(config)
|
||||
.Endpoint("End1", opt =>
|
||||
{
|
||||
Assert.Equal(SslProtocols.Tls11, opt.HttpsOptions.SslProtocols);
|
||||
ran1 = true;
|
||||
})
|
||||
.Load();
|
||||
serverOptions.ListenAnyIP(0, opt =>
|
||||
{
|
||||
opt.UseHttps(httpsOptions =>
|
||||
{
|
||||
// Kestrel default.
|
||||
Assert.Equal(SslProtocols.None, httpsOptions.SslProtocols);
|
||||
ran2 = true;
|
||||
});
|
||||
});
|
||||
|
||||
Assert.True(ranDefault);
|
||||
Assert.True(ran1);
|
||||
Assert.True(ran2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndpointConfigureSection_CanOverrideSslProtocolsFromConfigureHttpsDefaults()
|
||||
{
|
||||
var serverOptions = CreateServerOptions();
|
||||
|
||||
serverOptions.ConfigureHttpsDefaults(opt =>
|
||||
{
|
||||
opt.ServerCertificate = TestResources.GetTestCertificate();
|
||||
opt.SslProtocols = SslProtocols.Tls12;
|
||||
});
|
||||
|
||||
var ran1 = false;
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Endpoints:End1:SslProtocols:0", "Tls11"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
|
||||
}).Build();
|
||||
serverOptions.Configure(config)
|
||||
.Endpoint("End1", opt =>
|
||||
{
|
||||
Assert.Equal(SslProtocols.Tls11, opt.HttpsOptions.SslProtocols);
|
||||
ran1 = true;
|
||||
})
|
||||
.Load();
|
||||
|
||||
Assert.True(ran1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultEndpointConfigureSection_CanSetSslProtocols()
|
||||
{
|
||||
var serverOptions = CreateServerOptions();
|
||||
|
||||
serverOptions.ConfigureHttpsDefaults(opt =>
|
||||
{
|
||||
opt.ServerCertificate = TestResources.GetTestCertificate();
|
||||
});
|
||||
|
||||
var ran1 = false;
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("EndpointDefaults:SslProtocols:0", "Tls11"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
|
||||
}).Build();
|
||||
serverOptions.Configure(config)
|
||||
.Endpoint("End1", opt =>
|
||||
{
|
||||
Assert.Equal(SslProtocols.Tls11, opt.HttpsOptions.SslProtocols);
|
||||
ran1 = true;
|
||||
})
|
||||
.Load();
|
||||
|
||||
Assert.True(ran1);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void DefaultEndpointConfigureSection_ConfigureHttpsDefaultsCanOverrideSslProtocols()
|
||||
{
|
||||
var serverOptions = CreateServerOptions();
|
||||
|
||||
serverOptions.ConfigureHttpsDefaults(opt =>
|
||||
{
|
||||
opt.ServerCertificate = TestResources.GetTestCertificate();
|
||||
|
||||
Assert.Equal(SslProtocols.Tls11, opt.SslProtocols);
|
||||
opt.SslProtocols = SslProtocols.Tls12;
|
||||
});
|
||||
|
||||
var ran1 = false;
|
||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("EndpointDefaults:SslProtocols:0", "Tls11"),
|
||||
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
|
||||
}).Build();
|
||||
serverOptions.Configure(config)
|
||||
.Endpoint("End1", opt =>
|
||||
{
|
||||
Assert.Equal(SslProtocols.Tls12, opt.HttpsOptions.SslProtocols);
|
||||
ran1 = true;
|
||||
})
|
||||
.Load();
|
||||
|
||||
Assert.True(ran1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Latin1RequestHeadersReadFromConfig()
|
||||
{
|
||||
Loading…
Reference in New Issue