コード例 #1
0
        private async Task RegisterDefaultServerAddresses_Success(IEnumerable <string> addresses, bool mockHttps = false)
        {
            var hostBuilder = TransportSelector.GetHostBuilder()
                              .ConfigureWebHost(webHostBuilder =>
            {
                webHostBuilder
                .UseKestrel(options =>
                {
                    if (mockHttps)
                    {
                        options.DefaultCertificate = TestResources.GetTestCertificate();
                    }
                })
                .Configure(ConfigureEchoAddress);
            })
                              .ConfigureServices(AddTestLogging);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                Assert.Equal(5000, host.GetPort());

                if (mockHttps)
                {
                    Assert.Contains(5001, host.GetPorts());
                }

                Assert.Single(LogMessages, log => log.LogLevel == LogLevel.Debug &&
                              (string.Equals(CoreStrings.FormatBindingToDefaultAddresses(Constants.DefaultServerAddress, Constants.DefaultServerHttpsAddress), log.Message, StringComparison.Ordinal) ||
                               string.Equals(CoreStrings.FormatBindingToDefaultAddress(Constants.DefaultServerAddress), log.Message, StringComparison.Ordinal)));

                foreach (var address in addresses)
                {
                    Assert.Equal(new Uri(address).ToString(), await HttpClientSlim.GetStringAsync(address, validateCertificate: false));
                }

                await host.StopAsync();
            }
        }
コード例 #2
0
    public async Task ClientCertificate_NoOrDelayed_Available_Ignored(ClientCertificateMode mode)
    {
        var builder = CreateHostBuilder(async context =>
        {
            var hasCert = context.Connection.ClientCertificate != null;
            await context.Response.WriteAsync(hasCert.ToString());
        }, configureKestrel: kestrelOptions =>
        {
            kestrelOptions.ListenAnyIP(0, listenOptions =>
            {
                listenOptions.Protocols = HttpProtocols.Http3;
                listenOptions.UseHttps(httpsOptions =>
                {
                    httpsOptions.ServerCertificate     = TestResources.GetTestCertificate();
                    httpsOptions.ClientCertificateMode = mode;
                    httpsOptions.AllowAnyClientCertificate();
                });
            });
        });

        using var host   = builder.Build();
        using var client = HttpHelpers.CreateClient(includeClientCert: true);

        await host.StartAsync().DefaultTimeout();

        var request = new HttpRequestMessage(HttpMethod.Get, $"https://127.0.0.1:{host.GetPort()}/");

        request.Version       = HttpVersion.Version30;
        request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;

        var response = await client.SendAsync(request, CancellationToken.None).DefaultTimeout();

        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();

        Assert.Equal(HttpVersion.Version30, response.Version);
        Assert.Equal("False", result);

        await host.StopAsync().DefaultTimeout();
    }
コード例 #3
0
    public async Task ListenIPWithStaticPort_TransportsGetIPv6Any()
    {
        var options = new KestrelServerOptions();

        options.ApplicationServices = new ServiceCollection()
                                      .AddLogging()
                                      .BuildServiceProvider();
        options.ListenAnyIP(5000, options =>
        {
            options.UseHttps(TestResources.GetTestCertificate());
            options.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        });

        var mockTransportFactory            = new MockTransportFactory();
        var mockMultiplexedTransportFactory = new MockMultiplexedTransportFactory();

        using var server = new KestrelServerImpl(
                  Options.Create(options),
                  new List <IConnectionListenerFactory>()
        {
            mockTransportFactory
        },
                  new List <IMultiplexedConnectionListenerFactory>()
        {
            mockMultiplexedTransportFactory
        },
                  new LoggerFactory(new[] { new KestrelTestLoggerProvider() }));

        await server.StartAsync(new DummyApplication(context => Task.CompletedTask), CancellationToken.None);

        var transportEndPoint            = Assert.Single(mockTransportFactory.BoundEndPoints);
        var multiplexedTransportEndPoint = Assert.Single(mockMultiplexedTransportFactory.BoundEndPoints);

        // Both transports should get the IPv6Any
        Assert.Equal(IPAddress.IPv6Any, ((IPEndPoint)transportEndPoint.OriginalEndPoint).Address);
        Assert.Equal(IPAddress.IPv6Any, ((IPEndPoint)multiplexedTransportEndPoint.OriginalEndPoint).Address);

        Assert.Equal(5000, ((IPEndPoint)transportEndPoint.OriginalEndPoint).Port);
        Assert.Equal(5000, ((IPEndPoint)multiplexedTransportEndPoint.OriginalEndPoint).Port);
    }
コード例 #4
0
        public void Equals_Different_Value_Returns_False()
        {
            var options1 = new ProxyHttpClientOptions
            {
                SslProtocols = SslProtocols.Tls11,
                DangerousAcceptAnyServerCertificate = false,
                ClientCertificate       = TestResources.GetTestCertificate(),
                MaxConnectionsPerServer = 20
            };

            var options2 = new ProxyHttpClientOptions
            {
                SslProtocols = SslProtocols.Tls12,
                DangerousAcceptAnyServerCertificate = true,
                ClientCertificate       = TestResources.GetTestCertificate(),
                MaxConnectionsPerServer = 20
            };

            var equals = ProxyHttpClientOptions.Equals(options1, options2);

            Assert.False(equals);
        }
