-
Notifications
You must be signed in to change notification settings - Fork 5.5k
tls: fix detection of the upstream connection close event. #13858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
9a60742
47f12b9
ea472af
0ece50f
ca79634
a99576d
ebfe0d4
28ac59f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2540,6 +2540,178 @@ TEST_P(SslSocketTest, HalfClose) { | |
| dispatcher_->run(Event::Dispatcher::RunType::Block); | ||
| } | ||
|
|
||
| TEST_P(SslSocketTest, ShutdownWithCloseNotify) { | ||
| const std::string server_ctx_yaml = R"EOF( | ||
| common_tls_context: | ||
| tls_certificates: | ||
| certificate_chain: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/unittest_cert.pem" | ||
| private_key: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/unittest_key.pem" | ||
| validation_context: | ||
| trusted_ca: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_certificates.pem" | ||
| )EOF"; | ||
|
|
||
| envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext server_tls_context; | ||
| TestUtility::loadFromYaml(TestEnvironment::substitute(server_ctx_yaml), server_tls_context); | ||
| auto server_cfg = std::make_unique<ServerContextConfigImpl>(server_tls_context, factory_context_); | ||
| ContextManagerImpl manager(time_system_); | ||
| Stats::TestUtil::TestStore server_stats_store; | ||
| ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, | ||
| server_stats_store, std::vector<std::string>{}); | ||
|
|
||
| auto socket = std::make_shared<Network::TcpListenSocket>( | ||
| Network::Test::getCanonicalLoopbackAddress(GetParam()), nullptr, true); | ||
| Network::MockTcpListenerCallbacks listener_callbacks; | ||
| Network::MockConnectionHandler connection_handler; | ||
| Network::ListenerPtr listener = | ||
| dispatcher_->createListener(socket, listener_callbacks, true, ENVOY_TCP_BACKLOG_SIZE); | ||
| std::shared_ptr<Network::MockReadFilter> server_read_filter(new Network::MockReadFilter()); | ||
| std::shared_ptr<Network::MockReadFilter> client_read_filter(new Network::MockReadFilter()); | ||
|
|
||
| const std::string client_ctx_yaml = R"EOF( | ||
| common_tls_context: | ||
| )EOF"; | ||
|
|
||
| envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_context; | ||
| TestUtility::loadFromYaml(TestEnvironment::substitute(client_ctx_yaml), tls_context); | ||
| auto client_cfg = std::make_unique<ClientContextConfigImpl>(tls_context, factory_context_); | ||
| Stats::TestUtil::TestStore client_stats_store; | ||
| ClientSslSocketFactory client_ssl_socket_factory(std::move(client_cfg), manager, | ||
| client_stats_store); | ||
| Network::ClientConnectionPtr client_connection = dispatcher_->createClientConnection( | ||
| socket->localAddress(), Network::Address::InstanceConstSharedPtr(), | ||
| client_ssl_socket_factory.createTransportSocket(nullptr), nullptr); | ||
| Network::MockConnectionCallbacks client_connection_callbacks; | ||
| client_connection->enableHalfClose(true); | ||
| client_connection->addReadFilter(client_read_filter); | ||
| client_connection->addConnectionCallbacks(client_connection_callbacks); | ||
| client_connection->connect(); | ||
|
|
||
| Network::ConnectionPtr server_connection; | ||
| Network::MockConnectionCallbacks server_connection_callbacks; | ||
| EXPECT_CALL(listener_callbacks, onAccept_(_)) | ||
| .WillOnce(Invoke([&](Network::ConnectionSocketPtr& socket) -> void { | ||
| server_connection = dispatcher_->createServerConnection( | ||
| std::move(socket), server_ssl_socket_factory.createTransportSocket(nullptr), | ||
| stream_info_); | ||
| server_connection->enableHalfClose(true); | ||
| server_connection->addReadFilter(server_read_filter); | ||
| server_connection->addConnectionCallbacks(server_connection_callbacks); | ||
| })); | ||
| EXPECT_CALL(server_connection_callbacks, onEvent(Network::ConnectionEvent::Connected)) | ||
| .WillOnce(Invoke([&](Network::ConnectionEvent) -> void { | ||
| Buffer::OwnedImpl data("hello"); | ||
| server_connection->write(data, false); | ||
|
PiotrSikora marked this conversation as resolved.
Outdated
|
||
| server_connection->close(Network::ConnectionCloseType::NoFlush); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To ensure this always happens gracefully, close with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe that Also, changing this to results in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See: #13890.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I forgot that we're using half-open here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that we can test this behavior without
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this patch makes the test correctly cover what we want it to cover:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The extra call to onData("", true) was actually on the server connection, in response to the client finishing the close.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patch applied, thanks! |
||
| })); | ||
|
|
||
| EXPECT_CALL(*client_read_filter, onNewConnection()) | ||
| .WillOnce(Return(Network::FilterStatus::Continue)); | ||
| EXPECT_CALL(client_connection_callbacks, onEvent(Network::ConnectionEvent::Connected)); | ||
| EXPECT_CALL(*client_read_filter, onData(BufferStringEqual("hello"), true)) | ||
| .WillOnce(Invoke([&](Buffer::Instance& read_buffer, bool) -> Network::FilterStatus { | ||
| read_buffer.drain(read_buffer.length()); | ||
| client_connection->close(Network::ConnectionCloseType::NoFlush); | ||
| return Network::FilterStatus::StopIteration; | ||
| })); | ||
|
|
||
| EXPECT_CALL(server_connection_callbacks, onEvent(Network::ConnectionEvent::LocalClose)); | ||
| EXPECT_CALL(client_connection_callbacks, onEvent(Network::ConnectionEvent::LocalClose)) | ||
| .WillOnce(Invoke([&](Network::ConnectionEvent) -> void { dispatcher_->exit(); })); | ||
|
|
||
| dispatcher_->run(Event::Dispatcher::RunType::Block); | ||
| } | ||
|
|
||
| TEST_P(SslSocketTest, ShutdownWithoutCloseNotify) { | ||
| const std::string server_ctx_yaml = R"EOF( | ||
| common_tls_context: | ||
| tls_certificates: | ||
| certificate_chain: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/unittest_cert.pem" | ||
| private_key: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/unittest_key.pem" | ||
| validation_context: | ||
| trusted_ca: | ||
| filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ca_certificates.pem" | ||
| )EOF"; | ||
|
|
||
| envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext server_tls_context; | ||
| TestUtility::loadFromYaml(TestEnvironment::substitute(server_ctx_yaml), server_tls_context); | ||
| auto server_cfg = std::make_unique<ServerContextConfigImpl>(server_tls_context, factory_context_); | ||
| ContextManagerImpl manager(time_system_); | ||
| Stats::TestUtil::TestStore server_stats_store; | ||
| ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, | ||
| server_stats_store, std::vector<std::string>{}); | ||
|
|
||
| auto socket = std::make_shared<Network::TcpListenSocket>( | ||
| Network::Test::getCanonicalLoopbackAddress(GetParam()), nullptr, true); | ||
| Network::MockTcpListenerCallbacks listener_callbacks; | ||
| Network::MockConnectionHandler connection_handler; | ||
| Network::ListenerPtr listener = | ||
| dispatcher_->createListener(socket, listener_callbacks, true, ENVOY_TCP_BACKLOG_SIZE); | ||
| std::shared_ptr<Network::MockReadFilter> server_read_filter(new Network::MockReadFilter()); | ||
| std::shared_ptr<Network::MockReadFilter> client_read_filter(new Network::MockReadFilter()); | ||
|
|
||
| const std::string client_ctx_yaml = R"EOF( | ||
| common_tls_context: | ||
| )EOF"; | ||
|
|
||
| envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext tls_context; | ||
| TestUtility::loadFromYaml(TestEnvironment::substitute(client_ctx_yaml), tls_context); | ||
| auto client_cfg = std::make_unique<ClientContextConfigImpl>(tls_context, factory_context_); | ||
| Stats::TestUtil::TestStore client_stats_store; | ||
| ClientSslSocketFactory client_ssl_socket_factory(std::move(client_cfg), manager, | ||
| client_stats_store); | ||
| Network::ClientConnectionPtr client_connection = dispatcher_->createClientConnection( | ||
| socket->localAddress(), Network::Address::InstanceConstSharedPtr(), | ||
| client_ssl_socket_factory.createTransportSocket(nullptr), nullptr); | ||
| Network::MockConnectionCallbacks client_connection_callbacks; | ||
| client_connection->enableHalfClose(true); | ||
| client_connection->addReadFilter(client_read_filter); | ||
| client_connection->addConnectionCallbacks(client_connection_callbacks); | ||
| client_connection->connect(); | ||
|
|
||
| Network::ConnectionPtr server_connection; | ||
| Network::MockConnectionCallbacks server_connection_callbacks; | ||
| EXPECT_CALL(listener_callbacks, onAccept_(_)) | ||
| .WillOnce(Invoke([&](Network::ConnectionSocketPtr& socket) -> void { | ||
| server_connection = dispatcher_->createServerConnection( | ||
| std::move(socket), server_ssl_socket_factory.createTransportSocket(nullptr), | ||
| stream_info_); | ||
| server_connection->enableHalfClose(true); | ||
| server_connection->addReadFilter(server_read_filter); | ||
| server_connection->addConnectionCallbacks(server_connection_callbacks); | ||
| })); | ||
| EXPECT_CALL(server_connection_callbacks, onEvent(Network::ConnectionEvent::Connected)) | ||
| .WillOnce(Invoke([&](Network::ConnectionEvent) -> void { | ||
| Buffer::OwnedImpl data("hello"); | ||
| server_connection->write(data, false); | ||
| // Close without sending close_notify alert. | ||
| const SslHandshakerImpl* ssl_socket = | ||
| dynamic_cast<const SslHandshakerImpl*>(server_connection->ssl().get()); | ||
| SSL_set_quiet_shutdown(ssl_socket->ssl(), 1); | ||
| server_connection->close(Network::ConnectionCloseType::NoFlush); | ||
|
PiotrSikora marked this conversation as resolved.
|
||
| })); | ||
|
|
||
| EXPECT_CALL(*client_read_filter, onNewConnection()) | ||
| .WillOnce(Return(Network::FilterStatus::Continue)); | ||
| EXPECT_CALL(client_connection_callbacks, onEvent(Network::ConnectionEvent::Connected)); | ||
| EXPECT_CALL(*client_read_filter, onData(BufferStringEqual("hello"), true)) | ||
| .WillOnce(Invoke([&](Buffer::Instance& read_buffer, bool) -> Network::FilterStatus { | ||
| read_buffer.drain(read_buffer.length()); | ||
| client_connection->close(Network::ConnectionCloseType::NoFlush); | ||
| return Network::FilterStatus::StopIteration; | ||
| })); | ||
|
|
||
|
PiotrSikora marked this conversation as resolved.
|
||
| EXPECT_CALL(server_connection_callbacks, onEvent(Network::ConnectionEvent::LocalClose)); | ||
| EXPECT_CALL(client_connection_callbacks, onEvent(Network::ConnectionEvent::LocalClose)) | ||
| .WillOnce(Invoke([&](Network::ConnectionEvent) -> void { dispatcher_->exit(); })); | ||
|
|
||
| dispatcher_->run(Event::Dispatcher::RunType::Block); | ||
| } | ||
|
|
||
| TEST_P(SslSocketTest, ClientAuthMultipleCAs) { | ||
| const std::string server_ctx_yaml = R"EOF( | ||
| common_tls_context: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.