diff --git a/source/common/network/connection_impl.h b/source/common/network/connection_impl.h index 21aaa8e268c7e..bc80f1f92a0fa 100644 --- a/source/common/network/connection_impl.h +++ b/source/common/network/connection_impl.h @@ -122,6 +122,7 @@ class ConnectionImpl : public ConnectionImplBase, // Reconsider how to make fairness happen. void setTransportSocketIsReadable() override; void flushWriteBuffer() override; + TransportSocketPtr& transportSocket() { return transport_socket_; } // Obtain global next connection ID. This should only be used in tests. static uint64_t nextGlobalIdForTest() { return next_global_id_; } diff --git a/test/config/utility.cc b/test/config/utility.cc index 6a77b020e6909..b2a8e1600f9e1 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -146,49 +146,6 @@ std::string ConfigHelper::startTlsConfig() { TestEnvironment::runfilesPath("test/config/integration/certs/serverkey.pem"))); } -envoy::config::cluster::v3::Cluster ConfigHelper::buildStartTlsCluster(const std::string& address, - int port) { - API_NO_BOOST(envoy::config::cluster::v3::Cluster) cluster; - auto config_str = fmt::format( - R"EOF( - name: dummy_cluster - connect_timeout: 5s - type: STATIC - load_assignment: - cluster_name: dummy_cluster - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: {} - port_value: {} - transport_socket: - name: "starttls" - typed_config: - "@type": type.googleapis.com/envoy.extensions.transport_sockets.starttls.v3.UpstreamStartTlsConfig - cleartext_socket_config: - tls_socket_config: - common_tls_context: - tls_certificates: - certificate_chain: - filename: {} - private_key: - filename: {} - lb_policy: ROUND_ROBIN - typed_extension_protocol_options: - envoy.extensions.upstreams.http.v3.HttpProtocolOptions: - "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions - explicit_http_config: - http2_protocol_options: {{}} - )EOF", - address, port, TestEnvironment::runfilesPath("test/config/integration/certs/clientcert.pem"), - TestEnvironment::runfilesPath("test/config/integration/certs/clientkey.pem")); - - TestUtility::loadFromYaml(config_str, cluster); - return cluster; -} - std::string ConfigHelper::tlsInspectorFilter() { return R"EOF( name: "envoy.filters.listener.tls_inspector" diff --git a/test/extensions/transport_sockets/starttls/BUILD b/test/extensions/transport_sockets/starttls/BUILD index 64883b0c14201..966dd1e1b4ca8 100644 --- a/test/extensions/transport_sockets/starttls/BUILD +++ b/test/extensions/transport_sockets/starttls/BUILD @@ -62,11 +62,8 @@ envoy_extension_cc_test( extension_name = "envoy.transport_sockets.starttls", deps = [ ":starttls_integration_proto_cc_proto", - "//source/extensions/filters/network/tcp_proxy:config", - "//source/extensions/transport_sockets/raw_buffer:config", "//source/extensions/transport_sockets/starttls:config", "//test/integration:integration_lib", "//test/test_common:registry_lib", - "@envoy_api//envoy/extensions/transport_sockets/raw_buffer/v3:pkg_cc_proto", ], ) diff --git a/test/extensions/transport_sockets/starttls/upstream_starttls_integration_test.cc b/test/extensions/transport_sockets/starttls/upstream_starttls_integration_test.cc index df86c4f17e4aa..d00af9e2389a0 100644 --- a/test/extensions/transport_sockets/starttls/upstream_starttls_integration_test.cc +++ b/test/extensions/transport_sockets/starttls/upstream_starttls_integration_test.cc @@ -1,13 +1,12 @@ -#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.h" -#include "envoy/extensions/transport_sockets/raw_buffer/v3/raw_buffer.pb.validate.h" #include "envoy/network/filter.h" #include "envoy/server/filter_config.h" #include "common/network/connection_impl.h" #include "extensions/filters/network/common/factory_base.h" -#include "extensions/transport_sockets/raw_buffer/config.h" #include "extensions/transport_sockets/starttls/starttls_socket.h" +#include "extensions/transport_sockets/tls/context_config_impl.h" +#include "extensions/transport_sockets/tls/ssl_socket.h" #include "test/config/utility.h" #include "test/extensions/transport_sockets/starttls/starttls_integration_test.pb.h" @@ -20,52 +19,12 @@ namespace Envoy { -class TerminalServerTlsFilter : public Network::ReadFilter { -public: - // Network::ReadFilter - Network::FilterStatus onData(Buffer::Instance& buf, bool) override { - auto message = buf.toString(); - if (message != "usetls") { - // Just echo anything other than the 'usetls' command. - read_callbacks_->connection().write(buf, false); - } else { - read_callbacks_->connection().addBytesSentCallback([=](uint64_t bytes) -> bool { - // Wait until 6 bytes long "usetls" has been sent. - if (bytes >= 6) { - read_callbacks_->connection().startSecureTransport(); - // Unsubscribe the callback. - // Switch to tls has been completed. - return false; - } - return true; - }); - - buf.drain(buf.length()); - buf.add("switch"); - read_callbacks_->connection().write(buf, false); - } - - return Network::FilterStatus::StopIteration; - } - - Network::FilterStatus onNewConnection() override { return Network::FilterStatus::Continue; } - - void initializeReadFilterCallbacks(Network::ReadFilterCallbacks& callbacks) override { - read_callbacks_ = &callbacks; - } - -private: - Network::ReadFilterCallbacks* read_callbacks_{}; -}; - // Simple filter for test purposes. This filter will be injected into the filter chain during -// tests. The filter reacts only to few keywords. If received payload does not contain -// allowed keyword, filter will stop iteration. -// The filter will be configured to sit on top of tcp_proxy and use start-tls transport socket. -// If it receives a data which is not known keyword it means that transport socket has not been -// successfully converted to use TLS and filter receives either encrypted data or TLS handshake -// messages. -class StartTlsSwitchFilter : public Network::ReadFilter { +// tests. +// The filter reacts only to "switch" keyword to switch upstream startTls transport socket to secure +// mode. All other payloads are forwarded either downstream or upstream respectively. +// Filter will be instantiated as terminal filter in order to have access to upstream connection. +class StartTlsSwitchFilter : public Network::Filter { public: ~StartTlsSwitchFilter() override { if (upstream_connection_) { @@ -73,15 +32,22 @@ class StartTlsSwitchFilter : public Network::ReadFilter { } } - void upstreamWrite(Buffer::Instance& data, bool end_stream); + void onCommand(Buffer::Instance& data); // Network::ReadFilter Network::FilterStatus onData(Buffer::Instance& data, bool end_stream) override; - Network::FilterStatus onNewConnection() override; void initializeReadFilterCallbacks(Network::ReadFilterCallbacks& callbacks) override { read_callbacks_ = &callbacks; } + // Network::WriteFilter + Network::FilterStatus onWrite(Buffer::Instance& data, bool end_stream) override; + void initializeWriteFilterCallbacks(Network::WriteFilterCallbacks& callbacks) override { + write_callbacks_ = &callbacks; + } + + Network::FilterStatus onNewConnection() override; + static std::shared_ptr newInstance(Upstream::ClusterManager& cluster_manager) { auto p = std::shared_ptr(new StartTlsSwitchFilter(cluster_manager)); @@ -89,14 +55,14 @@ class StartTlsSwitchFilter : public Network::ReadFilter { return p; } + // Helper filter to catch onData coming on upstream connection. struct UpstreamReadFilter : public Network::ReadFilter { - UpstreamReadFilter(std::weak_ptr parent) : parent_(parent) {} Network::FilterStatus onData(Buffer::Instance& data, bool end_stream) override { if (auto parent = parent_.lock()) { - parent->upstreamWrite(data, end_stream); - return Network::FilterStatus::Continue; + parent->onCommand(data); + return parent->onWrite(data, end_stream); } else { read_callbacks_->connection().close(Network::ConnectionCloseType::FlushWrite); return Network::FilterStatus::StopIteration; @@ -119,12 +85,13 @@ class StartTlsSwitchFilter : public Network::ReadFilter { std::weak_ptr self_{}; Network::ReadFilterCallbacks* read_callbacks_{}; + Network::WriteFilterCallbacks* write_callbacks_{}; Network::ClientConnectionPtr upstream_connection_{}; Upstream::ClusterManager& cluster_manager_; }; Network::FilterStatus StartTlsSwitchFilter::onNewConnection() { - auto c = cluster_manager_.getThreadLocalCluster("dummy_cluster"); + auto c = cluster_manager_.getThreadLocalCluster("cluster_0"); auto h = c->loadBalancer().chooseHost(nullptr); upstream_connection_ = h->createConnection(read_callbacks_->connection().dispatcher(), nullptr, nullptr).connection_; @@ -139,35 +106,33 @@ Network::FilterStatus StartTlsSwitchFilter::onData(Buffer::Instance& data, bool return Network::FilterStatus::StopIteration; } + onCommand(data); upstream_connection_->write(data, end_stream); return Network::FilterStatus::Continue; } -void StartTlsSwitchFilter::upstreamWrite(Buffer::Instance& buf, bool end_stream) { +Network::FilterStatus StartTlsSwitchFilter::onWrite(Buffer::Instance& buf, bool end_stream) { + read_callbacks_->connection().write(buf, end_stream); + return Network::FilterStatus::Continue; +} + +void StartTlsSwitchFilter::onCommand(Buffer::Instance& buf) { const std::string message = buf.toString(); if (message == "switch") { // Start the upstream secure transport immediately since we clearly have all the bytes ASSERT_TRUE(upstream_connection_->startSecureTransport()); - read_callbacks_->connection().addBytesSentCallback([=](uint64_t bytes) -> bool { - // Wait until 6 bytes long "switch" has been sent. - if (bytes >= 6) { - read_callbacks_->connection().startSecureTransport(); - // Unsubscribe the callback. - // Switch to tls has been completed. - return false; - } - return true; - }); } - // Finally just forward the data downstream. - read_callbacks_->connection().write(buf, end_stream); } -// Config factory for StartTlsSwitchFilter. +// Config factory for StartTlsSwitchFilter terminal filter. class StartTlsSwitchFilterConfigFactory : public Extensions::NetworkFilters::Common::FactoryBase< test::integration::starttls::StartTlsFilterConfig> { public: explicit StartTlsSwitchFilterConfigFactory(const std::string& name) : FactoryBase(name) {} + bool isTerminalFilterByProtoTyped(const test::integration::starttls::StartTlsFilterConfig&, + Server::Configuration::FactoryContext&) override { + return true; + } Network::FilterFactoryCb createFilterFactoryFromProtoTyped(const test::integration::starttls::StartTlsFilterConfig&, @@ -183,225 +148,150 @@ class StartTlsSwitchFilterConfigFactory : public Extensions::NetworkFilters::Com const std::string name_; }; -// ClientTestConnection is used for simulating a client -// which initiates a connection to Envoy in clear-text and then switches to TLS -// without closing the socket. -class ClientTestConnection : public Network::ClientConnectionImpl { -public: - ClientTestConnection(Event::Dispatcher& dispatcher, - const Network::Address::InstanceConstSharedPtr& remote_address, - const Network::Address::InstanceConstSharedPtr& source_address, - Network::TransportSocketPtr&& transport_socket, - const Network::ConnectionSocket::OptionsSharedPtr& options) - : ClientConnectionImpl(dispatcher, remote_address, source_address, - std::move(transport_socket), options) {} - - void setTransportSocket(Network::TransportSocketPtr&& transport_socket) { - transport_socket_ = std::move(transport_socket); - transport_socket_->setTransportSocketCallbacks(*this); - - // Reset connection's state machine. - connecting_ = true; - - // Issue event which will trigger TLS handshake. - ioHandle().activateFileEvents(Event::FileReadyType::Write); - } -}; - // Fixture class for integration tests. class StartTlsIntegrationTest : public testing::TestWithParam, public BaseIntegrationTest { public: StartTlsIntegrationTest() - : BaseIntegrationTest(GetParam(), ConfigHelper::startTlsConfig()), + : BaseIntegrationTest(GetParam(), ConfigHelper::baseConfig()), stream_info_(timeSystem(), nullptr) {} void initialize() override; - void addStartTlsSwitchFilter(ConfigHelper& config_helper); - - // Contexts needed by raw buffer and tls transport sockets. - std::unique_ptr tls_context_manager_; - Network::TransportSocketFactoryPtr tls_context_; - Network::TransportSocketFactoryPtr cleartext_context_; - - MockWatermarkBuffer* client_write_buffer_{nullptr}; - ConnectionStatusCallbacks connect_callbacks_; // Config factory for StartTlsSwitchFilter. StartTlsSwitchFilterConfigFactory config_factory_{"startTls"}; Registry::InjectFactory registered_config_factory_{config_factory_}; - std::unique_ptr conn_; - std::shared_ptr payload_reader_; - Network::ListenerPtr listener_; - Network::MockTcpListenerCallbacks listener_callbacks_; - Network::ServerConnectionPtr server_connection_; + std::unique_ptr tls_context_manager_; + Network::TransportSocketFactoryPtr tls_context_; // Technically unused. StreamInfo::StreamInfoImpl stream_info_; }; void StartTlsIntegrationTest::initialize() { - EXPECT_CALL(*mock_buffer_factory_, create_(_, _, _)) - // Connection constructor will first create write buffer. - // Test tracks how many bytes are sent. - .WillOnce(Invoke([&](std::function below_low, std::function above_high, - std::function above_overflow) -> Buffer::Instance* { - client_write_buffer_ = - new NiceMock(below_low, above_high, above_overflow); - ON_CALL(*client_write_buffer_, move(_)) - .WillByDefault(Invoke(client_write_buffer_, &MockWatermarkBuffer::baseMove)); - ON_CALL(*client_write_buffer_, drain(_)) - .WillByDefault(Invoke(client_write_buffer_, &MockWatermarkBuffer::trackDrains)); - return client_write_buffer_; - })) - // Connection constructor will also create read buffer, but the test does - // not track received bytes. - .WillRepeatedly(Invoke([&](std::function below_low, std::function above_high, - std::function above_overflow) -> Buffer::Instance* { - return new Buffer::WatermarkBuffer(below_low, above_high, above_overflow); - })); - - config_helper_.renameListener("tcp_proxy"); - addStartTlsSwitchFilter(config_helper_); - - // Setup factories and contexts for upstream clear-text raw buffer transport socket. - auto config = std::make_unique(); - - auto factory = - std::make_unique(); - cleartext_context_ = Network::TransportSocketFactoryPtr{ - factory->createTransportSocketFactory(*config, factory_context_)}; - - // Setup factories and contexts for tls transport socket. - tls_context_manager_ = - std::make_unique(timeSystem()); - tls_context_ = Ssl::createClientSslTransportSocketFactory({}, *tls_context_manager_, *api_); - payload_reader_ = std::make_shared(*dispatcher_); - - auto socket = std::make_shared( - Network::Test::getCanonicalLoopbackAddress(GetParam()), nullptr, true); - - // Prepare for the server side listener - EXPECT_CALL(listener_callbacks_, onAccept_(_)) - .WillOnce(Invoke([&](Network::ConnectionSocketPtr& socket) -> void { - auto server_tls_context_ = Ssl::createUpstreamSslContext(*tls_context_manager_, *api_); - - auto startTlsTransportSocket = - Extensions::TransportSockets::StartTls::StartTlsSocketFactory(move(cleartext_context_), - move(server_tls_context_)) - .createTransportSocket(std::make_shared( - absl::string_view(""), std::vector(), std::vector())); - - server_connection_ = dispatcher_->createServerConnection( - std::move(socket), move(startTlsTransportSocket), stream_info_); - server_connection_->addReadFilter(std::make_shared()); - })); - - listener_ = - dispatcher_->createListener(socket, listener_callbacks_, true, ENVOY_TCP_BACKLOG_SIZE); - - // Add a start_tls cluster - config_helper_.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - *bootstrap.mutable_static_resources()->add_clusters() = ConfigHelper::buildStartTlsCluster( - socket->addressProvider().localAddress()->ip()->addressAsString(), - socket->addressProvider().localAddress()->ip()->port()); + config_helper_.renameListener("starttls_test"); + + // Modifications to ConfigHelper::baseConfig. + // Add starttls transport socket to cluster_0 + config_helper_.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + auto* cluster = bootstrap.mutable_static_resources()->mutable_clusters(0); + envoy::extensions::transport_sockets::starttls::v3::UpstreamStartTlsConfig starttls_config; + envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext* tls_context = + starttls_config.mutable_tls_socket_config(); + auto* tls_certificate = tls_context->mutable_common_tls_context()->add_tls_certificates(); + tls_certificate->mutable_certificate_chain()->set_filename( + TestEnvironment::runfilesPath("test/config/integration/certs/clientcert.pem")); + tls_certificate->mutable_private_key()->set_filename( + TestEnvironment::runfilesPath("test/config/integration/certs/clientkey.pem")); + cluster->mutable_transport_socket()->set_name("envoy.transport_sockets.starttls"); + cluster->mutable_transport_socket()->mutable_typed_config()->PackFrom(starttls_config); }); - BaseIntegrationTest::initialize(); - - Network::Address::InstanceConstSharedPtr address = - Ssl::getSslAddress(version_, lookupPort("tcp_proxy")); - - conn_ = std::make_unique( - *dispatcher_, address, Network::Address::InstanceConstSharedPtr(), - cleartext_context_->createTransportSocket( - std::make_shared( - absl::string_view(""), std::vector(), std::vector())), - nullptr); - - conn_->enableHalfClose(true); - conn_->addConnectionCallbacks(connect_callbacks_); - conn_->addReadFilter(payload_reader_); -} - -// Method adds StartTlsSwitchFilter into the filter chain. -// The filter is required to instruct StartTls transport -// socket to start using Tls. -void StartTlsIntegrationTest::addStartTlsSwitchFilter(ConfigHelper& config_helper) { - config_helper.addNetworkFilter(R"EOF( + // Modifications to ConfigHelper::baseConfig. + // Insert StartTlsSwitchFilter into filter chain. + config_helper_.addConfigModifier([&](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { + bootstrap.mutable_static_resources()->mutable_listeners(0)->add_filter_chains(); + config_helper_.addNetworkFilter(R"EOF( name: startTls typed_config: "@type": type.googleapis.com/test.integration.starttls.StartTlsFilterConfig )EOF"); - // double-check the filter was actually added - config_helper.addConfigModifier([](envoy::config::bootstrap::v3::Bootstrap& bootstrap) { - ASSERT_EQ("startTls", - bootstrap.static_resources().listeners(0).filter_chains(0).filters(0).name()); }); + + // Setup factory and context for tls transport socket. + // The tls transport socket will be inserted into fake_upstream when + // upstream starttls transport socket is converted to secure mode. + tls_context_manager_ = + std::make_unique(timeSystem()); + + envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext downstream_tls_context; + + std::string yaml_plain = R"EOF( + common_tls_context: + validation_context: + trusted_ca: + filename: "{{ test_rundir }}/test/config/integration/certs/cacert.pem" + tls_certificates: + certificate_chain: + filename: "{{ test_rundir }}/test/config/integration/certs/clientcert.pem" + private_key: + filename: "{{ test_rundir }}/test/config/integration/certs/clientkey.pem" +)EOF"; + + TestUtility::loadFromYaml(TestEnvironment::substitute(yaml_plain), downstream_tls_context); + + NiceMock mock_factory_ctx; + ON_CALL(mock_factory_ctx, api()).WillByDefault(testing::ReturnRef(*api_)); + auto cfg = std::make_unique( + downstream_tls_context, mock_factory_ctx); + static auto* client_stats_store = new Stats::TestIsolatedStoreImpl(); + tls_context_ = Network::TransportSocketFactoryPtr{ + new Extensions::TransportSockets::Tls::ServerSslSocketFactory( + std::move(cfg), *tls_context_manager_, *client_stats_store, {})}; + + BaseIntegrationTest::initialize(); } -// Test creates a clear-text connection from a client to Envoy and sends several messages. -// Then a special message is sent, which causes StartTlsSwitchFilter to -// instruct StartTls transport socket to start using tls for both the upstream and -// downstream. Connections. The Client connection starts using tls, performs tls handshake -// and a message is sent over tls. start-tls transport socket de-crypts the messages and -// forwards them upstream over yet another start-tls transport. +// Test creates a client connection to Envoy and passes some date to fake_upstream. +// After that fake_upstream is converted to use TLS transport socket. +// The client sends a special message to Envoy which causes upstream starttls +// transport socket to start using secure mode. +// The client sends a message to fake_upstream to test encrypted connection between +// Envoy and fake_upstream. +// Finally fake_upstream sends a message through encrypted connection to Envoy +// which is resent to the client in clear-text. TEST_P(StartTlsIntegrationTest, SwitchToTlsFromClient) { initialize(); // Open clear-text connection. - conn_->connect(); + IntegrationTcpClientPtr tcp_client = makeTcpConnection(lookupPort("starttls_test")); FakeRawConnectionPtr fake_upstream_connection; ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); - ASSERT_THAT(test_server_->server().listenerManager().numConnections(), 1); - dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - - // Send a message to switch to tls on the receiver side. - // StartTlsSwitchFilter will switch transport socket on the - // upstream side upon receiving "switch" message and forward - // back the message "switch" to this client. - payload_reader_->set_data_to_wait_for("switch"); - Buffer::OwnedImpl buffer; - buffer.add("usetls"); - conn_->write(buffer, false); - while (client_write_buffer_->bytesDrained() != 6) { - dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - } - - ASSERT_TRUE(payload_reader_->waitForLength(6, std::chrono::milliseconds(100000))); + // Send a message to fake_upstream via Envoy. + ASSERT_TRUE(tcp_client->write("hello")); + // Make sure the data makes it upstream. + ASSERT_TRUE(fake_upstream_connection->waitForData(5)); - // Make sure we received the 'switch' command from the upstream. - ASSERT_EQ("switch", payload_reader_->data()); - payload_reader_->clearData(); - - // Without closing the connection, switch to tls. - conn_->setTransportSocket( + // Create TLS transport socket and install it in fake_upstream. + Network::TransportSocketPtr ts = tls_context_->createTransportSocket(std::make_shared( - absl::string_view(""), std::vector(), std::vector()))); - connect_callbacks_.reset(); + absl::string_view(""), std::vector(), + std::vector{"envoyalpn"})); + + // Synchronization object used to suspend execution + // until dispatcher completes transport socket conversion. + absl::Notification notification; + + // Execute transport socket conversion to TLS on the same thread where received data + // is dispatched. Otherwise conversion may collide with data processing. + fake_upstreams_[0]->dispatcher()->post([&]() { + auto connection = + dynamic_cast(&fake_upstream_connection->connection()); + connection->transportSocket() = std::move(ts); + connection->transportSocket()->setTransportSocketCallbacks(*connection); + notification.Notify(); + }); - while (!connect_callbacks_.connected() && !connect_callbacks_.closed()) { - dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - } + // Wait until the transport socket conversion completes. + notification.WaitForNotification(); - // // Send few messages over the encrypted connection. - buffer.add("hola"); - conn_->write(buffer, false); - while (client_write_buffer_->bytesDrained() != 10) { - dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - } + // Send message which will trigger upstream starttls to use secure mode. + ASSERT_TRUE(tcp_client->write("switch")); + // Make sure the data makes it upstream. + ASSERT_TRUE(fake_upstream_connection->waitForData(11)); - // Make sure we get our echo back - ASSERT_TRUE(payload_reader_->waitForLength(4, std::chrono::milliseconds(100000))); - ASSERT_EQ("hola", payload_reader_->data()); - payload_reader_->clearData(); + // Send a message from upstream down through Envoy to tcp_client. + ASSERT_TRUE(fake_upstream_connection->write("upstream")); + tcp_client->waitForData("upstream"); - conn_->close(Network::ConnectionCloseType::FlushWrite); - server_connection_->close(Network::ConnectionCloseType::FlushWrite); + // Cleanup. + tcp_client->close(); + ASSERT_TRUE(fake_upstream_connection->waitForDisconnect()); + test_server_.reset(); } INSTANTIATE_TEST_SUITE_P(StartTlsIntegrationTestSuite, StartTlsIntegrationTest, diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index a2d170eb110e2..d10c7ce4d8f51 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -663,6 +663,8 @@ class FakeUpstream : Logger::Loggable, const envoy::config::core::v3::Http2ProtocolOptions& http2Options() { return http2_options_; } const envoy::config::core::v3::Http3ProtocolOptions& http3Options() { return http3_options_; } + Event::DispatcherPtr& dispatcher() { return dispatcher_; } + protected: Stats::IsolatedStoreImpl stats_store_; const FakeHttpConnection::Type http_type_;