コード例 #5
0
        public async Task LoggingConnectionAdapterCanBeAddedBeforeAndAfterHttpsAdapter()
        {
            using (var server = new TestServer(context =>
            {
                context.Response.ContentLength = 12;
                return(context.Response.WriteAsync("Hello World!"));
            },
                                               new TestServiceContext(LoggerFactory),
                                               listenOptions =>
            {
                listenOptions.UseConnectionLogging();
                listenOptions.UseHttps(TestResources.GetTestCertificate());
                listenOptions.UseConnectionLogging();
            }))
            {
                var response = await server.HttpClientSlim.GetStringAsync($"https://localhost:{server.Port}/", validateCertificate : false)
                               .DefaultTimeout();


                Assert.Equal("Hello World!", response);
            }
        }
コード例 #6
0
        public async Task ConnectionFilterDoesNotLeakBlock()
        {
            var loggerProvider = new HandshakeErrorLoggerProvider();

            LoggerFactory.AddProvider(loggerProvider);

            await using (var server = new TestServer(context => Task.CompletedTask,
                                                     new TestServiceContext(LoggerFactory)
            {
                ExpectedConnectionMiddlewareCount = 1
            },
                                                     listenOptions =>
            {
                listenOptions.UseHttps(TestResources.GetTestCertificate());
            }))
            {
                using (var connection = server.CreateConnection())
                {
                    connection.Reset();
                }
            }
        }
コード例 #7
0
    public async Task ListenWithCustomEndpoint_DoesNotThrow()
    {
        var options = new KestrelServerOptions();

        options.ApplicationServices = new ServiceCollection()
                                      .AddLogging()
                                      .BuildServiceProvider();

        var customEndpoint = new UriEndPoint(new("http://localhost:5000"));

        options.Listen(customEndpoint, options =>
        {
            options.UseHttps(TestResources.GetTestCertificate());
            options.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        });

        var mockTransportFactory            = new MockTransportFactory();
        var mockMultiplexedTransportFactory = new MockMultiplexedTransportFactory();

        using var server = new KestrelServerImpl(
                  Options.Create(options),
                  new List <IConnectionListenerFactory>()
        {
            mockTransportFactory
        },
                  new List <IMultiplexedConnectionListenerFactory>()
        {
            mockMultiplexedTransportFactory
        },
                  new LoggerFactory(new[] { new KestrelTestLoggerProvider() }));

        await server.StartAsync(new DummyApplication(context => Task.CompletedTask), CancellationToken.None);

        var transportEndPoint            = Assert.Single(mockTransportFactory.BoundEndPoints);
        var multiplexedTransportEndPoint = Assert.Single(mockMultiplexedTransportFactory.BoundEndPoints);

        Assert.Same(customEndpoint, transportEndPoint.BoundEndPoint);
        Assert.Same(customEndpoint, multiplexedTransportEndPoint.BoundEndPoint);
    }
コード例 #8
0
        public async Task OverrideDirectConfigurationWithIServerAddressesFeature_Succeeds()
        {
            var useUrlsAddress = $"http://127.0.0.1:0";
            var hostBuilder    = TransportSelector.GetWebHostBuilder()
                                 .UseKestrel(options =>
            {
                options.Listen(new IPEndPoint(IPAddress.Loopback, 0), listenOptions =>
                {
                    listenOptions.UseHttps(TestResources.GetTestCertificate());
                });
            })
                                 .UseUrls(useUrlsAddress)
                                 .PreferHostingUrls(true)
                                 .ConfigureServices(AddTestLogging)
                                 .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                var port = host.GetPort();

                // If this isn't working properly, we'll get the HTTPS endpoint defined in UseKestrel
                // instead of the HTTP endpoint defined in UseUrls.
                var serverAddresses = host.ServerFeatures.Get <IServerAddressesFeature>().Addresses;
                Assert.Equal(1, serverAddresses.Count);
                var useUrlsAddressWithPort = $"http://127.0.0.1:{port}";
                Assert.Equal(serverAddresses.First(), useUrlsAddressWithPort);

                Assert.Single(TestApplicationErrorLogger.Messages, log => log.LogLevel == LogLevel.Information &&
                              string.Equals(CoreStrings.FormatOverridingWithPreferHostingUrls(nameof(IServerAddressesFeature.PreferHostingUrls), useUrlsAddress),
                                            log.Message, StringComparison.Ordinal));

                Assert.Equal(new Uri(useUrlsAddressWithPort).ToString(), await HttpClientSlim.GetStringAsync(useUrlsAddressWithPort));

                await host.StopAsync();
            }
        }
コード例 #9
0
        public async Task RegisterHttpAddress_UpgradedToHttpsByConfigureEndpointDefaults()
        {
            var hostBuilder = TransportSelector.GetHostBuilder()
                              .ConfigureWebHost(webHostBuilder =>
            {
                webHostBuilder
                .UseKestrel(serverOptions =>
                {
                    serverOptions.ConfigureEndpointDefaults(listenOptions =>
                    {
                        listenOptions.UseHttps(TestResources.GetTestCertificate());
                    });
                })
                .UseUrls("http://127.0.0.1:0")
                .Configure(app =>
                {
                    var serverAddresses = app.ServerFeatures.Get <IServerAddressesFeature>();
                    app.Run(context =>
                    {
                        Assert.Single(serverAddresses.Addresses);
                        return(context.Response.WriteAsync(serverAddresses.Addresses.First()));
                    });
                });
            })
                              .ConfigureServices(AddTestLogging);

            using (var host = hostBuilder.Build())
            {
                host.Start();

                var expectedUrl = $"https://127.0.0.1:{host.GetPort()}";
                var response    = await HttpClientSlim.GetStringAsync(expectedUrl, validateCertificate : false);

                Assert.Equal(expectedUrl, response);

                await host.StopAsync();
            }
        }
