Skip to content

Commit a66a223

Browse files
committed
More tests
1 parent de503e8 commit a66a223

File tree

3 files changed

+239
-4
lines changed

3 files changed

+239
-4
lines changed

src/Servers/Kestrel/Core/test/KestrelServerOptionsTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ public void ConfigureThrowsInvalidOperationExceptionIfApplicationServicesIsNotSe
6363
Assert.Throws<InvalidOperationException>(() => options.Configure());
6464
}
6565

66+
[Fact]
67+
public void ConfigureThrowsInvalidOperationExceptionIfApplicationServicesDoesntHaveRequiredServices()
68+
{
69+
var options = new KestrelServerOptions
70+
{
71+
ApplicationServices = new ServiceCollection().BuildServiceProvider()
72+
};
73+
74+
Assert.Throws<InvalidOperationException>(() => options.Configure());
75+
}
76+
6677
[Fact]
6778
public void CanCallListenAfterConfigure()
6879
{

src/Servers/Kestrel/Core/test/SniOptionsSelectorTests.cs

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,230 @@ public void FallsBackToHttpsConnectionAdapterServerCertificateSelectorOverServer
431431
Assert.Same(selectorCertificate, options.ServerCertificate);
432432
}
433433

434+
[Fact]
435+
public void PrefersHttpProtocolsDefinedInSniConfig()
436+
{
437+
var sniDictionary = new Dictionary<string, SniConfig>
438+
{
439+
{
440+
"www.example.org",
441+
new SniConfig
442+
{
443+
Protocols = HttpProtocols.None,
444+
Certificate = new CertificateConfig()
445+
}
446+
}
447+
};
448+
449+
var sniOptionsSelector = new SniOptionsSelector(
450+
"TestEndpointName",
451+
sniDictionary,
452+
new MockCertificateConfigLoader(),
453+
new HttpsConnectionAdapterOptions(),
454+
fallbackHttpProtocols: HttpProtocols.Http1,
455+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
456+
457+
var mockConnectionContext = new MockConnectionContext();
458+
sniOptionsSelector.GetOptions(mockConnectionContext, "www.example.org");
459+
460+
var httpProtocolsFeature = mockConnectionContext.Features.Get<HttpProtocolsFeature>();
461+
Assert.NotNull(httpProtocolsFeature);
462+
Assert.Equal(HttpProtocols.None, httpProtocolsFeature.HttpProtocols);
463+
}
464+
465+
[Fact]
466+
public void ConfiguresAlpnBasedOnConfiguredHttpProtocols()
467+
{
468+
var sniDictionary = new Dictionary<string, SniConfig>
469+
{
470+
{
471+
"www.example.org",
472+
new SniConfig
473+
{
474+
// I'm not using Http1AndHttp2 or Http2 because I don't want to account for
475+
// validation and normalization. Other tests cover that.
476+
Protocols = HttpProtocols.Http1,
477+
Certificate = new CertificateConfig()
478+
}
479+
}
480+
};
481+
482+
var sniOptionsSelector = new SniOptionsSelector(
483+
"TestEndpointName",
484+
sniDictionary,
485+
new MockCertificateConfigLoader(),
486+
new HttpsConnectionAdapterOptions(),
487+
fallbackHttpProtocols: HttpProtocols.None,
488+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
489+
490+
var options = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
491+
var alpnList = options.ApplicationProtocols;
492+
493+
Assert.NotNull(alpnList);
494+
var protocol = Assert.Single(alpnList);
495+
Assert.Equal(SslApplicationProtocol.Http11, protocol);
496+
}
497+
498+
[Fact]
499+
public void FallsBackToFallbackHttpProtocols()
500+
{
501+
var sniDictionary = new Dictionary<string, SniConfig>
502+
{
503+
{
504+
"www.example.org",
505+
new SniConfig
506+
{
507+
Certificate = new CertificateConfig()
508+
}
509+
}
510+
};
511+
512+
var sniOptionsSelector = new SniOptionsSelector(
513+
"TestEndpointName",
514+
sniDictionary,
515+
new MockCertificateConfigLoader(),
516+
new HttpsConnectionAdapterOptions(),
517+
fallbackHttpProtocols: HttpProtocols.Http1,
518+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
519+
520+
var mockConnectionContext = new MockConnectionContext();
521+
sniOptionsSelector.GetOptions(mockConnectionContext, "www.example.org");
522+
523+
var httpProtocolsFeature = mockConnectionContext.Features.Get<HttpProtocolsFeature>();
524+
Assert.NotNull(httpProtocolsFeature);
525+
Assert.Equal(HttpProtocols.Http1, httpProtocolsFeature.HttpProtocols);
526+
}
527+
528+
[Fact]
529+
public void PrefersSslProtocolsDefinedInSniConfig()
530+
{
531+
var sniDictionary = new Dictionary<string, SniConfig>
532+
{
533+
{
534+
"www.example.org",
535+
new SniConfig
536+
{
537+
SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls11,
538+
Certificate = new CertificateConfig()
539+
}
540+
}
541+
};
542+
543+
var sniOptionsSelector = new SniOptionsSelector(
544+
"TestEndpointName",
545+
sniDictionary,
546+
new MockCertificateConfigLoader(),
547+
new HttpsConnectionAdapterOptions
548+
{
549+
SslProtocols = SslProtocols.Tls13
550+
},
551+
fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
552+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
553+
554+
var options = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
555+
Assert.Equal(SslProtocols.Tls13 | SslProtocols.Tls11, options.EnabledSslProtocols);
556+
}
557+
558+
[Fact]
559+
public void FallsBackToFallbackSslProtocols()
560+
{
561+
var sniDictionary = new Dictionary<string, SniConfig>
562+
{
563+
{
564+
"www.example.org",
565+
new SniConfig
566+
{
567+
Certificate = new CertificateConfig()
568+
}
569+
}
570+
};
571+
572+
var sniOptionsSelector = new SniOptionsSelector(
573+
"TestEndpointName",
574+
sniDictionary,
575+
new MockCertificateConfigLoader(),
576+
new HttpsConnectionAdapterOptions
577+
{
578+
SslProtocols = SslProtocols.Tls13
579+
},
580+
fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
581+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
582+
583+
var options = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
584+
Assert.Equal(SslProtocols.Tls13, options.EnabledSslProtocols);
585+
}
586+
587+
588+
[Fact]
589+
public void PrefersClientCertificateModeDefinedInSniConfig()
590+
{
591+
var sniDictionary = new Dictionary<string, SniConfig>
592+
{
593+
{
594+
"www.example.org",
595+
new SniConfig
596+
{
597+
ClientCertificateMode = ClientCertificateMode.RequireCertificate,
598+
Certificate = new CertificateConfig()
599+
}
600+
}
601+
};
602+
603+
var sniOptionsSelector = new SniOptionsSelector(
604+
"TestEndpointName",
605+
sniDictionary,
606+
new MockCertificateConfigLoader(),
607+
new HttpsConnectionAdapterOptions
608+
{
609+
ClientCertificateMode = ClientCertificateMode.AllowCertificate
610+
},
611+
fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
612+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
613+
614+
var options = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
615+
616+
Assert.True(options.ClientCertificateRequired);
617+
618+
Assert.NotNull(options.RemoteCertificateValidationCallback);
619+
// The RemoteCertificateValidationCallback should first check if the certificate is null and return false since it's required.
620+
Assert.False(options.RemoteCertificateValidationCallback(sender: null, certificate: null, chain: null, SslPolicyErrors.None));
621+
}
622+
623+
[Fact]
624+
public void FallsBackToFallbackClientCertificateMode()
625+
{
626+
var sniDictionary = new Dictionary<string, SniConfig>
627+
{
628+
{
629+
"www.example.org",
630+
new SniConfig
631+
{
632+
Certificate = new CertificateConfig()
633+
}
634+
}
635+
};
636+
637+
var sniOptionsSelector = new SniOptionsSelector(
638+
"TestEndpointName",
639+
sniDictionary,
640+
new MockCertificateConfigLoader(),
641+
new HttpsConnectionAdapterOptions
642+
{
643+
ClientCertificateMode = ClientCertificateMode.AllowCertificate
644+
},
645+
fallbackHttpProtocols: HttpProtocols.Http1AndHttp2,
646+
logger: Mock.Of<ILogger<HttpsConnectionMiddleware>>());
647+
648+
var options = sniOptionsSelector.GetOptions(new MockConnectionContext(), "www.example.org");
649+
650+
// Despite the confusing name, ClientCertificateRequired being true simply requests a certificate from the client, but doesn't require it.
651+
Assert.True(options.ClientCertificateRequired);
652+
653+
Assert.NotNull(options.RemoteCertificateValidationCallback);
654+
// The RemoteCertificateValidationCallback should see we're in the AllowCertificate mode and return true.
655+
Assert.True(options.RemoteCertificateValidationCallback(sender: null, certificate: null, chain: null, SslPolicyErrors.None));
656+
}
657+
434658
[Fact]
435659
public void CloneSslOptionsClonesAllProperties()
436660
{

src/Servers/Kestrel/Kestrel/test/KestrelConfigurationLoaderTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ public void DefaultConfigSection_CanConfigureSni()
839839
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
840840
{
841841
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
842-
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:Protocols", "Http1"),
842+
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:Protocols", "None"),
843843
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:SslProtocols:0", "Tls12"),
844844
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:ClientCertificateMode", "AllowCertificate"),
845845
}).Build();
@@ -849,7 +849,7 @@ public void DefaultConfigSection_CanConfigureSni()
849849
var (name, sniConfig) = Assert.Single(end1?.EndpointConfig?.Sni);
850850

851851
Assert.Equal("*.example.org", name);
852-
Assert.Equal(HttpProtocols.Http1, sniConfig.Protocols);
852+
Assert.Equal(HttpProtocols.None, sniConfig.Protocols);
853853
Assert.Equal(SslProtocols.Tls12, sniConfig.SslProtocols);
854854
Assert.Equal(ClientCertificateMode.AllowCertificate, sniConfig.ClientCertificateMode);
855855
}
@@ -862,7 +862,7 @@ public void DefaultConfigSection_SniConfigurationIsOverriddenByNotMergedWithEndp
862862
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
863863
{
864864
new KeyValuePair<string, string>("Endpoints:End1:Url", "https://*:5001"),
865-
new KeyValuePair<string, string>("Endpoints:End1:Sni:*:Protocols", "Http1AndHttp2"),
865+
new KeyValuePair<string, string>("Endpoints:End1:Sni:*:Protocols", "None"),
866866
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:Protocols", "Http1"),
867867
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:SslProtocols:0", "Tls12"),
868868
new KeyValuePair<string, string>("EndpointDefaults:Sni:*.example.org:ClientCertificateMode", "AllowCertificate"),
@@ -873,7 +873,7 @@ public void DefaultConfigSection_SniConfigurationIsOverriddenByNotMergedWithEndp
873873
var (name, sniConfig) = Assert.Single(end1?.EndpointConfig?.Sni);
874874

875875
Assert.Equal("*", name);
876-
Assert.Equal(HttpProtocols.Http1AndHttp2, sniConfig.Protocols);
876+
Assert.Equal(HttpProtocols.None, sniConfig.Protocols);
877877
}
878878

879879
[Fact]

0 commit comments

Comments
 (0)