This commit is contained in:
parent
23595db0d2
commit
a77e68f1c5
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Authentication;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
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 ProtocolsKey = "Protocols";
|
||||||
private const string CertificatesKey = "Certificates";
|
private const string CertificatesKey = "Certificates";
|
||||||
private const string CertificateKey = "Certificate";
|
private const string CertificateKey = "Certificate";
|
||||||
|
private const string SslProtocolsKey = "SslProtocols";
|
||||||
private const string EndpointDefaultsKey = "EndpointDefaults";
|
private const string EndpointDefaultsKey = "EndpointDefaults";
|
||||||
private const string EndpointsKey = "Endpoints";
|
private const string EndpointsKey = "Endpoints";
|
||||||
private const string UrlKey = "Url";
|
private const string UrlKey = "Url";
|
||||||
|
|
@ -49,13 +52,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
|
|
||||||
// "EndpointDefaults": {
|
// "EndpointDefaults": {
|
||||||
// "Protocols": "Http1AndHttp2",
|
// "Protocols": "Http1AndHttp2",
|
||||||
|
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||||
// }
|
// }
|
||||||
private EndpointDefaults ReadEndpointDefaults()
|
private EndpointDefaults ReadEndpointDefaults()
|
||||||
{
|
{
|
||||||
var configSection = _configuration.GetSection(EndpointDefaultsKey);
|
var configSection = _configuration.GetSection(EndpointDefaultsKey);
|
||||||
return new EndpointDefaults
|
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": {
|
// "EndpointName": {
|
||||||
// "Url": "https://*:5463",
|
// "Url": "https://*:5463",
|
||||||
// "Protocols": "Http1AndHttp2",
|
// "Protocols": "Http1AndHttp2",
|
||||||
|
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||||
// "Certificate": {
|
// "Certificate": {
|
||||||
// "Path": "testCert.pfx",
|
// "Path": "testCert.pfx",
|
||||||
// "Password": "testPassword"
|
// "Password": "testPassword"
|
||||||
|
|
@ -88,6 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
Protocols = ParseProtocols(endpointConfig[ProtocolsKey]),
|
Protocols = ParseProtocols(endpointConfig[ProtocolsKey]),
|
||||||
ConfigSection = endpointConfig,
|
ConfigSection = endpointConfig,
|
||||||
Certificate = new CertificateConfig(endpointConfig.GetSection(CertificateKey)),
|
Certificate = new CertificateConfig(endpointConfig.GetSection(CertificateKey)),
|
||||||
|
SslProtocols = ParseSslProcotols(endpointConfig.GetSection(SslProtocolsKey))
|
||||||
};
|
};
|
||||||
|
|
||||||
endpoints.Add(endpoint);
|
endpoints.Add(endpoint);
|
||||||
|
|
@ -105,19 +112,37 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
|
|
||||||
return null;
|
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": {
|
// "EndpointDefaults": {
|
||||||
// "Protocols": "Http1AndHttp2",
|
// "Protocols": "Http1AndHttp2",
|
||||||
|
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||||
// }
|
// }
|
||||||
internal class EndpointDefaults
|
internal class EndpointDefaults
|
||||||
{
|
{
|
||||||
public HttpProtocols? Protocols { get; set; }
|
public HttpProtocols? Protocols { get; set; }
|
||||||
|
public SslProtocols? SslProtocols { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// "EndpointName": {
|
// "EndpointName": {
|
||||||
// "Url": "https://*:5463",
|
// "Url": "https://*:5463",
|
||||||
// "Protocols": "Http1AndHttp2",
|
// "Protocols": "Http1AndHttp2",
|
||||||
|
// "SslProtocols": [ "Tls11", "Tls12", "Tls13"],
|
||||||
// "Certificate": {
|
// "Certificate": {
|
||||||
// "Path": "testCert.pfx",
|
// "Path": "testCert.pfx",
|
||||||
// "Password": "testPassword"
|
// "Password": "testPassword"
|
||||||
|
|
@ -131,6 +156,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
public HttpProtocols? Protocols { get; set; }
|
public HttpProtocols? Protocols { get; set; }
|
||||||
|
public SslProtocols? SslProtocols { get; set; }
|
||||||
public CertificateConfig Certificate { get; set; }
|
public CertificateConfig Certificate { get; set; }
|
||||||
|
|
||||||
// Compare config sections because it's accessible to app developers via an Action<EndpointConfiguration> callback.
|
// 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 &&
|
Url == other.Url &&
|
||||||
(Protocols ?? ListenOptions.DefaultHttpProtocols) == (other.Protocols ?? ListenOptions.DefaultHttpProtocols) &&
|
(Protocols ?? ListenOptions.DefaultHttpProtocols) == (other.Protocols ?? ListenOptions.DefaultHttpProtocols) &&
|
||||||
Certificate == other.Certificate &&
|
Certificate == other.Certificate &&
|
||||||
|
(SslProtocols ?? System.Security.Authentication.SslProtocols.None) == (other.SslProtocols ?? System.Security.Authentication.SslProtocols.None) &&
|
||||||
_configSectionClone == other._configSectionClone;
|
_configSectionClone == other._configSectionClone;
|
||||||
|
|
||||||
public override int GetHashCode() => HashCode.Combine(Name, Url, Protocols ?? ListenOptions.DefaultHttpProtocols, Certificate, _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.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.AspNetCore.Certificates.Generation;
|
using Microsoft.AspNetCore.Certificates.Generation;
|
||||||
|
|
@ -279,9 +280,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
||||||
var httpsOptions = new HttpsConnectionAdapterOptions();
|
var httpsOptions = new HttpsConnectionAdapterOptions();
|
||||||
if (https)
|
if (https)
|
||||||
{
|
{
|
||||||
|
httpsOptions.SslProtocols = ConfigurationReader.EndpointDefaults.SslProtocols ?? SslProtocols.None;
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
Options.ApplyHttpsDefaults(httpsOptions);
|
Options.ApplyHttpsDefaults(httpsOptions);
|
||||||
|
|
||||||
|
if (endpoint.SslProtocols.HasValue)
|
||||||
|
{
|
||||||
|
httpsOptions.SslProtocols = endpoint.SslProtocols.Value;
|
||||||
|
}
|
||||||
|
|
||||||
// Specified
|
// Specified
|
||||||
httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name)
|
httpsOptions.ServerCertificate = LoadCertificate(endpoint.Certificate, endpoint.Name)
|
||||||
?? httpsOptions.ServerCertificate;
|
?? httpsOptions.ServerCertificate;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Authentication;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -173,5 +174,84 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
||||||
Assert.Equal("cetlocation", cert4.Location);
|
Assert.Equal("cetlocation", cert4.Location);
|
||||||
Assert.True(cert4.AllowInvalid);
|
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.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Authentication;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
|
@ -18,7 +19,7 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
||||||
{
|
{
|
||||||
public class KestrelConfigurationBuilderTests
|
public class KestrelConfigurationLoaderTests
|
||||||
{
|
{
|
||||||
private KestrelServerOptions CreateServerOptions()
|
private KestrelServerOptions CreateServerOptions()
|
||||||
{
|
{
|
||||||
|
|
@ -456,6 +457,136 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Tests
|
||||||
Assert.True(ran3);
|
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]
|
[Fact]
|
||||||
public void Latin1RequestHeadersReadFromConfig()
|
public void Latin1RequestHeadersReadFromConfig()
|
||||||
{
|
{
|
||||||
Loading…
Reference in New Issue