コード例 #10
0
        public void Equals_Same_Value_Returns_True()
        {
            var options1 = new ProxyHttpClientOptions
            {
                SslProtocols = SslProtocols.Tls11,
                DangerousAcceptAnyServerCertificate = false,
                ClientCertificate       = TestResources.GetTestCertificate(),
                MaxConnectionsPerServer = 20,
                WebProxy = new WebProxyOptions()
                {
                    Address = new Uri("http://localhost:8080"), BypassOnLocal = true, UseDefaultCredentials = true
                },
#if NET
                RequestHeaderEncoding = Encoding.UTF8
#endif
            };

            var options2 = new ProxyHttpClientOptions
            {
                SslProtocols = SslProtocols.Tls11,
                DangerousAcceptAnyServerCertificate = false,
                ClientCertificate       = TestResources.GetTestCertificate(),
                MaxConnectionsPerServer = 20,
                WebProxy = new WebProxyOptions()
                {
                    Address = new Uri("http://localhost:8080"), BypassOnLocal = true, UseDefaultCredentials = true
                },
#if NET
                RequestHeaderEncoding = Encoding.UTF8
#endif
            };

            var equals = options1.Equals(options2);

            Assert.True(equals);
            Assert.True(options1 == options2);
            Assert.False(options1 != options2);
        }
コード例 #11
0
        public async Task OnAuthenticate_SeesOtherSettings()
        {
            var loggerProvider = new HandshakeErrorLoggerProvider();

            LoggerFactory.AddProvider(loggerProvider);

            var testCert             = TestResources.GetTestCertificate();
            var onAuthenticateCalled = false;

            await using (var server = new TestServer(context => Task.CompletedTask,
                                                     new TestServiceContext(LoggerFactory)
            {
                ExpectedConnectionMiddlewareCount = 1
            },
                                                     listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    httpsOptions.ServerCertificate = testCert;
                    httpsOptions.OnAuthenticate = (connectionContext, authOptions) =>
                    {
                        Assert.Same(testCert, authOptions.ServerCertificate);
                        onAuthenticateCalled = true;
                    };
                });
            }))
            {
                using (var connection = server.CreateConnection())
                    using (var sslStream = new SslStream(connection.Stream, true, (sender, certificate, chain, errors) => true))
                    {
                        await sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates : null,
                                                                  enabledSslProtocols : SslProtocols.Tls11 | SslProtocols.Tls12,
                                                                  checkCertificateRevocation : false);
                    }
            }

            Assert.True(onAuthenticateCalled, "onAuthenticateCalled");
        }
コード例 #12
0
        public async Task OnAuthenticate_CanSetSettings()
        {
            var loggerProvider = new HandshakeErrorLoggerProvider();

            LoggerFactory.AddProvider(loggerProvider);

            var testCert             = TestResources.GetTestCertificate();
            var onAuthenticateCalled = false;

            await using (var server = new TestServer(context => Task.CompletedTask,
                                                     new TestServiceContext(LoggerFactory),
                                                     listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    httpsOptions.ServerCertificateSelector = (_, __) => throw new NotImplementedException();
                    httpsOptions.OnAuthenticate = (connectionContext, authOptions) =>
                    {
                        Assert.Null(authOptions.ServerCertificate);
                        Assert.NotNull(authOptions.ServerCertificateSelectionCallback);
                        authOptions.ServerCertificate = testCert;
                        authOptions.ServerCertificateSelectionCallback = null;
                        onAuthenticateCalled = true;
                    };
                });
            }))
            {
                using (var connection = server.CreateConnection())
                    using (var sslStream = new SslStream(connection.Stream, true, (sender, certificate, chain, errors) => true))
                    {
                        await sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates : null,
                                                                  enabledSslProtocols : SslProtocols.Tls11 | SslProtocols.Tls12,
                                                                  checkCertificateRevocation : false);
                    }
            }

            Assert.True(onAuthenticateCalled, "onAuthenticateCalled");
        }
コード例 #13
0
        private async Task RegisterIPEndPoint_Success(IPEndPoint endPoint, string testUrl, int testPort = 0)
        {
            var hostBuilder = TransportSelector.GetHostBuilder()
                              .ConfigureWebHost(webHostBuilder =>
            {
                webHostBuilder
                .UseKestrel(options =>
                {
                    options.Listen(endPoint, listenOptions =>
                    {
                        if (testUrl.StartsWith("https", StringComparison.Ordinal))
                        {
                            listenOptions.UseHttps(TestResources.GetTestCertificate());
                        }
                    });
                })
                .Configure(ConfigureEchoAddress);
            })
                              .ConfigureServices(AddTestLogging);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                var testUrlWithPort = $"{testUrl}:{(testPort == 0 ? host.GetPort() : testPort)}";

                var options = ((IOptions <KestrelServerOptions>)host.Services.GetService(typeof(IOptions <KestrelServerOptions>))).Value;
                Assert.Single(options.ListenOptions);

                var response = await HttpClientSlim.GetStringAsync(testUrlWithPort, validateCertificate : false);

                // Compare the response with Uri.ToString(), rather than testUrl directly.
                // Required to handle IPv6 addresses with zone index, like "fe80::3%1"
                Assert.Equal(new Uri(testUrlWithPort).ToString(), response);

                await host.StopAsync();
            }
        }
コード例 #14
0
        public void ConfigureHttpsDefaultsNeverLoadsDefaultCert()
        {
            var serverOptions = CreateServerOptions();
            var testCert      = TestResources.GetTestCertificate();

            serverOptions.ConfigureHttpsDefaults(options =>
            {
                Assert.Null(options.ServerCertificate);
                options.ServerCertificate     = testCert;
                options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
            });
            serverOptions.ListenLocalhost(5000, options =>
            {
                options.UseHttps(opt =>
                {
                    Assert.Equal(testCert, opt.ServerCertificate);
                    Assert.Equal(ClientCertificateMode.RequireCertificate, opt.ClientCertificateMode);
                });
            });
            // Never lazy loaded
            Assert.False(serverOptions.IsDevCertLoaded);
            Assert.Null(serverOptions.DefaultCertificate);
        }
