Compare commits

...

67 Commits

Author SHA1 Message Date
Istio Automation 06da92fd5c
Automator: update envoy@ in istio/proxy@release-1.19 (#5440) 2024-04-04 17:57:35 -07:00
Istio Automation 9b2eb4ea8c
Automator: update envoy@ in istio/proxy@release-1.19 (#5431) 2024-04-02 19:07:07 -07:00
Istio Automation 7160620e52
Automator: update envoy@ in istio/proxy@release-1.19 (#5388) 2024-03-06 16:14:26 -08:00
Istio Automation 1b19a2a500
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5386) 2024-03-05 23:34:13 -08:00
Istio Automation 1eeb3a6180
Automator: update envoy@ in istio/proxy@release-1.19 (#5380) 2024-03-05 14:29:20 -08:00
Istio Automation 1716984e9e
Automator: update envoy@ in istio/proxy@release-1.19 (#5374) 2024-03-03 16:35:37 -08:00
Istio Automation 71e077cbc1
fips: force stackdriver to use TLSv1.2 (#5342)
Change-Id: Icd1cd577c039512bb90234642719a8b5d3523567

Signed-off-by: Kuat Yessenov <kuat@google.com>
Co-authored-by: Kuat Yessenov <kuat@google.com>
2024-02-17 03:26:51 -08:00
Istio Automation df03234fbb
Automator: update envoy@ in istio/proxy@release-1.19 (#5330) 2024-02-14 06:39:25 -08:00
Istio Automation 188e4b578d
Automator: update envoy@ in istio/proxy@release-1.19 (#5318) 2024-02-11 01:41:53 -08:00
Istio Automation 5f73db68b7
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5316) 2024-02-09 20:49:54 -08:00
Istio Automation 71cd58c6ac
Automator: update envoy@ in istio/proxy@release-1.19 (#5309) 2024-02-08 07:07:25 -08:00
Istio Automation ae80069bcb
Automator: update envoy@ in istio/proxy@release-1.19 (#5271) 2024-01-18 15:25:48 -08:00
Istio Automation 3cdaab0719
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5256) 2024-01-09 19:44:33 -08:00
Istio Automation 38b08e6452
Automator: update envoy@ in istio/proxy@release-1.19 (#5253) 2024-01-09 14:12:43 -08:00
Istio Automation 802428003a
Automator: update envoy@ in istio/proxy@release-1.19 (#5245) 2024-01-04 19:47:58 -08:00
Istio Automation dd4d22e6eb
Automator: update envoy@ in istio/proxy@release-1.19 (#5240) 2024-01-03 20:59:06 -08:00
Istio Automation 97afdc41e0
stats: fix memory leak in periodic reporting (#5221)
Change-Id: Ibd473bb14c51786c34f2d459ce5e1eea675e3d13

Signed-off-by: Kuat Yessenov <kuat@google.com>
Co-authored-by: Kuat Yessenov <kuat@google.com>
2023-12-20 00:06:38 -08:00
Istio Automation eb790e43d4
Automator: update envoy@ in istio/proxy@release-1.19 (#5216) 2023-12-19 17:57:48 -08:00
Istio Automation 7fc1e3be58
Automator: update envoy@ in istio/proxy@release-1.19 (#5211) 2023-12-16 08:20:47 -08:00
Istio Automation d475eda090
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5191) 2023-12-05 18:53:59 -08:00
zirain 37bf2b4817
enable zstd (#5179) 2023-11-29 18:27:15 -08:00
Istio Automation 25a358d473
Automator: update envoy@ in istio/proxy@release-1.19 (#5162) 2023-11-21 16:01:50 -08:00
Istio Automation 74d77fd3aa
Automator: update envoy@ in istio/proxy@release-1.19 (#5152) 2023-11-16 14:07:05 -08:00
zirain d839f09467
enable grpc_field_extraction filter (#5147) 2023-11-14 21:47:03 -08:00
Istio Automation f9707e29aa
Automator: update envoy@ in istio/proxy@release-1.19 (#5136) 2023-11-08 14:08:04 -08:00
Istio Automation c72a000d15
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5132) 2023-11-07 20:33:32 -08:00
Istio Automation 6709b394a4
fix update_envoy.sh (#5106)
Co-authored-by: zirain <zirain2009@gmail.com>
2023-10-31 09:01:29 -07:00
Istio Automation fb5e034fbc
Automator: update envoy@ in istio/proxy@release-1.19 (#5100) 2023-10-28 12:28:30 -07:00
Istio Automation 2e47601ff2
Automator: update envoy@ in istio/proxy@release-1.19 (#5096) 2023-10-25 15:03:27 -07:00
Istio Automation 6a145a6ace
Automator: update envoy@ in istio/proxy@release-1.19 (#5089) 2023-10-25 00:28:44 -07:00
Istio Automation 54f8fc4f97
[release-1.19] turn previously removed BAZEL_BIN_PATH in to target-specific variable to fix exportcache builds (#5091)
* add BAZEL_BIN_PATH back to fix builds

* add a target-specific variable for exportcache to set BAZEL_BIN_PATH only when calling the exportcache target

* remove the earlier definition of BAZEL_BIN_PATH

---------

Co-authored-by: Skyler Spaeth <skyler_spaeth@rapid7.com>
2023-10-24 18:27:43 -07:00
Istio Automation 517cd96513
Automator: update envoy@ in istio/proxy@release-1.19 (#5083) 2023-10-24 07:27:43 -07:00
Istio Automation a804636e5c
Automator: update envoy@ in istio/proxy@release-1.19 (#5067) 2023-10-19 20:48:27 -07:00
Istio Automation 9314f9ad2d
Automator: update envoy@ in istio/proxy@release-1.19 (#5060) 2023-10-19 01:24:09 -07:00
Istio Automation 33e880887a
Automator: update envoy@ in istio/proxy@release-1.19 (#5055) 2023-10-17 20:49:38 -07:00
Istio Automation cfed93480a
Automator: update envoy@ in istio/proxy@release-1.19 (#5049) 2023-10-16 15:01:38 -07:00
Istio Automation f413882189
Automator: update envoy@ in istio/proxy@release-1.19 (#5042) 2023-10-14 07:30:35 -07:00
Istio Automation 96f989cc74
enable connect_grpc_bridge filter (#5037)
Co-authored-by: zirain <zirain2009@gmail.com>
2023-10-14 06:05:34 -07:00
Istio Automation 11647e18d3
Automator: update envoy@ in istio/proxy@release-1.19 (#5033) 2023-10-12 20:29:33 -07:00
Istio Automation bdb31c9666
Automator: update envoy@ in istio/proxy@release-1.19 (#5030) 2023-10-11 17:28:41 -07:00
Istio Automation 4d518f8d51
add file system http cache filter (#5014)
Co-authored-by: zirain <zirain2009@gmail.com>
2023-10-10 18:49:30 -07:00
Istio Automation e9b7643ac1
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5024) 2023-10-10 17:44:56 -07:00
Istio Automation a1ff538a63
Automator: update envoy@ in istio/proxy@release-1.19 (#5019) 2023-10-10 14:54:46 -07:00
Istio Automation 0f19b5a369
Automator: update envoy@ in istio/proxy@release-1.19 (#5007) 2023-10-09 20:19:17 -07:00
Istio Automation 2891ae0979
Automator: update envoy@ in istio/proxy@release-1.19 (#4999) 2023-10-07 18:37:20 -07:00
Istio Automation ec466124d7
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#5000) 2023-10-06 18:52:18 -07:00
Kuat ed82e4b0fb
http mx: fix regression (#4990) (#4991)
* http mx: fix regression



* update test



---------

Signed-off-by: Kuat Yessenov <kuat@google.com>
2023-10-06 18:12:48 -07:00
Istio Automation db2e94f010
Automator: update envoy@ in istio/proxy@release-1.19 (#4986) 2023-10-03 20:44:35 -07:00
Istio Automation 103b0ac8fc
Automator: update envoy@ in istio/proxy@release-1.19 (#4963) 2023-09-20 18:54:02 -07:00
Istio Automation 0434620cc1
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#4936) 2023-09-07 00:16:55 -07:00
Greg Hanson 3b92829545
do not send mx headers for services out of mesh (#4895) (#4933)
* do not send mx headers for services out of mesh

* remove env var feature toggle, update config.proto

* move skip_external_clusters to IstioHeaders

* use bool value in cluster metadata

* formatting fixes

* add unit tests

* add unit tets for PassthroughCluster

* code review comments
2023-09-06 19:14:54 -07:00
Istio Automation 3ac8014570
Automator: update envoy@ in istio/proxy@release-1.19 (#4923) 2023-08-31 18:34:55 -07:00
Istio Automation 17c173b8ad
Automator: update envoy@ in istio/proxy@release-1.19 (#4913) 2023-08-25 06:44:57 -07:00
Istio Automation 31cf02691e
Automator: update envoy@ in istio/proxy@release-1.19 (#4906) 2023-08-22 20:04:51 -07:00
Istio Automation e78f346b66
Automator: update envoy@ in istio/proxy@release-1.19 (#4903) 2023-08-21 18:56:48 -07:00
Istio Automation c41b644613
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#4898) 2023-08-17 21:10:04 -07:00
Istio Automation e6816f641a
Fix skipping ALPN overwriting (#4890)
Signed-off-by: Jacek Ewertowski <jewertow@redhat.com>
Co-authored-by: Jacek Ewertowski <jewertow@redhat.com>
2023-08-11 03:32:04 -07:00
Istio Automation b954956ba1
[release-1.19] metadata_exchange: fix layered TCP/HTTP write conflict (#4887)
* metadata_exchange: fix layered TCP/HTTP write conflict

Signed-off-by: Kuat Yessenov <kuat@google.com>

* add test

Signed-off-by: Kuat Yessenov <kuat@google.com>

---------

Signed-off-by: Kuat Yessenov <kuat@google.com>
Co-authored-by: Kuat Yessenov <kuat@google.com>
2023-08-10 18:48:03 -07:00
Istio Automation beb639e84a
[release-1.19] metadata_exchange: stop waiting for data when upstream closes (#4880)
* metadata_exchange: stop waiting for data when upstream closes

* test/envoye2e: add errcheck in tcp driver

* metadata_exchange: reduce log severity in abort case

---------

Co-authored-by: Brenden Blanco <bblanco@vmware.com>
2023-08-09 19:37:03 -07:00
Istio Automation 01b89b4c43
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#4884) 2023-08-09 12:32:32 -07:00
Istio Automation 76e9677fb1
metadata exchange: fix cache data race (#4877)
Signed-off-by: Kuat Yessenov <kuat@google.com>
Co-authored-by: Kuat Yessenov <kuat@google.com>
2023-08-08 00:21:05 -07:00
Kalya Subramanian da2487b4c8
Use go-control-plane from last 1.27 cut (#4872)
Signed-off-by: Kalya Subramanian <kasubra@microsoft.com>
2023-08-07 19:38:04 -07:00
Istio Automation 6a20765e1f
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#4873) 2023-08-07 12:46:04 -07:00
Istio Automation d2bde2ec1b
Automator: update common-files@release-1.19 in istio/proxy@release-1.19 (#4867) 2023-08-04 11:07:09 -07:00
Istio Automation 467917862c
sync health_checkers extensions (#4863)
Co-authored-by: zirain <zirain2009@gmail.com>
2023-08-03 21:17:07 -07:00
Istio Automation 16a9e0b7fb
Automator: update envoy@ in istio/proxy@release-1.19 (#4864) 2023-08-03 17:32:07 -07:00
Eric Van Norman c5b8bd373e
[release-1.19] Automated branching step 4 (#4860) 2023-08-03 14:40:08 -07:00
30 changed files with 664 additions and 195 deletions

View File

@ -1 +1 @@
6.1.0 6.3.2

View File

@ -1,6 +1,6 @@
{ {
"name": "istio build-tools", "name": "istio build-tools",
"image": "gcr.io/istio-testing/build-tools:master-936207ec8823f21aa330a82c20649c6f9e2f7a22", "image": "gcr.io/istio-testing/build-tools:release-1.19-013f27a57a64f1d22f60c3dcb9b242cf4814065a",
"privileged": true, "privileged": true,
"remoteEnv": { "remoteEnv": {
"USE_GKE_GCLOUD_AUTH_PLUGIN": "True", "USE_GKE_GCLOUD_AUTH_PLUGIN": "True",

View File

@ -1 +1 @@
* @istio/wg-policies-and-telemetry-maintainers * @istio/release-managers-1-19

View File

@ -174,6 +174,7 @@ else
endif endif
# Used by build container to export the build output from the docker volume cache # Used by build container to export the build output from the docker volume cache
exportcache: BAZEL_BIN_PATH ?= $(shell bazel info $(BAZEL_BUILD_ARGS) $(BAZEL_CONFIG_CURRENT) bazel-bin)
exportcache: exportcache:
@mkdir -p /work/out/$(TARGET_OS)_$(TARGET_ARCH) @mkdir -p /work/out/$(TARGET_OS)_$(TARGET_ARCH)
@cp -a $(BAZEL_BIN_PATH)/envoy /work/out/$(TARGET_OS)_$(TARGET_ARCH) @cp -a $(BAZEL_BIN_PATH)/envoy /work/out/$(TARGET_OS)_$(TARGET_ARCH)

View File

@ -34,10 +34,10 @@ bind(
# 1. Determine SHA256 `wget https://github.com/envoyproxy/envoy/archive/$COMMIT.tar.gz && sha256sum $COMMIT.tar.gz` # 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. # 2. Update .bazelversion, envoy.bazelrc and .bazelrc if needed.
# #
# Commit date: 2023-07-31 # Commit date: 2024-04-04
ENVOY_SHA = "9b06b1b0c55bd61504ebae8b5897f89f6c898aed" ENVOY_SHA = "9134d6a65e5c2c714d503807eb31a8490471fc5f"
ENVOY_SHA256 = "968680005396de39358e57f2476bc9a4e027bdaf3d6a2acca6e794207b5c2cfa" ENVOY_SHA256 = "a60eaa0e6a2ffac6428777c4fe716444dc5fef5e885b5c50ab646112d35fc95d"
ENVOY_ORG = "envoyproxy" ENVOY_ORG = "envoyproxy"

View File

@ -35,6 +35,8 @@ ENVOY_EXTENSIONS = {
"envoy.compression.gzip.decompressor": "//source/extensions/compression/gzip/decompressor:config", "envoy.compression.gzip.decompressor": "//source/extensions/compression/gzip/decompressor:config",
"envoy.compression.brotli.compressor": "//source/extensions/compression/brotli/compressor:config", "envoy.compression.brotli.compressor": "//source/extensions/compression/brotli/compressor:config",
"envoy.compression.brotli.decompressor": "//source/extensions/compression/brotli/decompressor:config", "envoy.compression.brotli.decompressor": "//source/extensions/compression/brotli/decompressor:config",
"envoy.compression.zstd.compressor": "//source/extensions/compression/zstd/compressor:config",
"envoy.compression.zstd.decompressor": "//source/extensions/compression/zstd/decompressor:config",
# #
# gRPC Credentials Plugins # gRPC Credentials Plugins
@ -54,6 +56,9 @@ ENVOY_EXTENSIONS = {
# #
"envoy.health_checkers.redis": "//source/extensions/health_checkers/redis:config", "envoy.health_checkers.redis": "//source/extensions/health_checkers/redis:config",
"envoy.health_checkers.tcp": "//source/extensions/health_checkers/tcp:health_checker_lib",
"envoy.health_checkers.http": "//source/extensions/health_checkers/http:health_checker_lib",
"envoy.health_checkers.grpc": "//source/extensions/health_checkers/grpc:health_checker_lib",
# #
# Input Matchers # Input Matchers
@ -105,12 +110,15 @@ ENVOY_EXTENSIONS = {
"envoy.filters.http.compressor": "//source/extensions/filters/http/compressor:config", "envoy.filters.http.compressor": "//source/extensions/filters/http/compressor:config",
"envoy.filters.http.cors": "//source/extensions/filters/http/cors:config", "envoy.filters.http.cors": "//source/extensions/filters/http/cors:config",
"envoy.filters.http.composite": "//source/extensions/filters/http/composite:config", "envoy.filters.http.composite": "//source/extensions/filters/http/composite:config",
"envoy.filters.http.connect_grpc_bridge": "//source/extensions/filters/http/connect_grpc_bridge:config",
"envoy.filters.http.csrf": "//source/extensions/filters/http/csrf:config", "envoy.filters.http.csrf": "//source/extensions/filters/http/csrf:config",
"envoy.filters.http.decompressor": "//source/extensions/filters/http/decompressor:config", "envoy.filters.http.decompressor": "//source/extensions/filters/http/decompressor:config",
"envoy.filters.http.dynamic_forward_proxy": "//source/extensions/filters/http/dynamic_forward_proxy:config", "envoy.filters.http.dynamic_forward_proxy": "//source/extensions/filters/http/dynamic_forward_proxy:config",
"envoy.filters.http.ext_authz": "//source/extensions/filters/http/ext_authz:config", "envoy.filters.http.ext_authz": "//source/extensions/filters/http/ext_authz:config",
"envoy.filters.http.ext_proc": "//source/extensions/filters/http/ext_proc:config", "envoy.filters.http.ext_proc": "//source/extensions/filters/http/ext_proc:config",
"envoy.filters.http.fault": "//source/extensions/filters/http/fault:config", "envoy.filters.http.fault": "//source/extensions/filters/http/fault:config",
"envoy.filters.http.gcp_authn": "//source/extensions/filters/http/gcp_authn:config",
"envoy.filters.http.grpc_field_extraction": "//source/extensions/filters/http/grpc_field_extraction:config",
"envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config", "envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config",
"envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config", "envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config",
"envoy.filters.http.grpc_json_transcoder": "//source/extensions/filters/http/grpc_json_transcoder:config", "envoy.filters.http.grpc_json_transcoder": "//source/extensions/filters/http/grpc_json_transcoder:config",
@ -247,7 +255,8 @@ ENVOY_EXTENSIONS = {
# #
# CacheFilter plugins # CacheFilter plugins
# #
"envoy.extensions.http.cache.simple": "//source/extensions/http/cache/simple_http_cache:config", "envoy.extensions.http.cache.file_system_http_cache": "//source/extensions/http/cache/file_system_http_cache:config",
"envoy.extensions.http.cache.simple": "//source/extensions/http/cache/simple_http_cache:config",
# #
# Internal redirect predicates # Internal redirect predicates

View File

@ -1 +1 @@
3e7e4a6330e5a70608669a7bce30c737d961b36e bdb38aa251ecadf811809709d381eb2d8f62d9cf

View File

@ -91,7 +91,7 @@ mirror-licenses: mod-download-go
@license-lint --mirror @license-lint --mirror
TMP := $(shell mktemp -d -u) TMP := $(shell mktemp -d -u)
UPDATE_BRANCH ?= "master" UPDATE_BRANCH ?= "release-1.19"
BUILD_TOOLS_ORG ?= "istio" BUILD_TOOLS_ORG ?= "istio"

View File

@ -75,7 +75,7 @@ fi
TOOLS_REGISTRY_PROVIDER=${TOOLS_REGISTRY_PROVIDER:-gcr.io} TOOLS_REGISTRY_PROVIDER=${TOOLS_REGISTRY_PROVIDER:-gcr.io}
PROJECT_ID=${PROJECT_ID:-istio-testing} PROJECT_ID=${PROJECT_ID:-istio-testing}
if [[ "${IMAGE_VERSION:-}" == "" ]]; then if [[ "${IMAGE_VERSION:-}" == "" ]]; then
IMAGE_VERSION=master-936207ec8823f21aa330a82c20649c6f9e2f7a22 IMAGE_VERSION=release-1.19-013f27a57a64f1d22f60c3dcb9b242cf4814065a
fi fi
if [[ "${IMAGE_NAME:-}" == "" ]]; then if [[ "${IMAGE_NAME:-}" == "" ]]; then
IMAGE_NAME=build-tools IMAGE_NAME=build-tools

View File

@ -10,9 +10,11 @@
# Startup options cannot be selected via config. # Startup options cannot be selected via config.
startup --host_jvm_args=-Xmx3g startup --host_jvm_args=-Xmx3g
fetch --color=yes
run --color=yes run --color=yes
build --color=yes build --color=yes
build --jobs=HOST_CPUS-1
build --workspace_status_command="bash bazel/get_workspace_status" build --workspace_status_command="bash bazel/get_workspace_status"
build --incompatible_strict_action_env build --incompatible_strict_action_env
build --java_runtime_version=remotejdk_11 build --java_runtime_version=remotejdk_11
@ -40,6 +42,8 @@ build --action_env=BAZEL_FAKE_SCM_REVISION --host_action_env=BAZEL_FAKE_SCM_REVI
build --enable_platform_specific_config build --enable_platform_specific_config
build --test_summary=terse build --test_summary=terse
build:docs-ci --action_env=DOCS_RST_CHECK=1 --host_action_env=DOCS_RST_CHECK=1
# TODO(keith): Remove once these 2 are the default # TODO(keith): Remove once these 2 are the default
build --incompatible_config_setting_private_default_visibility build --incompatible_config_setting_private_default_visibility
build --incompatible_enforce_config_setting_visibility build --incompatible_enforce_config_setting_visibility
@ -69,8 +73,6 @@ build --@com_googlesource_googleurl//build_config:system_icu=0
# Common flags for sanitizers # Common flags for sanitizers
build:sanitizer --define tcmalloc=disabled build:sanitizer --define tcmalloc=disabled
build:sanitizer --linkopt -ldl build:sanitizer --linkopt -ldl
build:sanitizer --build_tag_filters=-no_san
build:sanitizer --test_tag_filters=-no_san
# Common flags for Clang # Common flags for Clang
build:clang --action_env=BAZEL_COMPILER=clang build:clang --action_env=BAZEL_COMPILER=clang
@ -90,6 +92,8 @@ build:asan --config=sanitizer
# ASAN install its signal handler, disable ours so the stacktrace will be printed by ASAN # ASAN install its signal handler, disable ours so the stacktrace will be printed by ASAN
build:asan --define signal_trace=disabled build:asan --define signal_trace=disabled
build:asan --define ENVOY_CONFIG_ASAN=1 build:asan --define ENVOY_CONFIG_ASAN=1
build:asan --build_tag_filters=-no_san
build:asan --test_tag_filters=-no_san
build:asan --copt -fsanitize=address,undefined build:asan --copt -fsanitize=address,undefined
build:asan --linkopt -fsanitize=address,undefined build:asan --linkopt -fsanitize=address,undefined
# vptr and function sanitizer are enabled in clang-asan if it is set up via bazel/setup_clang.sh. # vptr and function sanitizer are enabled in clang-asan if it is set up via bazel/setup_clang.sh.
@ -143,12 +147,15 @@ build:clang-tsan --copt -DEVENT__DISABLE_DEBUG_MODE
# https://github.com/abseil/abseil-cpp/issues/760 # https://github.com/abseil/abseil-cpp/issues/760
# https://github.com/google/sanitizers/issues/953 # https://github.com/google/sanitizers/issues/953
build:clang-tsan --test_env="TSAN_OPTIONS=report_atomic_races=0" build:clang-tsan --test_env="TSAN_OPTIONS=report_atomic_races=0"
build:clang-tsan --test_timeout=120,600,1500,4800
# Clang MSAN - this is the base config for remote-msan and docker-msan. To run this config without # Clang MSAN - this is the base config for remote-msan and docker-msan. To run this config without
# our build image, follow https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo # our build image, follow https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo
# with libc++ instruction and provide corresponding `--copt` and `--linkopt` as well. # with libc++ instruction and provide corresponding `--copt` and `--linkopt` as well.
build:clang-msan --action_env=ENVOY_MSAN=1 build:clang-msan --action_env=ENVOY_MSAN=1
build:clang-msan --config=sanitizer build:clang-msan --config=sanitizer
build:clang-msan --build_tag_filters=-no_san
build:clang-msan --test_tag_filters=-no_san
build:clang-msan --define ENVOY_CONFIG_MSAN=1 build:clang-msan --define ENVOY_CONFIG_MSAN=1
build:clang-msan --copt -fsanitize=memory build:clang-msan --copt -fsanitize=memory
build:clang-msan --linkopt -fsanitize=memory build:clang-msan --linkopt -fsanitize=memory
@ -182,6 +189,7 @@ build --test_env=HEAPCHECK=normal --test_env=PPROF_PATH
# Coverage options # Coverage options
coverage --config=coverage coverage --config=coverage
coverage --build_tests_only coverage --build_tests_only
build:coverage --action_env=BAZEL_USE_LLVM_NATIVE_COVERAGE=1 build:coverage --action_env=BAZEL_USE_LLVM_NATIVE_COVERAGE=1
build:coverage --action_env=GCOV=llvm-profdata build:coverage --action_env=GCOV=llvm-profdata
build:coverage --copt=-DNDEBUG build:coverage --copt=-DNDEBUG
@ -190,20 +198,31 @@ build:coverage --test_timeout=390,750,1500,5700
build:coverage --define=dynamic_link_tests=true build:coverage --define=dynamic_link_tests=true
build:coverage --define=ENVOY_CONFIG_COVERAGE=1 build:coverage --define=ENVOY_CONFIG_COVERAGE=1
build:coverage --cxxopt="-DENVOY_CONFIG_COVERAGE=1" build:coverage --cxxopt="-DENVOY_CONFIG_COVERAGE=1"
build:coverage --coverage_support=@envoy//bazel/coverage:coverage_support
build:coverage --test_env=CC_CODE_COVERAGE_SCRIPT=bazel/coverage/collect_cc_coverage.sh
build:coverage --test_env=HEAPCHECK= build:coverage --test_env=HEAPCHECK=
build:coverage --combined_report=lcov build:coverage --combined_report=lcov
build:coverage --strategy=TestRunner=sandboxed,local build:coverage --strategy=TestRunner=remote,sandboxed,local
build:coverage --strategy=CoverageReport=sandboxed,local build:coverage --strategy=CoverageReport=sandboxed,local
build:coverage --experimental_use_llvm_covmap build:coverage --experimental_use_llvm_covmap
build:coverage --experimental_generate_llvm_lcov
build:coverage --experimental_split_coverage_postprocessing
build:coverage --experimental_fetch_all_coverage_outputs
build:coverage --collect_code_coverage build:coverage --collect_code_coverage
build:coverage --test_tag_filters=-nocoverage build:coverage --instrumentation_filter="^//source(?!/common/quic/platform)[/:],^//envoy[/:],^//contrib(?!/.*/test)[/:]"
build:coverage --instrumentation_filter="//source(?!/common/quic/platform)[/:],//envoy[/:],//contrib(?!/.*/test)[/:]" build:coverage --remote_download_minimal
build:coverage --define=tcmalloc=gperftools
build:coverage --define=no_debug_info=1
# `--no-relax` is required for coverage to not err with `relocation R_X86_64_REX_GOTPCRELX`
build:coverage --linkopt=-Wl,-s,--no-relax
build:coverage --test_env=ENVOY_IP_TEST_VERSIONS=v4only
build:test-coverage --test_arg="-l trace" build:test-coverage --test_arg="-l trace"
build:test-coverage --test_arg="--log-path /dev/null" build:test-coverage --test_arg="--log-path /dev/null"
build:test-coverage --test_tag_filters=-nocoverage,-fuzz_target
build:fuzz-coverage --config=plain-fuzzer build:fuzz-coverage --config=plain-fuzzer
build:fuzz-coverage --run_under=@envoy//bazel/coverage:fuzz_coverage_wrapper.sh build:fuzz-coverage --run_under=@envoy//bazel/coverage:fuzz_coverage_wrapper.sh
build:fuzz-coverage --test_tag_filters=-nocoverage
build:cache-local --remote_cache=grpc://localhost:9092
# Remote execution: https://docs.bazel.build/versions/master/remote-execution.html # Remote execution: https://docs.bazel.build/versions/master/remote-execution.html
build:rbe-toolchain --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 build:rbe-toolchain --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
@ -263,10 +282,6 @@ build:remote --spawn_strategy=remote,sandboxed,local
build:remote --strategy=Javac=remote,sandboxed,local build:remote --strategy=Javac=remote,sandboxed,local
build:remote --strategy=Closure=remote,sandboxed,local build:remote --strategy=Closure=remote,sandboxed,local
build:remote --strategy=Genrule=remote,sandboxed,local build:remote --strategy=Genrule=remote,sandboxed,local
build:remote --remote_timeout=7200
build:remote --google_default_credentials=true
build:remote --remote_download_toplevel
build:remote --nobuild_runfile_links
# Windows bazel does not allow sandboxed as a spawn strategy # Windows bazel does not allow sandboxed as a spawn strategy
build:remote-windows --spawn_strategy=remote,local build:remote-windows --spawn_strategy=remote,local
@ -306,9 +321,28 @@ build:remote-clang-cl --config=remote-windows
build:remote-clang-cl --config=clang-cl build:remote-clang-cl --config=clang-cl
build:remote-clang-cl --config=rbe-toolchain-clang-cl build:remote-clang-cl --config=rbe-toolchain-clang-cl
## Compile-time-options testing
# Right now, none of the available compile-time options conflict with each other. If this
# changes, this build type may need to be broken up.
build:compile-time-options --define=admin_html=disabled
build:compile-time-options --define=signal_trace=disabled
build:compile-time-options --define=hot_restart=disabled
build:compile-time-options --define=google_grpc=disabled
build:compile-time-options --define=boringssl=fips
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
build:compile-time-options --config=libc++20
build:compile-time-options --test_env=ENVOY_HAS_EXTRA_EXTENSIONS=true
build:compile-time-options --@envoy//bazel:http3=False
build:compile-time-options --@envoy//source/extensions/filters/http/kill_request:enabled
# Docker sandbox # Docker sandbox
# NOTE: Update this from https://github.com/envoyproxy/envoy-build-tools/blob/main/toolchains/rbe_toolchains_config.bzl#L8 # NOTE: Update this from https://github.com/envoyproxy/envoy-build-tools/blob/main/toolchains/rbe_toolchains_config.bzl#L8
build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:41c5a05d708972d703661b702a63ef5060125c33 build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:fdd65c6270a8507a18d5acd6cf19a18cb695e4fa@sha256:3c8a3ce6f90dcfb5d09dc8f79bb01404d3526d420061f9a176e0a8e91e1e573e
build:docker-sandbox --spawn_strategy=docker build:docker-sandbox --spawn_strategy=docker
build:docker-sandbox --strategy=Javac=docker build:docker-sandbox --strategy=Javac=docker
build:docker-sandbox --strategy=Closure=docker build:docker-sandbox --strategy=Closure=docker
@ -339,16 +373,13 @@ build:docker-tsan --config=rbe-toolchain-clang-libc++
build:docker-tsan --config=rbe-toolchain-tsan build:docker-tsan --config=rbe-toolchain-tsan
# CI configurations # CI configurations
build:remote-ci --remote_cache=grpcs://remotebuildexecution.googleapis.com
build:remote-ci --remote_executor=grpcs://remotebuildexecution.googleapis.com
build:remote-ci --config=ci build:remote-ci --config=ci
build:remote-ci --remote_download_minimal
# Note this config is used by mobile CI also. # Note this config is used by mobile CI also.
build:ci --noshow_progress build:ci --noshow_progress
build:ci --noshow_loading_progress build:ci --noshow_loading_progress
build:ci --test_output=errors
# Build Event Service
build:google-bes --bes_backend=grpcs://buildeventservice.googleapis.com
build:google-bes --bes_results_url=https://source.cloud.google.com/results/invocations/
# Fuzz builds # Fuzz builds
@ -439,6 +470,64 @@ build:windows --features=fully_static_link
build:windows --features=static_link_msvcrt build:windows --features=static_link_msvcrt
build:windows --dynamic_mode=off build:windows --dynamic_mode=off
# RBE (Google)
build:rbe-google --google_default_credentials=true
build:rbe-google --remote_cache=grpcs://remotebuildexecution.googleapis.com
build:rbe-google --remote_executor=grpcs://remotebuildexecution.googleapis.com
build:rbe-google --remote_timeout=7200
build:rbe-google --remote_instance_name=projects/envoy-ci/instances/default_instance
build:rbe-google-bes --bes_backend=grpcs://buildeventservice.googleapis.com
build:rbe-google-bes --bes_results_url=https://source.cloud.google.com/results/invocations/
# RBE (Engflow mobile)
build:rbe-engflow --google_default_credentials=false
build:rbe-engflow --remote_cache=grpcs://envoy.cluster.engflow.com
build:rbe-engflow --remote_executor=grpcs://envoy.cluster.engflow.com
build:rbe-engflow --bes_backend=grpcs://envoy.cluster.engflow.com/
build:rbe-engflow --bes_results_url=https://envoy.cluster.engflow.com/invocation/
build:rbe-engflow --credential_helper=*.engflow.com=%workspace%/bazel/engflow-bazel-credential-helper.sh
build:rbe-engflow --grpc_keepalive_time=30s
build:rbe-engflow --remote_timeout=3600s
build:rbe-engflow --bes_timeout=3600s
build:rbe-engflow --bes_upload_mode=fully_async
build:cache-envoy-engflow --google_default_credentials=false
build:cache-envoy-engflow --remote_cache=grpcs://morganite.cluster.engflow.com
build:cache-envoy-engflow --remote_timeout=3600s
build:cache-envoy-engflow --credential_helper=*.engflow.com=%workspace%/bazel/engflow-bazel-credential-helper.sh
build:cache-envoy-engflow --grpc_keepalive_time=30s
build:bes-envoy-engflow --bes_backend=grpcs://morganite.cluster.engflow.com/
build:bes-envoy-engflow --bes_results_url=https://morganite.cluster.engflow.com/invocation/
build:bes-envoy-engflow --bes_timeout=3600s
build:bes-envoy-engflow --bes_upload_mode=fully_async
build:rbe-envoy-engflow --config=cache-envoy-engflow
build:rbe-envoy-engflow --config=bes-envoy-engflow
build:rbe-envoy-engflow --remote_executor=grpcs://morganite.cluster.engflow.com
build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:fdd65c6270a8507a18d5acd6cf19a18cb695e4fa@sha256:3c8a3ce6f90dcfb5d09dc8f79bb01404d3526d420061f9a176e0a8e91e1e573e
#############################################################################
# debug: Various Bazel debugging flags
#############################################################################
# debug/bazel
common:debug-bazel --announce_rc
common:debug-bazel -s
# debug/sandbox
common:debug-sandbox --verbose_failures
common:debug-sandbox --sandbox_debug
# debug/coverage
common:debug-coverage --action_env=VERBOSE_COVERAGE=true
common:debug-coverage --test_env=VERBOSE_COVERAGE=true
common:debug-coverage --test_env=DISPLAY_LCOV_CMD=true
common:debug-coverage --config=debug-tests
# debug/tests
common:debug-tests --test_output=all
# debug/everything
common:debug --config=debug-bazel
common:debug --config=debug-sandbox
common:debug --config=debug-coverage
common:debug --config=debug-tests
try-import %workspace%/clang.bazelrc try-import %workspace%/clang.bazelrc
try-import %workspace%/user.bazelrc try-import %workspace%/user.bazelrc
try-import %workspace%/local_tsan.bazelrc try-import %workspace%/local_tsan.bazelrc

View File

@ -347,7 +347,7 @@ PeerNodeInfo::PeerNodeInfo(const std::string_view peer_metadata_id_key,
const std::string_view peer_metadata_key) { const std::string_view peer_metadata_key) {
// Attempt to read from filter_state first. // Attempt to read from filter_state first.
found_ = getValue({peer_metadata_id_key}, &peer_id_); found_ = getValue({peer_metadata_id_key}, &peer_id_);
if (found_ && peer_id_ != kMetadataNotFoundValue) { if (found_) {
if (getValue({peer_metadata_key}, &peer_node_)) { if (getValue({peer_metadata_key}, &peer_node_)) {
return; return;
} }
@ -355,6 +355,9 @@ PeerNodeInfo::PeerNodeInfo(const std::string_view peer_metadata_id_key,
// Sentinel value is preserved as ID to implement maybeWaiting. // Sentinel value is preserved as ID to implement maybeWaiting.
found_ = false; found_ = false;
if (getValue({kMetadataNotFoundValue}, &peer_id_)) {
peer_id_ = kMetadataNotFoundValue;
}
// Downstream peer metadata will never be in localhost endpoint. Skip // Downstream peer metadata will never be in localhost endpoint. Skip
// looking for it. // looking for it.

View File

@ -32,8 +32,8 @@ constexpr std::string_view kUpstreamMetadataKey = "upstream_peer";
constexpr std::string_view kDownstreamMetadataIdKey = "downstream_peer_id"; constexpr std::string_view kDownstreamMetadataIdKey = "downstream_peer_id";
constexpr std::string_view kDownstreamMetadataKey = "downstream_peer"; constexpr std::string_view kDownstreamMetadataKey = "downstream_peer";
// Sentinel value assigned to peer metadata ID key, indicating that the peer // Sentinel key in the filter state, indicating that the peer metadata is
// metadata is absent. This is different from a missing peer metadata ID key // decidedly absent. This is different from a missing peer metadata ID key
// which could indicate that the metadata is not received yet. // which could indicate that the metadata is not received yet.
const std::string kMetadataNotFoundValue = "envoy.wasm.metadata_exchange.peer_unknown"; const std::string kMetadataNotFoundValue = "envoy.wasm.metadata_exchange.peer_unknown";

View File

@ -21,6 +21,7 @@
#include "extensions/stackdriver/common/constants.h" #include "extensions/stackdriver/common/constants.h"
#include "google/api/monitored_resource.pb.h" #include "google/api/monitored_resource.pb.h"
#include "grpcpp/grpcpp.h" #include "grpcpp/grpcpp.h"
#include "grpcpp/security/tls_certificate_provider.h"
namespace Extensions { namespace Extensions {
namespace Stackdriver { namespace Stackdriver {
@ -80,16 +81,19 @@ getStackdriverOptions(const Wasm::Common::FlatNode& local_node_info,
} }
} }
auto ssl_creds_options = grpc::SslCredentialsOptions(); grpc::experimental::TlsChannelCredentialsOptions tls_options;
tls_options.set_max_tls_version(grpc_tls_version::TLS1_2);
if (!stub_option.test_root_pem_path.empty()) { if (!stub_option.test_root_pem_path.empty()) {
std::ifstream file(stub_option.test_root_pem_path); std::ifstream file(stub_option.test_root_pem_path);
if (!file.fail()) { if (!file.fail()) {
std::stringstream file_string; std::stringstream file_string;
file_string << file.rdbuf(); file_string << file.rdbuf();
ssl_creds_options.pem_root_certs = file_string.str(); tls_options.set_certificate_provider(
std::make_shared<grpc::experimental::StaticDataCertificateProvider>(file_string.str()));
tls_options.watch_root_certs();
} }
} }
auto channel_creds = grpc::SslCredentials(ssl_creds_options); auto channel_creds = grpc::experimental::TlsCredentials(tls_options);
if (!stub_option.insecure_endpoint.empty()) { if (!stub_option.insecure_endpoint.empty()) {
auto channel = auto channel =

2
go.mod
View File

@ -7,7 +7,7 @@ require (
cloud.google.com/go/monitoring v1.13.0 cloud.google.com/go/monitoring v1.13.0
cloud.google.com/go/trace v1.9.0 cloud.google.com/go/trace v1.9.0
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4
github.com/envoyproxy/go-control-plane v0.11.2-0.20230726084335-b501c94cb61e github.com/envoyproxy/go-control-plane v0.11.2-0.20230725211550-11bfe846bcd4
github.com/golang/protobuf v1.5.3 github.com/golang/protobuf v1.5.3
github.com/google/go-cmp v0.5.9 github.com/google/go-cmp v0.5.9
github.com/prometheus/client_model v0.4.0 github.com/prometheus/client_model v0.4.0

2
go.sum
View File

@ -18,6 +18,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.11.2-0.20230725211550-11bfe846bcd4 h1:u4facp1hZe/ZmiAkiEFZmWAbg7s4+a5Z3tkz8Hg6I9w=
github.com/envoyproxy/go-control-plane v0.11.2-0.20230725211550-11bfe846bcd4/go.mod h1:djL+W7LURiPM8Szxc5/47R6qMRulOSkfsDLO1CaGUNM=
github.com/envoyproxy/go-control-plane v0.11.2-0.20230726084335-b501c94cb61e h1:HXKPsHR2TRMWMdbCqwWsWzNqml/+oMQO3zm5LhhoYOo= github.com/envoyproxy/go-control-plane v0.11.2-0.20230726084335-b501c94cb61e h1:HXKPsHR2TRMWMdbCqwWsWzNqml/+oMQO3zm5LhhoYOo=
github.com/envoyproxy/go-control-plane v0.11.2-0.20230726084335-b501c94cb61e/go.mod h1:djL+W7LURiPM8Szxc5/47R6qMRulOSkfsDLO1CaGUNM= github.com/envoyproxy/go-control-plane v0.11.2-0.20230726084335-b501c94cb61e/go.mod h1:djL+W7LURiPM8Szxc5/47R6qMRulOSkfsDLO1CaGUNM=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=

View File

@ -35,7 +35,7 @@ ENVOY_ORG="$(grep -Pom1 "^ENVOY_ORG = \"\K[a-zA-Z-]+" "${WORKSPACE}")"
ENVOY_REPO="$(grep -Pom1 "^ENVOY_REPO = \"\K[a-zA-Z-]+" "${WORKSPACE}")" ENVOY_REPO="$(grep -Pom1 "^ENVOY_REPO = \"\K[a-zA-Z-]+" "${WORKSPACE}")"
# get latest commit for specified org/repo # get latest commit for specified org/repo
LATEST_SHA="$(git ls-remote https://github.com/"${ENVOY_ORG}"/"${ENVOY_REPO}" "$UPDATE_BRANCH" | awk '{ print $1}')" LATEST_SHA="$(git ls-remote https://github.com/"${ENVOY_ORG}"/"${ENVOY_REPO}" "refs/heads/$UPDATE_BRANCH" | awk '{ print $1}')"
DATE=$(curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/"${ENVOY_ORG}""/""${ENVOY_REPO}"/commits/"${LATEST_SHA}" | jq '.commit.committer.date') DATE=$(curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/"${ENVOY_ORG}""/""${ENVOY_REPO}"/commits/"${LATEST_SHA}" | jq '.commit.committer.date')
DATE=$(echo "${DATE/\"/}" | cut -d'T' -f1) DATE=$(echo "${DATE/\"/}" | cut -d'T' -f1)

View File

@ -55,24 +55,6 @@ Http::Protocol AlpnFilterConfig::getHttpProtocol(
} }
Http::FilterHeadersStatus AlpnFilter::decodeHeaders(Http::RequestHeaderMap&, bool) { Http::FilterHeadersStatus AlpnFilter::decodeHeaders(Http::RequestHeaderMap&, bool) {
const auto upstream_info = decoder_callbacks_->streamInfo().upstreamInfo();
auto upstream_host = upstream_info ? upstream_info->upstreamHost() : nullptr;
if (upstream_host && upstream_host->metadata()) {
const auto& filter_metadata = upstream_host->metadata()->filter_metadata();
const auto& it = filter_metadata.find("istio");
if (it != filter_metadata.end()) {
const auto& alpn_it = it->second.fields().find("alpn_override");
if (alpn_it != it->second.fields().end()) {
const auto alpnOverrideMetadata = alpn_it->second.string_value();
if (alpnOverrideMetadata == "false") {
// Skip ALPN header rewrite
ENVOY_LOG(debug, "Skipping ALPN header rewrite because alpn_override metadata is false");
return Http::FilterHeadersStatus::Continue;
}
}
}
}
Router::RouteConstSharedPtr route = decoder_callbacks_->route(); Router::RouteConstSharedPtr route = decoder_callbacks_->route();
const Router::RouteEntry* route_entry; const Router::RouteEntry* route_entry;
if (!route || !(route_entry = route->routeEntry())) { if (!route || !(route_entry = route->routeEntry())) {
@ -87,6 +69,21 @@ Http::FilterHeadersStatus AlpnFilter::decodeHeaders(Http::RequestHeaderMap&, boo
return Http::FilterHeadersStatus::Continue; return Http::FilterHeadersStatus::Continue;
} }
const auto& filter_metadata = cluster->info()->metadata().filter_metadata();
const auto& istio = filter_metadata.find("istio");
if (istio != filter_metadata.end()) {
const auto& alpn_override = istio->second.fields().find("alpn_override");
if (alpn_override != istio->second.fields().end()) {
const auto alpn_override_value = alpn_override->second.string_value();
if (alpn_override_value == "false") {
// Skip ALPN header rewrite
ENVOY_LOG(debug,
"Skipping ALPN header rewrite because istio.alpn_override metadata is false");
return Http::FilterHeadersStatus::Continue;
}
}
}
auto protocols = auto protocols =
cluster->info()->upstreamHttpProtocol(decoder_callbacks_->streamInfo().protocol()); cluster->info()->upstreamHttpProtocol(decoder_callbacks_->streamInfo().protocol());
const auto& alpn_override = config_->alpnOverrides(protocols[0]); const auto& alpn_override = config_->alpnOverrides(protocols[0]);

View File

@ -169,28 +169,22 @@ TEST_F(AlpnFilterTest, EmptyOverrideAlpn) {
TEST_F(AlpnFilterTest, AlpnOverrideFalse) { TEST_F(AlpnFilterTest, AlpnOverrideFalse) {
NiceMock<StreamInfo::MockStreamInfo> stream_info; NiceMock<StreamInfo::MockStreamInfo> stream_info;
std::shared_ptr<NiceMock<StreamInfo::MockUpstreamInfo>> upstream_info( auto metadata = TestUtility::parseYaml<envoy::config::core::v3::Metadata>(R"EOF(
new NiceMock<StreamInfo::MockUpstreamInfo>());
std::shared_ptr<NiceMock<Envoy::Upstream::MockHostDescription>> upstream_host(
new NiceMock<Envoy::Upstream::MockHostDescription>());
auto metadata = std::make_shared<envoy::config::core::v3::Metadata>(
TestUtility::parseYaml<envoy::config::core::v3::Metadata>(
R"EOF(
filter_metadata: filter_metadata:
istio: istio:
alpn_override: "false" alpn_override: "false"
)EOF")); )EOF");
ON_CALL(callbacks_, streamInfo()).WillByDefault(ReturnRef(stream_info)); ON_CALL(callbacks_, streamInfo()).WillByDefault(ReturnRef(stream_info));
ON_CALL(stream_info, upstreamInfo()).WillByDefault(Return(upstream_info)); ON_CALL(cluster_manager_, getThreadLocalCluster(_)).WillByDefault(Return(fake_cluster_.get()));
ON_CALL(*upstream_info, upstreamHost()).WillByDefault(Return(upstream_host)); ON_CALL(*fake_cluster_, info()).WillByDefault(Return(cluster_info_));
ON_CALL(*upstream_host, metadata()).WillByDefault(Return(metadata)); ON_CALL(*cluster_info_, metadata()).WillByDefault(ReturnRef(metadata));
const AlpnOverrides alpn = {{Http::Protocol::Http10, {"foo", "bar"}}, const AlpnOverrides alpn = {{Http::Protocol::Http10, {"foo", "bar"}},
{Http::Protocol::Http11, {"baz"}}}; {Http::Protocol::Http11, {"baz"}}};
auto filter = makeAlpnOverrideFilter(alpn); auto filter = makeAlpnOverrideFilter(alpn);
EXPECT_CALL(callbacks_, route()).Times(0); EXPECT_CALL(*cluster_info_, upstreamHttpProtocol(_)).Times(0);
EXPECT_EQ(filter->decodeHeaders(headers_, false), Http::FilterHeadersStatus::Continue); EXPECT_EQ(filter->decodeHeaders(headers_, false), Http::FilterHeadersStatus::Continue);
} }

View File

@ -93,10 +93,8 @@ bool peerInfoRead(Reporter reporter, const StreamInfo::FilterState& filter_state
reporter == Reporter::ServerSidecar || reporter == Reporter::ServerGateway reporter == Reporter::ServerSidecar || reporter == Reporter::ServerGateway
? "wasm.downstream_peer_id" ? "wasm.downstream_peer_id"
: "wasm.upstream_peer_id"; : "wasm.upstream_peer_id";
const auto* object = return filter_state.hasDataWithName(filter_state_key) ||
filter_state.getDataReadOnly<Envoy::Extensions::Filters::Common::Expr::CelState>( filter_state.hasDataWithName("envoy.wasm.metadata_exchange.peer_unknown");
filter_state_key);
return object != nullptr;
} }
const Wasm::Common::FlatNode* peerInfo(Reporter reporter, const Wasm::Common::FlatNode* peerInfo(Reporter reporter,
@ -604,18 +602,21 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
// RAII for stream context propagation. // RAII for stream context propagation.
struct StreamOverrides : public Filters::Common::Expr::StreamActivation { struct StreamOverrides : public Filters::Common::Expr::StreamActivation {
StreamOverrides(Config& parent, Stats::StatNameDynamicPool& pool, StreamOverrides(Config& parent, Stats::StatNameDynamicPool& pool)
const StreamInfo::StreamInfo& info, : parent_(parent), pool_(pool) {}
const Http::RequestHeaderMap* request_headers = nullptr,
const Http::ResponseHeaderMap* response_headers = nullptr, void evaluate(const StreamInfo::StreamInfo& info,
const Http::ResponseTrailerMap* response_trailers = nullptr) const Http::RequestHeaderMap* request_headers = nullptr,
: parent_(parent) { const Http::ResponseHeaderMap* response_headers = nullptr,
const Http::ResponseTrailerMap* response_trailers = nullptr) {
evaluated_ = true;
if (parent_.metric_overrides_) { if (parent_.metric_overrides_) {
activation_info_ = &info; activation_info_ = &info;
activation_request_headers_ = request_headers; activation_request_headers_ = request_headers;
activation_response_headers_ = response_headers; activation_response_headers_ = response_headers;
activation_response_trailers_ = response_trailers; activation_response_trailers_ = response_trailers;
const auto& compiled_exprs = parent_.metric_overrides_->compiled_exprs_; const auto& compiled_exprs = parent_.metric_overrides_->compiled_exprs_;
expr_values_.clear();
expr_values_.reserve(compiled_exprs.size()); expr_values_.reserve(compiled_exprs.size());
for (size_t id = 0; id < compiled_exprs.size(); id++) { for (size_t id = 0; id < compiled_exprs.size(); id++) {
Protobuf::Arena arena; Protobuf::Arena arena;
@ -631,7 +632,7 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
} }
expr_values_.push_back(std::make_pair(Stats::StatName(), amount)); expr_values_.push_back(std::make_pair(Stats::StatName(), amount));
} else { } else {
expr_values_.push_back(std::make_pair(pool.add(string_value), 0)); expr_values_.push_back(std::make_pair(pool_.add(string_value), 0));
} }
} }
} }
@ -662,6 +663,7 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
void addCounter(Stats::StatName metric, const Stats::StatNameTagVector& tags, void addCounter(Stats::StatName metric, const Stats::StatNameTagVector& tags,
uint64_t amount = 1) { uint64_t amount = 1) {
ASSERT(evaluated_);
if (parent_.metric_overrides_) { if (parent_.metric_overrides_) {
if (parent_.metric_overrides_->drop_.contains(metric)) { if (parent_.metric_overrides_->drop_.contains(metric)) {
return; return;
@ -679,6 +681,7 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
void recordHistogram(Stats::StatName metric, Stats::Histogram::Unit unit, void recordHistogram(Stats::StatName metric, Stats::Histogram::Unit unit,
const Stats::StatNameTagVector& tags, uint64_t value) { const Stats::StatNameTagVector& tags, uint64_t value) {
ASSERT(evaluated_);
if (parent_.metric_overrides_) { if (parent_.metric_overrides_) {
if (parent_.metric_overrides_->drop_.contains(metric)) { if (parent_.metric_overrides_->drop_.contains(metric)) {
return; return;
@ -695,6 +698,7 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
} }
void recordCustomMetrics() { void recordCustomMetrics() {
ASSERT(evaluated_);
if (parent_.metric_overrides_) { if (parent_.metric_overrides_) {
for (const auto& [_, metric] : parent_.metric_overrides_->custom_metrics_) { for (const auto& [_, metric] : parent_.metric_overrides_->custom_metrics_) {
const auto tags = parent_.metric_overrides_->overrideTags(metric.name_, {}, expr_values_); const auto tags = parent_.metric_overrides_->overrideTags(metric.name_, {}, expr_values_);
@ -725,7 +729,9 @@ struct Config : public Logger::Loggable<Logger::Id::filter> {
} }
Config& parent_; Config& parent_;
Stats::StatNameDynamicPool& pool_;
std::vector<std::pair<Stats::StatName, uint64_t>> expr_values_; std::vector<std::pair<Stats::StatName, uint64_t>> expr_values_;
bool evaluated_{false};
}; };
void recordVersion() { void recordVersion() {
@ -760,7 +766,8 @@ class IstioStatsFilter : public Http::PassThroughFilter,
public Network::ConnectionCallbacks { public Network::ConnectionCallbacks {
public: public:
IstioStatsFilter(ConfigSharedPtr config) IstioStatsFilter(ConfigSharedPtr config)
: config_(config), context_(*config->context_), pool_(config->scope()->symbolTable()) { : config_(config), context_(*config->context_), pool_(config->scope()->symbolTable()),
stream_(*config_, pool_) {
tags_.reserve(25); tags_.reserve(25);
switch (config_->reporter()) { switch (config_->reporter()) {
case Reporter::ServerSidecar: case Reporter::ServerSidecar:
@ -813,23 +820,24 @@ public:
} }
populateFlagsAndConnectionSecurity(info); populateFlagsAndConnectionSecurity(info);
Config::StreamOverrides stream(*config_, pool_, info, request_headers, response_headers, // Evaluate the end stream override expressions for HTTP. This may change values for periodic
response_trailers); // metrics.
stream.addCounter(context_.requests_total_, tags_); stream_.evaluate(info, request_headers, response_headers, response_trailers);
stream_.addCounter(context_.requests_total_, tags_);
auto duration = info.requestComplete(); auto duration = info.requestComplete();
if (duration.has_value()) { if (duration.has_value()) {
stream.recordHistogram(context_.request_duration_milliseconds_, stream_.recordHistogram(context_.request_duration_milliseconds_,
Stats::Histogram::Unit::Milliseconds, tags_, Stats::Histogram::Unit::Milliseconds, tags_,
absl::FromChrono(duration.value()) / absl::Milliseconds(1)); absl::FromChrono(duration.value()) / absl::Milliseconds(1));
} }
auto meter = info.getDownstreamBytesMeter(); auto meter = info.getDownstreamBytesMeter();
if (meter) { if (meter) {
stream.recordHistogram(context_.request_bytes_, Stats::Histogram::Unit::Bytes, tags_, stream_.recordHistogram(context_.request_bytes_, Stats::Histogram::Unit::Bytes, tags_,
meter->wireBytesReceived()); meter->wireBytesReceived());
stream.recordHistogram(context_.response_bytes_, Stats::Histogram::Unit::Bytes, tags_, stream_.recordHistogram(context_.response_bytes_, Stats::Histogram::Unit::Bytes, tags_,
meter->wireBytesSent()); meter->wireBytesSent());
} }
stream.recordCustomMetrics(); stream_.recordCustomMetrics();
} }
// Network::ReadFilter // Network::ReadFilter
@ -877,6 +885,10 @@ private:
if (peer_read_ || end_stream) { if (peer_read_ || end_stream) {
populatePeerInfo(info, info.filterState()); populatePeerInfo(info, info.filterState());
} }
if (is_grpc_ && (peer_read_ || end_stream)) {
// For periodic HTTP metric, evaluate once when the peer info is read.
stream_.evaluate(decoder_callbacks_->streamInfo());
}
} }
if (is_grpc_ && (peer_read_ || end_stream)) { if (is_grpc_ && (peer_read_ || end_stream)) {
const auto* counters = const auto* counters =
@ -884,11 +896,10 @@ private:
.filterState() .filterState()
->getDataReadOnly<GrpcStats::GrpcStatsObject>("envoy.filters.http.grpc_stats"); ->getDataReadOnly<GrpcStats::GrpcStatsObject>("envoy.filters.http.grpc_stats");
if (counters) { if (counters) {
Config::StreamOverrides stream(*config_, pool_, decoder_callbacks_->streamInfo()); stream_.addCounter(context_.request_messages_total_, tags_,
stream.addCounter(context_.request_messages_total_, tags_, counters->request_message_count - request_message_count_);
counters->request_message_count - request_message_count_); stream_.addCounter(context_.response_messages_total_, tags_,
stream.addCounter(context_.response_messages_total_, tags_, counters->response_message_count - response_message_count_);
counters->response_message_count - response_message_count_);
request_message_count_ = counters->request_message_count; request_message_count_ = counters->request_message_count;
response_message_count_ = counters->response_message_count; response_message_count_ = counters->response_message_count;
} }
@ -906,7 +917,6 @@ private:
? *upstream_info->upstreamFilterState() ? *upstream_info->upstreamFilterState()
: info.filterState(); : info.filterState();
Config::StreamOverrides stream(*config_, pool_, info);
if (!peer_read_) { if (!peer_read_) {
peer_read_ = peerInfoRead(config_->reporter(), filter_state); peer_read_ = peerInfoRead(config_->reporter(), filter_state);
// Report connection open once peer info is read or connection is closed. // Report connection open once peer info is read or connection is closed.
@ -914,23 +924,25 @@ private:
populatePeerInfo(info, filter_state); populatePeerInfo(info, filter_state);
tags_.push_back({context_.request_protocol_, context_.tcp_}); tags_.push_back({context_.request_protocol_, context_.tcp_});
populateFlagsAndConnectionSecurity(info); populateFlagsAndConnectionSecurity(info);
stream.addCounter(context_.tcp_connections_opened_total_, tags_); // For TCP, evaluate only once immediately before emitting the first metric.
stream_.evaluate(info);
stream_.addCounter(context_.tcp_connections_opened_total_, tags_);
} }
} }
if (peer_read_ || end_stream) { if (peer_read_ || end_stream) {
auto meter = info.getDownstreamBytesMeter(); auto meter = info.getDownstreamBytesMeter();
if (meter) { if (meter) {
stream.addCounter(context_.tcp_sent_bytes_total_, tags_, stream_.addCounter(context_.tcp_sent_bytes_total_, tags_,
meter->wireBytesSent() - bytes_sent_); meter->wireBytesSent() - bytes_sent_);
bytes_sent_ = meter->wireBytesSent(); bytes_sent_ = meter->wireBytesSent();
stream.addCounter(context_.tcp_received_bytes_total_, tags_, stream_.addCounter(context_.tcp_received_bytes_total_, tags_,
meter->wireBytesReceived() - bytes_received_); meter->wireBytesReceived() - bytes_received_);
bytes_received_ = meter->wireBytesReceived(); bytes_received_ = meter->wireBytesReceived();
} }
} }
if (end_stream) { if (end_stream) {
stream.addCounter(context_.tcp_connections_closed_total_, tags_); stream_.addCounter(context_.tcp_connections_closed_total_, tags_);
stream.recordCustomMetrics(); stream_.recordCustomMetrics();
} }
} }
void onReportTimer() { void onReportTimer() {
@ -1196,6 +1208,8 @@ private:
bool is_grpc_{false}; bool is_grpc_{false};
uint64_t request_message_count_{0}; uint64_t request_message_count_{0};
uint64_t response_message_count_{0}; uint64_t response_message_count_{0};
// Custom expression values are evaluated at most twice: at the start and the end of the stream.
Config::StreamOverrides stream_;
}; };
} // namespace } // namespace

View File

@ -20,23 +20,26 @@ package io.istio.http.peer_metadata;
// Peer metadata provider filter. This filter encapsulates the discovery of the // Peer metadata provider filter. This filter encapsulates the discovery of the
// peer telemetry attributes for consumption by the telemetry filters. // peer telemetry attributes for consumption by the telemetry filters.
message Config { message Config {
// Use CONNECT baggage header encoding. // This method uses `baggage` header encoding.
message Baggage { message Baggage {
} }
// Use workload metadata xDS. Requires that the bootstrap extension is enabled. // This method uses the workload metadata xDS. Requires that the bootstrap extension is enabled.
// For downstream discovery, uses the remote address as the lookup key. // For downstream discovery, the remote address is the lookup key in xDS.
// For upstream discovery: // For upstream discovery:
// //
// * If the upstream host address is an IP, uses it as the lookup key; // * If the upstream host address is an IP, this IP is used as the lookup key;
// //
// * If the upstream host address is internal, uses the // * If the upstream host address is internal, uses the
// "filter_metadata.tunnel.destination" dynamic metadata value. // "filter_metadata.tunnel.destination" dynamic metadata value as the lookup key.
message WorkloadDiscovery { message WorkloadDiscovery {
} }
// Use Istio HTTP metadata exchange headers. Removes these headers if found. // This method uses Istio HTTP metadata exchange headers, e.g. `x-envoy-peer-metadata`. Removes these headers if found.
message IstioHeaders { message IstioHeaders {
// Strip x-envoy-peer-metadata and x-envoy-peer-metadata-id headers on HTTP requests to services outside the mesh.
// Detects upstream clusters with `istio` and `external` filter metadata fields
bool skip_external_clusters = 1;
} }
// An exhaustive list of the derivation methods. // An exhaustive list of the derivation methods.
@ -49,9 +52,11 @@ message Config {
} }
// The order of the derivation of the downstream peer metadata, in the precedence order. // The order of the derivation of the downstream peer metadata, in the precedence order.
// First successful lookup wins.
repeated DiscoveryMethod downstream_discovery = 1; repeated DiscoveryMethod downstream_discovery = 1;
// The order of the derivation of the upstream peer metadata, in the precedence order. // The order of the derivation of the upstream peer metadata, in the precedence order.
// First successful lookup wins.
repeated DiscoveryMethod upstream_discovery = 2; repeated DiscoveryMethod upstream_discovery = 2;
// An exhaustive list of the metadata propagation methods. // An exhaustive list of the metadata propagation methods.

View File

@ -56,8 +56,8 @@ using CelPrototypes = ConstSingleton<CelPrototypeValues>;
class BaggageMethod : public DiscoveryMethod { class BaggageMethod : public DiscoveryMethod {
public: public:
absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, Http::HeaderMap&,
Http::HeaderMap&) const override; Context&) const override;
}; };
class XDSMethod : public DiscoveryMethod { class XDSMethod : public DiscoveryMethod {
@ -65,28 +65,16 @@ public:
XDSMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context) XDSMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context)
: downstream_(downstream), : downstream_(downstream),
metadata_provider_(Extensions::Common::WorkloadDiscovery::GetProvider(factory_context)) {} metadata_provider_(Extensions::Common::WorkloadDiscovery::GetProvider(factory_context)) {}
absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, Http::HeaderMap&,
Http::HeaderMap&) const override; Context&) const override;
private: private:
const bool downstream_; const bool downstream_;
Extensions::Common::WorkloadDiscovery::WorkloadMetadataProviderSharedPtr metadata_provider_; Extensions::Common::WorkloadDiscovery::WorkloadMetadataProviderSharedPtr metadata_provider_;
}; };
class MXMethod : public DiscoveryMethod {
public:
absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&,
Http::HeaderMap&) const override;
void remove(Http::HeaderMap&) const override;
private:
absl::optional<PeerInfo> lookup(absl::string_view id, absl::string_view value) const;
mutable absl::flat_hash_map<std::string, std::string> cache_;
const int64_t max_peer_cache_size_{500};
};
absl::optional<PeerInfo> BaggageMethod::derivePeerInfo(const StreamInfo::StreamInfo&, absl::optional<PeerInfo> BaggageMethod::derivePeerInfo(const StreamInfo::StreamInfo&,
Http::HeaderMap& headers) const { Http::HeaderMap& headers, Context&) const {
const auto header_string = const auto header_string =
Http::HeaderUtility::getAllOfHeaderAsString(headers, Headers::get().Baggage); Http::HeaderUtility::getAllOfHeaderAsString(headers, Headers::get().Baggage);
const auto result = header_string.result(); const auto result = header_string.result();
@ -98,7 +86,7 @@ absl::optional<PeerInfo> BaggageMethod::derivePeerInfo(const StreamInfo::StreamI
} }
absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo& info, absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo& info,
Http::HeaderMap&) const { Http::HeaderMap&, Context&) const {
if (!metadata_provider_) { if (!metadata_provider_) {
return {}; return {};
} }
@ -140,12 +128,23 @@ absl::optional<PeerInfo> XDSMethod::derivePeerInfo(const StreamInfo::StreamInfo&
return {}; return {};
} }
MXMethod::MXMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context)
: downstream_(downstream), tls_(factory_context.threadLocal()) {
tls_.set([](Event::Dispatcher&) { return std::make_shared<MXCache>(); });
}
absl::optional<PeerInfo> MXMethod::derivePeerInfo(const StreamInfo::StreamInfo&, absl::optional<PeerInfo> MXMethod::derivePeerInfo(const StreamInfo::StreamInfo&,
Http::HeaderMap& headers) const { Http::HeaderMap& headers, Context& ctx) const {
const auto peer_id_header = headers.get(Headers::get().ExchangeMetadataHeaderId); const auto peer_id_header = headers.get(Headers::get().ExchangeMetadataHeaderId);
if (downstream_) {
ctx.request_peer_id_received_ = !peer_id_header.empty();
}
absl::string_view peer_id = absl::string_view peer_id =
peer_id_header.empty() ? "" : peer_id_header[0]->value().getStringView(); peer_id_header.empty() ? "" : peer_id_header[0]->value().getStringView();
const auto peer_info_header = headers.get(Headers::get().ExchangeMetadataHeader); const auto peer_info_header = headers.get(Headers::get().ExchangeMetadataHeader);
if (downstream_) {
ctx.request_peer_received_ = !peer_info_header.empty();
}
absl::string_view peer_info = absl::string_view peer_info =
peer_info_header.empty() ? "" : peer_info_header[0]->value().getStringView(); peer_info_header.empty() ? "" : peer_info_header[0]->value().getStringView();
if (!peer_info.empty()) { if (!peer_info.empty()) {
@ -162,9 +161,10 @@ void MXMethod::remove(Http::HeaderMap& headers) const {
absl::optional<PeerInfo> MXMethod::lookup(absl::string_view id, absl::string_view value) const { absl::optional<PeerInfo> MXMethod::lookup(absl::string_view id, absl::string_view value) const {
// This code is copied from: // This code is copied from:
// https://github.com/istio/proxy/blob/release-1.18/extensions/metadata_exchange/plugin.cc#L116 // https://github.com/istio/proxy/blob/release-1.18/extensions/metadata_exchange/plugin.cc#L116
auto& cache = tls_->cache_;
if (max_peer_cache_size_ > 0 && !id.empty()) { if (max_peer_cache_size_ > 0 && !id.empty()) {
auto it = cache_.find(id); auto it = cache.find(id);
if (it != cache_.end()) { if (it != cache.end()) {
return it->second; return it->second;
} }
} }
@ -177,17 +177,23 @@ absl::optional<PeerInfo> MXMethod::lookup(absl::string_view id, absl::string_vie
std::string out(reinterpret_cast<const char*>(fb.data()), fb.size()); std::string out(reinterpret_cast<const char*>(fb.data()), fb.size());
if (max_peer_cache_size_ > 0 && !id.empty()) { if (max_peer_cache_size_ > 0 && !id.empty()) {
// do not let the cache grow beyond max cache size. // do not let the cache grow beyond max cache size.
if (static_cast<uint32_t>(cache_.size()) > max_peer_cache_size_) { if (static_cast<uint32_t>(cache.size()) > max_peer_cache_size_) {
cache_.erase(cache_.begin(), std::next(cache_.begin(), max_peer_cache_size_ / 4)); cache.erase(cache.begin(), std::next(cache.begin(), max_peer_cache_size_ / 4));
} }
cache_.emplace(id, out); cache.emplace(id, out);
} }
return out; return out;
} }
MXPropagationMethod::MXPropagationMethod( MXPropagationMethod::MXPropagationMethod(
Server::Configuration::ServerFactoryContext& factory_context) bool downstream, Server::Configuration::ServerFactoryContext& factory_context,
: id_(factory_context.localInfo().node().id()) { const io::istio::http::peer_metadata::Config_IstioHeaders& istio_headers)
: downstream_(downstream), id_(factory_context.localInfo().node().id()),
value_(computeValue(factory_context)),
skip_external_clusters_(istio_headers.skip_external_clusters()) {}
std::string MXPropagationMethod::computeValue(
Server::Configuration::ServerFactoryContext& factory_context) const {
const auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct( const auto fb = ::Wasm::Common::extractNodeFlatBufferFromStruct(
factory_context.localInfo().node().metadata()); factory_context.localInfo().node().metadata());
google::protobuf::Struct metadata; google::protobuf::Struct metadata;
@ -195,12 +201,22 @@ MXPropagationMethod::MXPropagationMethod(
*flatbuffers::GetRoot<::Wasm::Common::FlatNode>(fb.data()), &metadata); *flatbuffers::GetRoot<::Wasm::Common::FlatNode>(fb.data()), &metadata);
std::string metadata_bytes; std::string metadata_bytes;
::Wasm::Common::serializeToStringDeterministic(metadata, &metadata_bytes); ::Wasm::Common::serializeToStringDeterministic(metadata, &metadata_bytes);
value_ = Base64::encode(metadata_bytes.data(), metadata_bytes.size()); return Base64::encode(metadata_bytes.data(), metadata_bytes.size());
} }
void MXPropagationMethod::inject(Http::HeaderMap& headers) const { void MXPropagationMethod::inject(const StreamInfo::StreamInfo& info, Http::HeaderMap& headers,
headers.setReference(Headers::get().ExchangeMetadataHeaderId, id_); Context& ctx) const {
headers.setReference(Headers::get().ExchangeMetadataHeader, value_); if (skip_external_clusters_) {
if (skipMXHeaders(info)) {
return;
}
}
if (!downstream_ || ctx.request_peer_id_received_) {
headers.setReference(Headers::get().ExchangeMetadataHeaderId, id_);
}
if (!downstream_ || ctx.request_peer_received_) {
headers.setReference(Headers::get().ExchangeMetadataHeader, value_);
}
} }
FilterConfig::FilterConfig(const io::istio::http::peer_metadata::Config& config, FilterConfig::FilterConfig(const io::istio::http::peer_metadata::Config& config,
@ -211,9 +227,9 @@ FilterConfig::FilterConfig(const io::istio::http::peer_metadata::Config& config,
upstream_discovery_( upstream_discovery_(
buildDiscoveryMethods(config.upstream_discovery(), false, factory_context)), buildDiscoveryMethods(config.upstream_discovery(), false, factory_context)),
downstream_propagation_( downstream_propagation_(
buildPropagationMethods(config.downstream_propagation(), factory_context)), buildPropagationMethods(config.downstream_propagation(), true, factory_context)),
upstream_propagation_( upstream_propagation_(
buildPropagationMethods(config.upstream_propagation(), factory_context)) {} buildPropagationMethods(config.upstream_propagation(), false, factory_context)) {}
std::vector<DiscoveryMethodPtr> FilterConfig::buildDiscoveryMethods( std::vector<DiscoveryMethodPtr> FilterConfig::buildDiscoveryMethods(
const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::DiscoveryMethod>& const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::DiscoveryMethod>&
@ -233,7 +249,8 @@ std::vector<DiscoveryMethodPtr> FilterConfig::buildDiscoveryMethods(
break; break;
case io::istio::http::peer_metadata::Config::DiscoveryMethod::MethodSpecifierCase:: case io::istio::http::peer_metadata::Config::DiscoveryMethod::MethodSpecifierCase::
kIstioHeaders: kIstioHeaders:
methods.push_back(std::make_unique<MXMethod>()); methods.push_back(
std::make_unique<MXMethod>(downstream, factory_context.getServerFactoryContext()));
break; break;
default: default:
break; break;
@ -245,15 +262,15 @@ std::vector<DiscoveryMethodPtr> FilterConfig::buildDiscoveryMethods(
std::vector<PropagationMethodPtr> FilterConfig::buildPropagationMethods( std::vector<PropagationMethodPtr> FilterConfig::buildPropagationMethods(
const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::PropagationMethod>& const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::PropagationMethod>&
config, config,
Server::Configuration::FactoryContext& factory_context) const { bool downstream, Server::Configuration::FactoryContext& factory_context) const {
std::vector<PropagationMethodPtr> methods; std::vector<PropagationMethodPtr> methods;
methods.reserve(config.size()); methods.reserve(config.size());
for (const auto& method : config) { for (const auto& method : config) {
switch (method.method_specifier_case()) { switch (method.method_specifier_case()) {
case io::istio::http::peer_metadata::Config::PropagationMethod::MethodSpecifierCase:: case io::istio::http::peer_metadata::Config::PropagationMethod::MethodSpecifierCase::
kIstioHeaders: kIstioHeaders:
methods.push_back( methods.push_back(std::make_unique<MXPropagationMethod>(
std::make_unique<MXPropagationMethod>(factory_context.getServerFactoryContext())); downstream, factory_context.getServerFactoryContext(), method.istio_headers()));
break; break;
default: default:
break; break;
@ -262,20 +279,20 @@ std::vector<PropagationMethodPtr> FilterConfig::buildPropagationMethods(
return methods; return methods;
} }
void FilterConfig::discoverDownstream(StreamInfo::StreamInfo& info, void FilterConfig::discoverDownstream(StreamInfo::StreamInfo& info, Http::RequestHeaderMap& headers,
Http::RequestHeaderMap& headers) const { Context& ctx) const {
discover(info, true, headers); discover(info, true, headers, ctx);
} }
void FilterConfig::discoverUpstream(StreamInfo::StreamInfo& info, void FilterConfig::discoverUpstream(StreamInfo::StreamInfo& info, Http::ResponseHeaderMap& headers,
Http::ResponseHeaderMap& headers) const { Context& ctx) const {
discover(info, false, headers); discover(info, false, headers, ctx);
} }
void FilterConfig::discover(StreamInfo::StreamInfo& info, bool downstream, void FilterConfig::discover(StreamInfo::StreamInfo& info, bool downstream, Http::HeaderMap& headers,
Http::HeaderMap& headers) const { Context& ctx) const {
for (const auto& method : downstream ? downstream_discovery_ : upstream_discovery_) { for (const auto& method : downstream ? downstream_discovery_ : upstream_discovery_) {
const auto result = method->derivePeerInfo(info, headers); const auto result = method->derivePeerInfo(info, headers, ctx);
if (result) { if (result) {
setFilterState(info, downstream, *result); setFilterState(info, downstream, *result);
break; break;
@ -286,43 +303,74 @@ void FilterConfig::discover(StreamInfo::StreamInfo& info, bool downstream,
} }
} }
void FilterConfig::injectDownstream(Http::ResponseHeaderMap& headers) const { void FilterConfig::injectDownstream(const StreamInfo::StreamInfo& info,
Http::ResponseHeaderMap& headers, Context& ctx) const {
for (const auto& method : downstream_propagation_) { for (const auto& method : downstream_propagation_) {
method->inject(headers); method->inject(info, headers, ctx);
} }
} }
void FilterConfig::injectUpstream(Http::RequestHeaderMap& headers) const { void FilterConfig::injectUpstream(const StreamInfo::StreamInfo& info,
Http::RequestHeaderMap& headers, Context& ctx) const {
for (const auto& method : upstream_propagation_) { for (const auto& method : upstream_propagation_) {
method->inject(headers); method->inject(info, headers, ctx);
} }
} }
void FilterConfig::setFilterState(StreamInfo::StreamInfo& info, bool downstream, void FilterConfig::setFilterState(StreamInfo::StreamInfo& info, bool downstream,
const std::string& value) const { const std::string& value) const {
auto node_info = std::make_unique<CelStateHashable>(CelPrototypes::get().NodeInfo); const absl::string_view key = downstream ? WasmDownstreamPeer : WasmUpstreamPeer;
node_info->setValue(value); if (!info.filterState()->hasDataWithName(key)) {
info.filterState()->setData(downstream ? WasmDownstreamPeer : WasmUpstreamPeer, auto node_info = std::make_unique<CelStateHashable>(CelPrototypes::get().NodeInfo);
std::move(node_info), StreamInfo::FilterState::StateType::Mutable, node_info->setValue(value);
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream()); info.filterState()->setData(
key, std::move(node_info), StreamInfo::FilterState::StateType::Mutable,
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream());
} else {
ENVOY_LOG(debug, "Duplicate peer metadata, skipping");
}
// This is needed because stats filter awaits for the prefix on the wire and checks for the key // This is needed because stats filter awaits for the prefix on the wire and checks for the key
// presence before emitting any telemetry. // presence before emitting any telemetry.
auto node_id = std::make_unique<Filters::Common::Expr::CelState>(CelPrototypes::get().NodeId); const absl::string_view id_key = downstream ? WasmDownstreamPeerID : WasmUpstreamPeerID;
node_id->setValue("unknown"); if (!info.filterState()->hasDataWithName(id_key)) {
info.filterState()->setData(downstream ? WasmDownstreamPeerID : WasmUpstreamPeerID, auto node_id = std::make_unique<Filters::Common::Expr::CelState>(CelPrototypes::get().NodeId);
std::move(node_id), StreamInfo::FilterState::StateType::Mutable, node_id->setValue("unknown");
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream()); info.filterState()->setData(
id_key, std::move(node_id), StreamInfo::FilterState::StateType::Mutable,
StreamInfo::FilterState::LifeSpan::FilterChain, sharedWithUpstream());
} else {
ENVOY_LOG(debug, "Duplicate peer id, skipping");
}
} }
Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, bool) { Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, bool) {
config_->discoverDownstream(decoder_callbacks_->streamInfo(), headers); config_->discoverDownstream(decoder_callbacks_->streamInfo(), headers, ctx_);
config_->injectUpstream(headers); config_->injectUpstream(decoder_callbacks_->streamInfo(), headers, ctx_);
return Http::FilterHeadersStatus::Continue; return Http::FilterHeadersStatus::Continue;
} }
bool MXPropagationMethod::skipMXHeaders(const StreamInfo::StreamInfo& info) const {
const auto& cluster_info = info.upstreamClusterInfo();
if (cluster_info && cluster_info.value()) {
const auto& cluster_name = cluster_info.value()->name();
if (cluster_name == "PassthroughCluster") {
return true;
}
const auto& filter_metadata = cluster_info.value()->metadata().filter_metadata();
const auto& it = filter_metadata.find("istio");
if (it != filter_metadata.end()) {
const auto& skip_mx = it->second.fields().find("external");
if (skip_mx != it->second.fields().end()) {
return skip_mx->second.bool_value();
}
}
}
return false;
}
Http::FilterHeadersStatus Filter::encodeHeaders(Http::ResponseHeaderMap& headers, bool) { Http::FilterHeadersStatus Filter::encodeHeaders(Http::ResponseHeaderMap& headers, bool) {
config_->discoverUpstream(decoder_callbacks_->streamInfo(), headers); config_->discoverUpstream(decoder_callbacks_->streamInfo(), headers, ctx_);
config_->injectDownstream(headers); config_->injectDownstream(decoder_callbacks_->streamInfo(), headers, ctx_);
return Http::FilterHeadersStatus::Continue; return Http::FilterHeadersStatus::Continue;
} }

View File

@ -43,44 +43,71 @@ using Headers = ConstSingleton<HeaderValues>;
// Peer info in the flatbuffers format. // Peer info in the flatbuffers format.
using PeerInfo = std::string; using PeerInfo = std::string;
struct Context {
bool request_peer_id_received_{false};
bool request_peer_received_{false};
};
// Base class for the discovery methods. First derivation wins but all methods perform removal. // Base class for the discovery methods. First derivation wins but all methods perform removal.
class DiscoveryMethod { class DiscoveryMethod {
public: public:
virtual ~DiscoveryMethod() = default; virtual ~DiscoveryMethod() = default;
virtual absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, virtual absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, Http::HeaderMap&,
Http::HeaderMap&) const PURE; Context&) const PURE;
virtual void remove(Http::HeaderMap&) const {} virtual void remove(Http::HeaderMap&) const {}
}; };
using DiscoveryMethodPtr = std::unique_ptr<DiscoveryMethod>; using DiscoveryMethodPtr = std::unique_ptr<DiscoveryMethod>;
class MXMethod : public DiscoveryMethod {
public:
MXMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context);
absl::optional<PeerInfo> derivePeerInfo(const StreamInfo::StreamInfo&, Http::HeaderMap&,
Context&) const override;
void remove(Http::HeaderMap&) const override;
private:
absl::optional<PeerInfo> lookup(absl::string_view id, absl::string_view value) const;
const bool downstream_;
struct MXCache : public ThreadLocal::ThreadLocalObject {
absl::flat_hash_map<std::string, std::string> cache_;
};
mutable ThreadLocal::TypedSlot<MXCache> tls_;
const int64_t max_peer_cache_size_{500};
};
// Base class for the propagation methods. // Base class for the propagation methods.
class PropagationMethod { class PropagationMethod {
public: public:
virtual ~PropagationMethod() = default; virtual ~PropagationMethod() = default;
virtual void inject(Http::HeaderMap&) const PURE; virtual void inject(const StreamInfo::StreamInfo&, Http::HeaderMap&, Context&) const PURE;
}; };
using PropagationMethodPtr = std::unique_ptr<PropagationMethod>; using PropagationMethodPtr = std::unique_ptr<PropagationMethod>;
class MXPropagationMethod : public PropagationMethod { class MXPropagationMethod : public PropagationMethod {
public: public:
MXPropagationMethod(Server::Configuration::ServerFactoryContext& factory_context); MXPropagationMethod(bool downstream, Server::Configuration::ServerFactoryContext& factory_context,
void inject(Http::HeaderMap&) const override; const io::istio::http::peer_metadata::Config_IstioHeaders&);
void inject(const StreamInfo::StreamInfo&, Http::HeaderMap&, Context&) const override;
private: private:
const bool downstream_;
std::string computeValue(Server::Configuration::ServerFactoryContext&) const;
const std::string id_; const std::string id_;
std::string value_; const std::string value_;
const bool skip_external_clusters_;
bool skipMXHeaders(const StreamInfo::StreamInfo&) const;
}; };
class FilterConfig { class FilterConfig : public Logger::Loggable<Logger::Id::filter> {
public: public:
FilterConfig(const io::istio::http::peer_metadata::Config&, FilterConfig(const io::istio::http::peer_metadata::Config&,
Server::Configuration::FactoryContext&); Server::Configuration::FactoryContext&);
void discoverDownstream(StreamInfo::StreamInfo&, Http::RequestHeaderMap&) const; void discoverDownstream(StreamInfo::StreamInfo&, Http::RequestHeaderMap&, Context&) const;
void discoverUpstream(StreamInfo::StreamInfo&, Http::ResponseHeaderMap&) const; void discoverUpstream(StreamInfo::StreamInfo&, Http::ResponseHeaderMap&, Context&) const;
void injectDownstream(Http::ResponseHeaderMap&) const; void injectDownstream(const StreamInfo::StreamInfo&, Http::ResponseHeaderMap&, Context&) const;
void injectUpstream(Http::RequestHeaderMap&) const; void injectUpstream(const StreamInfo::StreamInfo&, Http::RequestHeaderMap&, Context&) const;
private: private:
std::vector<DiscoveryMethodPtr> buildDiscoveryMethods( std::vector<DiscoveryMethodPtr> buildDiscoveryMethods(
@ -88,13 +115,13 @@ private:
bool downstream, Server::Configuration::FactoryContext&) const; bool downstream, Server::Configuration::FactoryContext&) const;
std::vector<PropagationMethodPtr> buildPropagationMethods( std::vector<PropagationMethodPtr> buildPropagationMethods(
const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::PropagationMethod>&, const Protobuf::RepeatedPtrField<io::istio::http::peer_metadata::Config::PropagationMethod>&,
Server::Configuration::FactoryContext&) const; bool downstream, Server::Configuration::FactoryContext&) const;
StreamInfo::StreamSharingMayImpactPooling sharedWithUpstream() const { StreamInfo::StreamSharingMayImpactPooling sharedWithUpstream() const {
return shared_with_upstream_ return shared_with_upstream_
? StreamInfo::StreamSharingMayImpactPooling::SharedWithUpstreamConnectionOnce ? StreamInfo::StreamSharingMayImpactPooling::SharedWithUpstreamConnectionOnce
: StreamInfo::StreamSharingMayImpactPooling::None; : StreamInfo::StreamSharingMayImpactPooling::None;
} }
void discover(StreamInfo::StreamInfo&, bool downstream, Http::HeaderMap&) const; void discover(StreamInfo::StreamInfo&, bool downstream, Http::HeaderMap&, Context&) const;
void setFilterState(StreamInfo::StreamInfo&, bool downstream, const std::string& value) const; void setFilterState(StreamInfo::StreamInfo&, bool downstream, const std::string& value) const;
const bool shared_with_upstream_; const bool shared_with_upstream_;
const std::vector<DiscoveryMethodPtr> downstream_discovery_; const std::vector<DiscoveryMethodPtr> downstream_discovery_;
@ -113,6 +140,7 @@ public:
private: private:
FilterConfigSharedPtr config_; FilterConfigSharedPtr config_;
Context ctx_;
}; };
class FilterConfigFactory : public Common::FactoryBase<io::istio::http::peer_metadata::Config> { class FilterConfigFactory : public Common::FactoryBase<io::istio::http::peer_metadata::Config> {

View File

@ -316,6 +316,24 @@ constexpr absl::string_view SampleIstioHeader =
"NWJjNzc4Ch8KDkFQUF9DT05UQUlORVJTEg0aC3Rlc3QsYm9uemFpChYKCU5BTUVTUEFDRRIJGgdkZWZhdWx0CjMKK1NUQU" "NWJjNzc4Ch8KDkFQUF9DT05UQUlORVJTEg0aC3Rlc3QsYm9uemFpChYKCU5BTUVTUEFDRRIJGgdkZWZhdWx0CjMKK1NUQU"
"NLRFJJVkVSX01PTklUT1JJTkdfRVhQT1JUX0lOVEVSVkFMX1NFQ1MSBBoCMjA"; "NLRFJJVkVSX01PTklUT1JJTkdfRVhQT1JUX0lOVEVSVkFMX1NFQ1MSBBoCMjA";
TEST(MXMethod, Cache) {
NiceMock<Server::Configuration::MockServerFactoryContext> context;
MXMethod method(true, context);
NiceMock<StreamInfo::MockStreamInfo> stream_info;
Http::TestRequestHeaderMapImpl request_headers;
const int32_t max = 1000;
for (int32_t run = 0; run < 3; run++) {
for (int32_t i = 0; i < max; i++) {
std::string id = absl::StrCat("test-", i);
request_headers.setReference(Headers::get().ExchangeMetadataHeaderId, id);
request_headers.setReference(Headers::get().ExchangeMetadataHeader, SampleIstioHeader);
Context ctx;
const auto result = method.derivePeerInfo(stream_info, request_headers, ctx);
EXPECT_TRUE(result.has_value());
}
}
}
TEST_F(PeerMetadataTest, DownstreamMX) { TEST_F(PeerMetadataTest, DownstreamMX) {
request_headers_.setReference(Headers::get().ExchangeMetadataHeaderId, "test-pod"); request_headers_.setReference(Headers::get().ExchangeMetadataHeaderId, "test-pod");
request_headers_.setReference(Headers::get().ExchangeMetadataHeader, SampleIstioHeader); request_headers_.setReference(Headers::get().ExchangeMetadataHeader, SampleIstioHeader);
@ -410,15 +428,31 @@ TEST_F(PeerMetadataTest, DownstreamMXPropagation) {
- istio_headers: {} - istio_headers: {}
)EOF"); )EOF");
EXPECT_EQ(0, request_headers_.size()); EXPECT_EQ(0, request_headers_.size());
EXPECT_EQ(2, response_headers_.size()); EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true); checkNoPeer(true);
checkNoPeer(false); checkNoPeer(false);
} }
TEST_F(PeerMetadataTest, DownstreamMXDiscoveryPropagation) {
request_headers_.setReference(Headers::get().ExchangeMetadataHeaderId, "test-pod");
request_headers_.setReference(Headers::get().ExchangeMetadataHeader, SampleIstioHeader);
initialize(R"EOF(
downstream_discovery:
- istio_headers: {}
downstream_propagation:
- istio_headers: {}
)EOF");
EXPECT_EQ(0, request_headers_.size());
EXPECT_EQ(2, response_headers_.size());
checkPeerNamespace(true, "default");
checkNoPeer(false);
}
TEST_F(PeerMetadataTest, UpstreamMXPropagation) { TEST_F(PeerMetadataTest, UpstreamMXPropagation) {
initialize(R"EOF( initialize(R"EOF(
upstream_propagation: upstream_propagation:
- istio_headers: {} - istio_headers:
skip_external_clusters: false
)EOF"); )EOF");
EXPECT_EQ(2, request_headers_.size()); EXPECT_EQ(2, request_headers_.size());
EXPECT_EQ(0, response_headers_.size()); EXPECT_EQ(0, response_headers_.size());
@ -426,6 +460,55 @@ TEST_F(PeerMetadataTest, UpstreamMXPropagation) {
checkNoPeer(false); checkNoPeer(false);
} }
TEST_F(PeerMetadataTest, UpstreamMXPropagationSkipNoMatch) {
initialize(R"EOF(
upstream_propagation:
- istio_headers:
skip_external_clusters: true
)EOF");
EXPECT_EQ(2, request_headers_.size());
EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true);
checkNoPeer(false);
}
TEST_F(PeerMetadataTest, UpstreamMXPropagationSkip) {
std::shared_ptr<Upstream::MockClusterInfo> cluster_info_{
std::make_shared<NiceMock<Upstream::MockClusterInfo>>()};
auto metadata = TestUtility::parseYaml<envoy::config::core::v3::Metadata>(R"EOF(
filter_metadata:
istio:
external: true
)EOF");
ON_CALL(stream_info_, upstreamClusterInfo()).WillByDefault(testing::Return(cluster_info_));
ON_CALL(*cluster_info_, metadata()).WillByDefault(ReturnRef(metadata));
initialize(R"EOF(
upstream_propagation:
- istio_headers:
skip_external_clusters: true
)EOF");
EXPECT_EQ(0, request_headers_.size());
EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true);
checkNoPeer(false);
}
TEST_F(PeerMetadataTest, UpstreamMXPropagationSkipPassthrough) {
std::shared_ptr<Upstream::MockClusterInfo> cluster_info_{
std::make_shared<NiceMock<Upstream::MockClusterInfo>>()};
cluster_info_->name_ = "PassthroughCluster";
ON_CALL(stream_info_, upstreamClusterInfo()).WillByDefault(testing::Return(cluster_info_));
initialize(R"EOF(
upstream_propagation:
- istio_headers:
skip_external_clusters: true
)EOF");
EXPECT_EQ(0, request_headers_.size());
EXPECT_EQ(0, response_headers_.size());
checkNoPeer(true);
checkNoPeer(false);
}
} // namespace } // namespace
} // namespace PeerMetadata } // namespace PeerMetadata
} // namespace HttpFilters } // namespace HttpFilters

View File

@ -69,7 +69,7 @@ MetadataExchangeConfig::MetadataExchangeConfig(const std::string& stat_prefix,
: scope_(scope), stat_prefix_(stat_prefix), protocol_(protocol), : scope_(scope), stat_prefix_(stat_prefix), protocol_(protocol),
filter_direction_(filter_direction), stats_(generateStats(stat_prefix, scope)) {} filter_direction_(filter_direction), stats_(generateStats(stat_prefix, scope)) {}
Network::FilterStatus MetadataExchangeFilter::onData(Buffer::Instance& data, bool) { Network::FilterStatus MetadataExchangeFilter::onData(Buffer::Instance& data, bool end_stream) {
switch (conn_state_) { switch (conn_state_) {
case Invalid: case Invalid:
FALLTHRU; FALLTHRU;
@ -103,6 +103,14 @@ Network::FilterStatus MetadataExchangeFilter::onData(Buffer::Instance& data, boo
case NeedMoreDataInitialHeader: { case NeedMoreDataInitialHeader: {
tryReadInitialProxyHeader(data); tryReadInitialProxyHeader(data);
if (conn_state_ == NeedMoreDataInitialHeader) { if (conn_state_ == NeedMoreDataInitialHeader) {
if (end_stream) {
// Upstream has entered a half-closed state, and will be sending no more data.
// Since this plugin would expect additional headers, but none is forthcoming,
// do not block the tcp_proxy downstream of us from draining the buffer.
ENVOY_LOG(debug, "Upstream closed early, aborting istio-peer-exchange");
conn_state_ = Invalid;
return Network::FilterStatus::Continue;
}
return Network::FilterStatus::StopIteration; return Network::FilterStatus::StopIteration;
} }
if (conn_state_ == Invalid) { if (conn_state_ == Invalid) {
@ -303,10 +311,7 @@ void MetadataExchangeFilter::getMetadata(google::protobuf::Struct* metadata) {
std::string MetadataExchangeFilter::getMetadataId() { return local_info_.node().id(); } std::string MetadataExchangeFilter::getMetadataId() { return local_info_.node().id(); }
void MetadataExchangeFilter::setMetadataNotFoundFilterState() { void MetadataExchangeFilter::setMetadataNotFoundFilterState() {
auto key = config_->filter_direction_ == FilterDirection::Downstream updatePeerId(::Wasm::Common::kMetadataNotFoundValue, ::Wasm::Common::kMetadataNotFoundValue);
? ::Wasm::Common::kDownstreamMetadataIdKey
: ::Wasm::Common::kUpstreamMetadataIdKey;
updatePeerId(toAbslStringView(key), ::Wasm::Common::kMetadataNotFoundValue);
} }
} // namespace MetadataExchange } // namespace MetadataExchange

View File

@ -61,7 +61,7 @@ func Get(port uint16, body string) *HTTPCall {
} }
} }
func (g *HTTPCall) Run(_ *Params) error { func (g *HTTPCall) Run(p *Params) error {
url := fmt.Sprintf("http://127.0.0.1:%d%v", g.Port, g.Path) url := fmt.Sprintf("http://127.0.0.1:%d%v", g.Port, g.Path)
if g.Timeout == 0 { if g.Timeout == 0 {
g.Timeout = DefaultTimeout g.Timeout = DefaultTimeout
@ -71,7 +71,11 @@ func (g *HTTPCall) Run(_ *Params) error {
return err return err
} }
for key, val := range g.RequestHeaders { for key, val := range g.RequestHeaders {
req.Header.Add(key, val) header, err := p.Fill(val)
if err != nil {
panic(err)
}
req.Header.Add(key, header)
} }
if len(g.Authority) > 0 { if len(g.Authority) > 0 {
req.Host = g.Authority req.Host = g.Authority

View File

@ -21,6 +21,7 @@ import (
"io" "io"
"log" "log"
"net" "net"
"strings"
"time" "time"
) )
@ -131,3 +132,92 @@ func (t *TCPConnection) Run(p *Params) error {
} }
func (t *TCPConnection) Cleanup() {} func (t *TCPConnection) Cleanup() {}
// TCPServerAcceptAndClose implements a TCP server
// which accepts the data and then closes the connection
// immediately without any response.
//
// The exception from this description is the "ping" data
// which is handled differently for checking if the server
// is already up.
type TCPServerAcceptAndClose struct {
lis net.Listener
}
var _ Step = &TCPServerAcceptAndClose{}
func (t *TCPServerAcceptAndClose) Run(p *Params) error {
var err error
t.lis, err = net.Listen("tcp", fmt.Sprintf(":%d", p.Ports.BackendPort))
if err != nil {
return fmt.Errorf("failed to listen on %v", err)
}
go t.serve()
if err = waitForTCPServer(p.Ports.BackendPort); err != nil {
return err
}
return nil
}
func (t *TCPServerAcceptAndClose) Cleanup() {
t.lis.Close()
}
func (t *TCPServerAcceptAndClose) serve() {
for {
conn, err := t.lis.Accept()
if err != nil {
return
}
go t.handleConnection(conn)
}
}
func (t *TCPServerAcceptAndClose) handleConnection(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
bytes, err := reader.ReadString('\n')
if err != nil {
if err != io.EOF {
log.Println("failed to read data, err:", err)
}
return
}
bytes = strings.TrimSpace(bytes)
if strings.HasSuffix(bytes, "ping") {
log.Println("pinged - the TCP Server is available")
_, _ = conn.Write([]byte("alive\n"))
}
log.Println("received data. Closing the connection")
}
// InterceptedTCPConnection is a connection which expects
// the terminated connection (before the timeout occurs)
type InterceptedTCPConnection struct {
ReadTimeout time.Duration
}
var _ Step = &InterceptedTCPConnection{}
func (t *InterceptedTCPConnection) Run(p *Params) error {
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", p.Ports.ClientPort))
if err != nil {
return fmt.Errorf("failed to connect to tcp server: %v", err)
}
defer conn.Close()
fmt.Fprintf(conn, "some data"+"\n")
err = conn.SetReadDeadline(time.Now().Add(t.ReadTimeout))
if err != nil {
return fmt.Errorf("failed to set read deadline: %v", err)
}
_, err = bufio.NewReader(conn).ReadString('\n')
if err != io.EOF {
return errors.New("the connection should be terminated")
}
return nil
}
func (t *InterceptedTCPConnection) Cleanup() {}

View File

@ -43,8 +43,7 @@ func TestHTTPExchange(t *testing.T) {
params := driver.NewTestParams(t, map[string]string{}, envoye2e.ProxyE2ETests) params := driver.NewTestParams(t, map[string]string{}, envoye2e.ProxyE2ETests)
params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl") params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl")
params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl") params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl")
params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_inbound.yaml.tmpl") params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_native_inbound.yaml.tmpl")
params.Vars["ClientHTTPFilters"] = params.LoadTestData("testdata/filters/mx_outbound.yaml.tmpl")
if err := (&driver.Scenario{ if err := (&driver.Scenario{
Steps: []driver.Step{ Steps: []driver.Step{
&driver.XDS{}, &driver.XDS{},
@ -87,3 +86,41 @@ func TestHTTPExchange(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestNativeHTTPExchange(t *testing.T) {
params := driver.NewTestParams(t, map[string]string{}, envoye2e.ProxyE2ETests)
params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl")
params.Vars["ServerHTTPFilters"] = params.LoadTestData("testdata/filters/mx_native_inbound.yaml.tmpl")
// TCP MX should not break HTTP MX when there is no TCP prefix or TCP MX ALPN.
params.Vars["ServerNetworkFilters"] = params.LoadTestData("testdata/filters/server_mx_network_filter.yaml.tmpl")
metadata := EncodeMetadata(t, params)
if err := (&driver.Scenario{
Steps: []driver.Step{
&driver.XDS{},
&driver.Update{Node: "server", Version: "0", Listeners: []string{driver.LoadTestData("testdata/listener/server.yaml.tmpl")}},
&driver.Envoy{Bootstrap: params.LoadTestData("testdata/bootstrap/server.yaml.tmpl"), Concurrency: 2},
&driver.Sleep{Duration: 1 * time.Second},
&driver.Repeat{
// Must be high enough to exercise cache eviction.
N: 1000,
Step: &driver.HTTPCall{
Port: params.Ports.ServerPort,
Body: "hello, world!",
RequestHeaders: map[string]string{
"x-envoy-peer-metadata-id": "client{{ .N }}",
"x-envoy-peer-metadata": metadata,
},
ResponseHeaders: map[string]string{
"x-envoy-peer-metadata-id": "server",
"x-envoy-peer-metadata": driver.Any,
},
},
},
&driver.Stats{AdminPort: params.Ports.ServerAdmin, Matchers: map[string]driver.StatMatcher{
"envoy_server_envoy_bug_failures": &driver.ExactStat{Metric: "testdata/metric/envoy_bug_failures.yaml"},
}},
},
}).Run(params); err != nil {
t.Fatal(err)
}
}

View File

@ -35,6 +35,7 @@ func init() {
"TestPassthroughCONNECT/quic", "TestPassthroughCONNECT/quic",
"TestPassthroughCONNECT/h2", "TestPassthroughCONNECT/h2",
"TestHTTPExchange", "TestHTTPExchange",
"TestNativeHTTPExchange",
"TestHTTPLocalRatelimit", "TestHTTPLocalRatelimit",
"TestStackdriverAccessLog/AllClientErrorRequestsGetsLoggedOnNoMxAndError", "TestStackdriverAccessLog/AllClientErrorRequestsGetsLoggedOnNoMxAndError",
"TestStackdriverAccessLog/AllErrorRequestsGetsLogged", "TestStackdriverAccessLog/AllErrorRequestsGetsLogged",
@ -89,6 +90,7 @@ func init() {
"TestStatsExpiry", "TestStatsExpiry",
"TestTCPMetadataExchange", "TestTCPMetadataExchange",
"TestTCPMetadataExchangeNoAlpn", "TestTCPMetadataExchangeNoAlpn",
"TestTCPMetadataExchangeWithConnectionTermination",
"TestOtelPayload", "TestOtelPayload",
}, },
} }

View File

@ -127,3 +127,52 @@ func TestTCPMetadataExchangeNoAlpn(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestTCPMetadataExchangeWithConnectionTermination(t *testing.T) {
params := driver.NewTestParams(t, map[string]string{
"DisableDirectResponse": "true",
"AlpnProtocol": "mx-protocol",
"StatsConfig": driver.LoadTestData("testdata/bootstrap/stats.yaml.tmpl"),
}, envoye2e.ProxyE2ETests)
params.Vars["ClientMetadata"] = params.LoadTestData("testdata/client_node_metadata.json.tmpl")
params.Vars["ServerMetadata"] = params.LoadTestData("testdata/server_node_metadata.json.tmpl")
params.Vars["ServerNetworkFilters"] = params.LoadTestData("testdata/filters/server_stats_network_filter.yaml.tmpl")
params.Vars["ClientUpstreamFilters"] = params.LoadTestData("testdata/filters/client_mx_network_filter.yaml.tmpl")
params.Vars["ClientNetworkFilters"] = params.LoadTestData("testdata/filters/server_mx_network_filter.yaml.tmpl") + "\n" +
params.LoadTestData("testdata/filters/client_stats_network_filter.yaml.tmpl")
params.Vars["ClientClusterTLSContext"] = params.LoadTestData("testdata/transport_socket/client.yaml.tmpl")
params.Vars["ServerListenerTLSContext"] = params.LoadTestData("testdata/transport_socket/server.yaml.tmpl")
if err := (&driver.Scenario{
Steps: []driver.Step{
&driver.XDS{},
&driver.Update{
Node: "client",
Version: "0",
Clusters: []string{params.LoadTestData("testdata/cluster/tcp_client.yaml.tmpl")},
Listeners: []string{params.LoadTestData("testdata/listener/tcp_client.yaml.tmpl")},
},
&driver.Update{
Node: "server",
Version: "0",
Clusters: []string{params.LoadTestData("testdata/cluster/tcp_server.yaml.tmpl")},
Listeners: []string{params.LoadTestData("testdata/listener/tcp_server.yaml.tmpl")},
},
&driver.Envoy{Bootstrap: params.LoadTestData("testdata/bootstrap/client.yaml.tmpl")},
&driver.Envoy{Bootstrap: params.LoadTestData("testdata/bootstrap/server.yaml.tmpl")},
&driver.Sleep{Duration: 1 * time.Second},
&driver.TCPServerAcceptAndClose{},
&driver.Repeat{
N: 10,
Step: &driver.InterceptedTCPConnection{
ReadTimeout: 10 * time.Second,
},
},
&driver.Stats{AdminPort: params.Ports.ServerAdmin, Matchers: map[string]driver.StatMatcher{
"istio_tcp_connections_opened_total": &driver.ExactStat{Metric: "testdata/metric/tcp_server_connection_open_without_mx.yaml.tmpl"},
}},
},
}).Run(params); err != nil {
t.Fatal(err)
}
}

View File

@ -0,0 +1,5 @@
name: envoy_server_envoy_bug_failures
type: COUNTER
metric:
- counter:
value: 0