diff --git a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto index e87c9478db635..00ce562f8dfb9 100644 --- a/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto +++ b/api/envoy/config/filter/http/jwt_authn/v2alpha/config.proto @@ -391,8 +391,7 @@ message FilterStateRule { // A map of string keys to requirements. The string key is the string value // in the FilterState with the name specified in the *name* field above. - map - requires = 3; + map requires = 3; } // This is the Envoy HTTP filter config for JWT authentication. diff --git a/api/envoy/config/listener/v3/listener_components.proto b/api/envoy/config/listener/v3/listener_components.proto index 710ac7ab75957..5f4fb8043204c 100644 --- a/api/envoy/config/listener/v3/listener_components.proto +++ b/api/envoy/config/listener/v3/listener_components.proto @@ -94,7 +94,7 @@ message Filter { // listed at the end, because that's how we want to list them in the docs. // // [#comment:TODO(PiotrSikora): Add support for configurable precedence of the rules] -// [#next-free-field: 14] +// [#next-free-field: 101] message FilterChainMatch { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.FilterChainMatch"; @@ -112,6 +112,9 @@ message FilterChainMatch { reserved 1; + // The Connection Metadata of the connection to match against. + string connection_metadata = 100; + // Optional destination port to consider when use_original_dst is set on the // listener in determining a filter chain match. google.protobuf.UInt32Value destination_port = 8 [(validate.rules).uint32 = {lte: 65535 gte: 1}]; diff --git a/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto b/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto index 65ddd88e9df8c..64ae483c953f1 100644 --- a/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto +++ b/api/envoy/extensions/filters/http/jwt_authn/v3/config.proto @@ -583,8 +583,7 @@ message FilterStateRule { // A map of string keys to requirements. The string key is the string value // in the FilterState with the name specified in the *name* field above. - map - requires = 3; + map requires = 3; } // This is the Envoy HTTP filter config for JWT authentication. diff --git a/envoy/network/listen_socket.h b/envoy/network/listen_socket.h index a900ad7ee5e14..8214ae5617fee 100644 --- a/envoy/network/listen_socket.h +++ b/envoy/network/listen_socket.h @@ -69,6 +69,16 @@ class ConnectionSocket : public virtual Socket, public virtual ScopeTrackedObjec */ virtual absl::string_view ja3Hash() const PURE; + /** + * Set Connection Metadata. + */ + virtual void setConnectionMetadata(absl::string_view connection_metadata) PURE; + + /** + * @return Connection Metadata. + */ + virtual absl::string_view connectionMetadata() const PURE; + /** * @return absl::optional An optional of the most recent round-trip * time of the connection. If the platform does not support this, then an empty optional is diff --git a/envoy/network/socket.h b/envoy/network/socket.h index 308cede895736..b06dd85737bec 100644 --- a/envoy/network/socket.h +++ b/envoy/network/socket.h @@ -78,6 +78,11 @@ class ConnectionInfoProvider { */ virtual absl::string_view requestedServerName() const PURE; + /** + * @return Connection Metadatafor downstream client. + */ + virtual absl::string_view connectionMetadata() const PURE; + /** * @return Connection ID of the downstream connection, or unset if not available. **/ @@ -142,6 +147,11 @@ class ConnectionInfoSetter : public ConnectionInfoProvider { */ virtual void setRequestedServerName(const absl::string_view requested_server_name) PURE; + /** + * @param Connection Metadata. + */ + virtual void setConnectionMetadata(const absl::string_view connection_metadata) PURE; + /** * @param id Connection ID of the downstream connection. **/ diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index 06de03b77e18f..975f3bd6eab88 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -627,6 +627,9 @@ class OverridableRemoteConnectionInfoSetterStreamInfo : public StreamInfo::Strea absl::string_view requestedServerName() const override { return StreamInfoImpl::downstreamAddressProvider().requestedServerName(); } + absl::string_view connectionMetadata() const override { + return StreamInfoImpl::downstreamAddressProvider().connectionMetadata(); + } absl::optional connectionID() const override { return StreamInfoImpl::downstreamAddressProvider().connectionID(); } diff --git a/source/common/network/listen_socket_impl.h b/source/common/network/listen_socket_impl.h index 14e5166718832..a6900fa5ee55b 100644 --- a/source/common/network/listen_socket_impl.h +++ b/source/common/network/listen_socket_impl.h @@ -224,6 +224,14 @@ class ConnectionSocketImpl : public SocketImpl, public ConnectionSocket { } absl::string_view ja3Hash() const override { return connectionInfoProvider().ja3Hash(); } + void setConnectionMetadata(absl::string_view connection_metadata) override { + // Always keep the connection_metadata as lower case. + connectionInfoProvider().setConnectionMetadata(absl::AsciiStrToLower(connection_metadata)); + } + absl::string_view connectionMetadata() const override { + return connectionInfoProvider().connectionMetadata(); + } + absl::optional lastRoundTripTime() override { return ioHandle().lastRoundTripTime(); } diff --git a/source/common/network/socket_impl.h b/source/common/network/socket_impl.h index 568ba44bc16ec..0af3a5db112bd 100644 --- a/source/common/network/socket_impl.h +++ b/source/common/network/socket_impl.h @@ -50,6 +50,10 @@ class ConnectionInfoSetterImpl : public ConnectionInfoSetter { void setRequestedServerName(const absl::string_view requested_server_name) override { server_name_ = std::string(requested_server_name); } + absl::string_view connectionMetadata() const override { return connection_metadata_; } + void setConnectionMetadata(const absl::string_view connection_metadata) override { + connection_metadata_ = std::string(connection_metadata); + } absl::optional connectionID() const override { return connection_id_; } void setConnectionID(uint64_t id) override { connection_id_ = id; } absl::optional interfaceName() const override { return interface_name_; } @@ -70,6 +74,7 @@ class ConnectionInfoSetterImpl : public ConnectionInfoSetter { Address::InstanceConstSharedPtr remote_address_; Address::InstanceConstSharedPtr direct_remote_address_; std::string server_name_; + std::string connection_metadata_; absl::optional connection_id_; absl::optional interface_name_; Ssl::ConnectionInfoConstSharedPtr ssl_info_; diff --git a/source/server/filter_chain_manager_impl.cc b/source/server/filter_chain_manager_impl.cc index 224315b7e245b..6b535da0a1bc7 100644 --- a/source/server/filter_chain_manager_impl.cc +++ b/source/server/filter_chain_manager_impl.cc @@ -225,8 +225,8 @@ void FilterChainManagerImpl::addFilterChains( ++new_filter_chain_size; } - addFilterChainForDestinationPorts( - destination_ports_map_, + addFilterChainForConnectionMetadata( + connection_metadata_map_, absl::AsciiStrToLower(filter_chain_match.connection_metadata()), PROTOBUF_GET_WRAPPED_OR_DEFAULT(filter_chain_match, destination_port, 0), destination_ips, server_names, filter_chain_match.transport_protocol(), filter_chain_match.application_protocols(), direct_source_ips, @@ -275,6 +275,25 @@ void FilterChainManagerImpl::copyOrRebuildDefaultFilterChain( } } +void FilterChainManagerImpl::addFilterChainForConnectionMetadata( + ConnectionMetadataMap& connection_metadata_map, const std::string& connection_metadata, + uint16_t destination_port, const std::vector& destination_ips, + const absl::Span server_names, const std::string& transport_protocol, + const absl::Span application_protocols, + const std::vector& direct_source_ips, + const envoy::config::listener::v3::FilterChainMatch::ConnectionSourceType source_type, + const std::vector& source_ips, + const absl::Span source_ports, + const Network::FilterChainSharedPtr& filter_chain) { + if (connection_metadata_map.find(connection_metadata) == connection_metadata_map.end()) { + connection_metadata_map[connection_metadata] = DestinationPortsMap{}; + } + addFilterChainForDestinationPorts(connection_metadata_map[connection_metadata], destination_port, + destination_ips, server_names, transport_protocol, + application_protocols, direct_source_ips, source_type, + source_ips, source_ports, filter_chain); +} + void FilterChainManagerImpl::addFilterChainForDestinationPorts( DestinationPortsMap& destination_ports_map, uint16_t destination_port, const std::vector& destination_ips, @@ -468,13 +487,46 @@ std::pair> makeCidrListEntry(const s const Network::FilterChain* FilterChainManagerImpl::findFilterChain(const Network::ConnectionSocket& socket) const { + const auto& connection_metadata = + absl::AsciiStrToLower(socket.connectionInfoProvider().connectionMetadata()); + + const Network::FilterChain* best_match_filter_chain = nullptr; + const auto connection_metadata_match = connection_metadata_map_.find(connection_metadata); + if (connection_metadata_match != connection_metadata_map_.end()) { + best_match_filter_chain = + findFilterChainForDestinationPort(connection_metadata_match->second, socket); + if (best_match_filter_chain != nullptr) { + return best_match_filter_chain; + } else { + // There is entry for specific tenant ID but none of the filter chain matches. Instead of + // matching catch-all tenant ID "", the fallback filter chain is returned. + return default_filter_chain_.get(); + } + } + + // Match on a filter chain without tenant ID requirements. + const auto connection_metadata_catchall_match = connection_metadata_map_.find(EMPTY_STRING); + if (connection_metadata_catchall_match != connection_metadata_map_.end()) { + best_match_filter_chain = + findFilterChainForDestinationPort(connection_metadata_catchall_match->second, socket); + } + + return best_match_filter_chain != nullptr + ? best_match_filter_chain + // Neither exact tenant ID nor catch-all tenant ID matches. Use fallback filter chain. + : default_filter_chain_.get(); +} + +const Network::FilterChain* FilterChainManagerImpl::findFilterChainForDestinationPort( + const DestinationPortsMap& destination_ports_map, + const Network::ConnectionSocket& socket) const { const auto& address = socket.connectionInfoProvider().localAddress(); const Network::FilterChain* best_match_filter_chain = nullptr; // Match on destination port (only for IP addresses). if (address->type() == Network::Address::Type::Ip) { - const auto port_match = destination_ports_map_.find(address->ip()->port()); - if (port_match != destination_ports_map_.end()) { + const auto port_match = destination_ports_map.find(address->ip()->port()); + if (port_match != destination_ports_map.end()) { best_match_filter_chain = findFilterChainForDestinationIP(*port_match->second.second, socket); if (best_match_filter_chain != nullptr) { return best_match_filter_chain; @@ -486,8 +538,8 @@ FilterChainManagerImpl::findFilterChain(const Network::ConnectionSocket& socket) } } // Match on catch-all port 0 if there is no specific port sub tree. - const auto port_match = destination_ports_map_.find(0); - if (port_match != destination_ports_map_.end()) { + const auto port_match = destination_ports_map.find(0); + if (port_match != destination_ports_map.end()) { best_match_filter_chain = findFilterChainForDestinationIP(*port_match->second.second, socket); } return best_match_filter_chain != nullptr @@ -670,58 +722,60 @@ const Network::FilterChain* FilterChainManagerImpl::findFilterChainForSourceIpAn } void FilterChainManagerImpl::convertIPsToTries() { - for (auto& [destination_port, destination_ips_pair] : destination_ports_map_) { - UNREFERENCED_PARAMETER(destination_port); - // These variables are used as we build up the destination CIDRs used for the trie. - auto& [destination_ips_map, destination_ips_trie] = destination_ips_pair; - std::vector>> - destination_ips_list; - destination_ips_list.reserve(destination_ips_map.size()); - - for (const auto& [destination_ip, server_names_map_ptr] : destination_ips_map) { - destination_ips_list.push_back(makeCidrListEntry(destination_ip, server_names_map_ptr)); - - // This hugely nested for loop greatly pains me, but I'm not sure how to make it better. - // We need to get access to all of the source IP strings so that we can convert them into - // a trie like we did for the destination IPs above. - for (auto& [server_name, transport_protocols_map] : *server_names_map_ptr) { - UNREFERENCED_PARAMETER(server_name); - for (auto& [transport_protocol, application_protocols_map] : transport_protocols_map) { - UNREFERENCED_PARAMETER(transport_protocol); - for (auto& [application_protocol, direct_source_ips_pair] : application_protocols_map) { - UNREFERENCED_PARAMETER(application_protocol); - auto& [direct_source_ips_map, direct_source_ips_trie] = direct_source_ips_pair; - - std::vector< - std::pair>> - direct_source_ips_list; - direct_source_ips_list.reserve(direct_source_ips_map.size()); - - for (auto& [direct_source_ip, source_arrays_ptr] : direct_source_ips_map) { - direct_source_ips_list.push_back( - makeCidrListEntry(direct_source_ip, source_arrays_ptr)); - - for (auto& [source_ips_map, source_ips_trie] : *source_arrays_ptr) { - std::vector< - std::pair>> - source_ips_list; - source_ips_list.reserve(source_ips_map.size()); - - for (auto& [source_ip, source_port_map_ptr] : source_ips_map) { - source_ips_list.push_back(makeCidrListEntry(source_ip, source_port_map_ptr)); + for (auto& [connection_metadata, destination_ports_map] : connection_metadata_map_) { + for (auto& [destination_port, destination_ips_pair] : destination_ports_map) { + UNREFERENCED_PARAMETER(destination_port); + // These variables are used as we build up the destination CIDRs used for the trie. + auto& [destination_ips_map, destination_ips_trie] = destination_ips_pair; + std::vector>> + destination_ips_list; + destination_ips_list.reserve(destination_ips_map.size()); + + for (const auto& [destination_ip, server_names_map_ptr] : destination_ips_map) { + destination_ips_list.push_back(makeCidrListEntry(destination_ip, server_names_map_ptr)); + + // This hugely nested for loop greatly pains me, but I'm not sure how to make it better. + // We need to get access to all of the source IP strings so that we can convert them into + // a trie like we did for the destination IPs above. + for (auto& [server_name, transport_protocols_map] : *server_names_map_ptr) { + UNREFERENCED_PARAMETER(server_name); + for (auto& [transport_protocol, application_protocols_map] : transport_protocols_map) { + UNREFERENCED_PARAMETER(transport_protocol); + for (auto& [application_protocol, direct_source_ips_pair] : application_protocols_map) { + UNREFERENCED_PARAMETER(application_protocol); + auto& [direct_source_ips_map, direct_source_ips_trie] = direct_source_ips_pair; + + std::vector< + std::pair>> + direct_source_ips_list; + direct_source_ips_list.reserve(direct_source_ips_map.size()); + + for (auto& [direct_source_ip, source_arrays_ptr] : direct_source_ips_map) { + direct_source_ips_list.push_back( + makeCidrListEntry(direct_source_ip, source_arrays_ptr)); + + for (auto& [source_ips_map, source_ips_trie] : *source_arrays_ptr) { + std::vector< + std::pair>> + source_ips_list; + source_ips_list.reserve(source_ips_map.size()); + + for (auto& [source_ip, source_port_map_ptr] : source_ips_map) { + source_ips_list.push_back(makeCidrListEntry(source_ip, source_port_map_ptr)); + } + + source_ips_trie = std::make_unique(source_ips_list, true); } - - source_ips_trie = std::make_unique(source_ips_list, true); } + direct_source_ips_trie = + std::make_unique(direct_source_ips_list, true); } - direct_source_ips_trie = - std::make_unique(direct_source_ips_list, true); } } } - } - destination_ips_trie = std::make_unique(destination_ips_list, true); + destination_ips_trie = std::make_unique(destination_ips_list, true); + } } } diff --git a/source/server/filter_chain_manager_impl.h b/source/server/filter_chain_manager_impl.h index 6fc0509f663b3..5420ca4cc26ca 100644 --- a/source/server/filter_chain_manager_impl.h +++ b/source/server/filter_chain_manager_impl.h @@ -277,7 +277,18 @@ class FilterChainManagerImpl : public Network::FilterChainManager, using DestinationIPsTriePtr = std::unique_ptr; using DestinationPortsMap = absl::flat_hash_map>; + using ConnectionMetadataMap = absl::flat_hash_map; + void addFilterChainForConnectionMetadata( + ConnectionMetadataMap& connection_metadata_map, const std::string& connection_metadata, + uint16_t destination_port, const std::vector& destination_ips, + const absl::Span server_names, const std::string& transport_protocol, + const absl::Span application_protocols, + const std::vector& direct_source_ips, + const envoy::config::listener::v3::FilterChainMatch::ConnectionSourceType source_type, + const std::vector& source_ips, + const absl::Span source_ports, + const Network::FilterChainSharedPtr& filter_chain); void addFilterChainForDestinationPorts( DestinationPortsMap& destination_ports_map, uint16_t destination_port, const std::vector& destination_ips, @@ -334,6 +345,9 @@ class FilterChainManagerImpl : public Network::FilterChainManager, const Network::FilterChainSharedPtr& filter_chain); const Network::FilterChain* + findFilterChainForDestinationPort(const DestinationPortsMap& destination_ports_map, + const Network::ConnectionSocket& socket) const; + const Network::FilterChain* findFilterChainForDestinationIP(const DestinationIPsTrie& destination_ips_trie, const Network::ConnectionSocket& socket) const; const Network::FilterChain* @@ -372,7 +386,11 @@ class FilterChainManagerImpl : public Network::FilterChainManager, // Mapping of FilterChain's configured destination ports, IPs, server names, transport protocols // and application protocols, using structures defined above. - DestinationPortsMap destination_ports_map_; + // DestinationPortsMap destination_ports_map_; + + // Mapping of FilterChain's configured Connection Metadata, destination ports, IPs, server names, + // transport protocols and application protocols, using structures defined above. + ConnectionMetadataMap connection_metadata_map_; const Network::Address::InstanceConstSharedPtr address_; // This is the reference to a factory context which all the generations of listener share. diff --git a/test/common/http/header_map_impl_test.cc b/test/common/http/header_map_impl_test.cc index 1b95f4b49ad14..7813ff5c1874e 100644 --- a/test/common/http/header_map_impl_test.cc +++ b/test/common/http/header_map_impl_test.cc @@ -423,9 +423,8 @@ TEST_P(HeaderMapImplTest, AllInlineHeaders) { INLINE_REQ_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) } { - // No request trailer O(1) headers. - } - { + // No request trailer O(1) headers. + } { auto header_map = ResponseHeaderMapImpl::create(); INLINE_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) INLINE_REQ_RESP_STRING_HEADERS(TEST_INLINE_STRING_HEADER_FUNCS) diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 40e5c43edd2ad..8c0dc8b12ea6a 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -332,6 +332,8 @@ class MockConnectionSocket : public ConnectionSocket { MOCK_METHOD(absl::string_view, requestedServerName, (), (const)); MOCK_METHOD(void, setJA3Hash, (absl::string_view)); MOCK_METHOD(absl::string_view, ja3Hash, (), (const)); + MOCK_METHOD(void, setConnectionMetadata, (absl::string_view)); + MOCK_METHOD(absl::string_view, connectionMetadata, (), (const)); MOCK_METHOD(void, addOption_, (const Socket::OptionConstSharedPtr&)); MOCK_METHOD(void, addOptions_, (const Socket::OptionsSharedPtr&)); MOCK_METHOD(const Network::ConnectionSocket::OptionsSharedPtr&, options, (), (const)); diff --git a/test/server/filter_chain_benchmark_test.cc b/test/server/filter_chain_benchmark_test.cc index e2d4a9b891e1d..de9f080fee03e 100644 --- a/test/server/filter_chain_benchmark_test.cc +++ b/test/server/filter_chain_benchmark_test.cc @@ -76,6 +76,7 @@ class MockConnectionSocket : public Network::ConnectionSocket { absl::string_view detectedTransportProtocol() const override { return transport_protocol_; } absl::string_view requestedServerName() const override { return server_name_; } absl::string_view ja3Hash() const override { return ja3_hash_; } + absl::string_view connectionMetadata() const override { return connection_metadata_; } const std::vector& requestedApplicationProtocols() const override { return application_protocols_; } @@ -111,6 +112,7 @@ class MockConnectionSocket : public Network::ConnectionSocket { const OptionsSharedPtr& options() const override { return options_; } void setRequestedServerName(absl::string_view) override {} void setJA3Hash(absl::string_view) override {} + void setConnectionMetadata(absl::string_view) override {} Api::SysCallIntResult bind(Network::Address::InstanceConstSharedPtr) override { return {0, 0}; } Api::SysCallIntResult listen(int) override { return {0, 0}; } Api::SysCallIntResult connect(const Network::Address::InstanceConstSharedPtr) override { @@ -136,6 +138,7 @@ class MockConnectionSocket : public Network::ConnectionSocket { std::shared_ptr connection_info_provider_; std::string server_name_; std::string ja3_hash_; + std::string connection_metadata_; std::string transport_protocol_; std::vector application_protocols_; }; diff --git a/test/server/filter_chain_manager_impl_test.cc b/test/server/filter_chain_manager_impl_test.cc index e62d8c399da0f..724535643cf42 100644 --- a/test/server/filter_chain_manager_impl_test.cc +++ b/test/server/filter_chain_manager_impl_test.cc @@ -66,13 +66,16 @@ class FilterChainManagerImplTest : public testing::Test { } const Network::FilterChain* - findFilterChainHelper(uint16_t destination_port, const std::string& destination_address, - const std::string& server_name, const std::string& transport_protocol, + findFilterChainHelper(const std::string& connection_metadata, uint16_t destination_port, + const std::string& destination_address, const std::string& server_name, + const std::string& transport_protocol, const std::vector& application_protocols, const std::string& source_address, uint16_t source_port) { auto mock_socket = std::make_shared>(); sockets_.push_back(mock_socket); + mock_socket->connection_info_provider_->setConnectionMetadata(connection_metadata); + if (absl::StartsWith(destination_address, "/")) { local_address_ = std::make_shared(destination_address); } else { @@ -143,24 +146,25 @@ class FilterChainManagerImplTest : public testing::Test { }; TEST_F(FilterChainManagerImplTest, FilterChainMatchNothing) { - auto filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChainHelper("", 10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); } TEST_F(FilterChainManagerImplTest, FilterChainMatchCaseInSensitive) { envoy::config::listener::v3::FilterChain new_filter_chain = filter_chain_template_; + new_filter_chain.mutable_filter_chain_match()->set_connection_metadata("SOME_metadata"); new_filter_chain.mutable_filter_chain_match()->add_server_names("foo.EXAMPLE.com"); filter_chain_manager_.addFilterChains( std::vector{&new_filter_chain}, nullptr, filter_chain_factory_builder_, filter_chain_manager_); - auto filter_chain = - findFilterChainHelper(10000, "127.0.0.1", "FOO.example.com", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChainHelper("some_METADATA", 10000, "127.0.0.1", "FOO.example.com", + "tls", {}, "8.8.8.8", 111); EXPECT_NE(filter_chain, nullptr); } TEST_F(FilterChainManagerImplTest, AddSingleFilterChain) { addSingleFilterChainHelper(filter_chain_template_); - auto* filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto* filter_chain = findFilterChainHelper("", 10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_NE(filter_chain, nullptr); } @@ -173,10 +177,10 @@ TEST_F(FilterChainManagerImplTest, FilterChainUseFallbackIfNoFilterChainMatches) .RetiresOnSaturation(); addSingleFilterChainHelper(filter_chain_template_, &fallback_filter_chain_); - auto filter_chain = findFilterChainHelper(10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChainHelper("", 10000, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_NE(filter_chain, nullptr); auto fallback_filter_chain = - findFilterChainHelper(9999, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + findFilterChainHelper("", 9999, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(fallback_filter_chain, build_out_fallback_filter_chain_.get()); } diff --git a/test/server/listener_manager_impl_quic_only_test.cc b/test/server/listener_manager_impl_quic_only_test.cc index c60143bada353..21340a5fa894b 100644 --- a/test/server/listener_manager_impl_quic_only_test.cc +++ b/test/server/listener_manager_impl_quic_only_test.cc @@ -130,9 +130,9 @@ TEST_F(ListenerManagerImplQuicOnlyTest, QuicListenerFactoryAndSslContext) { EXPECT_EQ(udp_packet_writer->isBatchMode(), Api::OsSysCallsSingleton::get().supportsUdpGso()); // No filter chain found with non-matching transport protocol. - EXPECT_EQ(nullptr, findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111)); + EXPECT_EQ(nullptr, findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111)); - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "quic", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "quic", {}, "8.8.8.8", 111); ASSERT_NE(nullptr, filter_chain); auto& quic_socket_factory = dynamic_cast( filter_chain->transportSocketFactory()); diff --git a/test/server/listener_manager_impl_test.cc b/test/server/listener_manager_impl_test.cc index 69f7166ef1295..b75d4c7d60f80 100644 --- a/test/server/listener_manager_impl_test.cc +++ b/test/server/listener_manager_impl_test.cc @@ -281,7 +281,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TlsTransportSocket) { manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); EXPECT_EQ(1U, manager_->listeners().size()); - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); } @@ -299,7 +299,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, TransportSocketConnectTimeout) { EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, _, 0)); manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_EQ(filter_chain->transportSocketConnectTimeout(), std::chrono::seconds(3)); } @@ -2479,6 +2479,52 @@ TEST_F(ListenerManagerImplTest, EarlyShutdown) { manager_->stopWorkers(); } +TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithConnectionMetadataMatch) { + const std::string yaml = TestEnvironment::substitute(R"EOF( + address: + socket_address: { address: 127.0.0.1, port_value: 1234 } + listener_filters: + - name: "envoy.filters.listener.tls_inspector" + filter_chains: + - filter_chain_match: + connection_metadata: "some_metadata" + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } + private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } + )EOF", + Network::Address::IpVersion::v4); + + EXPECT_CALL(server_.api_.random_, uuid()); + EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, 0)); + manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + EXPECT_EQ(1U, manager_->listeners().size()); + + // TLS client connects to unknown connection metadata - no match. + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + EXPECT_EQ(filter_chain, nullptr); + + // TLS client without matching connection metadata - no match. + filter_chain = + findFilterChain("some_other_metadata", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + EXPECT_EQ(filter_chain, nullptr); + + // TLS client with matching connection metadata - using 1st filter chain. + filter_chain = findFilterChain("some_metadata", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + ASSERT_NE(filter_chain, nullptr); + EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); + auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); + auto ssl_socket = + dynamic_cast(transport_socket.get()); + auto server_names = ssl_socket->ssl()->dnsSansLocalCertificate(); + EXPECT_EQ(server_names.size(), 1); + EXPECT_EQ(server_names.front(), "server1.example.com"); +} + TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationPortMatch) { const std::string yaml = TestEnvironment::substitute(R"EOF( address: @@ -2505,11 +2551,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationP EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown port - no match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // IPv4 client connects to valid port - using 1st filter chain. - filter_chain = findFilterChain(8080, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + filter_chain = findFilterChain("", 8080, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2520,7 +2566,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationP EXPECT_EQ(server_names.front(), "server1.example.com"); // UDS client - no match. - filter_chain = findFilterChain(0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); + filter_chain = findFilterChain("", 0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); EXPECT_EQ(filter_chain, nullptr); } @@ -2551,11 +2597,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSource EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown IP - no match. - auto filter_chain = findFilterChain(1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111, "1.2.3.4"); + auto filter_chain = + findFilterChain("", 1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111, "1.2.3.4"); EXPECT_EQ(filter_chain, nullptr); // IPv4 client connects to valid IP - using 1st filter chain. - filter_chain = findFilterChain(1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111, "127.0.0.1"); + filter_chain = findFilterChain("", 1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111, "127.0.0.1"); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2566,7 +2613,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDirectSource EXPECT_EQ(server_names.front(), "server1.example.com"); // UDS client - no match. - filter_chain = findFilterChain(0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); + filter_chain = findFilterChain("", 0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); EXPECT_EQ(filter_chain, nullptr); } @@ -2596,11 +2643,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationI EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to unknown IP - no match. - auto filter_chain = findFilterChain(1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "1.2.3.4", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // IPv4 client connects to valid IP - using 1st filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2611,7 +2658,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithDestinationI EXPECT_EQ(server_names.front(), "server1.example.com"); // UDS client - no match. - filter_chain = findFilterChain(0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); + filter_chain = findFilterChain("", 0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); EXPECT_EQ(filter_chain, nullptr); } @@ -2641,16 +2688,17 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithServerNamesM EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI - no match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // TLS client without matching SNI - no match. - filter_chain = findFilterChain(1234, "127.0.0.1", "www.example.com", "tls", {}, "8.8.8.8", 111); + filter_chain = + findFilterChain("", 1234, "127.0.0.1", "www.example.com", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // TLS client with matching SNI - using 1st filter chain. filter_chain = - findFilterChain(1234, "127.0.0.1", "server1.example.com", "tls", {}, "8.8.8.8", 111); + findFilterChain("", 1234, "127.0.0.1", "server1.example.com", "tls", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2687,11 +2735,11 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithTransportPro EXPECT_EQ(1U, manager_->listeners().size()); // TCP client - no match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "raw_buffer", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "raw_buffer", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // TLS client - using 1st filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2729,12 +2777,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithApplicationP EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without ALPN - no match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // TLS client with "http/1.1" ALPN - using 1st filter chain. filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "8.8.8.8", 111); ASSERT_NE(filter_chain, nullptr); @@ -2774,12 +2822,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMa EXPECT_EQ(1U, manager_->listeners().size()); // EXTERNAL IPv4 client without "http/1.1" ALPN - no match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "8.8.8.8", 111); EXPECT_EQ(filter_chain, nullptr); // LOCAL IPv4 client with "http/1.1" ALPN - using 1st filter chain. filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); @@ -2793,7 +2841,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceTypeMa // LOCAL UDS client with "http/1.1" ALPN - using 1st filter chain. filter_chain = findFilterChain( - 0, "/tmp/test.sock", "", "tls", + "", 0, "/tmp/test.sock", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "/tmp/test.sock", 111); ASSERT_NE(filter_chain, nullptr); @@ -2834,12 +2882,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatc EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client with source 10.0.1.1. No match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "10.0.1.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "10.0.1.1", 111); EXPECT_EQ(filter_chain, nullptr); // IPv4 client with source 10.0.0.10, Match. filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "10.0.0.10", 111); ASSERT_NE(filter_chain, nullptr); @@ -2852,13 +2900,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpMatc EXPECT_EQ(server_names.front(), "server1.example.com"); // IPv6 client. No match. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", 111); EXPECT_EQ(filter_chain, nullptr); // UDS client. No match. filter_chain = findFilterChain( - 0, "/tmp/test.sock", "", "tls", + "", 0, "/tmp/test.sock", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "/tmp/test.sock", 0); ASSERT_EQ(filter_chain, nullptr); @@ -2893,12 +2941,12 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourceIpv6Ma EXPECT_EQ(1U, manager_->listeners().size()); // IPv6 client with matching subnet. Match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", 111); EXPECT_NE(filter_chain, nullptr); // IPv6 client with non-matching subnet. No match. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "2001:0db8:85a3:0001:0000:8a2e:0370:7334", 111); EXPECT_EQ(filter_chain, nullptr); } @@ -2931,7 +2979,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMa EXPECT_EQ(1U, manager_->listeners().size()); // Client with source port 100. Match. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 100); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 100); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -2943,7 +2991,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, SingleFilterChainWithSourcePortMa // Client with source port 101. No match. filter_chain = findFilterChain( - 1234, "8.8.8.8", "", "tls", + "", 1234, "8.8.8.8", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "4.4.4.4", 101); ASSERT_EQ(filter_chain, nullptr); @@ -2998,13 +3046,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType // LOCAL TLS client with "http/1.1" ALPN - no match. auto filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "127.0.0.1", 111); EXPECT_EQ(filter_chain, nullptr); // LOCAL TLS client without "http/1.1" ALPN - using 1st filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3016,7 +3064,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType // EXTERNAL TLS client with "http/1.1" ALPN - using 2nd filter chain. filter_chain = findFilterChain( - 1234, "8.8.8.8", "", "tls", + "", 1234, "8.8.8.8", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "4.4.4.4", 111); ASSERT_NE(filter_chain, nullptr); @@ -3027,7 +3075,95 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainWithSourceType EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // EXTERNAL TLS client without "http/1.1" ALPN - using 3rd filter chain. - filter_chain = findFilterChain(1234, "8.8.8.8", "", "tls", {}, "4.4.4.4", 111); + filter_chain = findFilterChain("", 1234, "8.8.8.8", "", "tls", {}, "4.4.4.4", 111); + ASSERT_NE(filter_chain, nullptr); + EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); + transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); + ssl_socket = dynamic_cast(transport_socket.get()); + server_names = ssl_socket->ssl()->dnsSansLocalCertificate(); + EXPECT_EQ(server_names.size(), 2); + EXPECT_EQ(server_names.front(), "*.example.com"); +} + +TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithConnectionMetadataMatch) { + const std::string yaml = TestEnvironment::substitute(R"EOF( + address: + socket_address: { address: 127.0.0.1, port_value: 1234 } + listener_filters: + - name: "envoy.filters.listener.tls_inspector" + filter_chains: + - filter_chain_match: + # empty + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_cert.pem" } + private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_uri_key.pem" } + session_ticket_keys: + keys: + - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" + - filter_chain_match: + connection_metadata: "some_metadata" + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_cert.pem" } + private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_dns_key.pem" } + session_ticket_keys: + keys: + - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" + - filter_chain_match: + connection_metadata: "some_other_metadata" + transport_socket: + name: tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + common_tls_context: + tls_certificates: + - certificate_chain: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_cert.pem" } + private_key: { filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/san_multiple_dns_key.pem" } + session_ticket_keys: + keys: + - filename: "{{ test_rundir }}/test/extensions/transport_sockets/tls/test_data/ticket_key_a" + )EOF", + Network::Address::IpVersion::v4); + + EXPECT_CALL(server_.api_.random_, uuid()); + EXPECT_CALL(listener_factory_, createListenSocket(_, _, _, default_bind_type, 0)); + manager_->addOrUpdateListener(parseListenerFromV3Yaml(yaml), "", true); + EXPECT_EQ(1U, manager_->listeners().size()); + + // TLS client without matching connection metadata - using 1st filter chain. + auto filter_chain = + findFilterChain("different_metadata", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + ASSERT_NE(filter_chain, nullptr); + EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); + auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); + auto ssl_socket = + dynamic_cast(transport_socket.get()); + auto uri = ssl_socket->ssl()->uriSanLocalCertificate(); + EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); + + // TLS client with some_metadata match - using 2nd filter chain. + filter_chain = + findFilterChain("some_metadata", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + ASSERT_NE(filter_chain, nullptr); + EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); + transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); + ssl_socket = dynamic_cast(transport_socket.get()); + auto server_names = ssl_socket->ssl()->dnsSansLocalCertificate(); + EXPECT_EQ(server_names.size(), 1); + EXPECT_EQ(server_names.front(), "server1.example.com"); + + // TLS client with some_other_metadata match - using 3rd filter chain. + filter_chain = + findFilterChain("some_other_metadata", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3083,7 +3219,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(1U, manager_->listeners().size()); // IPv4 client connects to default port - using 1st filter chain. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3093,7 +3229,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // IPv4 client connects to port 8080 - using 2nd filter chain. - filter_chain = findFilterChain(8080, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 8080, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3103,7 +3239,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(server_names.front(), "server1.example.com"); // IPv4 client connects to port 8081 - using 3rd filter chain. - filter_chain = findFilterChain(8081, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 8081, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3113,7 +3249,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(server_names.front(), "*.example.com"); // UDS client - using 1st filter chain. - filter_chain = findFilterChain(0, "/tmp/test.sock", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 0, "/tmp/test.sock", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3168,7 +3304,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(1U, manager_->listeners().size()); // UDS client connects - using 1st filter chain with no IP match - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3178,7 +3314,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // IPv4 client connects to default IP - using 1st filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3187,7 +3323,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // IPv4 client connects to exact IP match - using 2nd filter chain. - filter_chain = findFilterChain(1234, "192.168.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 1234, "192.168.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3197,7 +3333,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(server_names.front(), "server1.example.com"); // IPv4 client connects to wildcard IP match - using 3rd filter chain. - filter_chain = findFilterChain(1234, "192.168.1.1", "", "tls", {}, "192.168.1.1", 111); + filter_chain = findFilterChain("", 1234, "192.168.1.1", "", "tls", {}, "192.168.1.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3207,7 +3343,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDestinati EXPECT_EQ(server_names.front(), "*.example.com"); // UDS client - using 1st filter chain. - filter_chain = findFilterChain(0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); + filter_chain = findFilterChain("", 0, "/tmp/test.sock", "", "tls", {}, "/tmp/test.sock", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3263,7 +3399,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou EXPECT_EQ(1U, manager_->listeners().size()); // UDS client connects - using 1st filter chain with no IP match - auto filter_chain = findFilterChain(1234, "/uds_1", "", "tls", {}, "/uds_2", 111, "/uds_3"); + auto filter_chain = findFilterChain("", 1234, "/uds_1", "", "tls", {}, "/uds_2", 111, "/uds_3"); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3273,7 +3409,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // IPv4 client connects to default IP - using 1st filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "127.0.0.1"); + filter_chain = + findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "127.0.0.1"); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3282,7 +3419,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou EXPECT_EQ(uri[0], "spiffe://lyft.com/test-team"); // IPv4 client connects to exact IP match - using 2nd filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "192.168.0.1"); + filter_chain = + findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "192.168.0.1"); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3292,7 +3430,8 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithDirectSou EXPECT_EQ(server_names.front(), "server1.example.com"); // IPv4 client connects to wildcard IP match - using 3rd filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "192.168.1.1"); + filter_chain = + findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111, "192.168.1.1"); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3357,7 +3496,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI - using 1st filter chain. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3368,7 +3507,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam // TLS client with exact SNI match - using 2nd filter chain. filter_chain = - findFilterChain(1234, "127.0.0.1", "server1.example.com", "tls", {}, "127.0.0.1", 111); + findFilterChain("", 1234, "127.0.0.1", "server1.example.com", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3379,7 +3518,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam // TLS client with wildcard SNI match - using 3rd filter chain. filter_chain = - findFilterChain(1234, "127.0.0.1", "server2.example.com", "tls", {}, "127.0.0.1", 111); + findFilterChain("", 1234, "127.0.0.1", "server2.example.com", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3390,7 +3529,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithServerNam // TLS client with wildcard SNI match - using 3rd filter chain. filter_chain = - findFilterChain(1234, "127.0.0.1", "www.wildcard.com", "tls", {}, "127.0.0.1", 111); + findFilterChain("", 1234, "127.0.0.1", "www.wildcard.com", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3428,12 +3567,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithTransport EXPECT_EQ(1U, manager_->listeners().size()); // TCP client - using 1st filter chain. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "raw_buffer", {}, "127.0.0.1", 111); + auto filter_chain = + findFilterChain("", 1234, "127.0.0.1", "", "raw_buffer", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_FALSE(filter_chain->transportSocketFactory().implementsSecureTransport()); // TLS client - using 2nd filter chain. - filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_TRUE(filter_chain->transportSocketFactory().implementsSecureTransport()); auto transport_socket = filter_chain->transportSocketFactory().createTransportSocket(nullptr); @@ -3472,13 +3612,13 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithApplicati EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without ALPN - using 1st filter chain. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_FALSE(filter_chain->transportSocketFactory().implementsSecureTransport()); // TLS client with "h2,http/1.1" ALPN - using 2nd filter chain. filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); @@ -3521,18 +3661,18 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleR EXPECT_EQ(1U, manager_->listeners().size()); // TLS client without SNI and ALPN - using 1st filter chain. - auto filter_chain = findFilterChain(1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); + auto filter_chain = findFilterChain("", 1234, "127.0.0.1", "", "tls", {}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); EXPECT_FALSE(filter_chain->transportSocketFactory().implementsSecureTransport()); // TLS client with exact SNI match but without ALPN - no match (SNI blackholed by configuration). filter_chain = - findFilterChain(1234, "127.0.0.1", "server1.example.com", "tls", {}, "127.0.0.1", 111); + findFilterChain("", 1234, "127.0.0.1", "server1.example.com", "tls", {}, "127.0.0.1", 111); EXPECT_EQ(filter_chain, nullptr); // TLS client with ALPN match but without SNI - using 1st filter chain. filter_chain = findFilterChain( - 1234, "127.0.0.1", "", "tls", + "", 1234, "127.0.0.1", "", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); @@ -3540,7 +3680,7 @@ TEST_F(ListenerManagerImplWithRealFiltersTest, MultipleFilterChainsWithMultipleR // TLS client with exact SNI match and ALPN match - using 2nd filter chain. filter_chain = findFilterChain( - 1234, "127.0.0.1", "server1.example.com", "tls", + "", 1234, "127.0.0.1", "server1.example.com", "tls", {Http::Utility::AlpnNames::get().Http2, Http::Utility::AlpnNames::get().Http11}, "127.0.0.1", 111); ASSERT_NE(filter_chain, nullptr); diff --git a/test/server/listener_manager_impl_test.h b/test/server/listener_manager_impl_test.h index 6febd935efa37..1b1aca712a97a 100644 --- a/test/server/listener_manager_impl_test.h +++ b/test/server/listener_manager_impl_test.h @@ -183,8 +183,9 @@ class ListenerManagerImplTest : public testing::Test { } const Network::FilterChain* - findFilterChain(uint16_t destination_port, const std::string& destination_address, - const std::string& server_name, const std::string& transport_protocol, + findFilterChain(const std::string& connection_metadata, uint16_t destination_port, + const std::string& destination_address, const std::string& server_name, + const std::string& transport_protocol, const std::vector& application_protocols, const std::string& source_address, uint16_t source_port, std::string direct_source_address = "") { @@ -196,6 +197,8 @@ class ListenerManagerImplTest : public testing::Test { } socket_->connection_info_provider_->setLocalAddress(local_address_); + socket_->connection_info_provider_->setConnectionMetadata(connection_metadata); + ON_CALL(*socket_, requestedServerName()).WillByDefault(Return(absl::string_view(server_name))); ON_CALL(*socket_, detectedTransportProtocol()) .WillByDefault(Return(absl::string_view(transport_protocol)));