コード例 #15
0
ファイル: ChromeTests.cs プロジェクト: zmkchina/aspnetcore
        public async Task Http2(string requestSuffix, string expectedResponse)
        {
            InitializeArgs();

            var hostBuilder = new WebHostBuilder()
                              .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, 0, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                    listenOptions.UseHttps(TestResources.GetTestCertificate());
                });
            })
                              .ConfigureServices(AddTestLogging)
                              .Configure(app => app.Run(async context =>
            {
                if (HttpMethods.IsPost(context.Request.Query["TestMethod"]))
                {
                    await context.Response.WriteAsync(_postHtml);
                }
                else
                {
                    await context.Response.WriteAsync($"Interop {context.Request.Protocol} {context.Request.Method}");
                }
            }));

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                var chromeOutput = RunHeadlessChrome($"https://localhost:{host.GetPort()}/{requestSuffix}");

                AssertExpectedResponseOrShowDebugInstructions(expectedResponse, chromeOutput);

                await host.StopAsync();
            }
        }
コード例 #16
0
    public async Task Listen_Http3AndSocketsCoexistOnDifferentEndpoints_ClientSuccess(int http3Port, int http1Port)
    {
        // Arrange
        var builder = new HostBuilder()
                      .ConfigureWebHost(webHostBuilder =>
        {
            webHostBuilder
            .UseKestrel(o =>
            {
                o.Listen(IPAddress.Parse("127.0.0.1"), http3Port, listenOptions =>
                {
                    listenOptions.Protocols = Core.HttpProtocols.Http3;
                    listenOptions.UseHttps(TestResources.GetTestCertificate());
                });
                o.Listen(IPAddress.Parse("127.0.0.1"), http1Port, listenOptions =>
                {
                    listenOptions.Protocols = Core.HttpProtocols.Http1;
                    listenOptions.UseHttps(TestResources.GetTestCertificate());
                });
            })
            .Configure(app =>
            {
                app.Run(async context =>
                {
                    await context.Response.WriteAsync("hello, world");
                });
            });
        })
                      .ConfigureServices(AddTestLogging);

        using var host = builder.Build();
        await host.StartAsync().DefaultTimeout();

        await CallHttp3AndHttp1EndpointsAsync(http3Port, http1Port);

        await host.StopAsync().DefaultTimeout();
    }
コード例 #17
0
ファイル: Http3TlsTests.cs プロジェクト: propil5/aspnetcore
        public async Task ClientCertificate_Allow_NotAvailable_Optional()
        {
            var builder = CreateHostBuilder(async context =>
            {
                var hasCert = context.Connection.ClientCertificate != null;
                await context.Response.WriteAsync(hasCert.ToString());
            }, configureKestrel: kestrelOptions =>
            {
                kestrelOptions.ListenAnyIP(0, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http3;
                    listenOptions.UseHttps(httpsOptions =>
                    {
                        httpsOptions.ServerCertificate     = TestResources.GetTestCertificate();
                        httpsOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
                        httpsOptions.AllowAnyClientCertificate();
                    });
                });
            });

            using var host   = builder.Build();
            using var client = Http3Helpers.CreateClient(includeClientCert: false);

            await host.StartAsync().DefaultTimeout();

            var request = new HttpRequestMessage(HttpMethod.Get, $"https://127.0.0.1:{host.GetPort()}/");

            request.Version       = HttpVersion.Version30;
            request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;

            // https://github.com/dotnet/runtime/issues/57308, optional client certs aren't supported.
            var ex = await Assert.ThrowsAsync <HttpRequestException>(() => client.SendAsync(request, CancellationToken.None).DefaultTimeout());

            Assert.StartsWith("Connection has been shutdown by transport. Error Code: 0x80410100", ex.Message);

            await host.StopAsync().DefaultTimeout();
        }
コード例 #18
0
        public async Task RunIndividualTestCase(H2SpecTestCase testCase)
        {
            var hostBuilder = new WebHostBuilder()
                              .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, 0, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                    if (testCase.Https)
                    {
                        listenOptions.UseHttps(TestResources.GetTestCertificate());
                    }
                });
            })
                              .ConfigureServices(AddTestLogging)
                              .Configure(ConfigureHelloWorld);

            using (var host = hostBuilder.Build())
            {
                await host.StartAsync();

                H2SpecCommands.RunTest(testCase.Id, host.GetPort(), testCase.Https, Logger);
            }
        }
コード例 #19
0
            public async Task UsesExpectedFileName(bool fileExists)
            {
                // Arrange
                var certificate       = TestResources.GetTestCertificate(TestResources.TrustedCARootCertificate);
                var sha256Thumbprint  = certificate.ComputeSHA256Thumbprint().ToUpperInvariant();
                var expectedFileName  = GetExpectedFileName(sha256Thumbprint);
                var cancellationToken = CancellationToken.None;
                var storage           = new Mock <IStorage>(MockBehavior.Strict);

                storage
                .Setup(m => m.ExistsAsync(expectedFileName, cancellationToken))
                .ReturnsAsync(fileExists)
                .Verifiable();

                var logger           = new Mock <ILogger <CertificateStore> >(MockBehavior.Strict);
                var certificateStore = new CertificateStore(storage.Object, logger.Object);

                // Act
                var result = await certificateStore.ExistsAsync(sha256Thumbprint, cancellationToken);

                // Assert
                Assert.Equal(fileExists, result);
                storage.Verify();
            }
