Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# 1. Determine SHA256 `wget https://github.com/envoyproxy/envoy/archive/$COMMIT.tar.gz && sha256sum $COMMIT.tar.gz`
# 2. Update .bazelversion, envoy.bazelrc and .bazelrc if needed.
#
# Commit date: 2026-01-20
ENVOY_SHA = "9c7136b8f8c559075fb7c76bcc7e0113b356a78a"
# Commit date: 2026-01-27
ENVOY_SHA = "450b21f19863373396d3c586437d3cb49c88486c"

ENVOY_SHA256 = "d83c1f66ec79a7b9d1ddabe1a36456d2915101c80b597cde0ec02f3fa0d4b49b"
ENVOY_SHA256 = "9365d37689c24c1de63f21c4fa6cae148fcc9e9721b69e72da64d2d5a4c2cae2"

ENVOY_ORG = "envoyproxy"

Expand Down
1 change: 0 additions & 1 deletion envoy.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ build:compile-time-options --define=log_debug_assert_in_release=enabled
build:compile-time-options --define=path_normalization_by_default=true
build:compile-time-options --define=deprecated_features=disabled
build:compile-time-options --define=tcmalloc=gperftools
build:compile-time-options --define=zlib=ng
build:compile-time-options --define=uhv=enabled
# gRPC has a lot of deprecated-enum-enum-conversion warnings with C++20
build:compile-time-options --copt=-Wno-error=deprecated-enum-enum-conversion
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.24.0
require (
github.com/cncf/xds/go v0.0.0-20251110193048-8bfbf64dc13e
github.com/envoyproxy/go-control-plane v0.14.1-0.20260103185439-d6ff64e48402
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260117034604-3a80eae751cf
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260124093652-ddecef433399
github.com/golang/protobuf v1.5.4
github.com/google/go-cmp v0.7.0
github.com/prometheus/client_model v0.6.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.14.1-0.20260103185439-d6ff64e48402 h1:Jm3kw/Enxm3pcwPwKpjNanZSVq6N/XyA0pkcLI9BVpk=
github.com/envoyproxy/go-control-plane v0.14.1-0.20260103185439-d6ff64e48402/go.mod h1:iuP4OVLgz85ISHlL+dS0cf6wg5cCz/KmuySk+g+F3uY=
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260117034604-3a80eae751cf h1:xZp0i/4HHESpsaPxpTy1am8g0JUFjw7JMR58ECOD7Qo=
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260117034604-3a80eae751cf/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260124093652-ddecef433399 h1:cTrEVtd48YOyrc24AcZHJGAxg8uvaYjqWlq1/QTp++U=
github.com/envoyproxy/go-control-plane/envoy v1.36.1-0.20260124093652-ddecef433399/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
Expand Down
35 changes: 32 additions & 3 deletions source/extensions/filters/http/peer_metadata/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,38 @@ class XDSMethod : public DiscoveryMethod {
public:
XDSMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context)
: downstream_(downstream),
metadata_provider_(Extensions::Common::WorkloadDiscovery::GetProvider(factory_context)) {}
metadata_provider_(Extensions::Common::WorkloadDiscovery::GetProvider(factory_context)),
local_info_(factory_context.localInfo()) {}
absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, Http::HeaderMap&,
Context&) const override;

private:
const bool downstream_;
Extensions::Common::WorkloadDiscovery::WorkloadMetadataProviderSharedPtr metadata_provider_;
const LocalInfo::LocalInfo& local_info_;
};

absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo& info,
Http::HeaderMap&, Context&) const {
Http::HeaderMap& headers, Context&) const {
if (!metadata_provider_) {
return {};
}
Network::Address::InstanceConstSharedPtr peer_address;
if (downstream_) {
peer_address = info.downstreamAddressProvider().remoteAddress();
const auto origin_network_header = headers.get(Headers::get().ExchangeMetadataOriginNetwork);
const auto& local_metadata = local_info_.node().metadata();
const auto& it = local_metadata.fields().find("NETWORK");
// We might not have a local network configured in the single cluster case, so default to empty.
auto local_network = it != local_metadata.fields().end() ? it->second.string_value() : "";
if (!origin_network_header.empty() &&
origin_network_header[0]->value().getStringView() != local_network) {
ENVOY_LOG_MISC(debug,
"Origin network header present: {}; skipping downstream workload discovery",
origin_network_header[0]->value().getStringView());
peer_address = {};
} else {
peer_address = info.downstreamAddressProvider().remoteAddress();
}
} else {
if (info.upstreamInfo().has_value()) {
auto upstream_host = info.upstreamInfo().value().get().upstreamHost();
Expand All @@ -64,6 +79,20 @@ absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo&
case Network::Address::Type::EnvoyInternal:
if (upstream_host->metadata()) {
const auto& filter_metadata = upstream_host->metadata()->filter_metadata();
const auto& istio_it = filter_metadata.find("istio");
if (istio_it != filter_metadata.end()) {
const auto& double_hbone_it = istio_it->second.fields().find("double_hbone");
// This is an E/W gateway endpoint, so we should explicitly not use workload discovery
if (double_hbone_it != istio_it->second.fields().end()) {
ENVOY_LOG_MISC(
debug,
"Skipping upstream workload discovery for an endpoint on a remote network");
peer_address = nullptr;
break;
}
} else {
ENVOY_LOG_MISC(debug, "No istio metadata found on upstream host.");
}
const auto& it = filter_metadata.find("envoy.filters.listener.original_dst");
if (it != filter_metadata.end()) {
const auto& destination_it = it->second.fields().find("local");
Expand Down
1 change: 1 addition & 0 deletions source/extensions/filters/http/peer_metadata/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct HeaderValues {
const Http::LowerCaseString Baggage{"baggage"};
const Http::LowerCaseString ExchangeMetadataHeader{"x-envoy-peer-metadata"};
const Http::LowerCaseString ExchangeMetadataHeaderId{"x-envoy-peer-metadata-id"};
const Http::LowerCaseString ExchangeMetadataOriginNetwork{"x-forwarded-network"};
};

using Headers = ConstSingleton<HeaderValues>;
Expand Down
65 changes: 65 additions & 0 deletions source/extensions/filters/http/peer_metadata/filter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,31 @@ TEST_F(PeerMetadataTest, DownstreamXDS) {
checkShared(false);
}

TEST_F(PeerMetadataTest, DownstreamXDSCrossNetwork) {
request_headers_.setReference(Headers::get().ExchangeMetadataOriginNetwork, "remote-network");
const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "default", "foo", "foo-service",
"v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "",
"");
EXPECT_CALL(*metadata_provider_, GetMetadata(_))
.WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address)
-> std::optional<WorkloadMetadataObject> {
if (absl::StartsWith(address->asStringView(), "127.0.0.1")) {
return {pod};
}
return {};
}));
initialize(R"EOF(
downstream_discovery:
- workload_discovery: {}
)EOF");
EXPECT_EQ(1, request_headers_.size()); // We don't remove the header because we terminate the
// tunnel that delivered it
EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true); // No downstream peer because it's a cross-network request
checkNoPeer(false);
checkShared(false);
}

TEST_F(PeerMetadataTest, UpstreamXDS) {
const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service",
"v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "",
Expand Down Expand Up @@ -210,6 +235,46 @@ TEST_F(PeerMetadataTest, UpstreamXDSInternal) {
checkPeerNamespace(false, "foo");
}

TEST_F(PeerMetadataTest, UpstreamXDSInternalCrossNetwork) {
Network::Address::InstanceConstSharedPtr upstream_address =
std::make_shared<Network::Address::EnvoyInternalInstance>("internal_address", "endpoint_id");
std::shared_ptr<NiceMock<Envoy::Upstream::MockHostDescription>> upstream_host(
new NiceMock<Envoy::Upstream::MockHostDescription>());
EXPECT_CALL(*upstream_host, address()).WillRepeatedly(Return(upstream_address));
stream_info_.upstreamInfo()->setUpstreamHost(upstream_host);
auto host_metadata = std::make_shared<envoy::config::core::v3::Metadata>();
ON_CALL(*upstream_host, metadata()).WillByDefault(testing::Return(host_metadata));
TestUtility::loadFromYaml(R"EOF(
filter_metadata:
envoy.filters.listener.original_dst:
local: 127.0.0.100:80
istio:
double_hbone:
hbone_target_address: 10.0.0.1
)EOF",
*host_metadata);

const WorkloadMetadataObject pod("pod-foo-1234", "my-cluster", "foo", "foo", "foo-service",
"v1alpha3", "", "", Istio::Common::WorkloadType::Pod, "", "",
"");
EXPECT_CALL(*metadata_provider_, GetMetadata(_))
.WillRepeatedly(Invoke([&](const Network::Address::InstanceConstSharedPtr& address)
-> std::optional<WorkloadMetadataObject> {
if (absl::StartsWith(address->asStringView(), "127.0.0.100")) {
return {pod};
}
return {};
}));
initialize(R"EOF(
upstream_discovery:
- workload_discovery: {}
)EOF");
EXPECT_EQ(0, request_headers_.size());
EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true);
checkNoPeer(false); // Shouldn't be any upstream filter state since it's a cross-network endpoint
}

TEST_F(PeerMetadataTest, DownstreamMXEmpty) {
initialize(R"EOF(
downstream_discovery:
Expand Down