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 ############################################################################# 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 diff --git a/VERSION.txt b/VERSION.txt index ad7c780d0488..25691b4f1d0e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -1.26.7 +1.26.8 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, diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 86bef0589c5c..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.57.0", - sha256 = "1e3258453784d3b7e6cc48d0be087b168f8360b5d588c66bfeda05d07ad39ffd", + 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-10", + 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", 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 d3bbb6481105..9f951b8d916c 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -1,8 +1,17 @@ -date: February 9, 2024 +date: April 4, 2024 bug_fixes: -- area: buffer +- area: http2 change: | + Update nghttp2 to resolve CVE-2024-30255 (https://github.com/envoyproxy/envoy/security/advisories/GHSA-j654-3ccm-vfmm). + +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. + fixed a bug where handshake may fail when both private key provider and cert validation are set. - area: buffer change: | diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 7f6f0bd13911..396e1fb1d770 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 @@ -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:0cf184cfdb9ac2878822b15b8917fae5d42fba26da654cd75ab3ed34add0737f AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] diff --git a/docs/inventories/v1.26/objects.inv b/docs/inventories/v1.26/objects.inv index 477894d1f6bc..26b06951df94 100644 Binary files a/docs/inventories/v1.26/objects.inv and b/docs/inventories/v1.26/objects.inv differ 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 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/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 { diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 367f382e71e6..01bff8ab8ce6 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -115,6 +115,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/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/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_; }; 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_); }