コード例 #20
0
        public async Task DoesNotThrowObjectDisposedExceptionOnEmptyConnection()
        {
            var loggerProvider = new HandshakeErrorLoggerProvider();

            LoggerFactory.AddProvider(loggerProvider);

            await using (var server = new TestServer(context => Task.CompletedTask,
                                                     new TestServiceContext(LoggerFactory),
                                                     listenOptions =>
            {
                listenOptions.UseHttps(TestResources.GetTestCertificate());
            }))
            {
                using (var connection = server.CreateConnection())
                    using (var sslStream = new SslStream(connection.Stream, true, (sender, certificate, chain, errors) => true))
                    {
                        await sslStream.AuthenticateAsClientAsync("127.0.0.1", clientCertificates : null,
                                                                  enabledSslProtocols : SslProtocols.Tls11 | SslProtocols.Tls12,
                                                                  checkCertificateRevocation : false);
                    }
            }

            Assert.False(loggerProvider.ErrorLogger.ObjectDisposedExceptionLogged);
        }
コード例 #21
0
        private async Task RegisterAddresses_Success(string addressInput, string[] testUrls, int testPort = 0)
        {
            var hostBuilder = TransportSelector.GetWebHostBuilder()
                              .UseKestrel(serverOptions =>
            {
                serverOptions.ConfigureHttpsDefaults(httpsOptions =>
                {
                    httpsOptions.ServerCertificate = TestResources.GetTestCertificate();
                });
            })
                              .ConfigureServices(AddTestLogging)
                              .UseUrls(addressInput)
                              .Configure(ConfigureEchoAddress);

            using (var host = hostBuilder.Build())
            {
                host.Start();

                foreach (var testUrl in testUrls.Select(testUrl => $"{testUrl}:{(testPort == 0 ? host.GetPort() : testPort)}"))
                {
                    var response = await HttpClientSlim.GetStringAsync(testUrl, validateCertificate : false);

                    // Filter out the scope id for IPv6, that's not sent over the wire. "fe80::3%1"
                    // See https://github.com/aspnet/Common/pull/369
                    var uri = new Uri(testUrl);
                    if (uri.HostNameType == UriHostNameType.IPv6)
                    {
                        var builder = new UriBuilder(uri);
                        var ip      = IPAddress.Parse(builder.Host);
                        builder.Host = new IPAddress(ip.GetAddressBytes()).ToString(); // Without the scope id.
                        uri          = builder.Uri;
                    }
                    Assert.Equal(uri.ToString(), response);
                }
            }
        }
コード例 #22
0
        public void UseHttpsDefaultsToDefaultCert()
        {
            var serverOptions = CreateServerOptions();
            var defaultCert   = TestResources.GetTestCertificate();

            serverOptions.DefaultCertificate = defaultCert;

            serverOptions.ListenLocalhost(5000, options =>
            {
                options.UseHttps();
            });

            Assert.False(serverOptions.IsDevCertLoaded);

            serverOptions.ListenLocalhost(5001, options =>
            {
                options.UseHttps(opt =>
                {
                    // The default cert is applied after UseHttps.
                    Assert.Null(opt.ServerCertificate);
                });
            });
            Assert.False(serverOptions.IsDevCertLoaded);
        }
コード例 #23
0
    public static FeatureCollection CreateBindAsyncFeatures(bool clientCertificateRequired = false)
    {
        var cert = TestResources.GetTestCertificate();

        var sslServerAuthenticationOptions = new SslServerAuthenticationOptions();

        sslServerAuthenticationOptions.ApplicationProtocols = new List <SslApplicationProtocol>()
        {
            SslApplicationProtocol.Http3
        };
        sslServerAuthenticationOptions.ServerCertificate = cert;
        sslServerAuthenticationOptions.RemoteCertificateValidationCallback = RemoteCertificateValidationCallback;
        sslServerAuthenticationOptions.ClientCertificateRequired           = clientCertificateRequired;

        var features = new FeatureCollection();

        features.Set(new TlsConnectionCallbackOptions
        {
            ApplicationProtocols = sslServerAuthenticationOptions.ApplicationProtocols,
            OnConnection         = (context, cancellationToken) => ValueTask.FromResult(sslServerAuthenticationOptions)
        });

        return(features);
    }
