From 772b4189c363e8e9b621ad141e609ae42f35f9f3 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 13 Feb 2024 14:22:28 +0000 Subject: [PATCH 01/16] repo: Dev 1.26.8 (#32331) Signed-off-by: Ryan Northey --- VERSION.txt | 2 +- changelogs/current.yaml | 41 +++++++++++++++-------------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index ad7c780d0488..7bcab65f68b4 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.26.7 +1.26.8-dev diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 48e27387880c..9ecf0d6e48ce 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -1,28 +1,17 @@ -date: February 9, 2024 +date: Pending + +behavior_changes: +# *Changes that are expected to cause an incompatibility if applicable; deployment changes are likely required* + +minor_behavior_changes: +# *Changes that may cause incompatibilities for some users, but should not for most* bug_fixes: -- area: buffer - change: | - Fixed a bug (https://github.com/envoyproxy/envoy/issues/28760) that the internal listener causes an undefined - behavior due to the unintended release of the buffer memory. -- area: http - change: | - Fixed recursion when HTTP connection is disconnected due to a high number of premature resets. -- area: proxy protocol - change: | - fixed a crash when Envoy is configured for PROXY protocol on both a listener and cluster, and the listener receives - a PROXY protocol header with address type LOCAL (typically used for health checks). -- area: proxy_protocol - change: | - Fix crash due to uncaught exception when the operating system does not support an address type (such as IPv6) that is - received in a proxy protocol header. Connections will instead be dropped/reset. -- area: proxy_protocol - change: | - Fixed a bug where TLVs with non utf8 characters were inserted as protobuf values into filter metadata circumventing - ext_authz checks when ``failure_mode_allow`` is set to ``true``. -- area: http - change: | - Fixed crash when HTTP request idle and per try timeouts occurs within backoff interval. -- area: url matching - change: | - Fixed excessive CPU utilization when using regex URL template matcher. +# *Changes expected to improve the state of the world and are unlikely to have negative effects* + +removed_config_or_runtime: +# *Normally occurs at the end of the* :ref:`deprecation period ` + +new_features: + +deprecated: From d9c97546ee5a490acf18a421032bc11a4f70120f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 07:01:59 +0000 Subject: [PATCH 02/16] build(deps): bump distroless/base-nossl-debian12 from `51ab103` to `49edf70` in /ci (#32348) build(deps): bump distroless/base-nossl-debian12 in /ci Bumps distroless/base-nossl-debian12 from `51ab103` to `49edf70`. --- updated-dependencies: - dependency-name: distroless/base-nossl-debian12 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 7f6f0bd13911..cf7e0d7dc0b3 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:51ab103bb161fdf8fee4c6311a2d41f484effc409d4f4c58342ab68b2da7ccc2 AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:49edf7003af1015b0841f34a04197e8b1c5f1d0c91e897c97749c78ee38b8ec2 AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From b7688ade206dd5b84bfbbe60e70719dd0181e0f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:43:52 +0000 Subject: [PATCH 03/16] build(deps): bump distroless/base-nossl-debian12 from `49edf70` to `0e777c6` in /ci (#32576) build(deps): bump distroless/base-nossl-debian12 in /ci Bumps distroless/base-nossl-debian12 from `49edf70` to `0e777c6`. --- updated-dependencies: - dependency-name: distroless/base-nossl-debian12 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey Signed-off-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index cf7e0d7dc0b3..9e4e156bc75e 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:49edf7003af1015b0841f34a04197e8b1c5f1d0c91e897c97749c78ee38b8ec2 AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:0e777c69ba810353b9f3f2033280bbe7d029d81fa55760f6eec817ef595aa19c AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From 3abf41389b1d66c9a185631b046625944065455a Mon Sep 17 00:00:00 2001 From: Kuat Date: Fri, 23 Feb 2024 01:11:34 -0800 Subject: [PATCH 04/16] google_grpc: add a runtime flag to disable TLSv1.3 (#32532) * google_grpc: add a runtime flag to disable TLSv1.3 (#32315) Change-Id: Id88723a81d4b1586bf12be6f4dc7a81ae7b0d9c4 Commit Message: Adds a temporary runtime flag to disable TLSv1.3 by gRPC SDK until a proper xDS extension can be added. Additional Description: Risk Level: low, default false Testing: regression Change-Id: I34daae55ede7c8093b0dac1fa6ff5a5dc8df677d Signed-off-by: Kuat Yessenov --- changelogs/current.yaml | 5 +++ source/common/grpc/BUILD | 1 + source/common/grpc/google_grpc_creds_impl.cc | 38 +++++++++++++++---- source/common/runtime/runtime_features.cc | 4 ++ test/common/grpc/BUILD | 1 + .../grpc/grpc_client_integration_test.cc | 24 ++++++++++++ .../grpc_client_integration_test_harness.h | 16 +++++++- 7 files changed, 81 insertions(+), 8 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 9ecf0d6e48ce..2b8dc99df2e0 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -13,5 +13,10 @@ removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` new_features: +- area: google_grpc + change: | + Added an off-by-default runtime flag + ``envoy.reloadable_features.google_grpc_disable_tls_13`` to disable TLSv1.3 + usage by gRPC SDK for ``google_grpc`` services. deprecated: diff --git a/source/common/grpc/BUILD b/source/common/grpc/BUILD index c5d338b5e5ec..60cac0ceb90a 100644 --- a/source/common/grpc/BUILD +++ b/source/common/grpc/BUILD @@ -207,6 +207,7 @@ envoy_cc_library( "//envoy/grpc:google_grpc_creds_interface", "//envoy/registry", "//source/common/config:datasource_lib", + "//source/common/runtime:runtime_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], alwayslink = LEGACY_ALWAYSLINK, diff --git a/source/common/grpc/google_grpc_creds_impl.cc b/source/common/grpc/google_grpc_creds_impl.cc index ae49d3257a7f..5aa2ea91fd8a 100644 --- a/source/common/grpc/google_grpc_creds_impl.cc +++ b/source/common/grpc/google_grpc_creds_impl.cc @@ -4,6 +4,9 @@ #include "envoy/grpc/google_grpc_creds.h" #include "source/common/config/datasource.h" +#include "source/common/runtime/runtime_features.h" + +#include "grpcpp/security/tls_certificate_provider.h" namespace Envoy { namespace Grpc { @@ -15,12 +18,29 @@ std::shared_ptr CredsUtility::getChannelCredentials( case envoy::config::core::v3::GrpcService::GoogleGrpc::ChannelCredentials:: CredentialSpecifierCase::kSslCredentials: { const auto& ssl_credentials = google_grpc.channel_credentials().ssl_credentials(); - const grpc::SslCredentialsOptions ssl_credentials_options = { - Config::DataSource::read(ssl_credentials.root_certs(), true, api), - Config::DataSource::read(ssl_credentials.private_key(), true, api), - Config::DataSource::read(ssl_credentials.cert_chain(), true, api), - }; - return grpc::SslCredentials(ssl_credentials_options); + const auto root_certs = Config::DataSource::read(ssl_credentials.root_certs(), true, api); + const auto private_key = Config::DataSource::read(ssl_credentials.private_key(), true, api); + const auto cert_chain = Config::DataSource::read(ssl_credentials.cert_chain(), true, api); + grpc::experimental::TlsChannelCredentialsOptions options; + if (!private_key.empty() || !cert_chain.empty()) { + options.set_certificate_provider( + std::make_shared( + root_certs, + std::vector{{private_key, cert_chain}})); + } else if (!root_certs.empty()) { + options.set_certificate_provider( + std::make_shared(root_certs)); + } + if (!root_certs.empty()) { + options.watch_root_certs(); + } + if (!private_key.empty() || !cert_chain.empty()) { + options.watch_identity_key_cert_pairs(); + } + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.google_grpc_disable_tls_13")) { + options.set_max_tls_version(grpc_tls_version::TLS1_2); + } + return grpc::experimental::TlsCredentials(options); } case envoy::config::core::v3::GrpcService::GoogleGrpc::ChannelCredentials:: CredentialSpecifierCase::kLocalCredentials: { @@ -43,7 +63,11 @@ std::shared_ptr CredsUtility::defaultSslChannelCredent if (creds != nullptr) { return creds; } - return grpc::SslCredentials({}); + grpc::experimental::TlsChannelCredentialsOptions options; + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.google_grpc_disable_tls_13")) { + options.set_max_tls_version(grpc_tls_version::TLS1_2); + } + return grpc::experimental::TlsCredentials(options); } std::vector> diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 37b11a74fb56..058352532229 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -112,6 +112,10 @@ FALSE_RUNTIME_GUARD(envoy_reloadable_features_no_delay_close_for_upgrades); // TODO(pradeepcrao) reset this to true after 2 releases (1.27) FALSE_RUNTIME_GUARD(envoy_reloadable_features_enable_include_histograms); +// A flag to set the maximum TLS version for google_grpc client to TLS1.2, when needed for +// compliance restrictions. +FALSE_RUNTIME_GUARD(envoy_reloadable_features_google_grpc_disable_tls_13); + // Block of non-boolean flags. Use of int flags is deprecated. Do not add more. ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT ABSL_FLAG(uint64_t, re2_max_program_size_warn_level, // NOLINT diff --git a/test/common/grpc/BUILD b/test/common/grpc/BUILD index 6cf74e7f7d7e..0c8cb3380684 100644 --- a/test/common/grpc/BUILD +++ b/test/common/grpc/BUILD @@ -176,6 +176,7 @@ envoy_cc_test( ":grpc_client_integration_test_harness_lib", "//source/common/grpc:async_client_lib", "//source/extensions/grpc_credentials/example:config", + "//test/test_common:test_runtime_lib", ] + envoy_select_google_grpc(["//source/common/grpc:google_async_client_lib"]), ) diff --git a/test/common/grpc/grpc_client_integration_test.cc b/test/common/grpc/grpc_client_integration_test.cc index 96be74c4871a..a3279ed8b3f3 100644 --- a/test/common/grpc/grpc_client_integration_test.cc +++ b/test/common/grpc/grpc_client_integration_test.cc @@ -5,6 +5,7 @@ #endif +#include "test/test_common/test_runtime.h" #include "test/common/grpc/grpc_client_integration_test_harness.h" using testing::Eq; @@ -402,6 +403,29 @@ TEST_P(GrpcSslClientIntegrationTest, BasicSslRequestWithClientCert) { dispatcher_helper_.runDispatcher(); } +// Validate TLS version mismatch between the client and the server. +TEST_P(GrpcSslClientIntegrationTest, BasicSslRequestHandshakeFailure) { + SKIP_IF_GRPC_CLIENT(ClientType::EnvoyGrpc); + TestScopedRuntime scoped_runtime; + scoped_runtime.mergeValues({{"envoy.reloadable_features.google_grpc_disable_tls_13", "true"}}); + use_server_tls_13_ = true; + initialize(); + auto request = createRequest(empty_metadata_, false); + EXPECT_CALL(*request->child_span_, setTag(Eq(Tracing::Tags::get().GrpcStatusCode), Eq("13"))); + EXPECT_CALL(*request->child_span_, + setTag(Eq(Tracing::Tags::get().Error), Eq(Tracing::Tags::get().True))); + EXPECT_CALL(*request, onFailure(Status::Internal, "", _)).WillOnce(InvokeWithoutArgs([this]() { + dispatcher_helper_.dispatcher_.exit(); + })); + EXPECT_CALL(*request->child_span_, finishSpan()); + FakeRawConnectionPtr fake_connection; + ASSERT_TRUE(fake_upstream_->waitForRawConnection(fake_connection)); + if (fake_connection->connected()) { + ASSERT_TRUE(fake_connection->waitForDisconnect()); + } + dispatcher_helper_.dispatcher_.run(Event::Dispatcher::RunType::Block); +} + #ifdef ENVOY_GOOGLE_GRPC // AccessToken credential validation tests. class GrpcAccessTokenClientIntegrationTest : public GrpcSslClientIntegrationTest { diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index dd3bb0831afe..cb60ccf32f93 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -365,7 +365,8 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { virtual void expectExtraHeaders(FakeStream&) {} - HelloworldRequestPtr createRequest(const TestMetadata& initial_metadata) { + HelloworldRequestPtr createRequest(const TestMetadata& initial_metadata, + bool expect_upstream_request = true) { auto request = std::make_unique(dispatcher_helper_); EXPECT_CALL(*request, onCreateInitialMetadata(_)) .WillOnce(Invoke([&initial_metadata](Http::HeaderMap& headers) { @@ -392,6 +393,10 @@ class GrpcClientIntegrationTest : public GrpcClientIntegrationParamTest { active_span, Http::AsyncClient::RequestOptions()); EXPECT_NE(request->grpc_request_, nullptr); + if (!expect_upstream_request) { + return request; + } + if (!fake_connection_) { AssertionResult result = fake_upstream_->waitForHttpConnection(*dispatcher_, fake_connection_); @@ -523,6 +528,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { tls_cert->mutable_private_key()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/clientkey.pem")); } + auto cfg = std::make_unique( tls_context, factory_context_); @@ -554,6 +560,13 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { validation_context->mutable_trusted_ca()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); } + if (use_server_tls_13_) { + auto* tls_params = common_tls_context->mutable_tls_params(); + tls_params->set_tls_minimum_protocol_version( + envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_3); + tls_params->set_tls_maximum_protocol_version( + envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLSv1_3); + } auto cfg = std::make_unique( tls_context, factory_context_); @@ -565,6 +578,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { } bool use_client_cert_{}; + bool use_server_tls_13_{false}; testing::NiceMock factory_context_; }; From e85ec4afef2cfd61ed94062fd57c96db0db710d5 Mon Sep 17 00:00:00 2001 From: Sebastian Schepens Date: Fri, 1 Mar 2024 17:45:20 -0300 Subject: [PATCH 05/16] populate histogram summary sample sum Signed-off-by: Sebastian Schepens --- .../stat_sinks/metrics_service/grpc_metrics_service_impl.cc | 1 + .../metrics_service/grpc_metrics_service_impl_test.cc | 2 ++ 2 files changed, 3 insertions(+) diff --git a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc index 2b74663df397..f1f593a83aa6 100644 --- a/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc +++ b/source/extensions/stat_sinks/metrics_service/grpc_metrics_service_impl.cc @@ -135,6 +135,7 @@ void MetricsFlusher::flushSummary(io::prometheus::client::MetricFamily& metrics_ quantile->set_value(hist_stats.computedQuantiles()[i]); } summary->set_sample_count(hist_stats.sampleCount()); + summary->set_sample_sum(hist_stats.sampleSum()); } io::prometheus::client::Metric* diff --git a/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc b/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc index 6e7dc7425ce0..59ceb061fbd4 100644 --- a/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc +++ b/test/extensions/stats_sinks/metrics_service/grpc_metrics_service_impl_test.cc @@ -344,6 +344,7 @@ TEST_F(MetricsServiceSinkTest, HistogramEmitModeBoth) { const auto& metric1 = (*metrics)[0].metric(0); EXPECT_TRUE(metric1.has_summary()); + EXPECT_TRUE(metric1.summary().has_sample_sum()); const auto& metric2 = (*metrics)[1].metric(0); EXPECT_TRUE(metric2.has_histogram()); })); @@ -364,6 +365,7 @@ TEST_F(MetricsServiceSinkTest, HistogramEmitModeSummary) { const auto& metric1 = (*metrics)[0].metric(0); EXPECT_TRUE(metric1.has_summary()); + EXPECT_TRUE(metric1.summary().has_sample_sum()); })); sink.flush(snapshot_); } From f0c74cc90475048176c7482d86feab171d1cce70 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 23 Feb 2024 09:10:36 +0000 Subject: [PATCH 06/16] ci/macos: Use Engflow for bazel cache (#32520) Signed-off-by: Ryan Northey Signed-off-by: phlax --- .bazelrc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.bazelrc b/.bazelrc index b148a5ae6099..cec7b50451ac 100644 --- a/.bazelrc +++ b/.bazelrc @@ -489,16 +489,18 @@ build:rbe-engflow --remote_timeout=3600s build:rbe-engflow --bes_timeout=3600s build:rbe-engflow --bes_upload_mode=fully_async -build:rbe-envoy-engflow --google_default_credentials=false -build:rbe-envoy-engflow --remote_cache=grpcs://morganite.cluster.engflow.com +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 --bes_backend=grpcs://morganite.cluster.engflow.com/ -build:rbe-envoy-engflow --bes_results_url=https://morganite.cluster.engflow.com/invocation/ -build:rbe-envoy-engflow --credential_helper=*.engflow.com=%workspace%/bazel/engflow-bazel-credential-helper.sh -build:rbe-envoy-engflow --grpc_keepalive_time=30s -build:rbe-envoy-engflow --remote_timeout=3600s -build:rbe-envoy-engflow --bes_timeout=3600s -build:rbe-envoy-engflow --bes_upload_mode=fully_async build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:cmake-fdd65c6270a8507a18d5acd6cf19a18cb695e4fa@sha256:06d3d10a99cce5bf4036be65190f192a30503fa93b9df3c119fd1260d3ed7024 ############################################################################# From 1c35dac40177ffff7cf0ac90b582320577bc1c0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:53:42 +0000 Subject: [PATCH 07/16] build(deps): bump distroless/base-nossl-debian12 from `0e777c6` to `099c134` in /ci (#32843) build(deps): bump distroless/base-nossl-debian12 in /ci Bumps distroless/base-nossl-debian12 from `0e777c6` to `099c134`. --- updated-dependencies: - dependency-name: distroless/base-nossl-debian12 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 9e4e156bc75e..9c5c824d38c3 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:0e777c69ba810353b9f3f2033280bbe7d029d81fa55760f6eec817ef595aa19c AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:099c13463fdd2f52d31af8b61f5a991ed8e97bdac529f10b22c4f4ebf0c21c0d AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From f8e6292a7f2621a4b2205ecabb554ab1ed11fd4e Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 22:59:48 +0000 Subject: [PATCH 08/16] deps: Bump `com_github_nghttp2_nghttp2` -> 1.58.0 (#31361) Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 86bef0589c5c..e8ddfd338fab 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -455,12 +455,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Nghttp2", project_desc = "Implementation of HTTP/2 and its header compression algorithm HPACK in C", project_url = "https://nghttp2.org", - version = "1.57.0", - sha256 = "1e3258453784d3b7e6cc48d0be087b168f8360b5d588c66bfeda05d07ad39ffd", + version = "1.58.0", + sha256 = "9ebdfbfbca164ef72bdf5fd2a94a4e6dfb54ec39d2ef249aeb750a91ae361dfb", strip_prefix = "nghttp2-{version}", urls = ["https://github.com/nghttp2/nghttp2/releases/download/v{version}/nghttp2-{version}.tar.gz"], use_category = ["controlplane", "dataplane_core"], - release_date = "2023-10-10", + release_date = "2023-10-27", cpe = "cpe:2.3:a:nghttp2:nghttp2:*", license = "MIT", license_url = "https://github.com/nghttp2/nghttp2/blob/v{version}/LICENSE", From accd9bcb4fd0a186085d78d4645541914901e824 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 12:44:06 +0000 Subject: [PATCH 09/16] deps: Bump `com_github_nghttp2_nghttp2` -> 1.59.0 (#31953) Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index e8ddfd338fab..c05defa81917 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -455,12 +455,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Nghttp2", project_desc = "Implementation of HTTP/2 and its header compression algorithm HPACK in C", project_url = "https://nghttp2.org", - version = "1.58.0", - sha256 = "9ebdfbfbca164ef72bdf5fd2a94a4e6dfb54ec39d2ef249aeb750a91ae361dfb", + version = "1.59.0", + sha256 = "90fd27685120404544e96a60ed40398a3457102840c38e7215dc6dec8684470f", strip_prefix = "nghttp2-{version}", urls = ["https://github.com/nghttp2/nghttp2/releases/download/v{version}/nghttp2-{version}.tar.gz"], use_category = ["controlplane", "dataplane_core"], - release_date = "2023-10-27", + release_date = "2024-01-21", cpe = "cpe:2.3:a:nghttp2:nghttp2:*", license = "MIT", license_url = "https://github.com/nghttp2/nghttp2/blob/v{version}/LICENSE", From 8e7ad1c2234a0b19fcc63dc416111910c8425d89 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 14 Mar 2024 20:41:52 +0000 Subject: [PATCH 10/16] ci: Disable windows (#32904) Signed-off-by: Ryan Northey --- .github/config.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.github/config.yml b/.github/config.yml index 5f51af3d0a2f..74f2be76cdd1 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -81,27 +81,8 @@ checks: - publish - verify required: true - windows: - name: Envoy/Windows - required: true - on-run: - - build-windows run: - build-windows: - paths: - - .bazelrc - - .bazelversion - - .github/config.yml - - api/**/* - - bazel/**/* - - ci/**/* - - configs/**/* - - contrib/**/* - - envoy/**/* - - source/**/* - - test/**/* - - VERSION.txt build-macos: paths: - .bazelrc From 02f1bacb12dc456439783be3418ea49dd86b02c8 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Wed, 3 Apr 2024 17:49:28 +0100 Subject: [PATCH 11/16] docker/release: Update Ubuntu images (80ef4a44) Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 9c5c824d38c3..1752d328fe0f 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -1,5 +1,5 @@ ARG BUILD_OS=ubuntu -ARG BUILD_TAG=20.04@sha256:bb1c41682308d7040f74d103022816d41c50d7b0c89e9d706a74b4e548636e54 +ARG BUILD_TAG=20.04@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9c35d ARG ENVOY_VRP_BASE_IMAGE=envoy-base From bcb619d4f9d7a495dfc77218def795a142b067b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 09:16:32 +0100 Subject: [PATCH 12/16] build(deps): bump distroless/base-nossl-debian12 from `099c134` to `0cf184c` in /ci (#33282) build(deps): bump distroless/base-nossl-debian12 in /ci Bumps distroless/base-nossl-debian12 from `099c134` to `0cf184c`. --- updated-dependencies: - dependency-name: distroless/base-nossl-debian12 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 1752d328fe0f..396e1fb1d770 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:099c13463fdd2f52d31af8b61f5a991ed8e97bdac529f10b22c4f4ebf0c21c0d AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:0cf184cfdb9ac2878822b15b8917fae5d42fba26da654cd75ab3ed34add0737f AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From 2d94d69d83566fb35929a4fbab40472858b94f40 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Thu, 4 Apr 2024 12:08:41 +0100 Subject: [PATCH 13/16] deps/CVE: Fix (nghttp2) CVE-2024-30255 Signed-off-by: Ryan Northey --- bazel/foreign_cc/nghttp2.patch | 168 +++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/bazel/foreign_cc/nghttp2.patch b/bazel/foreign_cc/nghttp2.patch index d1cbab6356e5..511e2a2e4b29 100644 --- a/bazel/foreign_cc/nghttp2.patch +++ b/bazel/foreign_cc/nghttp2.patch @@ -14,3 +14,171 @@ diff -u -r a/CMakeLists.txt b/CMakeLists.txt endif() # AC_TYPE_UINT8_T # AC_TYPE_UINT16_T +diff --git a/doc/Makefile.am b/doc/Makefile.am +index 7d7f31c6..ce50d89e 100644 +--- a/doc/Makefile.am ++++ b/doc/Makefile.am +@@ -74,6 +74,7 @@ APIDOCS= \ + nghttp2_option_set_peer_max_concurrent_streams.rst \ + nghttp2_option_set_server_fallback_rfc7540_priorities.rst \ + nghttp2_option_set_user_recv_extension_type.rst \ ++ nghttp2_option_set_max_continuations.rst \ + nghttp2_option_set_max_outbound_ack.rst \ + nghttp2_option_set_max_settings.rst \ + nghttp2_option_set_stream_reset_rate_limit.rst \ +diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h +index 7910db23..a54efbfd 100644 +--- a/lib/includes/nghttp2/nghttp2.h ++++ b/lib/includes/nghttp2/nghttp2.h +@@ -440,7 +440,12 @@ typedef enum { + * exhaustion on server side to send these frames forever and does + * not read network. + */ +- NGHTTP2_ERR_FLOODED = -904 ++ NGHTTP2_ERR_FLOODED = -904, ++ /** ++ * When a local endpoint receives too many CONTINUATION frames ++ * following a HEADER frame. ++ */ ++ NGHTTP2_ERR_TOO_MANY_CONTINUATIONS = -905, + } nghttp2_error; + + /** +@@ -2773,6 +2778,17 @@ NGHTTP2_EXTERN void + nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, + uint64_t burst, uint64_t rate); + ++/** ++ * @function ++ * ++ * This function sets the maximum number of CONTINUATION frames ++ * following an incoming HEADER frame. If more than those frames are ++ * received, the remote endpoint is considered to be misbehaving and ++ * session will be closed. The default value is 8. ++ */ ++NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option, ++ size_t val); ++ + /** + * @function + * +diff --git a/lib/nghttp2_helper.c b/lib/nghttp2_helper.c +index 93dd4754..b3563d98 100644 +--- a/lib/nghttp2_helper.c ++++ b/lib/nghttp2_helper.c +@@ -336,6 +336,8 @@ const char *nghttp2_strerror(int error_code) { + "closed"; + case NGHTTP2_ERR_TOO_MANY_SETTINGS: + return "SETTINGS frame contained more than the maximum allowed entries"; ++ case NGHTTP2_ERR_TOO_MANY_CONTINUATIONS: ++ return "Too many CONTINUATION frames following a HEADER frame"; + default: + return "Unknown error code"; + } +diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c +index 43d4e952..53144b9b 100644 +--- a/lib/nghttp2_option.c ++++ b/lib/nghttp2_option.c +@@ -150,3 +150,8 @@ void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, + option->stream_reset_burst = burst; + option->stream_reset_rate = rate; + } ++ ++void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) { ++ option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS; ++ option->max_continuations = val; ++} +diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h +index 2259e184..c89cb97f 100644 +--- a/lib/nghttp2_option.h ++++ b/lib/nghttp2_option.h +@@ -71,6 +71,7 @@ typedef enum { + NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13, + NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14, + NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15, ++ NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16, + } nghttp2_option_flag; + + /** +@@ -98,6 +99,10 @@ struct nghttp2_option { + * NGHTTP2_OPT_MAX_SETTINGS + */ + size_t max_settings; ++ /** ++ * NGHTTP2_OPT_MAX_CONTINUATIONS ++ */ ++ size_t max_continuations; + /** + * Bitwise OR of nghttp2_option_flag to determine that which fields + * are specified. +diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c +index ce21caf9..18949528 100644 +--- a/lib/nghttp2_session.c ++++ b/lib/nghttp2_session.c +@@ -496,6 +496,7 @@ static int session_new(nghttp2_session **session_ptr, + (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN; + (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; + (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS; ++ (*session_ptr)->max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS; + + if (option) { + if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) && +@@ -584,6 +585,10 @@ static int session_new(nghttp2_session **session_ptr, + option->stream_reset_burst, + option->stream_reset_rate); + } ++ ++ if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) { ++ (*session_ptr)->max_continuations = option->max_continuations; ++ } + } + + rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, +@@ -6778,6 +6783,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + } + } + session_inbound_frame_reset(session); ++ ++ session->num_continuations = 0; + } + break; + } +@@ -6899,6 +6906,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + } + #endif /* DEBUGBUILD */ + ++ if (++session->num_continuations > session->max_continuations) { ++ return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS; ++ } ++ + readlen = inbound_frame_buf_read(iframe, in, last); + in += readlen; + +diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h +index b119329a..ef8f7b27 100644 +--- a/lib/nghttp2_session.h ++++ b/lib/nghttp2_session.h +@@ -110,6 +110,10 @@ typedef struct { + #define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000 + #define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33 + ++/* The default max number of CONTINUATION frames following an incoming ++ HEADER frame. */ ++#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8 ++ + /* Internal state when receiving incoming frame */ + typedef enum { + /* Receiving frame header */ +@@ -290,6 +294,12 @@ struct nghttp2_session { + size_t max_send_header_block_length; + /* The maximum number of settings accepted per SETTINGS frame. */ + size_t max_settings; ++ /* The maximum number of CONTINUATION frames following an incoming ++ HEADER frame. */ ++ size_t max_continuations; ++ /* The number of CONTINUATION frames following an incoming HEADER ++ frame. This variable is reset when END_HEADERS flag is seen. */ ++ size_t num_continuations; + /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ + uint32_t next_stream_id; + /* The last stream ID this session initiated. For client session, From a34313495a499462e7c84d21bc0a6bece169b5d8 Mon Sep 17 00:00:00 2001 From: Yan Avlasov Date: Wed, 3 Apr 2024 19:24:35 +0000 Subject: [PATCH 14/16] Update Envoy to use the patch Signed-off-by: Yan Avlasov Signed-off-by: Ryan Northey --- source/common/http/http2/codec_impl.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/common/http/http2/codec_impl.cc b/source/common/http/http2/codec_impl.cc index 4be1206db910..6080ac479897 100644 --- a/source/common/http/http2/codec_impl.cc +++ b/source/common/http/http2/codec_impl.cc @@ -1793,6 +1793,11 @@ ConnectionImpl::Http2Options::Http2Options( // on this mitigation, set back to the old 10K number to avoid any changes in the HTTP/2 codec // behavior. nghttp2_option_set_max_outbound_ack(options_, 10000); + + // nghttp2 REQUIRES setting max number of CONTINUATION frames. + // 1024 is chosen to accommodate Envoy's 8Mb max limit of max_request_headers_kb + // in both headers and trailers + nghttp2_option_set_max_continuations(options_, 1024); } ConnectionImpl::Http2Options::~Http2Options() { nghttp2_option_del(options_); } @@ -1807,6 +1812,11 @@ ConnectionImpl::ClientHttp2Options::ClientHttp2Options( // TODO(PiotrSikora): remove this once multiple upstream connections or queuing are implemented. nghttp2_option_set_peer_max_concurrent_streams( options_, ::Envoy::Http2::Utility::OptionsLimits::DEFAULT_MAX_CONCURRENT_STREAMS); + + // nghttp2 REQUIRES setting max number of CONTINUATION frames. + // 1024 is chosen to accommodate Envoy's 8Mb max limit of max_request_headers_kb + // in both headers and trailers + nghttp2_option_set_max_continuations(options_, 1024); } void ConnectionImpl::dumpState(std::ostream& os, int indent_level) const { From 3d2b7e2ae24c4d5c01b232d650e879fe52e49ec5 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Thu, 4 Apr 2024 11:53:31 +0100 Subject: [PATCH 15/16] changelogs: Add changelog for CVE-2024-30255 https://github.com/envoyproxy/envoy/security/advisories/GHSA-j654-3ccm-vfmm Signed-off-by: Ryan Northey --- changelogs/current.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 2b8dc99df2e0..cc4a32e98705 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -8,6 +8,9 @@ minor_behavior_changes: bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* +- area: http2 + change: | + Update nghttp2 to resolve CVE-2024-30255 (https://github.com/envoyproxy/envoy/security/advisories/GHSA-j654-3ccm-vfmm). removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` From 1257d4e845ff7c5075b03d7ccbfa4767aa295279 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Thu, 4 Apr 2024 11:47:01 +0000 Subject: [PATCH 16/16] repo: Release v1.26.8 **Summary of changes**: - Patch nghttp2 to resolve [CVE-2024-30255](https://github.com/envoyproxy/envoy/security/advisories/GHSA-j654-3ccm-vfmm) - Assorted fixes **Docker images**: https://hub.docker.com/r/envoyproxy/envoy/tags?page=1&name=v1.26.8 **Docs**: https://www.envoyproxy.io/docs/envoy/v1.26.8/ **Release notes**: https://www.envoyproxy.io/docs/envoy/v1.26.8/version_history/v1.26/v1.26.8 **Full changelog**: https://github.com/envoyproxy/envoy/compare/v1.26.7...v1.26.8 Signed-off-by: Ryan Northey Signed-off-by: Yan Avlasov --- VERSION.txt | 2 +- changelogs/1.26.7.yaml | 28 ++++++++++++++++++++++++++++ changelogs/current.yaml | 14 +------------- docs/inventories/v1.26/objects.inv | Bin 153917 -> 153965 bytes docs/versions.yaml | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 changelogs/1.26.7.yaml diff --git a/VERSION.txt b/VERSION.txt index 7bcab65f68b4..25691b4f1d0e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.26.8-dev +1.26.8 diff --git a/changelogs/1.26.7.yaml b/changelogs/1.26.7.yaml new file mode 100644 index 000000000000..48e27387880c --- /dev/null +++ b/changelogs/1.26.7.yaml @@ -0,0 +1,28 @@ +date: February 9, 2024 + +bug_fixes: +- area: buffer + change: | + Fixed a bug (https://github.com/envoyproxy/envoy/issues/28760) that the internal listener causes an undefined + behavior due to the unintended release of the buffer memory. +- area: http + change: | + Fixed recursion when HTTP connection is disconnected due to a high number of premature resets. +- area: proxy protocol + change: | + fixed a crash when Envoy is configured for PROXY protocol on both a listener and cluster, and the listener receives + a PROXY protocol header with address type LOCAL (typically used for health checks). +- area: proxy_protocol + change: | + Fix crash due to uncaught exception when the operating system does not support an address type (such as IPv6) that is + received in a proxy protocol header. Connections will instead be dropped/reset. +- area: proxy_protocol + change: | + Fixed a bug where TLVs with non utf8 characters were inserted as protobuf values into filter metadata circumventing + ext_authz checks when ``failure_mode_allow`` is set to ``true``. +- area: http + change: | + Fixed crash when HTTP request idle and per try timeouts occurs within backoff interval. +- area: url matching + change: | + Fixed excessive CPU utilization when using regex URL template matcher. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index cc4a32e98705..a59f0acb0ad0 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -1,25 +1,13 @@ -date: Pending - -behavior_changes: -# *Changes that are expected to cause an incompatibility if applicable; deployment changes are likely required* - -minor_behavior_changes: -# *Changes that may cause incompatibilities for some users, but should not for most* +date: April 4, 2024 bug_fixes: -# *Changes expected to improve the state of the world and are unlikely to have negative effects* - area: http2 change: | Update nghttp2 to resolve CVE-2024-30255 (https://github.com/envoyproxy/envoy/security/advisories/GHSA-j654-3ccm-vfmm). -removed_config_or_runtime: -# *Normally occurs at the end of the* :ref:`deprecation period ` - new_features: - area: google_grpc change: | Added an off-by-default runtime flag ``envoy.reloadable_features.google_grpc_disable_tls_13`` to disable TLSv1.3 usage by gRPC SDK for ``google_grpc`` services. - -deprecated: diff --git a/docs/inventories/v1.26/objects.inv b/docs/inventories/v1.26/objects.inv index 477894d1f6bccd82887a88b242a0da1ebc5bf066..26b06951df94722c60592253d264b2378a4075bd 100644 GIT binary patch delta 8466 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 delta 8413 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 diff --git a/docs/versions.yaml b/docs/versions.yaml index f67cbd85ae24..62dff4aabf8c 100644 --- a/docs/versions.yaml +++ b/docs/versions.yaml @@ -19,4 +19,4 @@ "1.23": 1.23.12 "1.24": 1.24.12 "1.25": 1.25.11 -"1.26": 1.26.6 +"1.26": 1.26.7