コード例 #24
0
        public async Task InitialLoadAsync_ProxyHttpClientOptionsSet_CreateAndSetHttpClient()
        {
            const string TestAddress = "https://localhost:123/";

            var clientCertificate = TestResources.GetTestCertificate();
            var cluster           = new Cluster
            {
                Id           = "cluster1",
                Destinations = new Dictionary <string, Destination>(StringComparer.OrdinalIgnoreCase)
                {
                    { "d1", new Destination {
                          Address = TestAddress
                      } }
                },
                HttpClient = new ProxyHttpClientOptions
                {
                    SslProtocols            = SslProtocols.Tls11 | SslProtocols.Tls12,
                    MaxConnectionsPerServer = 10,
                    ClientCertificate       = clientCertificate,
#if NET
                    RequestHeaderEncoding = Encoding.UTF8
#endif
                }
            };
            var route = new ProxyRoute
            {
                RouteId   = "route1",
                ClusterId = "cluster1",
                Match     = new RouteMatch {
                    Path = "/"
                }
            };

            var services = CreateServices(new List <ProxyRoute>()
            {
                route
            }, new List <Cluster>()
            {
                cluster
            });

            var manager    = services.GetRequiredService <ProxyConfigManager>();
            var dataSource = await manager.InitialLoadAsync();

            Assert.NotNull(dataSource);
            var endpoint    = Assert.Single(dataSource.Endpoints);
            var routeConfig = endpoint.Metadata.GetMetadata <RouteConfig>();
            var clusterInfo = routeConfig.Cluster;

            Assert.Equal("cluster1", clusterInfo.ClusterId);
            var clusterConfig = clusterInfo.Config;

            Assert.NotNull(clusterConfig.HttpClient);
            Assert.Equal(SslProtocols.Tls11 | SslProtocols.Tls12, clusterConfig.Options.HttpClient.SslProtocols);
            Assert.Equal(10, clusterConfig.Options.HttpClient.MaxConnectionsPerServer);
            Assert.Same(clientCertificate, clusterConfig.Options.HttpClient.ClientCertificate);
#if NET
            Assert.Equal(Encoding.UTF8, clusterConfig.Options.HttpClient.RequestHeaderEncoding);
#endif

            var handler = Proxy.Tests.ProxyHttpClientFactoryTests.GetHandler(clusterConfig.HttpClient);
            Assert.Equal(SslProtocols.Tls11 | SslProtocols.Tls12, handler.SslOptions.EnabledSslProtocols);
            Assert.Equal(10, handler.MaxConnectionsPerServer);
            Assert.Single(handler.SslOptions.ClientCertificates, clientCertificate);
#if NET
            Assert.Equal(Encoding.UTF8, handler.RequestHeaderEncodingSelector(default, default));
コード例 #25
0
        public async Task HttpsConnectionClosedWhenResponseDoesNotSatisfyMinimumDataRate()
        {
            const int chunkSize = 1024;
            const int chunks    = 256 * 1024;
            var       chunkData = new byte[chunkSize];

            var certificate = TestResources.GetTestCertificate();

            var responseRateTimeoutMessageLogged = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var connectionStopMessageLogged      = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var aborted          = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);
            var appFuncCompleted = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously);

            var mockKestrelTrace = new Mock <IKestrelTrace>();

            mockKestrelTrace
            .Setup(trace => trace.ResponseMinimumDataRateNotSatisfied(It.IsAny <string>(), It.IsAny <string>()))
            .Callback(() => responseRateTimeoutMessageLogged.SetResult(null));
            mockKestrelTrace
            .Setup(trace => trace.ConnectionStop(It.IsAny <string>()))
            .Callback(() => connectionStopMessageLogged.SetResult(null));

            var testContext = new TestServiceContext(LoggerFactory, mockKestrelTrace.Object)
            {
                ServerOptions =
                {
                    Limits                  =
                    {
                        MinResponseDataRate = new MinDataRate(bytesPerSecond: 1024 * 1024, gracePeriod: TimeSpan.FromSeconds(2))
                    }
                }
            };

            testContext.InitializeHeartbeat();

            void ConfigureListenOptions(ListenOptions listenOptions)
            {
                listenOptions.UseHttps(new HttpsConnectionAdapterOptions {
                    ServerCertificate = certificate
                });
            }

            using (var server = new TestServer(async context =>
            {
                context.RequestAborted.Register(() =>
                {
                    aborted.SetResult(null);
                });

                context.Response.ContentLength = chunks * chunkSize;

                try
                {
                    for (var i = 0; i < chunks; i++)
                    {
                        await context.Response.BodyWriter.WriteAsync(new Memory <byte>(chunkData, 0, chunkData.Length), context.RequestAborted);
                    }
                }
                catch (OperationCanceledException)
                {
                    appFuncCompleted.SetResult(null);
                    throw;
                }
                finally
                {
                    await aborted.Task.DefaultTimeout();
                }
            }, testContext, ConfigureListenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    using (var sslStream = new SslStream(connection.Stream, false, (sender, cert, chain, errors) => true, null))
                    {
                        await sslStream.AuthenticateAsClientAsync("localhost", new X509CertificateCollection(), SslProtocols.Tls12 | SslProtocols.Tls11, false);

                        var request = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost:\r\n\r\n");
                        await sslStream.WriteAsync(request, 0, request.Length);

                        await aborted.Task.DefaultTimeout();

                        await responseRateTimeoutMessageLogged.Task.DefaultTimeout();

                        await connectionStopMessageLogged.Task.DefaultTimeout();

                        await appFuncCompleted.Task.DefaultTimeout();

                        await AssertStreamAborted(connection.Stream, chunkSize *chunks);
                    }
                }
                await server.StopAsync();
            }
        }
コード例 #26
0
        public void CachedCertificateIsDisposed_RemoveItFromCache()
        {
            var config = new ConfigurationData()
            {
                Clusters =
                {
                    {
                        "cluster1",
                        new ClusterData {
                            Destinations ={    { "destinationA", new DestinationData {
                                                   Address = "https://localhost:10001/destC"
                                               } } },
                            HttpClient = new ProxyHttpClientData{
                                ClientCertificate = new CertificateConfigData{
                                    Path = "testCert.pfx"
                                }
                            }
                        }
                    }
                },
                Routes = { new ProxyRouteData {
                               RouteId = "routeA", ClusterId = "cluster1", Order = 1, Match ={ Hosts                                                 = new List <string> {
                                                    "host-B"
                                                } }
                           } }
            };

            var configMonitor = new Mock <IOptionsMonitor <ConfigurationData> >();
            Action <ConfigurationData, string> onChangeCallback = (a, s) => { Assert.False(true, "OnChange method was not called."); };

            configMonitor.SetupGet(m => m.CurrentValue).Returns(config);
            configMonitor.Setup(m => m.OnChange(It.IsAny <Action <ConfigurationData, string> >())).Callback((Action <ConfigurationData, string> a) => { onChangeCallback = a; });
            var provider = GetProvider(configMonitor.Object, "testCert.pfx", null, () => TestResources.GetTestCertificate(), null);

            // Get several certificates.
            var certificateConfig = new List <X509Certificate2>();

            for (var i = 0; i < 5; i++)
            {
                certificateConfig.AddRange(provider.GetConfig().Clusters.Select(c => c.HttpClient.ClientCertificate));
                if (i < 4)
                {
                    onChangeCallback(config, null);
                }
            }

            // Verify cache contents match the configuration objects.
            var cachedCertificates = GetCachedCertificates(provider);

            Assert.Equal(certificateConfig.Count, cachedCertificates.Length);
            for (var i = 0; i < certificateConfig.Count; i++)
            {
                Assert.Same(certificateConfig[i], cachedCertificates[i]);
            }

            // Get several certificates.
            certificateConfig[1].Dispose();
            certificateConfig[3].Dispose();

            // Trigger cache compaction.
            onChangeCallback(config, null);

            // Verify disposed certificates were purged out.
            cachedCertificates = GetCachedCertificates(provider);
            Assert.Equal(4, cachedCertificates.Length);
            Assert.Same(certificateConfig[0], cachedCertificates[0]);
            Assert.Same(certificateConfig[2], cachedCertificates[1]);
            Assert.Same(certificateConfig[4], cachedCertificates[2]);
        }
コード例 #27
0
        public void GetConfig_ValidConfiguration_AllAbstractionsPropertiesAreSet()
        {
            var certificate           = TestResources.GetTestCertificate();
            var abstractionsNamespace = typeof(Abstractions.Cluster).Namespace;
            var provider       = GetProvider(_validConfigurationData, "mycert.pfx", "myPassword1234", () => certificate);
            var abstractConfig = (ConfigurationSnapshot)provider.GetConfig();

            //Removed incompletely filled out instances.
            abstractConfig.Clusters = abstractConfig.Clusters.Where(c => c.Id == "cluster1").ToList();
            abstractConfig.Routes   = abstractConfig.Routes.Where(r => r.RouteId == "routeA").ToList();

            VerifyAllPropertiesAreSet(abstractConfig);

            void VerifyFullyInitialized(object obj, string name)
            {
                switch (obj)
                {
                case null:
                    Assert.True(false, $"Property {name} is not initialized.");
                    break;

                case Enum m:
                    Assert.NotEqual(0, (int)(object)m);
                    break;

                case string str:
                    Assert.NotEmpty(str);
                    break;

                case ValueType v:
                    var equals = Equals(Activator.CreateInstance(v.GetType()), v);
                    Assert.False(equals, $"Property {name} is not initialized.");
                    if (v.GetType().Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(v);
                    }
                    break;

                case IDictionary d:
                    Assert.NotEmpty(d);
                    foreach (var value in d.Values)
                    {
                        VerifyFullyInitialized(value, name);
                    }
                    break;

                case IEnumerable e:
                    Assert.NotEmpty(e);
                    foreach (var item in e)
                    {
                        VerifyFullyInitialized(item, name);
                    }

                    var type = e.GetType();
                    if (!type.IsArray && type.Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(e);
                    }
                    break;

                case object o:
                    if (o.GetType().Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(o);
                    }
                    break;
                }
            }

            void VerifyAllPropertiesAreSet(object obj)
            {
                var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Cast <PropertyInfo>();

                foreach (var property in properties)
                {
                    VerifyFullyInitialized(property.GetValue(obj), $"{property.DeclaringType.Name}.{property.Name}");
                }
            }
        }
コード例 #28
0
        public async Task HttpsConnectionClosedWhenResponseDoesNotSatisfyMinimumDataRate()
        {
            const int chunkSize = 1024;
            const int chunks    = 256 * 1024;
            var       chunkData = new byte[chunkSize];

            var certificate = TestResources.GetTestCertificate();

            var responseRateTimeoutMessageLogged = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var connectionStopMessageLogged      = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var aborted          = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var appFuncCompleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

            TestSink.MessageLogged += context =>
            {
                if (context.EventId.Name == "ResponseMinimumDataRateNotSatisfied")
                {
                    responseRateTimeoutMessageLogged.SetResult();
                }
                if (context.EventId.Name == "ConnectionStop")
                {
                    connectionStopMessageLogged.SetResult();
                }
            };

            var testContext = new TestServiceContext(LoggerFactory)
            {
                ServerOptions =
                {
                    Limits                  =
                    {
                        MinResponseDataRate = new MinDataRate(bytesPerSecond: 1024 * 1024, gracePeriod: TimeSpan.FromSeconds(2))
                    }
                }
            };

            testContext.InitializeHeartbeat();

            void ConfigureListenOptions(ListenOptions listenOptions)
            {
                listenOptions.UseHttps(new HttpsConnectionAdapterOptions {
                    ServerCertificate = certificate
                });
            }

            await using (var server = new TestServer(async context =>
            {
                context.RequestAborted.Register(() =>
                {
                    aborted.SetResult();
                });

                context.Response.ContentLength = chunks * chunkSize;

                try
                {
                    for (var i = 0; i < chunks; i++)
                    {
                        await context.Response.BodyWriter.WriteAsync(new Memory <byte>(chunkData, 0, chunkData.Length), context.RequestAborted);
                    }
                }
                catch (OperationCanceledException)
                {
                    appFuncCompleted.SetResult();
                    throw;
                }
                finally
                {
                    await aborted.Task.DefaultTimeout();
                }
            }, testContext, ConfigureListenOptions))
            {
                using (var connection = server.CreateConnection())
                {
                    using (var sslStream = new SslStream(connection.Stream, false, (sender, cert, chain, errors) => true, null))
                    {
                        await sslStream.AuthenticateAsClientAsync("localhost", new X509CertificateCollection(), SslProtocols.None, false);

                        var request = Encoding.ASCII.GetBytes("GET / HTTP/1.1\r\nHost:\r\n\r\n");
                        await sslStream.WriteAsync(request, 0, request.Length);

                        // Don't use the 5 second timeout for debug builds. This can actually take a while.
                        await aborted.Task.DefaultTimeout(TimeSpan.FromSeconds(30));

                        await responseRateTimeoutMessageLogged.Task.DefaultTimeout();

                        await connectionStopMessageLogged.Task.DefaultTimeout();

                        await appFuncCompleted.Task.DefaultTimeout();

                        await AssertStreamAborted(connection.Stream, chunkSize *chunks);
                    }
                }
            }
        }
        public void GetConfig_ValidConfiguration_AllAbstractionsPropertiesAreSet()
        {
            var builder = new ConfigurationBuilder();

            using var stream = new MemoryStream(Encoding.UTF8.GetBytes(_validJsonConfig));
            var proxyConfig = builder.AddJsonStream(stream).Build();
            var certLoader  = new Mock <ICertificateConfigLoader>(MockBehavior.Strict);

            using var certificate = TestResources.GetTestCertificate();
            certLoader.Setup(l => l.LoadCertificate(It.Is <IConfigurationSection>(o => o["Path"] == "mycert.pfx" && o["Password"] == "myPassword1234"))).Returns(certificate);
            var logger = new Mock <ILogger <ConfigurationConfigProvider> >();

            var provider       = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object);
            var abstractConfig = (ConfigurationSnapshot)provider.GetConfig();

            var abstractionsNamespace = typeof(Cluster).Namespace;

            // Removed incompletely filled out instances.
            abstractConfig.Clusters = abstractConfig.Clusters.Where(c => c.Id == "cluster1").ToList();
            abstractConfig.Routes   = abstractConfig.Routes.Where(r => r.RouteId == "routeA").ToList();

            VerifyAllPropertiesAreSet(abstractConfig);

            void VerifyFullyInitialized(object obj, string name)
            {
                switch (obj)
                {
                case null:
                    Assert.True(false, $"Property {name} is not initialized.");
                    break;

                case Enum m:
                    Assert.NotEqual(0, (int)(object)m);
                    break;

                case string str:
                    Assert.NotEmpty(str);
                    break;

                case ValueType v:
                    var equals = Equals(Activator.CreateInstance(v.GetType()), v);
                    Assert.False(equals, $"Property {name} is not initialized.");
                    if (v.GetType().Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(v);
                    }
                    break;

                case IDictionary d:
                    Assert.NotEmpty(d);
                    foreach (var value in d.Values)
                    {
                        VerifyFullyInitialized(value, name);
                    }
                    break;

                case IEnumerable e:
                    Assert.NotEmpty(e);
                    foreach (var item in e)
                    {
                        VerifyFullyInitialized(item, name);
                    }

                    var type = e.GetType();
                    if (!type.IsArray && type.Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(e);
                    }
                    break;

                case object o:
                    if (o.GetType().Namespace == abstractionsNamespace)
                    {
                        VerifyAllPropertiesAreSet(o);
                    }
                    break;
                }
            }

            void VerifyAllPropertiesAreSet(object obj)
            {
                var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Cast <PropertyInfo>();

                foreach (var property in properties)
                {
                    VerifyFullyInitialized(property.GetValue(obj), $"{property.DeclaringType.Name}.{property.Name}");
                }
            }
        }
        public void CachedCertificateIsDisposed_RemoveItFromCache()
        {
            var builder     = new ConfigurationBuilder();
            var proxyConfig = builder.AddInMemoryCollection(new Dictionary <string, string>
            {
                ["Clusters:cluster1:Destinations:destinationA:Address"] = "https://localhost:10001/destC",
                ["Clusters:cluster1:HttpClient:ClientCertificate:Path"] = "testCert.pfx",
                ["Routes:0:RouteId"]       = "routeA",
                ["Routes:0:ClusterId"]     = "cluster1",
                ["Routes:0:Order"]         = "1",
                ["Routes:0:Match:Hosts:0"] = "host-B",
            }).Build();
            var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict);

            using var certificate = TestResources.GetTestCertificate();
            certLoader.Setup(l => l.LoadCertificate(It.IsAny <IConfigurationSection>())).Returns(() => TestResources.GetTestCertificate());
            var logger = new Mock <ILogger <ConfigurationConfigProvider> >();

            logger.Setup(l => l.IsEnabled(LogLevel.Error)).Returns(true);
            var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object);

            // Get several certificates.
            var certificateConfig = new List <X509Certificate2>();

            for (var i = 0; i < 5; i++)
            {
                certificateConfig.AddRange(provider.GetConfig().Clusters.Select(c => c.HttpClient.ClientCertificate));
                if (i < 4)
                {
                    TriggerOnChange(proxyConfig);
                }
            }

            // Verify cache contents match the configuration objects.
            var cachedCertificates = GetCachedCertificates(provider);

            Assert.Equal(certificateConfig.Count, cachedCertificates.Length);
            for (var i = 0; i < certificateConfig.Count; i++)
            {
                Assert.Same(certificateConfig[i], cachedCertificates[i]);
            }

            // Get several certificates.
            certificateConfig[1].Dispose();
            certificateConfig[3].Dispose();

            // Trigger cache compaction.
            TriggerOnChange(proxyConfig);

            // Verify disposed certificates were purged out.
            cachedCertificates = GetCachedCertificates(provider);
            Assert.Equal(4, cachedCertificates.Length);
            Assert.Same(certificateConfig[0], cachedCertificates[0]);
            Assert.Same(certificateConfig[2], cachedCertificates[1]);
            Assert.Same(certificateConfig[4], cachedCertificates[2]);
        }