diff --git a/.circleci/config.yml b/.circleci/config.yml index 64cc32f9c251..f2045b98bef4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,6 @@ references: envoy-build-image: &envoy-build-image - envoyproxy/envoy-build:1ef23d481a4701ad4a414d1ef98036bd2ed322e7 + envoyproxy/envoy-build:e994c1c0b1cdc9a9470cff728311ff7c995685e6 version: 2 jobs: diff --git a/api/envoy/config/filter/network/thrift_proxy/v2alpha1/thrift_proxy.proto b/api/envoy/config/filter/network/thrift_proxy/v2alpha1/thrift_proxy.proto index 1a7176dc3303..97c905eafc60 100644 --- a/api/envoy/config/filter/network/thrift_proxy/v2alpha1/thrift_proxy.proto +++ b/api/envoy/config/filter/network/thrift_proxy/v2alpha1/thrift_proxy.proto @@ -23,6 +23,9 @@ message ThriftProxy { // The Thrift proxy will assume the client is using the Thrift unframed transport. UNFRAMED = 2; + + // The Thrift proxy will assume the client is using the Thrift header transport. + HEADER = 3; } // Supplies the type of transport that the Thrift proxy should use. Defaults to `AUTO_TRANSPORT`. diff --git a/bazel/README.md b/bazel/README.md index 2c0c278a3608..1decc7937741 100644 --- a/bazel/README.md +++ b/bazel/README.md @@ -33,7 +33,7 @@ On Ubuntu, run the following commands: apt-get install libtool apt-get install cmake apt-get install realpath - apt-get install clang-format-5.0 + apt-get install clang-format-6.0 apt-get install automake apt-get install ninja-build apt-get install curl @@ -231,7 +231,7 @@ bazel test -c dbg --config=asan //test/... The ASAN failure stack traces include line numbers as a result of running ASAN with a `dbg` build above. -If you have clang-5.0, additional checks are provided with: +If you have clang-5.0 or newer, additional checks are provided with: ``` bazel test -c dbg --config=clang-asan //test/... diff --git a/ci/README.md b/ci/README.md index 4bc941cf962e..49135af40a0c 100644 --- a/ci/README.md +++ b/ci/README.md @@ -26,7 +26,7 @@ Currently there are three build images: * `envoyproxy/envoy-build-ubuntu` — based on Ubuntu 16.04 (Xenial) which uses the GCC 5.4 compiler. * `envoyproxy/envoy-build-centos` — based on CentOS 7 which uses the GCC 5.3.1 compiler (devtoolset-4). -We also install and use the clang-5.0 compiler for some sanitizing runs. +We also install and use the clang-6.0 compiler for some sanitizing runs. # Building and running tests as a developer @@ -77,8 +77,8 @@ The build artifact can be found in `/tmp/envoy-docker-build/envoy/source/exe/env The `./ci/run_envoy_docker.sh './ci/do_ci.sh '` targets are: -* `bazel.api` — build and run API tests under `-c fastbuild` with clang-5.0. -* `bazel.asan` — build and run tests under `-c dbg --config=clang-asan` with clang-5.0. +* `bazel.api` — build and run API tests under `-c fastbuild` with clang-6.0. +* `bazel.asan` — build and run tests under `-c dbg --config=clang-asan` with clang-6.0. * `bazel.debug` — build Envoy static binary and run tests under `-c dbg`. * `bazel.debug.server_only` — build Envoy static binary under `-c dbg`. * `bazel.dev` — build Envoy static binary and run tests under `-c fastbuild` with gcc. @@ -87,9 +87,9 @@ The `./ci/run_envoy_docker.sh './ci/do_ci.sh '` targets are: * `bazel.release.server_only` — build Envoy static binary under `-c opt` with gcc. * `bazel.coverage` — build and run tests under `-c dbg` with gcc, generating coverage information in `$ENVOY_DOCKER_BUILD_DIR/envoy/generated/coverage/coverage.html`. * `bazel.coverity` — build Envoy static binary and run Coverity Scan static analysis. -* `bazel.tsan` — build and run tests under `-c dbg --config=clang-tsan` with clang-5.0. -* `check_format`— run `clang-format` 5.0 and `buildifier` on entire source tree. -* `fix_format`— run and enforce `clang-format` 5.0 and `buildifier` on entire source tree. +* `bazel.tsan` — build and run tests under `-c dbg --config=clang-tsan` with clang-6.0. +* `check_format`— run `clang-format-6.0` and `buildifier` on entire source tree. +* `fix_format`— run and enforce `clang-format-6.0` and `buildifier` on entire source tree. * `docs`— build documentation tree in `generated/docs`. # Testing changes to the build image as a developer diff --git a/ci/build_setup.sh b/ci/build_setup.sh index dba93c0dd78d..327448e51371 100755 --- a/ci/build_setup.sh +++ b/ci/build_setup.sh @@ -17,9 +17,9 @@ function setup_gcc_toolchain() { } function setup_clang_toolchain() { - export CC=clang-5.0 - export CXX=clang++-5.0 - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer + export CC=clang-6.0 + export CXX=clang++-6.0 + export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer echo "$CC/$CXX toolchain configured" } diff --git a/include/envoy/common/pure.h b/include/envoy/common/pure.h index 70a748253c9d..ecc74586618b 100644 --- a/include/envoy/common/pure.h +++ b/include/envoy/common/pure.h @@ -5,4 +5,4 @@ namespace Envoy { * Friendly name for a pure virtual routine. */ #define PURE = 0 -} // Envoy +} // namespace Envoy diff --git a/include/envoy/secret/BUILD b/include/envoy/secret/BUILD index 6124d51a3210..7ed7b2be4e66 100644 --- a/include/envoy/secret/BUILD +++ b/include/envoy/secret/BUILD @@ -8,10 +8,16 @@ load( envoy_package() +envoy_cc_library( + name = "secret_callbacks_interface", + hdrs = ["secret_callbacks.h"], +) + envoy_cc_library( name = "secret_provider_interface", hdrs = ["secret_provider.h"], deps = [ + ":secret_callbacks_interface", "//include/envoy/ssl:tls_certificate_config_interface", ], ) @@ -22,5 +28,6 @@ envoy_cc_library( deps = [ ":secret_provider_interface", "@envoy_api//envoy/api/v2/auth:cert_cc", + "@envoy_api//envoy/api/v2/core:config_source_cc", ], ) diff --git a/include/envoy/secret/secret_callbacks.h b/include/envoy/secret/secret_callbacks.h new file mode 100644 index 000000000000..b4c637c59cf9 --- /dev/null +++ b/include/envoy/secret/secret_callbacks.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "envoy/common/pure.h" + +namespace Envoy { +namespace Secret { + +/** + * Callbacks invoked by a dynamic secret provider. + */ +class SecretCallbacks { +public: + virtual ~SecretCallbacks() {} + + virtual void onAddOrUpdateSecret() PURE; +}; + +} // namespace Secret +} // namespace Envoy \ No newline at end of file diff --git a/include/envoy/secret/secret_manager.h b/include/envoy/secret/secret_manager.h index 85f5e7228f72..c3775f1b0de0 100644 --- a/include/envoy/secret/secret_manager.h +++ b/include/envoy/secret/secret_manager.h @@ -6,12 +6,17 @@ #include "envoy/secret/secret_provider.h" namespace Envoy { + +namespace Server { +namespace Configuration { +class TransportSocketFactoryContext; +} // namespace Configuration +} // namespace Server + namespace Secret { /** - * A manager for static secrets. - * - * TODO(jaebong) Support dynamic secrets. + * A manager for static and dynamic secrets. */ class SecretManager { public: @@ -37,6 +42,20 @@ class SecretManager { */ virtual TlsCertificateConfigProviderSharedPtr createInlineTlsCertificateProvider( const envoy::api::v2::auth::TlsCertificate& tls_certificate) PURE; + + /** + * Finds and returns a dynamic secret provider associated to SDS config. Create + * a new one if such provider does not exist. + * + * @param config_source a protobuf message object contains SDS config source. + * @param config_name a name that uniquely refers to the SDS config source + * @param secret_provider_context context that provides components for creating and initializing + * secret provider. + * @return the dynamic TLS secret provider. + */ + virtual TlsCertificateConfigProviderSharedPtr findOrCreateDynamicSecretProvider( + const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context) PURE; }; } // namespace Secret diff --git a/include/envoy/secret/secret_provider.h b/include/envoy/secret/secret_provider.h index b6f9f26ca76c..2c762da96f25 100644 --- a/include/envoy/secret/secret_provider.h +++ b/include/envoy/secret/secret_provider.h @@ -1,6 +1,7 @@ #pragma once #include "envoy/common/pure.h" +#include "envoy/secret/secret_callbacks.h" #include "envoy/ssl/tls_certificate_config.h" namespace Envoy { @@ -18,7 +19,17 @@ template class SecretProvider { */ virtual const SecretType* secret() const PURE; - // TODO(lizan): Add more methods for dynamic secret provider. + /** + * Add secret callback into secret provider. + * @param callback callback that is executed by secret provider. + */ + virtual void addUpdateCallback(SecretCallbacks& callback) PURE; + + /** + * Remove secret callback from secret provider. + * @param callback callback that is executed by secret provider. + */ + virtual void removeUpdateCallback(SecretCallbacks& callback) PURE; }; typedef SecretProvider TlsCertificateConfigProvider; diff --git a/include/envoy/server/BUILD b/include/envoy/server/BUILD index 35f6829a7fad..3a367b75343f 100644 --- a/include/envoy/server/BUILD +++ b/include/envoy/server/BUILD @@ -177,6 +177,7 @@ envoy_cc_library( hdrs = ["transport_socket_config.h"], deps = [ "//include/envoy/event:dispatcher_interface", + "//include/envoy/init:init_interface", "//include/envoy/local_info:local_info_interface", "//include/envoy/network:transport_socket_interface", "//include/envoy/runtime:runtime_interface", diff --git a/include/envoy/server/transport_socket_config.h b/include/envoy/server/transport_socket_config.h index 143be130d079..5f082fda925d 100644 --- a/include/envoy/server/transport_socket_config.h +++ b/include/envoy/server/transport_socket_config.h @@ -3,6 +3,7 @@ #include #include "envoy/event/dispatcher.h" +#include "envoy/init/init.h" #include "envoy/local_info/local_info.h" #include "envoy/network/transport_socket.h" #include "envoy/runtime/runtime.h" @@ -63,6 +64,18 @@ class TransportSocketFactoryContext { * @return the server-wide stats store. */ virtual Stats::Store& stats() PURE; + + /** + * Pass an init manager to register dynamic secret provider. + * @param init_manager instance of init manager. + */ + virtual void setInitManager(Init::Manager& init_manager) PURE; + + /** + * @return a pointer pointing to the instance of an init manager, or nullptr + * if not set. + */ + virtual Init::Manager* initManager() PURE; }; class TransportSocketConfigFactory { diff --git a/include/envoy/ssl/BUILD b/include/envoy/ssl/BUILD index 315b9a5071d5..e4e8582d124f 100644 --- a/include/envoy/ssl/BUILD +++ b/include/envoy/ssl/BUILD @@ -22,7 +22,7 @@ envoy_cc_library( name = "context_config_interface", hdrs = ["context_config.h"], deps = [ - ":tls_certificate_config_interface", + "//include/envoy/secret:secret_provider_interface", ], ) diff --git a/include/envoy/ssl/context_config.h b/include/envoy/ssl/context_config.h index 749cc8451656..5b74602348e3 100644 --- a/include/envoy/ssl/context_config.h +++ b/include/envoy/ssl/context_config.h @@ -5,9 +5,12 @@ #include #include "envoy/common/pure.h" -#include "envoy/ssl/tls_certificate_config.h" +#include "envoy/secret/secret_provider.h" namespace Envoy { +namespace Secret { +class SecretCallbacks; +} // namespace Secret namespace Ssl { /** @@ -95,6 +98,17 @@ class ContextConfig { * @return The maximum TLS protocol version to negotiate. */ virtual unsigned maxProtocolVersion() const PURE; + + /** + * @return true if the ssl config is ready. + */ + virtual bool isReady() const PURE; + + /** + * Add secret callback into context config. + * @param callback callback that is executed by context config. + */ + virtual void setSecretUpdateCallback(Secret::SecretCallbacks& callback) PURE; }; class ClientContextConfig : public virtual ContextConfig { diff --git a/include/envoy/stats/stats_macros.h b/include/envoy/stats/stats_macros.h index 0520b31a845e..eb1c89557c66 100644 --- a/include/envoy/stats/stats_macros.h +++ b/include/envoy/stats/stats_macros.h @@ -40,4 +40,4 @@ namespace Envoy { #define POOL_COUNTER(POOL) POOL_COUNTER_PREFIX(POOL, "") #define POOL_GAUGE(POOL) POOL_GAUGE_PREFIX(POOL, "") #define POOL_HISTOGRAM(POOL) POOL_HISTOGRAM_PREFIX(POOL, "") -} // Envoy +} // namespace Envoy diff --git a/include/envoy/tcp/conn_pool.h b/include/envoy/tcp/conn_pool.h index 8237af37fea3..15e2eaacc377 100644 --- a/include/envoy/tcp/conn_pool.h +++ b/include/envoy/tcp/conn_pool.h @@ -57,6 +57,22 @@ class UpstreamCallbacks : public Network::ConnectionCallbacks { virtual void onUpstreamData(Buffer::Instance& data, bool end_stream) PURE; }; +/** + * ConnectionState is a base class for connection state maintained across requests. For example, a + * protocol may maintain a connection-specific request sequence number or negotiate options that + * affect the behavior of requests for the duration of the connection. A ConnectionState subclass + * is assigned to the ConnectionData to track this state when the connection is returned to the + * pool so that the state is available when the connection is re-used for a subsequent request. + * The ConnectionState assigned to a connection is automatically destroyed when the connection is + * closed. + */ +class ConnectionState { +public: + virtual ~ConnectionState() {} +}; + +typedef std::unique_ptr ConnectionStatePtr; + /* * ConnectionData wraps a ClientConnection allocated to a caller. Open ClientConnections are * released back to the pool for re-use when their containing ConnectionData is destroyed. @@ -70,6 +86,18 @@ class ConnectionData { */ virtual Network::ClientConnection& connection() PURE; + /** + * Sets the ConnectionState for this connection. Any existing ConnectionState is destroyed. + * @param ConnectionStatePtr&& new ConnectionState for this connection. + */ + virtual void setConnectionState(ConnectionStatePtr&& state) PURE; + + /** + * @return T* the current ConnectionState or nullptr if no state is set or if the state's type + * is not T. + */ + template T* connectionStateTyped() { return dynamic_cast(connectionState()); } + /** * Sets the ConnectionPool::UpstreamCallbacks for the connection. If no callback is attached, * data from the upstream will cause the connection to be closed. Callbacks cease when the @@ -77,6 +105,12 @@ class ConnectionData { * @param callback the UpstreamCallbacks to invoke for upstream data */ virtual void addUpstreamCallbacks(ConnectionPool::UpstreamCallbacks& callback) PURE; + +protected: + /** + * @return ConnectionState* pointer to the current ConnectionState or nullptr if not set + */ + virtual ConnectionState* connectionState() PURE; }; typedef std::unique_ptr ConnectionDataPtr; diff --git a/include/envoy/upstream/host_description.h b/include/envoy/upstream/host_description.h index 9f5eb67f7ba2..3cac6809d372 100644 --- a/include/envoy/upstream/host_description.h +++ b/include/envoy/upstream/host_description.h @@ -112,5 +112,5 @@ class HostDescription { typedef std::shared_ptr HostDescriptionConstSharedPtr; -} // Upstream +} // namespace Upstream } // namespace Envoy diff --git a/source/common/common/assert.h b/source/common/common/assert.h index 3654a160df2c..d19270e27296 100644 --- a/source/common/common/assert.h +++ b/source/common/common/assert.h @@ -66,4 +66,4 @@ namespace Envoy { // after a switch (some_enum) with all enum values included in the cases. The macro name includes // "GCOVR_EXCL_LINE" to exclude the macro's usage from code coverage reports. #define NOT_REACHED_GCOVR_EXCL_LINE PANIC("not reached") -} // Envoy +} // namespace Envoy diff --git a/source/common/common/compiler_requirements.h b/source/common/common/compiler_requirements.h index 5048737cdde7..377b0286a5ac 100644 --- a/source/common/common/compiler_requirements.h +++ b/source/common/common/compiler_requirements.h @@ -17,4 +17,4 @@ namespace Envoy { "ENVOY_IGNORE_GLIBCXX_USE_CXX11_ABI_ERROR=1 in your build." #endif -} // Envoy +} // namespace Envoy diff --git a/source/common/common/logger.cc b/source/common/common/logger.cc index 2acb67335d52..080c7fb92c5e 100644 --- a/source/common/common/logger.cc +++ b/source/common/common/logger.cc @@ -88,5 +88,5 @@ void Registry::setLogFormat(const std::string& log_format) { } } -} // Logger +} // namespace Logger } // namespace Envoy diff --git a/source/common/common/logger.h b/source/common/common/logger.h index f83063cc08c4..6e86eaa5acb9 100644 --- a/source/common/common/logger.h +++ b/source/common/common/logger.h @@ -44,6 +44,7 @@ namespace Logger { FUNCTION(router) \ FUNCTION(runtime) \ FUNCTION(stats) \ + FUNCTION(secret) \ FUNCTION(testing) \ FUNCTION(thrift) \ FUNCTION(tracing) \ @@ -240,7 +241,7 @@ template class Loggable { } }; -} // Logger +} // namespace Logger // Convert the line macro to a string literal for concatenation in log macros. #define DO_STRINGIZE(x) STRINGIZE(x) diff --git a/source/common/common/macros.h b/source/common/common/macros.h index 8a16a19a3c1f..60955adc7729 100644 --- a/source/common/common/macros.h +++ b/source/common/common/macros.h @@ -44,4 +44,4 @@ namespace Envoy { #define FALLTHRU #endif -} // Envoy +} // namespace Envoy diff --git a/source/common/config/BUILD b/source/common/config/BUILD index cd52a50719dc..179a9d32c95b 100644 --- a/source/common/config/BUILD +++ b/source/common/config/BUILD @@ -242,6 +242,7 @@ envoy_cc_library( hdrs = ["protobuf_link_hacks.h"], deps = [ "@envoy_api//envoy/service/discovery/v2:ads_cc", + "@envoy_api//envoy/service/discovery/v2:sds_cc", "@envoy_api//envoy/service/ratelimit/v2:rls_cc", ], ) diff --git a/source/common/config/filter_json.cc b/source/common/config/filter_json.cc index b411262c4a63..f37279fc234d 100644 --- a/source/common/config/filter_json.cc +++ b/source/common/config/filter_json.cc @@ -161,8 +161,9 @@ void FilterJson::translateHttpConnectionManager( json_filter->getString("name"))); JSON_UTIL_SET_STRING(*json_filter, *filter->mutable_deprecated_v1(), type); - const std::string deprecated_config = "{\"deprecated_v1\": true, \"value\": " + - json_filter->getObject("config")->asJsonString() + "}"; + const std::string deprecated_config = + "{\"deprecated_v1\": true, \"value\": " + json_filter->getObject("config")->asJsonString() + + "}"; const auto status = Protobuf::util::JsonStringToMessage(deprecated_config, filter->mutable_config()); diff --git a/source/common/config/lds_json.cc b/source/common/config/lds_json.cc index 45daf88a91cb..9a0e6ab2cf41 100644 --- a/source/common/config/lds_json.cc +++ b/source/common/config/lds_json.cc @@ -41,8 +41,9 @@ void LdsJson::translateListener(const Json::Object& json_listener, json_filter->getString("name"))); JSON_UTIL_SET_STRING(*json_filter, *filter->mutable_deprecated_v1(), type); - const std::string json_config = "{\"deprecated_v1\": true, \"value\": " + - json_filter->getObject("config")->asJsonString() + "}"; + const std::string json_config = + "{\"deprecated_v1\": true, \"value\": " + json_filter->getObject("config")->asJsonString() + + "}"; const auto status = Protobuf::util::JsonStringToMessage(json_config, filter->mutable_config()); // JSON schema has already validated that this is a valid JSON object. diff --git a/source/common/config/protobuf_link_hacks.h b/source/common/config/protobuf_link_hacks.h index 6792f3e797c1..6a9284625355 100644 --- a/source/common/config/protobuf_link_hacks.h +++ b/source/common/config/protobuf_link_hacks.h @@ -1,6 +1,7 @@ #pragma once #include "envoy/service/discovery/v2/ads.pb.h" +#include "envoy/service/discovery/v2/sds.pb.h" #include "envoy/service/ratelimit/v2/rls.pb.h" namespace Envoy { @@ -9,4 +10,5 @@ namespace Envoy { // This file should be included ONLY if this hack is required. const envoy::service::discovery::v2::AdsDummy _ads_dummy; const envoy::service::ratelimit::v2::RateLimitRequest _rls_dummy; +const envoy::service::discovery::v2::SdsDummy _sds_dummy; } // namespace Envoy diff --git a/source/common/config/resources.h b/source/common/config/resources.h index 03f0c9a2efd8..69ed2d91a46d 100644 --- a/source/common/config/resources.h +++ b/source/common/config/resources.h @@ -15,6 +15,7 @@ class TypeUrlValues { const std::string Listener{"type.googleapis.com/envoy.api.v2.Listener"}; const std::string Cluster{"type.googleapis.com/envoy.api.v2.Cluster"}; const std::string ClusterLoadAssignment{"type.googleapis.com/envoy.api.v2.ClusterLoadAssignment"}; + const std::string Secret{"type.googleapis.com/envoy.api.v2.auth.Secret"}; const std::string RouteConfiguration{"type.googleapis.com/envoy.api.v2.RouteConfiguration"}; }; diff --git a/source/common/filesystem/filesystem_impl.h b/source/common/filesystem/filesystem_impl.h index 7f50a89a6d02..2ce5d9090d86 100644 --- a/source/common/filesystem/filesystem_impl.h +++ b/source/common/filesystem/filesystem_impl.h @@ -132,10 +132,10 @@ class FileImpl : public File { Thread::CondVar flush_event_; std::atomic flush_thread_exit_{}; std::atomic reopen_file_{}; - Buffer::OwnedImpl flush_buffer_ - GUARDED_BY(write_lock_); // This buffer is used by multiple threads. It gets filled and - // then flushed either when max size is reached or when a timer - // fires. + Buffer::OwnedImpl + flush_buffer_ GUARDED_BY(write_lock_); // This buffer is used by multiple threads. It gets + // filled and then flushed either when max size is + // reached or when a timer fires. // TODO(jmarantz): this should be GUARDED_BY(flush_lock_) but the analysis cannot poke through // the std::make_unique assignment. I do not believe it's possible to annotate this properly now // due to limitations in the clang thread annotation analysis. @@ -153,4 +153,4 @@ class FileImpl : public File { }; } // namespace Filesystem -} // Envoy +} // namespace Envoy diff --git a/source/common/http/conn_manager_config.h b/source/common/http/conn_manager_config.h index a38a9035f46f..a1dae7a55e2a 100644 --- a/source/common/http/conn_manager_config.h +++ b/source/common/http/conn_manager_config.h @@ -293,5 +293,5 @@ class ConnectionManagerConfig { */ virtual const Http::Http1Settings& http1Settings() const PURE; }; -} +} // namespace Http } // namespace Envoy diff --git a/source/common/http/header_map_impl.h b/source/common/http/header_map_impl.h index ae507866d2af..fd2ae9570e7e 100644 --- a/source/common/http/header_map_impl.h +++ b/source/common/http/header_map_impl.h @@ -209,5 +209,5 @@ class HeaderMapImpl : public HeaderMap, NonCopyable { typedef std::unique_ptr HeaderMapImplPtr; -} // Http +} // namespace Http } // namespace Envoy diff --git a/source/common/http/http2/codec_impl.cc b/source/common/http/http2/codec_impl.cc index 200c33441995..c9f623a43445 100644 --- a/source/common/http/http2/codec_impl.cc +++ b/source/common/http/http2/codec_impl.cc @@ -673,7 +673,6 @@ ConnectionImpl::Http2Callbacks::Http2Callbacks() { callbacks_, [](nghttp2_session*, const nghttp2_frame* frame, const uint8_t* raw_name, size_t name_length, const uint8_t* raw_value, size_t value_length, uint8_t, void* user_data) -> int { - // TODO PERF: Can reference count here to avoid copies. HeaderString name; name.setCopy(reinterpret_cast(raw_name), name_length); diff --git a/source/common/http/user_agent.h b/source/common/http/user_agent.h index d63ff8126a58..257be50ad8e6 100644 --- a/source/common/http/user_agent.h +++ b/source/common/http/user_agent.h @@ -68,4 +68,4 @@ class UserAgent { }; } // namespace Http -} // Envoy +} // namespace Envoy diff --git a/source/common/router/router.cc b/source/common/router/router.cc index 838d937454c7..544cda92b8f7 100644 --- a/source/common/router/router.cc +++ b/source/common/router/router.cc @@ -222,14 +222,14 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::HeaderMap& headers, bool e direct_response->rewritePathHeader(headers, !config_.suppress_envoy_headers_); callbacks_->sendLocalReply( direct_response->responseCode(), direct_response->responseBody(), - [ this, direct_response, &request_headers = headers ](Http::HeaderMap & response_headers) - ->void { - const auto new_path = direct_response->newPath(request_headers); - if (!new_path.empty()) { - response_headers.addReferenceKey(Http::Headers::get().Location, new_path); - } - direct_response->finalizeResponseHeaders(response_headers, callbacks_->requestInfo()); - }); + [this, direct_response, + &request_headers = headers](Http::HeaderMap& response_headers) -> void { + const auto new_path = direct_response->newPath(request_headers); + if (!new_path.empty()) { + response_headers.addReferenceKey(Http::Headers::get().Location, new_path); + } + direct_response->finalizeResponseHeaders(response_headers, callbacks_->requestInfo()); + }); return Http::FilterHeadersStatus::StopIteration; } diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc index 99bd48a4f6ec..8f4178282190 100644 --- a/source/common/runtime/runtime_impl.cc +++ b/source/common/runtime/runtime_impl.cc @@ -315,7 +315,7 @@ std::unique_ptr LoaderImpl::createNewSnapshot() { void LoaderImpl::loadNewSnapshot() { ThreadLocal::ThreadLocalObjectSharedPtr ptr = createNewSnapshot(); - tls_->set([ptr = std::move(ptr)](Event::Dispatcher&)->ThreadLocal::ThreadLocalObjectSharedPtr { + tls_->set([ptr = std::move(ptr)](Event::Dispatcher&) -> ThreadLocal::ThreadLocalObjectSharedPtr { return ptr; }); } diff --git a/source/common/secret/BUILD b/source/common/secret/BUILD index 598d8249fa5e..b568425ddf01 100644 --- a/source/common/secret/BUILD +++ b/source/common/secret/BUILD @@ -13,8 +13,11 @@ envoy_cc_library( srcs = ["secret_manager_impl.cc"], hdrs = ["secret_manager_impl.h"], deps = [ + ":sds_api_lib", ":secret_provider_impl_lib", "//include/envoy/secret:secret_manager_interface", + "//include/envoy/server:transport_socket_config_interface", + "//source/common/common:assert_lib", "//source/common/common:minimal_logger_lib", "@envoy_api//envoy/api/v2/auth:cert_cc", ], @@ -30,3 +33,22 @@ envoy_cc_library( "@envoy_api//envoy/api/v2/auth:cert_cc", ], ) + +envoy_cc_library( + name = "sds_api_lib", + srcs = ["sds_api.cc"], + hdrs = ["sds_api.h"], + deps = [ + "//include/envoy/config:subscription_interface", + "//include/envoy/event:dispatcher_interface", + "//include/envoy/init:init_interface", + "//include/envoy/local_info:local_info_interface", + "//include/envoy/runtime:runtime_interface", + "//include/envoy/secret:secret_provider_interface", + "//include/envoy/stats:stats_interface", + "//source/common/config:resources_lib", + "//source/common/config:subscription_factory_lib", + "//source/common/protobuf:utility_lib", + "//source/common/ssl:tls_certificate_config_impl_lib", + ], +) diff --git a/source/common/secret/sds_api.cc b/source/common/secret/sds_api.cc new file mode 100644 index 000000000000..18a975d87127 --- /dev/null +++ b/source/common/secret/sds_api.cc @@ -0,0 +1,89 @@ +#include "common/secret/sds_api.h" + +#include + +#include "envoy/api/v2/auth/cert.pb.validate.h" + +#include "common/config/resources.h" +#include "common/config/subscription_factory.h" +#include "common/protobuf/utility.h" +#include "common/ssl/tls_certificate_config_impl.h" + +namespace Envoy { +namespace Secret { + +SdsApi::SdsApi(const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispatcher, + Runtime::RandomGenerator& random, Stats::Store& stats, + Upstream::ClusterManager& cluster_manager, Init::Manager& init_manager, + const envoy::api::v2::core::ConfigSource& sds_config, std::string sds_config_name, + std::function unregister_secret_provider) + : local_info_(local_info), dispatcher_(dispatcher), random_(random), stats_(stats), + cluster_manager_(cluster_manager), sds_config_(sds_config), sds_config_name_(sds_config_name), + secret_hash_(0), unregister_secret_provider_cb_(unregister_secret_provider) { + // TODO(JimmyCYJ): Implement chained_init_manager, so that multiple init_manager + // can be chained together to behave as one init_manager. In that way, we let + // two listeners which share same SdsApi to register at separate init managers, and + // each init manager has a chance to initialize its targets. + init_manager.registerTarget(*this); +} + +SdsApi::~SdsApi() { unregister_secret_provider_cb_(); } + +void SdsApi::initialize(std::function callback) { + initialize_callback_ = callback; + + subscription_ = Envoy::Config::SubscriptionFactory::subscriptionFromConfigSource< + envoy::api::v2::auth::Secret>( + sds_config_, local_info_.node(), dispatcher_, cluster_manager_, random_, stats_, + /* rest_legacy_constructor */ nullptr, + "envoy.service.discovery.v2.SecretDiscoveryService.FetchSecrets", + "envoy.service.discovery.v2.SecretDiscoveryService.StreamSecrets"); + Config::Utility::checkLocalInfo("sds", local_info_); + + subscription_->start({sds_config_name_}, *this); +} + +void SdsApi::onConfigUpdate(const ResourceVector& resources, const std::string&) { + if (resources.empty()) { + throw EnvoyException( + fmt::format("Missing SDS resources for {} in onConfigUpdate()", sds_config_name_)); + } + if (resources.size() != 1) { + throw EnvoyException(fmt::format("Unexpected SDS secrets length: {}", resources.size())); + } + const auto& secret = resources[0]; + MessageUtil::validate(secret); + if (!(secret.name() == sds_config_name_)) { + throw EnvoyException( + fmt::format("Unexpected SDS secret (expecting {}): {}", sds_config_name_, secret.name())); + } + + const uint64_t new_hash = MessageUtil::hash(secret); + if (new_hash != secret_hash_ && + secret.type_case() == envoy::api::v2::auth::Secret::TypeCase::kTlsCertificate) { + secret_hash_ = new_hash; + tls_certificate_secrets_ = + std::make_unique(secret.tls_certificate()); + + for (auto cb : update_callbacks_) { + cb->onAddOrUpdateSecret(); + } + } + + runInitializeCallbackIfAny(); +} + +void SdsApi::onConfigUpdateFailed(const EnvoyException*) { + // We need to allow server startup to continue, even if we have a bad config. + runInitializeCallbackIfAny(); +} + +void SdsApi::runInitializeCallbackIfAny() { + if (initialize_callback_) { + initialize_callback_(); + initialize_callback_ = nullptr; + } +} + +} // namespace Secret +} // namespace Envoy diff --git a/source/common/secret/sds_api.h b/source/common/secret/sds_api.h new file mode 100644 index 000000000000..78227bf43907 --- /dev/null +++ b/source/common/secret/sds_api.h @@ -0,0 +1,81 @@ +#pragma once + +#include + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/api/v2/core/config_source.pb.h" +#include "envoy/config/subscription.h" +#include "envoy/event/dispatcher.h" +#include "envoy/init/init.h" +#include "envoy/local_info/local_info.h" +#include "envoy/runtime/runtime.h" +#include "envoy/secret/secret_callbacks.h" +#include "envoy/secret/secret_manager.h" +#include "envoy/secret/secret_provider.h" +#include "envoy/stats/stats.h" +#include "envoy/upstream/cluster_manager.h" + +namespace Envoy { +namespace Secret { + +/** + * SDS API implementation that fetches secrets from SDS server via Subscription. + */ +class SdsApi : public Init::Target, + public TlsCertificateConfigProvider, + public Config::SubscriptionCallbacks { +public: + SdsApi(const LocalInfo::LocalInfo& local_info, Event::Dispatcher& dispatcher, + Runtime::RandomGenerator& random, Stats::Store& stats, + Upstream::ClusterManager& cluster_manager, Init::Manager& init_manager, + const envoy::api::v2::core::ConfigSource& sds_config, std::string sds_config_name, + std::function unregister_secret_provider); + + ~SdsApi() override; + + // Init::Target + void initialize(std::function callback) override; + + // Config::SubscriptionCallbacks + void onConfigUpdate(const ResourceVector& resources, const std::string& version_info) override; + void onConfigUpdateFailed(const EnvoyException* e) override; + std::string resourceName(const ProtobufWkt::Any& resource) override { + return MessageUtil::anyConvert(resource).name(); + } + + // SecretProvider + const Ssl::TlsCertificateConfig* secret() const override { + return tls_certificate_secrets_.get(); + } + + void addUpdateCallback(SecretCallbacks& callback) override { + update_callbacks_.push_back(&callback); + } + void removeUpdateCallback(SecretCallbacks& callback) override { + update_callbacks_.remove(&callback); + } + +private: + void runInitializeCallbackIfAny(); + + const LocalInfo::LocalInfo& local_info_; + Event::Dispatcher& dispatcher_; + Runtime::RandomGenerator& random_; + Stats::Store& stats_; + Upstream::ClusterManager& cluster_manager_; + + const envoy::api::v2::core::ConfigSource sds_config_; + std::unique_ptr> subscription_; + std::function initialize_callback_; + const std::string sds_config_name_; + + uint64_t secret_hash_; + std::function unregister_secret_provider_cb_; + Ssl::TlsCertificateConfigPtr tls_certificate_secrets_; + std::list update_callbacks_; +}; + +typedef std::unique_ptr SdsApiPtr; + +} // namespace Secret +} // namespace Envoy \ No newline at end of file diff --git a/source/common/secret/secret_manager_impl.cc b/source/common/secret/secret_manager_impl.cc index f3f2c9549ea8..745e01ace9ef 100644 --- a/source/common/secret/secret_manager_impl.cc +++ b/source/common/secret/secret_manager_impl.cc @@ -3,6 +3,7 @@ #include "envoy/common/exception.h" #include "common/common/assert.h" +#include "common/secret/sds_api.h" #include "common/secret/secret_provider_impl.h" #include "common/ssl/tls_certificate_config_impl.h" @@ -37,5 +38,37 @@ TlsCertificateConfigProviderSharedPtr SecretManagerImpl::createInlineTlsCertific return std::make_shared(tls_certificate); } +void SecretManagerImpl::removeDynamicSecretProvider(const std::string& map_key) { + ENVOY_LOG(debug, "Unregister secret provider. hash key: {}", map_key); + + if (dynamic_secret_providers_.erase(map_key) == 0) { + ENVOY_LOG(error, "secret provider does not exist. hash key: {}", map_key); + } +} + +TlsCertificateConfigProviderSharedPtr SecretManagerImpl::findOrCreateDynamicSecretProvider( + const envoy::api::v2::core::ConfigSource& sds_config_source, const std::string& config_name, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context) { + std::string map_key = std::to_string(MessageUtil::hash(sds_config_source)) + config_name; + + auto secret_provider = dynamic_secret_providers_[map_key].lock(); + if (!secret_provider) { + ASSERT(secret_provider_context.initManager() != nullptr); + + std::function unregister_secret_provider = [map_key, this]() { + removeDynamicSecretProvider(map_key); + }; + + secret_provider = std::make_shared( + secret_provider_context.localInfo(), secret_provider_context.dispatcher(), + secret_provider_context.random(), secret_provider_context.stats(), + secret_provider_context.clusterManager(), *secret_provider_context.initManager(), + sds_config_source, config_name, unregister_secret_provider); + dynamic_secret_providers_[map_key] = secret_provider; + } + + return secret_provider; +} + } // namespace Secret } // namespace Envoy diff --git a/source/common/secret/secret_manager_impl.h b/source/common/secret/secret_manager_impl.h index 6af790f50c42..b68047281d36 100644 --- a/source/common/secret/secret_manager_impl.h +++ b/source/common/secret/secret_manager_impl.h @@ -4,6 +4,7 @@ #include "envoy/secret/secret_manager.h" #include "envoy/secret/secret_provider.h" +#include "envoy/server/transport_socket_config.h" #include "envoy/ssl/tls_certificate_config.h" #include "common/common/logger.h" @@ -11,17 +12,31 @@ namespace Envoy { namespace Secret { -class SecretManagerImpl : public SecretManager, Logger::Loggable { +class SecretManagerImpl : public SecretManager, Logger::Loggable { public: void addStaticSecret(const envoy::api::v2::auth::Secret& secret) override; + TlsCertificateConfigProviderSharedPtr findStaticTlsCertificateProvider(const std::string& name) const override; + TlsCertificateConfigProviderSharedPtr createInlineTlsCertificateProvider( const envoy::api::v2::auth::TlsCertificate& tls_certificate) override; + TlsCertificateConfigProviderSharedPtr findOrCreateDynamicSecretProvider( + const envoy::api::v2::core::ConfigSource& config_source, const std::string& config_name, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context) override; + private: + // Remove dynamic secret provider which has been deleted. + void removeDynamicSecretProvider(const std::string& map_key); + + // Manages pairs of secret name and TlsCertificateConfigProviderSharedPtr. std::unordered_map static_tls_certificate_providers_; + + // map hash code of SDS config source and SdsApi object. + std::unordered_map> + dynamic_secret_providers_; }; } // namespace Secret diff --git a/source/common/secret/secret_provider_impl.h b/source/common/secret/secret_provider_impl.h index 9ac79c66009c..e6731e0b0af8 100644 --- a/source/common/secret/secret_provider_impl.h +++ b/source/common/secret/secret_provider_impl.h @@ -13,6 +13,10 @@ class TlsCertificateConfigProviderImpl : public TlsCertificateConfigProvider { const Ssl::TlsCertificateConfig* secret() const override { return tls_certificate_.get(); } + void addUpdateCallback(SecretCallbacks&) override {} + + void removeUpdateCallback(SecretCallbacks&) override {} + private: Ssl::TlsCertificateConfigPtr tls_certificate_; }; diff --git a/source/common/ssl/BUILD b/source/common/ssl/BUILD index abc98f802ff0..8a4a4b015432 100644 --- a/source/common/ssl/BUILD +++ b/source/common/ssl/BUILD @@ -19,6 +19,7 @@ envoy_cc_library( ":utility_lib", "//include/envoy/network:connection_interface", "//include/envoy/network:transport_socket_interface", + "//include/envoy/stats:stats_macros", "//source/common/common:assert_lib", "//source/common/common:empty_string", "//source/common/common:minimal_logger_lib", @@ -34,8 +35,9 @@ envoy_cc_library( "ssl", ], deps = [ - "//include/envoy/secret:secret_manager_interface", + "//include/envoy/secret:secret_callbacks_interface", "//include/envoy/secret:secret_provider_interface", + "//include/envoy/server:transport_socket_config_interface", "//include/envoy/ssl:context_config_interface", "//source/common/common:assert_lib", "//source/common/common:empty_string", diff --git a/source/common/ssl/context_config_impl.cc b/source/common/ssl/context_config_impl.cc index fd9f49ed210c..8d8591be21f7 100644 --- a/source/common/ssl/context_config_impl.cc +++ b/source/common/ssl/context_config_impl.cc @@ -16,26 +16,31 @@ namespace Ssl { namespace { -Secret::TlsCertificateConfigProviderSharedPtr -getTlsCertificateConfigProvider(const envoy::api::v2::auth::CommonTlsContext& config, - Secret::SecretManager& secret_manager) { +Secret::TlsCertificateConfigProviderSharedPtr getTlsCertificateConfigProvider( + const envoy::api::v2::auth::CommonTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) { if (!config.tls_certificates().empty()) { const auto& tls_certificate = config.tls_certificates(0); if (!tls_certificate.has_certificate_chain() && !tls_certificate.has_private_key()) { return nullptr; } - return secret_manager.createInlineTlsCertificateProvider(config.tls_certificates(0)); + return factory_context.secretManager().createInlineTlsCertificateProvider( + config.tls_certificates(0)); } if (!config.tls_certificate_sds_secret_configs().empty()) { const auto& sds_secret_config = config.tls_certificate_sds_secret_configs(0); - - auto secret_provider = - secret_manager.findStaticTlsCertificateProvider(sds_secret_config.name()); - if (!secret_provider) { - throw EnvoyException( - fmt::format("Static secret is not defined: {}", sds_secret_config.name())); + if (!sds_secret_config.has_sds_config()) { + // static secret + auto secret_provider = factory_context.secretManager().findStaticTlsCertificateProvider( + sds_secret_config.name()); + if (!secret_provider) { + throw EnvoyException(fmt::format("Unknown static secret: {}", sds_secret_config.name())); + } + return secret_provider; + } else { + return factory_context.secretManager().findOrCreateDynamicSecretProvider( + sds_secret_config.sds_config(), sds_secret_config.name(), factory_context); } - return secret_provider; } return nullptr; } @@ -58,8 +63,9 @@ const std::string ContextConfigImpl::DEFAULT_CIPHER_SUITES = const std::string ContextConfigImpl::DEFAULT_ECDH_CURVES = "X25519:P-256"; -ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config, - Secret::SecretManager& secret_manager) +ContextConfigImpl::ContextConfigImpl( + const envoy::api::v2::auth::CommonTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) : alpn_protocols_(RepeatedPtrUtil::join(config.alpn_protocols(), ",")), alt_alpn_protocols_(config.deprecated_v1().alt_alpn_protocols()), cipher_suites_(StringUtil::nonEmptyStringOrDefault( @@ -73,7 +79,8 @@ ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContex Config::DataSource::read(config.validation_context().crl(), true)), certificate_revocation_list_path_( Config::DataSource::getPath(config.validation_context().crl()).value_or(EMPTY_STRING)), - tls_certficate_provider_(getTlsCertificateConfigProvider(config, secret_manager)), + secret_callback_(nullptr), + tls_certficate_provider_(getTlsCertificateConfigProvider(config, factory_context)), verify_subject_alt_name_list_(config.validation_context().verify_subject_alt_name().begin(), config.validation_context().verify_subject_alt_name().end()), verify_certificate_hash_list_(config.validation_context().verify_certificate_hash().begin(), @@ -85,6 +92,7 @@ ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContex tlsVersionFromProto(config.tls_params().tls_minimum_protocol_version(), TLS1_VERSION)), max_protocol_version_( tlsVersionFromProto(config.tls_params().tls_maximum_protocol_version(), TLS1_2_VERSION)) { + if (ca_cert_.empty()) { if (!certificate_revocation_list_.empty()) { throw EnvoyException(fmt::format("Failed to load CRL from {} without trusted CA", @@ -101,6 +109,13 @@ ContextConfigImpl::ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContex } } +ContextConfigImpl::~ContextConfigImpl() { + if (tls_certficate_provider_.get() != nullptr && secret_callback_ != nullptr) { + tls_certficate_provider_->removeUpdateCallback(*secret_callback_); + secret_callback_ = nullptr; + } +} + unsigned ContextConfigImpl::tlsVersionFromProto( const envoy::api::v2::auth::TlsParameters_TlsProtocol& version, unsigned default_version) { switch (version) { @@ -122,8 +137,9 @@ unsigned ContextConfigImpl::tlsVersionFromProto( } ClientContextConfigImpl::ClientContextConfigImpl( - const envoy::api::v2::auth::UpstreamTlsContext& config, Secret::SecretManager& secret_manager) - : ContextConfigImpl(config.common_tls_context(), secret_manager), + const envoy::api::v2::auth::UpstreamTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) + : ContextConfigImpl(config.common_tls_context(), factory_context), server_name_indication_(config.sni()), allow_renegotiation_(config.allow_renegotiation()) { // BoringSSL treats this as a C string, so embedded NULL characters will not // be handled correctly. @@ -137,19 +153,21 @@ ClientContextConfigImpl::ClientContextConfigImpl( } } -ClientContextConfigImpl::ClientContextConfigImpl(const Json::Object& config, - Secret::SecretManager& secret_manager) +ClientContextConfigImpl::ClientContextConfigImpl( + const Json::Object& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) : ClientContextConfigImpl( [&config] { envoy::api::v2::auth::UpstreamTlsContext upstream_tls_context; Config::TlsContextJson::translateUpstreamTlsContext(config, upstream_tls_context); return upstream_tls_context; }(), - secret_manager) {} + factory_context) {} ServerContextConfigImpl::ServerContextConfigImpl( - const envoy::api::v2::auth::DownstreamTlsContext& config, Secret::SecretManager& secret_manager) - : ContextConfigImpl(config.common_tls_context(), secret_manager), + const envoy::api::v2::auth::DownstreamTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) + : ContextConfigImpl(config.common_tls_context(), factory_context), require_client_certificate_( PROTOBUF_GET_WRAPPED_OR_DEFAULT(config, require_client_certificate, false)), session_ticket_keys_([&config] { @@ -180,15 +198,16 @@ ServerContextConfigImpl::ServerContextConfigImpl( } } -ServerContextConfigImpl::ServerContextConfigImpl(const Json::Object& config, - Secret::SecretManager& secret_manager) +ServerContextConfigImpl::ServerContextConfigImpl( + const Json::Object& config, + Server::Configuration::TransportSocketFactoryContext& factory_context) : ServerContextConfigImpl( [&config] { envoy::api::v2::auth::DownstreamTlsContext downstream_tls_context; Config::TlsContextJson::translateDownstreamTlsContext(config, downstream_tls_context); return downstream_tls_context; }(), - secret_manager) {} + factory_context) {} // Append a SessionTicketKey to keys, initializing it with key_data. // Throws if key_data is invalid. diff --git a/source/common/ssl/context_config_impl.h b/source/common/ssl/context_config_impl.h index cb6b1c92c969..ee378e5208a1 100644 --- a/source/common/ssl/context_config_impl.h +++ b/source/common/ssl/context_config_impl.h @@ -4,8 +4,9 @@ #include #include "envoy/api/v2/auth/cert.pb.h" -#include "envoy/secret/secret_manager.h" +#include "envoy/secret/secret_callbacks.h" #include "envoy/secret/secret_provider.h" +#include "envoy/server/transport_socket_config.h" #include "envoy/ssl/context_config.h" #include "common/common/empty_string.h" @@ -18,6 +19,8 @@ static const std::string INLINE_STRING = ""; class ContextConfigImpl : public virtual Ssl::ContextConfig { public: + ~ContextConfigImpl() override; + // Ssl::ContextConfig const std::string& alpnProtocols() const override { return alpn_protocols_; } const std::string& altAlpnProtocols() const override { return alt_alpn_protocols_; } @@ -51,9 +54,25 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { unsigned minProtocolVersion() const override { return min_protocol_version_; }; unsigned maxProtocolVersion() const override { return max_protocol_version_; }; + bool isReady() const override { + // either tls_certficate_provider_ is nullptr or + // tls_certficate_provider_->secret() is NOT nullptr. + return !tls_certficate_provider_ || tls_certficate_provider_->secret(); + } + + void setSecretUpdateCallback(Secret::SecretCallbacks& callback) override { + if (tls_certficate_provider_) { + if (secret_callback_) { + tls_certficate_provider_->removeUpdateCallback(*secret_callback_); + } + secret_callback_ = &callback; + tls_certficate_provider_->addUpdateCallback(callback); + } + } + protected: ContextConfigImpl(const envoy::api::v2::auth::CommonTlsContext& config, - Secret::SecretManager& secret_manager); + Server::Configuration::TransportSocketFactoryContext& factory_context); private: static unsigned @@ -71,6 +90,7 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { const std::string ca_cert_path_; const std::string certificate_revocation_list_; const std::string certificate_revocation_list_path_; + Secret::SecretCallbacks* secret_callback_; Secret::TlsCertificateConfigProviderSharedPtr tls_certficate_provider_; const std::vector verify_subject_alt_name_list_; const std::vector verify_certificate_hash_list_; @@ -82,10 +102,12 @@ class ContextConfigImpl : public virtual Ssl::ContextConfig { class ClientContextConfigImpl : public ContextConfigImpl, public ClientContextConfig { public: - explicit ClientContextConfigImpl(const envoy::api::v2::auth::UpstreamTlsContext& config, - Secret::SecretManager& secret_manager); - explicit ClientContextConfigImpl(const Json::Object& config, - Secret::SecretManager& secret_manager); + explicit ClientContextConfigImpl( + const envoy::api::v2::auth::UpstreamTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context); + explicit ClientContextConfigImpl( + const Json::Object& config, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context); // Ssl::ClientContextConfig const std::string& serverNameIndication() const override { return server_name_indication_; } @@ -98,10 +120,12 @@ class ClientContextConfigImpl : public ContextConfigImpl, public ClientContextCo class ServerContextConfigImpl : public ContextConfigImpl, public ServerContextConfig { public: - explicit ServerContextConfigImpl(const envoy::api::v2::auth::DownstreamTlsContext& config, - Secret::SecretManager& secret_manager); - explicit ServerContextConfigImpl(const Json::Object& config, - Secret::SecretManager& secret_manager); + explicit ServerContextConfigImpl( + const envoy::api::v2::auth::DownstreamTlsContext& config, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context); + explicit ServerContextConfigImpl( + const Json::Object& config, + Server::Configuration::TransportSocketFactoryContext& secret_provider_context); // Ssl::ServerContextConfig bool requireClientCertificate() const override { return require_client_certificate_; } diff --git a/source/common/ssl/context_manager_impl.cc b/source/common/ssl/context_manager_impl.cc index 0409a608332b..2b5958a8152a 100644 --- a/source/common/ssl/context_manager_impl.cc +++ b/source/common/ssl/context_manager_impl.cc @@ -22,6 +22,10 @@ void ContextManagerImpl::removeEmptyContexts() { ClientContextSharedPtr ContextManagerImpl::createSslClientContext(Stats::Scope& scope, const ClientContextConfig& config) { + if (!config.isReady()) { + return nullptr; + } + ClientContextSharedPtr context = std::make_shared(scope, config); removeEmptyContexts(); contexts_.emplace_back(context); @@ -31,6 +35,10 @@ ContextManagerImpl::createSslClientContext(Stats::Scope& scope, const ClientCont ServerContextSharedPtr ContextManagerImpl::createSslServerContext(Stats::Scope& scope, const ServerContextConfig& config, const std::vector& server_names) { + if (!config.isReady()) { + return nullptr; + } + ServerContextSharedPtr context = std::make_shared(scope, config, server_names, runtime_); removeEmptyContexts(); diff --git a/source/common/ssl/ssl_socket.cc b/source/common/ssl/ssl_socket.cc index 3f634c7d9fa2..d23e2cc3baee 100644 --- a/source/common/ssl/ssl_socket.cc +++ b/source/common/ssl/ssl_socket.cc @@ -17,6 +17,38 @@ using Envoy::Network::PostIoAction; namespace Envoy { namespace Ssl { +namespace { + +// This SslSocket will be used when SSL secret is not fetched from SDS server. +class NotReadySslSocket : public Network::TransportSocket, public Connection { +public: + // Ssl::Connection + bool peerCertificatePresented() const override { return false; } + std::string uriSanLocalCertificate() const override { return EMPTY_STRING; } + const std::string& sha256PeerCertificateDigest() const override { return EMPTY_STRING; } + std::string serialNumberPeerCertificate() const override { return EMPTY_STRING; } + std::string subjectPeerCertificate() const override { return EMPTY_STRING; } + std::string subjectLocalCertificate() const override { return EMPTY_STRING; } + std::string uriSanPeerCertificate() const override { return EMPTY_STRING; } + const std::string& urlEncodedPemEncodedPeerCertificate() const override { return EMPTY_STRING; } + std::vector dnsSansPeerCertificate() const override { return {}; } + std::vector dnsSansLocalCertificate() const override { return {}; } + + // Network::TransportSocket + void setTransportSocketCallbacks(Network::TransportSocketCallbacks&) override {} + std::string protocol() const override { return EMPTY_STRING; } + bool canFlushClose() override { return true; } + void closeSocket(Network::ConnectionEvent) override {} + Network::IoResult doRead(Buffer::Instance&) override { return {PostIoAction::Close, 0, false}; } + Network::IoResult doWrite(Buffer::Instance&, bool) override { + return {PostIoAction::Close, 0, false}; + } + void onConnected() override {} + const Ssl::Connection* ssl() const override { return this; } +}; + +} // namespace + SslSocket::SslSocket(ContextSharedPtr ctx, InitialState state) : ctx_(std::dynamic_pointer_cast(ctx)), ssl_(ctx_->newSsl()) { if (state == InitialState::Client) { @@ -384,31 +416,67 @@ std::string SslSocket::subjectLocalCertificate() const { return getSubjectFromCertificate(cert); } +namespace { +SslSocketFactoryStats generateStats(const std::string& prefix, Stats::Scope& store) { + return { + ALL_SSL_SOCKET_FACTORY_STATS(POOL_COUNTER_PREFIX(store, prefix + "_ssl_socket_factory."))}; +} +} // namespace + ClientSslSocketFactory::ClientSslSocketFactory(ClientContextConfigPtr config, Ssl::ContextManager& manager, Stats::Scope& stats_scope) - : manager_(manager), stats_scope_(stats_scope), config_(std::move(config)), - ssl_ctx_(manager_.createSslClientContext(stats_scope_, *config_)) {} + : manager_(manager), stats_scope_(stats_scope), stats_(generateStats("client", stats_scope)), + config_(std::move(config)), + ssl_ctx_(manager_.createSslClientContext(stats_scope_, *config_)) { + config_->setSecretUpdateCallback(*this); +} Network::TransportSocketPtr ClientSslSocketFactory::createTransportSocket() const { - return std::make_unique(ssl_ctx_, Ssl::InitialState::Client); + if (ssl_ctx_) { + return std::make_unique(ssl_ctx_, Ssl::InitialState::Client); + } else { + ENVOY_LOG(debug, "Create NotReadySslSocket"); + stats_.upstream_connection_reset_by_sds_.inc(); + return std::make_unique(); + } } bool ClientSslSocketFactory::implementsSecureTransport() const { return true; } +void ClientSslSocketFactory::onAddOrUpdateSecret() { + ENVOY_LOG(debug, "Secret is updated."); + ssl_ctx_ = manager_.createSslClientContext(stats_scope_, *config_); + stats_.ssl_context_update_by_sds_.inc(); +} + ServerSslSocketFactory::ServerSslSocketFactory(ServerContextConfigPtr config, Ssl::ContextManager& manager, Stats::Scope& stats_scope, const std::vector& server_names) - : manager_(manager), stats_scope_(stats_scope), config_(std::move(config)), - server_names_(server_names), - ssl_ctx_(manager_.createSslServerContext(stats_scope_, *config_, server_names_)) {} + : manager_(manager), stats_scope_(stats_scope), stats_(generateStats("server", stats_scope)), + config_(std::move(config)), server_names_(server_names), + ssl_ctx_(manager_.createSslServerContext(stats_scope_, *config_, server_names_)) { + config_->setSecretUpdateCallback(*this); +} Network::TransportSocketPtr ServerSslSocketFactory::createTransportSocket() const { - return std::make_unique(ssl_ctx_, Ssl::InitialState::Server); + if (ssl_ctx_) { + return std::make_unique(ssl_ctx_, Ssl::InitialState::Server); + } else { + ENVOY_LOG(debug, "Create NotReadySslSocket"); + stats_.downstream_connection_reset_by_sds_.inc(); + return std::make_unique(); + } } bool ServerSslSocketFactory::implementsSecureTransport() const { return true; } +void ServerSslSocketFactory::onAddOrUpdateSecret() { + ENVOY_LOG(debug, "Secret is updated."); + ssl_ctx_ = manager_.createSslServerContext(stats_scope_, *config_, server_names_); + stats_.ssl_context_update_by_sds_.inc(); +} + } // namespace Ssl } // namespace Envoy diff --git a/source/common/ssl/ssl_socket.h b/source/common/ssl/ssl_socket.h index c6b8f92b4d63..b195e3d4ed7d 100644 --- a/source/common/ssl/ssl_socket.h +++ b/source/common/ssl/ssl_socket.h @@ -5,7 +5,9 @@ #include "envoy/network/connection.h" #include "envoy/network/transport_socket.h" +#include "envoy/secret/secret_callbacks.h" #include "envoy/stats/scope.h" +#include "envoy/stats/stats_macros.h" #include "common/common/logger.h" #include "common/ssl/context_impl.h" @@ -15,6 +17,20 @@ namespace Envoy { namespace Ssl { +// clang-format off +#define ALL_SSL_SOCKET_FACTORY_STATS(COUNTER) \ + COUNTER(ssl_context_update_by_sds) \ + COUNTER(upstream_connection_reset_by_sds) \ + COUNTER(downstream_connection_reset_by_sds) +// clang-format on + +/** + * Wrapper struct for SSL socket factory stats. @see stats_macros.h + */ +struct SslSocketFactoryStats { + ALL_SSL_SOCKET_FACTORY_STATS(GENERATE_COUNTER_STRUCT) +}; + enum class InitialState { Client, Server }; class SslSocket : public Network::TransportSocket, @@ -67,7 +83,9 @@ class SslSocket : public Network::TransportSocket, mutable std::string cached_url_encoded_pem_encoded_peer_certificate_; }; -class ClientSslSocketFactory : public Network::TransportSocketFactory { +class ClientSslSocketFactory : public Network::TransportSocketFactory, + public Secret::SecretCallbacks, + Logger::Loggable { public: ClientSslSocketFactory(ClientContextConfigPtr config, Ssl::ContextManager& manager, Stats::Scope& stats_scope); @@ -75,14 +93,20 @@ class ClientSslSocketFactory : public Network::TransportSocketFactory { Network::TransportSocketPtr createTransportSocket() const override; bool implementsSecureTransport() const override; + // Secret::SecretCallbacks + void onAddOrUpdateSecret() override; + private: Ssl::ContextManager& manager_; Stats::Scope& stats_scope_; + SslSocketFactoryStats stats_; ClientContextConfigPtr config_; ClientContextSharedPtr ssl_ctx_; }; -class ServerSslSocketFactory : public Network::TransportSocketFactory { +class ServerSslSocketFactory : public Network::TransportSocketFactory, + public Secret::SecretCallbacks, + Logger::Loggable { public: ServerSslSocketFactory(ServerContextConfigPtr config, Ssl::ContextManager& manager, Stats::Scope& stats_scope, const std::vector& server_names); @@ -90,9 +114,13 @@ class ServerSslSocketFactory : public Network::TransportSocketFactory { Network::TransportSocketPtr createTransportSocket() const override; bool implementsSecureTransport() const override; + // Secret::SecretCallbacks + void onAddOrUpdateSecret() override; + private: Ssl::ContextManager& manager_; Stats::Scope& stats_scope_; + SslSocketFactoryStats stats_; ServerContextConfigPtr config_; const std::vector server_names_; ServerContextSharedPtr ssl_ctx_; diff --git a/source/common/stats/thread_local_store.cc b/source/common/stats/thread_local_store.cc index de98b3aaff3c..c7f71308ae3f 100644 --- a/source/common/stats/thread_local_store.cc +++ b/source/common/stats/thread_local_store.cc @@ -144,7 +144,7 @@ void ThreadLocalStoreImpl::releaseScopeCrossThread(ScopeImpl* scope) { // cache flush operation. if (!shutting_down_ && main_thread_dispatcher_) { main_thread_dispatcher_->post( - [ this, scope_id = scope->scope_id_ ]()->void { clearScopeFromCaches(scope_id); }); + [this, scope_id = scope->scope_id_]() -> void { clearScopeFromCaches(scope_id); }); } } diff --git a/source/common/tcp/conn_pool.h b/source/common/tcp/conn_pool.h index 42f8dc52bd7b..ff74c2d85847 100644 --- a/source/common/tcp/conn_pool.h +++ b/source/common/tcp/conn_pool.h @@ -39,6 +39,11 @@ class ConnPoolImpl : Logger::Loggable, public ConnectionPool:: Network::ClientConnection& connection(); void addUpstreamCallbacks(ConnectionPool::UpstreamCallbacks& callbacks); + void setConnectionState(ConnectionPool::ConnectionStatePtr&& state) { + parent_.setConnectionState(std::move(state)); + }; + ConnectionPool::ConnectionState* connectionState() { return parent_.connectionState(); } + void release(bool closed); void invalidate() { conn_valid_ = false; } @@ -60,6 +65,12 @@ class ConnPoolImpl : Logger::Loggable, public ConnectionPool:: void addUpstreamCallbacks(ConnectionPool::UpstreamCallbacks& callbacks) override { wrapper_->addUpstreamCallbacks(callbacks); }; + void setConnectionState(ConnectionPool::ConnectionStatePtr&& state) override { + wrapper_->setConnectionState(std::move(state)); + } + ConnectionPool::ConnectionState* connectionState() override { + return wrapper_->connectionState(); + } ConnectionWrapperSharedPtr wrapper_; }; @@ -90,10 +101,16 @@ class ConnPoolImpl : Logger::Loggable, public ConnectionPool:: void onAboveWriteBufferHighWatermark() override; void onBelowWriteBufferLowWatermark() override; + void setConnectionState(ConnectionPool::ConnectionStatePtr&& state) { + conn_state_ = std::move(state); + } + ConnectionPool::ConnectionState* connectionState() { return conn_state_.get(); } + ConnPoolImpl& parent_; Upstream::HostDescriptionConstSharedPtr real_host_description_; ConnectionWrapperSharedPtr wrapper_; Network::ClientConnectionPtr conn_; + ConnectionPool::ConnectionStatePtr conn_state_; Event::TimerPtr connect_timer_; Stats::TimespanPtr conn_length_; uint64_t remaining_requests_; diff --git a/source/common/tcp_proxy/tcp_proxy.cc b/source/common/tcp_proxy/tcp_proxy.cc index 45e6ca76a4de..071fd93200c4 100644 --- a/source/common/tcp_proxy/tcp_proxy.cc +++ b/source/common/tcp_proxy/tcp_proxy.cc @@ -466,17 +466,14 @@ void Filter::onUpstreamEvent(Network::ConnectionEvent event) { // The idle_timer_ can be moved to a Drainer, so related callbacks call into // the UpstreamCallbacks, which has the same lifetime as the timer, and can dispatch // the call to either TcpProxy or to Drainer, depending on the current state. - idle_timer_ = - read_callbacks_->connection().dispatcher().createTimer([upstream_callbacks = - upstream_callbacks_]() { - upstream_callbacks->onIdleTimeout(); - }); + idle_timer_ = read_callbacks_->connection().dispatcher().createTimer( + [upstream_callbacks = upstream_callbacks_]() { upstream_callbacks->onIdleTimeout(); }); resetIdleTimer(); read_callbacks_->connection().addBytesSentCallback([this](uint64_t) { resetIdleTimer(); }); - upstream_conn_data_->connection().addBytesSentCallback([upstream_callbacks = - upstream_callbacks_](uint64_t) { - upstream_callbacks->onBytesSent(); - }); + upstream_conn_data_->connection().addBytesSentCallback( + [upstream_callbacks = upstream_callbacks_](uint64_t) { + upstream_callbacks->onBytesSent(); + }); } } } diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 2d43d7509e81..5dc2bdd54ca6 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -406,6 +406,8 @@ envoy_cc_library( "//source/common/stats:isolated_store_lib", "//source/common/stats:stats_lib", "//source/common/upstream:locality_lib", + "//source/server:init_manager_lib", + "//source/server:transport_socket_config_lib", "@envoy_api//envoy/api/v2/core:base_cc", "@envoy_api//envoy/api/v2/endpoint:endpoint_cc", ], diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index f17f8d605387..91bdb9b21b58 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -521,28 +521,24 @@ bool ClusterManagerImpl::addOrUpdateCluster(const envoy::api::v2::Cluster& clust } void ClusterManagerImpl::createOrUpdateThreadLocalCluster(ClusterData& cluster) { - tls_->runOnAllThreads( - [ - this, new_cluster = cluster.cluster_->info(), - thread_aware_lb_factory = cluster.loadBalancerFactory() - ]() - ->void { - ThreadLocalClusterManagerImpl& cluster_manager = - tls_->getTyped(); - - if (cluster_manager.thread_local_clusters_.count(new_cluster->name()) > 0) { - ENVOY_LOG(debug, "updating TLS cluster {}", new_cluster->name()); - } else { - ENVOY_LOG(debug, "adding TLS cluster {}", new_cluster->name()); - } - - auto thread_local_cluster = new ThreadLocalClusterManagerImpl::ClusterEntry( - cluster_manager, new_cluster, thread_aware_lb_factory); - cluster_manager.thread_local_clusters_[new_cluster->name()].reset(thread_local_cluster); - for (auto& cb : cluster_manager.update_callbacks_) { - cb->onClusterAddOrUpdate(*thread_local_cluster); - } - }); + tls_->runOnAllThreads([this, new_cluster = cluster.cluster_->info(), + thread_aware_lb_factory = cluster.loadBalancerFactory()]() -> void { + ThreadLocalClusterManagerImpl& cluster_manager = + tls_->getTyped(); + + if (cluster_manager.thread_local_clusters_.count(new_cluster->name()) > 0) { + ENVOY_LOG(debug, "updating TLS cluster {}", new_cluster->name()); + } else { + ENVOY_LOG(debug, "adding TLS cluster {}", new_cluster->name()); + } + + auto thread_local_cluster = new ThreadLocalClusterManagerImpl::ClusterEntry( + cluster_manager, new_cluster, thread_aware_lb_factory); + cluster_manager.thread_local_clusters_[new_cluster->name()].reset(thread_local_cluster); + for (auto& cb : cluster_manager.update_callbacks_) { + cb->onClusterAddOrUpdate(*thread_local_cluster); + } + }); } bool ClusterManagerImpl::removeCluster(const std::string& cluster_name) { @@ -693,15 +689,14 @@ void ClusterManagerImpl::postThreadLocalClusterUpdate(const Cluster& cluster, ui HostsPerLocalityConstSharedPtr healthy_hosts_per_locality_copy = host_set->healthyHostsPerLocality().clone(); - tls_->runOnAllThreads([ - this, name = cluster.info()->name(), priority, hosts_copy, healthy_hosts_copy, - hosts_per_locality_copy, healthy_hosts_per_locality_copy, - locality_weights = host_set->localityWeights(), hosts_added, hosts_removed - ]() { - ThreadLocalClusterManagerImpl::updateClusterMembership( - name, priority, hosts_copy, healthy_hosts_copy, hosts_per_locality_copy, - healthy_hosts_per_locality_copy, locality_weights, hosts_added, hosts_removed, *tls_); - }); + tls_->runOnAllThreads( + [this, name = cluster.info()->name(), priority, hosts_copy, healthy_hosts_copy, + hosts_per_locality_copy, healthy_hosts_per_locality_copy, + locality_weights = host_set->localityWeights(), hosts_added, hosts_removed]() { + ThreadLocalClusterManagerImpl::updateClusterMembership( + name, priority, hosts_copy, healthy_hosts_copy, hosts_per_locality_copy, + healthy_hosts_per_locality_copy, locality_weights, hosts_added, hosts_removed, *tls_); + }); } void ClusterManagerImpl::postThreadLocalHealthFailure(const HostSharedPtr& host) { diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index 35573b69df4e..fc9244ced6ee 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -220,6 +220,7 @@ ClusterInfoConstSharedPtr ProdClusterInfoFactory::createClusterInfo( Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context( ssl_context_manager, *scope, cm, local_info, dispatcher, random, stats); + // TODO(JimmyCYJ): Support SDS for HDS cluster. Network::TransportSocketFactoryPtr socket_factory = Upstream::createTransportSocketFactory(cluster, factory_context); diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index 4446e6ea36c5..1b3f41bc57ba 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -497,6 +497,7 @@ ClusterImplBase::ClusterImplBase( Server::Configuration::TransportSocketFactoryContext& factory_context, Stats::ScopePtr&& stats_scope, bool added_via_api) : runtime_(runtime) { + factory_context.setInitManager(init_manager_); auto socket_factory = createTransportSocketFactory(cluster, factory_context); info_ = std::make_unique(cluster, factory_context.clusterManager().bindConfig(), runtime, std::move(socket_factory), @@ -560,6 +561,10 @@ void ClusterImplBase::onPreInitComplete() { } initialization_started_ = true; + init_manager_.initialize([this]() { onInitDone(); }); +} + +void ClusterImplBase::onInitDone() { if (health_checker_ && pending_initialize_health_checks_ == 0) { for (auto& host_set : prioritySet().hostSetsPerPriority()) { pending_initialize_health_checks_ += host_set->hosts().size(); diff --git a/source/common/upstream/upstream_impl.h b/source/common/upstream/upstream_impl.h index 9d34dba7ce53..a7deaf7f1323 100644 --- a/source/common/upstream/upstream_impl.h +++ b/source/common/upstream/upstream_impl.h @@ -40,6 +40,8 @@ #include "common/upstream/outlier_detection_impl.h" #include "common/upstream/resource_manager_impl.h" +#include "server/init_manager_impl.h" + namespace Envoy { namespace Upstream { @@ -507,12 +509,21 @@ class ClusterImplBase : public Cluster, protected Logger::Loggable grpc_access_log_streamer = context.singletonManager().getTyped( SINGLETON_MANAGER_REGISTERED_NAME(grpc_access_log_streamer), - [&context, grpc_service = proto_config.common_config().grpc_service() ] { + [&context, grpc_service = proto_config.common_config().grpc_service()] { return std::make_shared( context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( grpc_service, context.scope(), false), diff --git a/source/extensions/filters/common/lua/lua.h b/source/extensions/filters/common/lua/lua.h index 9f2ee6032834..a12ba7132b9c 100644 --- a/source/extensions/filters/common/lua/lua.h +++ b/source/extensions/filters/common/lua/lua.h @@ -402,7 +402,7 @@ class LuaException : public EnvoyException { public: using EnvoyException::EnvoyException; }; -} +} // namespace Lua } // namespace Common } // namespace Filters } // namespace Extensions diff --git a/source/extensions/filters/http/ext_authz/config.cc b/source/extensions/filters/http/ext_authz/config.cc index 5556aef4d813..b2c8c655e1aa 100644 --- a/source/extensions/filters/http/ext_authz/config.cc +++ b/source/extensions/filters/http/ext_authz/config.cc @@ -28,10 +28,10 @@ Http::FilterFactoryCb ExtAuthzFilterConfig::createFilterFactoryFromProtoTyped( if (proto_config.has_http_service()) { const uint32_t timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT(proto_config.http_service().server_uri(), timeout, DefaultTimeout); - return [ - filter_config, timeout_ms, cluster_name = proto_config.http_service().server_uri().cluster(), - path_prefix = proto_config.http_service().path_prefix() - ](Http::FilterChainFactoryCallbacks & callbacks) { + return [filter_config, timeout_ms, + cluster_name = proto_config.http_service().server_uri().cluster(), + path_prefix = proto_config.http_service().path_prefix()]( + Http::FilterChainFactoryCallbacks& callbacks) { auto client = std::make_unique( cluster_name, filter_config->cm(), std::chrono::milliseconds(timeout_ms), path_prefix, filter_config->allowedAuthorizationHeaders(), filter_config->allowedRequestHeaders()); @@ -43,8 +43,8 @@ Http::FilterFactoryCb ExtAuthzFilterConfig::createFilterFactoryFromProtoTyped( const uint32_t timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT(proto_config.grpc_service(), timeout, DefaultTimeout); - return [ grpc_service = proto_config.grpc_service(), &context, filter_config, - timeout_ms ](Http::FilterChainFactoryCallbacks & callbacks) { + return [grpc_service = proto_config.grpc_service(), &context, filter_config, + timeout_ms](Http::FilterChainFactoryCallbacks& callbacks) { const auto async_client_factory = context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( grpc_service, context.scope(), true); diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc index 20846dd34d2b..40404656ddf5 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.cc +++ b/source/extensions/filters/http/ext_authz/ext_authz.cc @@ -104,16 +104,15 @@ void Filter::onComplete(Filters::Common::ExtAuthz::ResponsePtr&& response) { ENVOY_STREAM_LOG(debug, "Ext_authz rejected the request", *callbacks_); ENVOY_STREAM_LOG(trace, "Ext_authz downstream header(s):", *callbacks_); callbacks_->sendLocalReply(response->status_code, response->body, - [& headers = response->headers_to_add, - &callbacks = *callbacks_ ](Http::HeaderMap & response_headers) - ->void { - for (const auto& header : headers) { - response_headers.remove(header.first); - response_headers.addCopy(header.first, header.second); - ENVOY_STREAM_LOG(trace, " '{}':'{}'", callbacks, - header.first.get(), header.second); - } - }); + [& headers = response->headers_to_add, &callbacks = *callbacks_]( + Http::HeaderMap& response_headers) -> void { + for (const auto& header : headers) { + response_headers.remove(header.first); + response_headers.addCopy(header.first, header.second); + ENVOY_STREAM_LOG(trace, " '{}':'{}'", callbacks, + header.first.get(), header.second); + } + }); callbacks_->requestInfo().setResponseFlag( RequestInfo::ResponseFlag::UnauthorizedExternalService); } else { diff --git a/source/extensions/filters/http/health_check/config.cc b/source/extensions/filters/http/health_check/config.cc index 56b682dafa38..aa2b594a6f49 100644 --- a/source/extensions/filters/http/health_check/config.cc +++ b/source/extensions/filters/http/health_check/config.cc @@ -52,7 +52,6 @@ Http::FilterFactoryCb HealthCheckFilterConfig::createFilterFactoryFromProtoTyped callbacks.addStreamFilter(std::make_shared(context, pass_through_mode, cache_manager, header_match_data, cluster_min_healthy_percentages)); - }; } diff --git a/source/extensions/filters/http/jwt_authn/extractor.cc b/source/extensions/filters/http/jwt_authn/extractor.cc index 6560a1a58a83..452232b67423 100644 --- a/source/extensions/filters/http/jwt_authn/extractor.cc +++ b/source/extensions/filters/http/jwt_authn/extractor.cc @@ -5,8 +5,8 @@ #include "common/http/utility.h" #include "common/singleton/const_singleton.h" -using ::Envoy::Http::LowerCaseString; using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtAuthentication; +using ::Envoy::Http::LowerCaseString; namespace Envoy { namespace Extensions { diff --git a/source/extensions/filters/network/client_ssl_auth/client_ssl_auth.h b/source/extensions/filters/network/client_ssl_auth/client_ssl_auth.h index be90fa5758e0..b6e183bd0baf 100644 --- a/source/extensions/filters/network/client_ssl_auth/client_ssl_auth.h +++ b/source/extensions/filters/network/client_ssl_auth/client_ssl_auth.h @@ -128,7 +128,7 @@ class ClientSslAuthFilter : public Network::ReadFilter, public Network::Connecti Network::ReadFilterCallbacks* read_callbacks_{}; }; -} // ClientSsl +} // namespace ClientSslAuth } // namespace NetworkFilters } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/filters/network/ext_authz/config.cc b/source/extensions/filters/network/ext_authz/config.cc index 54e5de374a3d..cab5ea49c1ca 100644 --- a/source/extensions/filters/network/ext_authz/config.cc +++ b/source/extensions/filters/network/ext_authz/config.cc @@ -24,10 +24,8 @@ Network::FilterFactoryCb ExtAuthzConfigFactory::createFilterFactoryFromProtoType ConfigSharedPtr ext_authz_config(new Config(proto_config, context.scope())); const uint32_t timeout_ms = PROTOBUF_GET_MS_OR_DEFAULT(proto_config.grpc_service(), timeout, 200); - return [ grpc_service = proto_config.grpc_service(), &context, ext_authz_config, - timeout_ms ](Network::FilterManager & filter_manager) - ->void { - + return [grpc_service = proto_config.grpc_service(), &context, ext_authz_config, + timeout_ms](Network::FilterManager& filter_manager) -> void { auto async_client_factory = context.clusterManager().grpcAsyncClientManager().factoryForGrpcService( grpc_service, context.scope(), true); diff --git a/source/extensions/filters/network/ext_authz/ext_authz.h b/source/extensions/filters/network/ext_authz/ext_authz.h index 65df54414fe9..c685a9a3e727 100644 --- a/source/extensions/filters/network/ext_authz/ext_authz.h +++ b/source/extensions/filters/network/ext_authz/ext_authz.h @@ -113,7 +113,7 @@ class Filter : public Network::ReadFilter, bool calling_check_{}; envoy::service::auth::v2alpha::CheckRequest check_request_{}; }; -} +} // namespace ExtAuthz } // namespace NetworkFilters } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/filters/network/thrift_proxy/BUILD b/source/extensions/filters/network/thrift_proxy/BUILD index e75efa1c0760..011949996723 100644 --- a/source/extensions/filters/network/thrift_proxy/BUILD +++ b/source/extensions/filters/network/thrift_proxy/BUILD @@ -187,11 +187,13 @@ envoy_cc_library( name = "transport_lib", srcs = [ "framed_transport_impl.cc", + "header_transport_impl.cc", "transport_impl.cc", "unframed_transport_impl.cc", ], hdrs = [ "framed_transport_impl.h", + "header_transport_impl.h", "transport_impl.h", "unframed_transport_impl.h", ], diff --git a/source/extensions/filters/network/thrift_proxy/config.cc b/source/extensions/filters/network/thrift_proxy/config.cc index 22ce4fbf3e16..54134537a056 100644 --- a/source/extensions/filters/network/thrift_proxy/config.cc +++ b/source/extensions/filters/network/thrift_proxy/config.cc @@ -41,6 +41,8 @@ static const TransportTypeMap& transportTypeMap() { {envoy::config::filter::network::thrift_proxy::v2alpha1:: ThriftProxy_TransportType_UNFRAMED, TransportType::Unframed}, + {envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_TransportType_HEADER, + TransportType::Header}, }); } @@ -92,6 +94,20 @@ ConfigImpl::ConfigImpl( transport_(config.transport()), proto_(config.protocol()), route_matcher_(new Router::RouteMatcher(config.route_config())) { + if (transportTypeMap().find(transport_) == transportTypeMap().end()) { + throw EnvoyException(fmt::format( + "unknown transport {}", + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_TransportType_Name( + transport_))); + } + + if (protocolTypeMap().find(proto_) == protocolTypeMap().end()) { + throw EnvoyException(fmt::format( + "unknown protocol {}", + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_ProtocolType_Name( + proto_))); + } + // Construct the only Thrift DecoderFilter: the Router auto& factory = Envoy::Config::Utility::getAndCheckFactory( @@ -115,14 +131,14 @@ DecoderPtr ConfigImpl::createDecoder(DecoderCallbacks& callbacks) { TransportPtr ConfigImpl::createTransport() { TransportTypeMap::const_iterator i = transportTypeMap().find(transport_); - RELEASE_ASSERT(i != transportTypeMap().end(), "invalid transport type"); + ASSERT(i != transportTypeMap().end()); return NamedTransportConfigFactory::getFactory(i->second).createTransport(); } ProtocolPtr ConfigImpl::createProtocol() { ProtocolTypeMap::const_iterator i = protocolTypeMap().find(proto_); - RELEASE_ASSERT(i != protocolTypeMap().end(), "invalid protocol type"); + ASSERT(i != protocolTypeMap().end()); return NamedProtocolConfigFactory::getFactory(i->second).createProtocol(); } diff --git a/source/extensions/filters/network/thrift_proxy/decoder.cc b/source/extensions/filters/network/thrift_proxy/decoder.cc index d3d69b8e0979..f2219d68acb5 100644 --- a/source/extensions/filters/network/thrift_proxy/decoder.cc +++ b/source/extensions/filters/network/thrift_proxy/decoder.cc @@ -385,6 +385,25 @@ ThriftFilters::FilterStatus Decoder::onData(Buffer::Instance& data, bool& buffer } ENVOY_LOG(debug, "thrift: {} transport started", transport_->name()); + if (metadata_->hasProtocol()) { + if (protocol_->type() == ProtocolType::Auto) { + protocol_->setType(metadata_->protocol()); + ENVOY_LOG(debug, "thrift: {} transport forced {} protocol", transport_->name(), + protocol_->name()); + } else if (metadata_->protocol() != protocol_->type()) { + throw EnvoyException(fmt::format("transport reports protocol {}, but configured for {}", + ProtocolNames::get().fromType(metadata_->protocol()), + ProtocolNames::get().fromType(protocol_->type()))); + } + } + if (metadata_->hasAppException()) { + AppExceptionType ex_type = metadata_->appExceptionType(); + std::string ex_msg = metadata_->appExceptionMessage(); + // Force new metadata if we get called again. + metadata_.reset(); + throw AppException(ex_type, ex_msg); + } + request_ = std::make_unique(callbacks_.newDecoderFilter()); frame_started_ = true; state_machine_ = diff --git a/source/extensions/filters/network/thrift_proxy/header_transport_impl.cc b/source/extensions/filters/network/thrift_proxy/header_transport_impl.cc new file mode 100644 index 000000000000..0dee09aed8c0 --- /dev/null +++ b/source/extensions/filters/network/thrift_proxy/header_transport_impl.cc @@ -0,0 +1,316 @@ +#include "extensions/filters/network/thrift_proxy/header_transport_impl.h" + +#include + +#include "envoy/common/exception.h" + +#include "common/buffer/buffer_impl.h" + +#include "extensions/filters/network/thrift_proxy/buffer_helper.h" +#include "extensions/filters/network/thrift_proxy/transport_impl.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace ThriftProxy { +namespace { + +// c.f. +// https://github.com/apache/thrift/blob/master/lib/cpp/src/thrift/protocol/TProtocolTypes.h#L27 +enum class HeaderProtocolType { + Binary = 0, + JSON = 1, + Compact = 2, + + FirstHeaderProtocolType = Binary, + LastHeaderProtocolType = Compact, +}; + +// Fixed portion of frame header: +// Header magic: 2 bytes + +// Flags: 2 bytes + +// Sequence number: 4 bytes +// Header data size: 2 bytes +constexpr uint64_t MinFrameStartSizeNoHeaders = 10; + +// Minimum frame size: fixed portion of frame header + 4 bytes of header data (the minimum) +constexpr int32_t MinFrameStartSize = MinFrameStartSizeNoHeaders + 4; + +// Minimum to start decoding: 4 bytes of frame size + the fixed portion of the frame header +constexpr uint64_t MinDecodeBytes = MinFrameStartSizeNoHeaders + 4; + +// Maximum size for header data. +constexpr int32_t MaxHeadersSize = 65536; + +} // namespace + +bool HeaderTransportImpl::decodeFrameStart(Buffer::Instance& buffer, MessageMetadata& metadata) { + if (buffer.length() < MinDecodeBytes) { + return false; + } + + // Size of frame, not including the length bytes. + const int32_t frame_size = BufferHelper::peekI32(buffer); + + // Minimum header frame size is 18 bytes (4 bytes of frame size + 10 bytes of fixed header + + // minimum 4 bytes of variable header data), so frame_size must be at least 14. + if (frame_size < MinFrameStartSize || frame_size > MaxFrameSize) { + throw EnvoyException(fmt::format("invalid thrift header transport frame size {}", frame_size)); + } + + int16_t magic = BufferHelper::peekU16(buffer, 4); + if (!isMagic(magic)) { + throw EnvoyException(fmt::format("invalid thrift header transport magic {:04x}", magic)); + } + + // offset 6: 16 bit flags field, unused + // offset 8: 32 bit sequence number field + int32_t seq_id = BufferHelper::peekI32(buffer, 8); + + // offset 12: 16 bit (remaining) header size / 4 (spec erroneously claims / 32). + int16_t raw_header_size = BufferHelper::peekI16(buffer, 12); + int32_t header_size = static_cast(raw_header_size) * 4; + if (header_size < 0 || header_size > MaxHeadersSize) { + throw EnvoyException(fmt::format("invalid thrift header transport header size {} ({:04x})", + header_size, static_cast(raw_header_size))); + } + + if (header_size == 0) { + throw EnvoyException("no header data"); + } + + if (buffer.length() < static_cast(header_size) + MinDecodeBytes) { + // Need more header data. + return false; + } + + // Header data starts at offset 14 (4 bytes of frame size followed by 10 bytes of fixed header). + buffer.drain(MinDecodeBytes); + + // Remaining frame size is the original frame size (which does not count itself), less the 10 + // fixed bytes of the header (magic, flags, etc), less the size of the variable header data + // (header_size). + metadata.setFrameSize( + static_cast(frame_size - header_size - MinFrameStartSizeNoHeaders)); + metadata.setSequenceId(seq_id); + + ProtocolType proto = ProtocolType::Auto; + HeaderProtocolType header_proto = + static_cast(drainVarIntI16(buffer, header_size, "protocol id")); + switch (header_proto) { + case HeaderProtocolType::Binary: + proto = ProtocolType::Binary; + break; + case HeaderProtocolType::Compact: + proto = ProtocolType::Compact; + break; + default: + throw EnvoyException(fmt::format("Unknown protocol {}", static_cast(header_proto))); + } + metadata.setProtocol(proto); + + int16_t num_xforms = drainVarIntI16(buffer, header_size, "transform count"); + if (num_xforms < 0) { + throw EnvoyException(fmt::format("invalid header transport transform count {}", num_xforms)); + } + + while (num_xforms-- > 0) { + int32_t xform_id = drainVarIntI32(buffer, header_size, "transform id"); + + // To date, no transforms have a data field. In the future, some transform IDs may require + // consuming another varint 32 at this point. The known transform IDs are: + // 1: zlib compression + // 2: hmac (appended to end of packet) + // 3: snappy compression + buffer.drain(header_size); + metadata.setAppException(AppExceptionType::MissingResult, + fmt::format("Unknown transform {}", xform_id)); + return true; + } + + while (header_size > 0) { + // Attempt to read info blocks + int32_t info_id = drainVarIntI32(buffer, header_size, "info id"); + if (info_id != 1) { + // 0 indicates a padding byte, and the end of the info block. + // 1 indicates an info id header/value pair. + // Any other value is an unknown info id block, which we ignore. + break; + } + + int32_t num_headers = drainVarIntI32(buffer, header_size, "header count"); + if (num_headers < 0) { + throw EnvoyException(fmt::format("invalid header transport header count {}", num_headers)); + } + + while (num_headers-- > 0) { + std::string key = drainVarString(buffer, header_size, "header key"); + std::string value = drainVarString(buffer, header_size, "header value"); + metadata.addHeader(Header(key, value)); + } + } + + // Remaining bytes are padding or ignored info blocks. + if (header_size > 0) { + buffer.drain(header_size); + } + + return true; +} + +bool HeaderTransportImpl::decodeFrameEnd(Buffer::Instance&) { + exception_.reset(); + exception_reason_.clear(); + + return true; +} + +void HeaderTransportImpl::encodeFrame(Buffer::Instance& buffer, const MessageMetadata& metadata, + Buffer::Instance& message) { + uint64_t msg_size = message.length(); + if (msg_size == 0) { + throw EnvoyException(fmt::format("invalid thrift header transport message size {}", msg_size)); + } + + const HeaderMap& headers = metadata.headers(); + if (headers.size() > MaxHeadersSize / 2) { + // Each header takes a minimum of 2 bytes, yielding this limit. + throw EnvoyException( + fmt::format("invalid thrift header transport too many headers {}", headers.size())); + } + + Buffer::OwnedImpl header_buffer; + + if (!metadata.hasProtocol()) { + throw EnvoyException("missing header transport protocol"); + } + + switch (metadata.protocol()) { + case ProtocolType::Binary: + BufferHelper::writeVarIntI32(header_buffer, static_cast(HeaderProtocolType::Binary)); + break; + case ProtocolType::Compact: + BufferHelper::writeVarIntI32(header_buffer, static_cast(HeaderProtocolType::Compact)); + break; + default: + throw EnvoyException(fmt::format("invalid header transport protocol {}", + ProtocolNames::get().fromType(metadata.protocol()))); + } + + BufferHelper::writeVarIntI32(header_buffer, 0); // num transforms + if (headers.size() > 0) { + // Info ID 1 + BufferHelper::writeI8(header_buffer, 1); + + // Num headers + BufferHelper::writeVarIntI32(header_buffer, static_cast(headers.size())); + + for (const Header& header : headers) { + writeVarString(header_buffer, header.key()); + writeVarString(header_buffer, header.value()); + } + } + + uint64_t header_size = header_buffer.length(); + + // Always pad (as the Apache implementation does). + int padding = 4 - (header_size % 4); + header_buffer.add("\0\0\0\0", padding); + header_size += padding; + + if (header_size > MaxHeadersSize) { + throw EnvoyException( + fmt::format("invalid thrift header transport header size {}", header_size)); + } + + // Frame size does not include the frame length itself. + uint64_t size = header_size + msg_size + MinFrameStartSizeNoHeaders; + if (size > MaxFrameSize) { + throw EnvoyException(fmt::format("invalid thrift header transport frame size {}", size)); + } + + int32_t seq_id = 0; + if (metadata.hasSequenceId()) { + seq_id = metadata.sequenceId(); + } + + BufferHelper::writeU32(buffer, static_cast(size)); + BufferHelper::writeU16(buffer, Magic); + BufferHelper::writeU16(buffer, 0); // flags + BufferHelper::writeI32(buffer, seq_id); + BufferHelper::writeU16(buffer, static_cast(header_size / 4)); + buffer.move(header_buffer); + buffer.move(message); +} + +int16_t HeaderTransportImpl::drainVarIntI16(Buffer::Instance& buffer, int32_t& header_size, + const char* desc) { + int32_t value = drainVarIntI32(buffer, header_size, desc); + if (value > static_cast(std::numeric_limits::max())) { + throw EnvoyException(fmt::format("header transport {}: value {} exceeds max i16 ({})", desc, + value, std::numeric_limits::max())); + } + return static_cast(value); +} + +int32_t HeaderTransportImpl::drainVarIntI32(Buffer::Instance& buffer, int32_t& header_size, + const char* desc) { + if (header_size <= 0) { + throw EnvoyException(fmt::format("unable to read header transport {}: header too small", desc)); + } + + int size; + int32_t value = BufferHelper::peekVarIntI32(buffer, 0, size); + if (size < 0 || (header_size - size) < 0) { + throw EnvoyException(fmt::format("unable to read header transport {}: header too small", desc)); + } + buffer.drain(size); + header_size -= size; + return value; +} + +std::string HeaderTransportImpl::drainVarString(Buffer::Instance& buffer, int32_t& header_size, + const char* desc) { + int16_t str_len = drainVarIntI16(buffer, header_size, desc); + if (str_len == 0) { + return ""; + } + + if (header_size < static_cast(str_len)) { + throw EnvoyException(fmt::format("unable to read header transport {}: header too small", desc)); + } + + std::string value(static_cast(buffer.linearize(str_len)), str_len); + buffer.drain(str_len); + header_size -= str_len; + return value; +} + +void HeaderTransportImpl::writeVarString(Buffer::Instance& buffer, const std::string& str) { + std::string::size_type len = str.length(); + if (len > static_cast(std::numeric_limits::max())) { + throw EnvoyException(fmt::format("header string too long: {}", len)); + } + + BufferHelper::writeVarIntI32(buffer, static_cast(len)); + if (len == 0) { + return; + } + buffer.add(str); +} + +class HeaderTransportConfigFactory : public TransportFactoryBase { +public: + HeaderTransportConfigFactory() : TransportFactoryBase(TransportNames::get().HEADER) {} +}; + +/** + * Static registration for the header transport. @see RegisterFactory. + */ +static Registry::RegisterFactory + register_; + +} // namespace ThriftProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/network/thrift_proxy/header_transport_impl.h b/source/extensions/filters/network/thrift_proxy/header_transport_impl.h new file mode 100644 index 000000000000..88807904018f --- /dev/null +++ b/source/extensions/filters/network/thrift_proxy/header_transport_impl.h @@ -0,0 +1,64 @@ +#pragma once + +#include + +#include "envoy/buffer/buffer.h" + +#include "extensions/filters/network/thrift_proxy/app_exception_impl.h" +#include "extensions/filters/network/thrift_proxy/metadata.h" +#include "extensions/filters/network/thrift_proxy/protocol.h" +#include "extensions/filters/network/thrift_proxy/transport_impl.h" + +#include "absl/types/optional.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace ThriftProxy { + +/** + * HeaderTransportImpl implements the Thrift Header transport. + * See https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md and + * https://github.com/apache/thrift/blob/master/lib/cpp/src/thrift/transport/THeaderTransport.h + * (for constants not specified in the spec). + */ +class HeaderTransportImpl : public Transport { +public: + // Transport + const std::string& name() const override { return TransportNames::get().HEADER; } + TransportType type() const override { return TransportType::Header; } + bool decodeFrameStart(Buffer::Instance& buffer, MessageMetadata& metadata) override; + bool decodeFrameEnd(Buffer::Instance& buffer) override; + void encodeFrame(Buffer::Instance& buffer, const MessageMetadata& metadata, + Buffer::Instance& message) override; + + static bool isMagic(uint16_t word) { return word == Magic; } + + static constexpr int32_t MaxFrameSize = 0x3FFFFFFF; + +private: + static constexpr uint16_t Magic = 0x0FFF; + + static int16_t drainVarIntI16(Buffer::Instance& buffer, int32_t& header_size, const char* desc); + static int32_t drainVarIntI32(Buffer::Instance& buffer, int32_t& header_size, const char* desc); + static std::string drainVarString(Buffer::Instance& buffer, int32_t& header_size, + const char* desc); + static void writeVarString(Buffer::Instance& buffer, const std::string& str); + + void setException(AppExceptionType type, std::string reason) { + if (exception_.has_value()) { + return; + } + + exception_ = type; + exception_reason_ = reason; + } + + absl::optional exception_; + std::string exception_reason_; +}; + +} // namespace ThriftProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/network/thrift_proxy/protocol.h b/source/extensions/filters/network/thrift_proxy/protocol.h index 7d5baa3b9d9f..0e4066021ce9 100644 --- a/source/extensions/filters/network/thrift_proxy/protocol.h +++ b/source/extensions/filters/network/thrift_proxy/protocol.h @@ -39,6 +39,13 @@ class Protocol { */ virtual ProtocolType type() const PURE; + /** + * For protocol-detecting implementations, set the underlying type based on external + * (e.g. transport-level) information). + * @param type ProtocolType to explicitly set + */ + virtual void setType(ProtocolType) { NOT_IMPLEMENTED_GCOVR_EXCL_LINE; } + /** * Reads the start of a Thrift protocol message from the buffer and updates the metadata * parameter with values from the message header. If successful, the message header is removed diff --git a/source/extensions/filters/network/thrift_proxy/protocol_impl.cc b/source/extensions/filters/network/thrift_proxy/protocol_impl.cc index d0780b20d959..4d1cb437252a 100644 --- a/source/extensions/filters/network/thrift_proxy/protocol_impl.cc +++ b/source/extensions/filters/network/thrift_proxy/protocol_impl.cc @@ -17,6 +17,22 @@ namespace Extensions { namespace NetworkFilters { namespace ThriftProxy { +void AutoProtocolImpl::setType(ProtocolType type) { + if (!protocol_) { + switch (type) { + case ProtocolType::Binary: + setProtocol(std::make_unique()); + break; + case ProtocolType::Compact: + setProtocol(std::make_unique()); + break; + default: + // Ignored: attempt protocol detection. + break; + } + } +} + bool AutoProtocolImpl::readMessageBegin(Buffer::Instance& buffer, MessageMetadata& metadata) { if (protocol_ == nullptr) { if (buffer.length() < 2) { @@ -25,9 +41,9 @@ bool AutoProtocolImpl::readMessageBegin(Buffer::Instance& buffer, MessageMetadat uint16_t version = BufferHelper::peekU16(buffer); if (BinaryProtocolImpl::isMagic(version)) { - setProtocol(std::make_unique()); + setType(ProtocolType::Binary); } else if (CompactProtocolImpl::isMagic(version)) { - setProtocol(std::make_unique()); + setType(ProtocolType::Compact); } if (!protocol_) { diff --git a/source/extensions/filters/network/thrift_proxy/protocol_impl.h b/source/extensions/filters/network/thrift_proxy/protocol_impl.h index 227941ca5811..1f720f458cce 100644 --- a/source/extensions/filters/network/thrift_proxy/protocol_impl.h +++ b/source/extensions/filters/network/thrift_proxy/protocol_impl.h @@ -30,6 +30,7 @@ class AutoProtocolImpl : public Protocol { } return ProtocolType::Auto; } + void setType(ProtocolType type) override; bool readMessageBegin(Buffer::Instance& buffer, MessageMetadata& metadata) override; bool readMessageEnd(Buffer::Instance& buffer) override; diff --git a/source/extensions/filters/network/thrift_proxy/thrift.h b/source/extensions/filters/network/thrift_proxy/thrift.h index fe3d7022a59e..3fa29944fd7b 100644 --- a/source/extensions/filters/network/thrift_proxy/thrift.h +++ b/source/extensions/filters/network/thrift_proxy/thrift.h @@ -10,6 +10,7 @@ namespace ThriftProxy { enum class TransportType { Framed, + Header, Unframed, Auto, @@ -26,6 +27,9 @@ class TransportNameValues { // Framed transport const std::string FRAMED = "framed"; + // Header transport + const std::string HEADER = "header"; + // Unframed transport const std::string UNFRAMED = "unframed"; @@ -36,6 +40,8 @@ class TransportNameValues { switch (type) { case TransportType::Framed: return FRAMED; + case TransportType::Header: + return HEADER; case TransportType::Unframed: return UNFRAMED; case TransportType::Auto: diff --git a/source/extensions/filters/network/thrift_proxy/transport_impl.cc b/source/extensions/filters/network/thrift_proxy/transport_impl.cc index 0d5971f03e7e..d7efc6024239 100644 --- a/source/extensions/filters/network/thrift_proxy/transport_impl.cc +++ b/source/extensions/filters/network/thrift_proxy/transport_impl.cc @@ -8,6 +8,7 @@ #include "extensions/filters/network/thrift_proxy/buffer_helper.h" #include "extensions/filters/network/thrift_proxy/compact_protocol_impl.h" #include "extensions/filters/network/thrift_proxy/framed_transport_impl.h" +#include "extensions/filters/network/thrift_proxy/header_transport_impl.h" #include "extensions/filters/network/thrift_proxy/unframed_transport_impl.h" namespace Envoy { @@ -25,7 +26,16 @@ bool AutoTransportImpl::decodeFrameStart(Buffer::Instance& buffer, MessageMetada int32_t size = BufferHelper::peekI32(buffer); uint16_t proto_start = BufferHelper::peekU16(buffer, 4); - if (size > 0 && size <= FramedTransportImpl::MaxFrameSize) { + // Currently, transport detection depends on the following: + // 1. Protocol may only be binary or compact, which start with 0x8001 or 0x8201. + // 2. If unframed transport, size will appear negative due to leading protocol bytes. + // 3. If header transport, size is followed by 0x0FFF which is distinct from leading + // protocol bytes. + // 4. For framed transport, size is followed by protocol bytes. + if (size > 0 && size <= HeaderTransportImpl::MaxFrameSize && + HeaderTransportImpl::isMagic(proto_start)) { + setTransport(std::make_unique()); + } else if (size > 0 && size <= FramedTransportImpl::MaxFrameSize) { // TODO(zuercher): Spec says max size is 16,384,000 (0xFA0000). Apache C++ TFramedTransport // is configurable, but defaults to 256 MB (0x1000000). if (BinaryProtocolImpl::isMagic(proto_start) || CompactProtocolImpl::isMagic(proto_start)) { diff --git a/source/extensions/tracers/common/ot/opentracing_driver_impl.h b/source/extensions/tracers/common/ot/opentracing_driver_impl.h index faeaf51b5519..54c5e57528e2 100644 --- a/source/extensions/tracers/common/ot/opentracing_driver_impl.h +++ b/source/extensions/tracers/common/ot/opentracing_driver_impl.h @@ -76,7 +76,7 @@ class OpenTracingDriver : public Tracing::Driver, protected Logger::Loggable options_; const PropagationMode propagation_mode_; }; -} +} // namespace Lightstep } // namespace Tracers } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.h b/source/extensions/tracers/zipkin/zipkin_tracer_impl.h index 32590b2afda5..7c7ecc4a4323 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.h +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.h @@ -204,7 +204,7 @@ class ReporterImpl : public Reporter, Http::AsyncClient::Callbacks { SpanBuffer span_buffer_; const std::string collector_endpoint_; }; -} +} // namespace Zipkin } // namespace Tracers } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/transport_sockets/ssl/config.cc b/source/extensions/transport_sockets/ssl/config.cc index c3f69f301983..d211d8607586 100644 --- a/source/extensions/transport_sockets/ssl/config.cc +++ b/source/extensions/transport_sockets/ssl/config.cc @@ -18,7 +18,7 @@ Network::TransportSocketFactoryPtr UpstreamSslSocketFactory::createTransportSock Server::Configuration::TransportSocketFactoryContext& context) { auto client_config = std::make_unique( MessageUtil::downcastAndValidate(message), - context.secretManager()); + context); return std::make_unique( std::move(client_config), context.sslContextManager(), context.statsScope()); } @@ -36,7 +36,7 @@ Network::TransportSocketFactoryPtr DownstreamSslSocketFactory::createTransportSo const std::vector& server_names) { auto server_config = std::make_unique( MessageUtil::downcastAndValidate(message), - context.secretManager()); + context); return std::make_unique( std::move(server_config), context.sslContextManager(), context.statsScope(), server_names); } diff --git a/source/server/backtrace.h b/source/server/backtrace.h index 7fb2c6a96480..24eb010436a3 100644 --- a/source/server/backtrace.h +++ b/source/server/backtrace.h @@ -129,4 +129,4 @@ class BackwardsTrace : Logger::Loggable { static const int MAX_STACK_DEPTH = 64; backward::StackTrace stack_trace_; }; -} // Envoy +} // namespace Envoy diff --git a/source/server/connection_handler_impl.h b/source/server/connection_handler_impl.h index 9a2f4c192438..c841ee0bc555 100644 --- a/source/server/connection_handler_impl.h +++ b/source/server/connection_handler_impl.h @@ -168,5 +168,5 @@ class ConnectionHandlerImpl : public Network::ConnectionHandler, NonCopyable { std::atomic num_connections_{}; }; -} // Server +} // namespace Server } // namespace Envoy diff --git a/source/server/listener_manager_impl.cc b/source/server/listener_manager_impl.cc index 03afc4c08e1e..d15199203a39 100644 --- a/source/server/listener_manager_impl.cc +++ b/source/server/listener_manager_impl.cc @@ -231,6 +231,7 @@ ListenerImpl::ListenerImpl(const envoy::api::v2::Listener& config, const std::st parent_.server_.sslContextManager(), *listener_scope_, parent_.server_.clusterManager(), parent_.server_.localInfo(), parent_.server_.dispatcher(), parent_.server_.random(), parent_.server_.stats()); + factory_context.setInitManager(initManager()); addFilterChain( PROTOBUF_GET_WRAPPED_OR_DEFAULT(filter_chain_match, destination_port, 0), destination_ips, server_names, filter_chain_match.transport_protocol(), application_protocols, diff --git a/source/server/server.cc b/source/server/server.cc index 5f3f4ddd2166..1b56491a09ac 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -53,9 +53,9 @@ InstanceImpl::InstanceImpl(Options& options, Network::Address::InstanceConstShar api_(new Api::Impl(options.fileFlushIntervalMsec())), dispatcher_(api_->allocateDispatcher()), singleton_manager_(new Singleton::ManagerImpl()), handler_(new ConnectionHandlerImpl(ENVOY_LOGGER(), *dispatcher_)), - random_generator_(std::move(random_generator)), listener_component_factory_(*this), + random_generator_(std::move(random_generator)), + secret_manager_(new Secret::SecretManagerImpl()), listener_component_factory_(*this), worker_factory_(thread_local_, *api_, hooks), - secret_manager_(new Secret::SecretManagerImpl()), dns_resolver_(dispatcher_->createDnsResolver({})), access_log_manager_(*api_, *dispatcher_, access_log_lock, store), terminated_(false) { diff --git a/source/server/server.h b/source/server/server.h index 40cb5001539e..b43c0ffa7d49 100644 --- a/source/server/server.h +++ b/source/server/server.h @@ -206,11 +206,11 @@ class InstanceImpl : Logger::Loggable, public Instance { Network::ConnectionHandlerPtr handler_; Runtime::RandomGeneratorPtr random_generator_; Runtime::LoaderPtr runtime_loader_; + std::unique_ptr secret_manager_; std::unique_ptr ssl_context_manager_; ProdListenerComponentFactory listener_component_factory_; ProdWorkerFactory worker_factory_; std::unique_ptr listener_manager_; - std::unique_ptr secret_manager_; std::unique_ptr config_; Network::DnsResolverSharedPtr dns_resolver_; Event::TimerPtr stat_flush_timer_; diff --git a/source/server/transport_socket_config_impl.h b/source/server/transport_socket_config_impl.h index d5adcd09a575..c9747cc6b541 100644 --- a/source/server/transport_socket_config_impl.h +++ b/source/server/transport_socket_config_impl.h @@ -24,12 +24,12 @@ class TransportSocketFactoryContextImpl : public TransportSocketFactoryContext { Stats::Scope& statsScope() const override { return stats_scope_; } - Upstream::ClusterManager& clusterManager() override { return cluster_manager_; } - Secret::SecretManager& secretManager() override { return cluster_manager_.clusterManagerFactory().secretManager(); } + Upstream::ClusterManager& clusterManager() override { return cluster_manager_; } + const LocalInfo::LocalInfo& localInfo() override { return local_info_; } Event::Dispatcher& dispatcher() override { return dispatcher_; } @@ -38,6 +38,10 @@ class TransportSocketFactoryContextImpl : public TransportSocketFactoryContext { Stats::Store& stats() override { return stats_; } + void setInitManager(Init::Manager& init_manager) override { init_manager_ = &init_manager; } + + Init::Manager* initManager() override { return init_manager_; } + private: Ssl::ContextManager& context_manager_; Stats::Scope& stats_scope_; @@ -46,6 +50,7 @@ class TransportSocketFactoryContextImpl : public TransportSocketFactoryContext { Event::Dispatcher& dispatcher_; Envoy::Runtime::RandomGenerator& random_; Stats::Store& stats_; + Init::Manager* init_manager_{}; }; } // namespace Configuration diff --git a/test/common/access_log/access_log_formatter_test.cc b/test/common/access_log/access_log_formatter_test.cc index 44c0ddf9eda8..a620486df7f0 100644 --- a/test/common/access_log/access_log_formatter_test.cc +++ b/test/common/access_log/access_log_formatter_test.cc @@ -16,10 +16,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace AccessLog { diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index cf9b939d825c..f7d0ded0074d 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -25,10 +25,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::SaveArg; -using testing::_; namespace Envoy { namespace AccessLog { diff --git a/test/common/access_log/access_log_manager_impl_test.cc b/test/common/access_log/access_log_manager_impl_test.cc index 02e358dbb2fd..d4b644ad6db7 100644 --- a/test/common/access_log/access_log_manager_impl_test.cc +++ b/test/common/access_log/access_log_manager_impl_test.cc @@ -11,8 +11,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Return; using testing::_; +using testing::Return; namespace Envoy { namespace AccessLog { diff --git a/test/common/buffer/owned_impl_test.cc b/test/common/buffer/owned_impl_test.cc index 0cbbd7f97d77..227f93284662 100644 --- a/test/common/buffer/owned_impl_test.cc +++ b/test/common/buffer/owned_impl_test.cc @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Return; using testing::_; +using testing::Return; namespace Envoy { namespace Buffer { diff --git a/test/common/common/token_bucket_impl_test.cc b/test/common/common/token_bucket_impl_test.cc index 397d77718a62..e31717892be1 100644 --- a/test/common/common/token_bucket_impl_test.cc +++ b/test/common/common/token_bucket_impl_test.cc @@ -8,8 +8,8 @@ #include "gtest/gtest.h" using ::testing::Mock; -using ::testing::Return; using testing::NiceMock; +using ::testing::Return; namespace Envoy { diff --git a/test/common/config/filesystem_subscription_test_harness.h b/test/common/config/filesystem_subscription_test_harness.h index 16a42f054380..3ad7886969d2 100644 --- a/test/common/config/filesystem_subscription_test_harness.h +++ b/test/common/config/filesystem_subscription_test_harness.h @@ -14,9 +14,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Config { diff --git a/test/common/config/grpc_mux_impl_test.cc b/test/common/config/grpc_mux_impl_test.cc index d0a1be52d76e..7eba78672f35 100644 --- a/test/common/config/grpc_mux_impl_test.cc +++ b/test/common/config/grpc_mux_impl_test.cc @@ -17,13 +17,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AtLeast; using testing::InSequence; using testing::Invoke; using testing::IsSubstring; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Config { diff --git a/test/common/config/grpc_subscription_test_harness.h b/test/common/config/grpc_subscription_test_harness.h index 06e22e0ef28a..515888ccb82e 100644 --- a/test/common/config/grpc_subscription_test_harness.h +++ b/test/common/config/grpc_subscription_test_harness.h @@ -16,11 +16,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Mock; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Config { diff --git a/test/common/config/http_subscription_test_harness.h b/test/common/config/http_subscription_test_harness.h index 180b7647bf13..2efa3b0ce7a4 100644 --- a/test/common/config/http_subscription_test_harness.h +++ b/test/common/config/http_subscription_test_harness.h @@ -17,9 +17,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; -using testing::_; namespace Envoy { namespace Config { diff --git a/test/common/config/subscription_factory_test.cc b/test/common/config/subscription_factory_test.cc index 6a2384a35eb7..136a60a36a81 100644 --- a/test/common/config/subscription_factory_test.cc +++ b/test/common/config/subscription_factory_test.cc @@ -16,9 +16,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using ::testing::_; using ::testing::Invoke; using ::testing::Return; -using ::testing::_; namespace Envoy { namespace Config { diff --git a/test/common/config/utility_test.cc b/test/common/config/utility_test.cc index d71ab74e2ac6..631b1cdc7780 100644 --- a/test/common/config/utility_test.cc +++ b/test/common/config/utility_test.cc @@ -19,11 +19,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AtLeast; using testing::Ref; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Config { diff --git a/test/common/filesystem/filesystem_impl_test.cc b/test/common/filesystem/filesystem_impl_test.cc index cd32ec5f0fee..e4a8f5cf354e 100644 --- a/test/common/filesystem/filesystem_impl_test.cc +++ b/test/common/filesystem/filesystem_impl_test.cc @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; @@ -24,7 +25,6 @@ using testing::Return; using testing::SaveArg; using testing::Sequence; using testing::Throw; -using testing::_; namespace Envoy { diff --git a/test/common/grpc/BUILD b/test/common/grpc/BUILD index 3294b133c88a..566a23313e77 100644 --- a/test/common/grpc/BUILD +++ b/test/common/grpc/BUILD @@ -98,6 +98,7 @@ envoy_cc_test_library( "//source/common/http/http2:conn_pool_lib", "//test/integration:integration_lib", "//test/mocks/local_info:local_info_mocks", + "//test/mocks/server:server_mocks", "//test/proto:helloworld_proto", ], ) diff --git a/test/common/grpc/async_client_impl_test.cc b/test/common/grpc/async_client_impl_test.cc index fcc1c475f592..c0f89abc080e 100644 --- a/test/common/grpc/async_client_impl_test.cc +++ b/test/common/grpc/async_client_impl_test.cc @@ -8,11 +8,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnRef; using testing::Throw; -using testing::_; namespace Envoy { namespace Grpc { diff --git a/test/common/grpc/google_async_client_impl_test.cc b/test/common/grpc/google_async_client_impl_test.cc index 01a03a21850d..9dc85bca0b0c 100644 --- a/test/common/grpc/google_async_client_impl_test.cc +++ b/test/common/grpc/google_async_client_impl_test.cc @@ -11,8 +11,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Return; using testing::_; +using testing::Return; namespace Envoy { namespace Grpc { diff --git a/test/common/grpc/grpc_client_integration_test_harness.h b/test/common/grpc/grpc_client_integration_test_harness.h index 2c3dfcf89026..0ed7187a55cf 100644 --- a/test/common/grpc/grpc_client_integration_test_harness.h +++ b/test/common/grpc/grpc_client_integration_test_harness.h @@ -13,18 +13,18 @@ #include "test/integration/fake_upstream.h" #include "test/mocks/grpc/mocks.h" #include "test/mocks/local_info/mocks.h" -#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "test/mocks/tracing/mocks.h" #include "test/mocks/upstream/mocks.h" #include "test/proto/helloworld.pb.h" #include "test/test_common/environment.h" +using testing::_; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Grpc { @@ -461,7 +461,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, secret_manager_); + auto cfg = std::make_unique(tls_context, factory_context_); mock_cluster_info_->transport_socket_factory_ = std::make_unique( std::move(cfg), context_manager_, *stats_store_); @@ -491,7 +491,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); } - auto cfg = std::make_unique(tls_context, secret_manager_); + auto cfg = std::make_unique(tls_context, factory_context_); static Stats::Scope* upstream_stats_store = new Stats::IsolatedStoreImpl(); return std::make_unique( @@ -499,7 +499,7 @@ class GrpcSslClientIntegrationTest : public GrpcClientIntegrationTest { } bool use_client_cert_{}; - NiceMock secret_manager_; + testing::NiceMock factory_context_; }; } // namespace diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index fc3b36990bae..7ade4bbefba3 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -21,12 +21,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Ref; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/codec_client_test.cc b/test/common/http/codec_client_test.cc index e902232c7705..5cc31cb0ef81 100644 --- a/test/common/http/codec_client_test.cc +++ b/test/common/http/codec_client_test.cc @@ -23,6 +23,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AtMost; using testing::Invoke; using testing::InvokeWithoutArgs; @@ -32,7 +33,6 @@ using testing::Ref; using testing::Return; using testing::SaveArg; using testing::Throw; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/codes_test.cc b/test/common/http/codes_test.cc index 55d2795be3b6..a9127ee1d2d4 100644 --- a/test/common/http/codes_test.cc +++ b/test/common/http/codes_test.cc @@ -16,8 +16,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Property; using testing::_; +using testing::Property; namespace Envoy { namespace Http { diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index 013385aab627..9e23e99d74be 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -42,6 +42,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::DoAll; @@ -54,7 +55,6 @@ using testing::Return; using testing::ReturnRef; using testing::Sequence; using testing::Test; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/conn_manager_utility_test.cc b/test/common/http/conn_manager_utility_test.cc index 411d0f483a3b..00bc9ac8a52b 100644 --- a/test/common/http/conn_manager_utility_test.cc +++ b/test/common/http/conn_manager_utility_test.cc @@ -18,11 +18,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/http1/codec_impl_test.cc b/test/common/http/http1/codec_impl_test.cc index 2427f9c4f4a2..0755246b6235 100644 --- a/test/common/http/http1/codec_impl_test.cc +++ b/test/common/http/http1/codec_impl_test.cc @@ -16,12 +16,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/http1/conn_pool_test.cc b/test/common/http/http1/conn_pool_test.cc index 0c396d8818fd..e2706d83e4b2 100644 --- a/test/common/http/http1/conn_pool_test.cc +++ b/test/common/http/http1/conn_pool_test.cc @@ -22,6 +22,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -30,7 +31,6 @@ using testing::Property; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/http2/codec_impl_fuzz_test.cc b/test/common/http/http2/codec_impl_fuzz_test.cc index 209846de9f29..0e0b6f9952dc 100644 --- a/test/common/http/http2/codec_impl_fuzz_test.cc +++ b/test/common/http/http2/codec_impl_fuzz_test.cc @@ -22,9 +22,9 @@ #include "gmock/gmock.h" +using testing::_; using testing::Invoke; using testing::InvokeWithoutArgs; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/http2/codec_impl_test.cc b/test/common/http/http2/codec_impl_test.cc index f9bb1f0a4c3c..186bb097f9f4 100644 --- a/test/common/http/http2/codec_impl_test.cc +++ b/test/common/http/http2/codec_impl_test.cc @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::InSequence; @@ -24,7 +25,6 @@ using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/http2/conn_pool_test.cc b/test/common/http/http2/conn_pool_test.cc index 659676f8b8b1..67e37b7bb315 100644 --- a/test/common/http/http2/conn_pool_test.cc +++ b/test/common/http/http2/conn_pool_test.cc @@ -19,6 +19,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -27,7 +28,6 @@ using testing::Property; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/user_agent_test.cc b/test/common/http/user_agent_test.cc index a479a7cde225..db581d3fb9e3 100644 --- a/test/common/http/user_agent_test.cc +++ b/test/common/http/user_agent_test.cc @@ -7,9 +7,9 @@ #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Property; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/http/utility_test.cc b/test/common/http/utility_test.cc index c50be78887ab..2a3473d80168 100644 --- a/test/common/http/utility_test.cc +++ b/test/common/http/utility_test.cc @@ -14,9 +14,9 @@ #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::InvokeWithoutArgs; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/common/network/connection_impl_test.cc b/test/common/network/connection_impl_test.cc index abb352e02f06..fd4f98ba85b8 100644 --- a/test/common/network/connection_impl_test.cc +++ b/test/common/network/connection_impl_test.cc @@ -25,6 +25,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::DoAll; using testing::InSequence; @@ -35,7 +36,6 @@ using testing::SaveArg; using testing::Sequence; using testing::StrictMock; using testing::Test; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/common/network/dns_impl_test.cc b/test/common/network/dns_impl_test.cc index 026cfa58bc9c..b718ed21a800 100644 --- a/test/common/network/dns_impl_test.cc +++ b/test/common/network/dns_impl_test.cc @@ -31,11 +31,11 @@ #include "ares_dns.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Mock; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/common/network/filter_manager_impl_test.cc b/test/common/network/filter_manager_impl_test.cc index 7da939a2413d..06837dfbd450 100644 --- a/test/common/network/filter_manager_impl_test.cc +++ b/test/common/network/filter_manager_impl_test.cc @@ -23,12 +23,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/common/network/listen_socket_impl_test.cc b/test/common/network/listen_socket_impl_test.cc index f723398fbc24..3a42ebf6ba27 100644 --- a/test/common/network/listen_socket_impl_test.cc +++ b/test/common/network/listen_socket_impl_test.cc @@ -10,8 +10,8 @@ #include "gtest/gtest.h" -using testing::Return; using testing::_; +using testing::Return; namespace Envoy { namespace Network { diff --git a/test/common/network/listener_impl_test.cc b/test/common/network/listener_impl_test.cc index 76b4bfc1345c..dcf6c7bb8e4e 100644 --- a/test/common/network/listener_impl_test.cc +++ b/test/common/network/listener_impl_test.cc @@ -11,9 +11,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/common/network/socket_option_test.h b/test/common/network/socket_option_test.h index 4ba3f83f9078..0f21917c7673 100644 --- a/test/common/network/socket_option_test.h +++ b/test/common/network/socket_option_test.h @@ -8,10 +8,10 @@ #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/common/ratelimit/ratelimit_impl_test.cc b/test/common/ratelimit/ratelimit_impl_test.cc index 02e09fb4fccc..7c2fe8e9d7b1 100644 --- a/test/common/ratelimit/ratelimit_impl_test.cc +++ b/test/common/ratelimit/ratelimit_impl_test.cc @@ -17,12 +17,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AtLeast; using testing::Invoke; using testing::Ref; using testing::Return; using testing::WithArg; -using testing::_; namespace Envoy { namespace RateLimit { diff --git a/test/common/request_info/utility_test.cc b/test/common/request_info/utility_test.cc index e9058a1f1ed5..d2e677d2d324 100644 --- a/test/common/request_info/utility_test.cc +++ b/test/common/request_info/utility_test.cc @@ -6,9 +6,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace RequestInfo { diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 16874a5224e6..5fe3ff018629 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -29,6 +29,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ContainerEq; using testing::ElementsAreArray; using testing::MockFunction; @@ -36,7 +37,6 @@ using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::StrNe; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/rds_impl_test.cc b/test/common/router/rds_impl_test.cc index f68a73851c64..a0657aa985a6 100644 --- a/test/common/router/rds_impl_test.cc +++ b/test/common/router/rds_impl_test.cc @@ -24,12 +24,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/retry_state_impl_test.cc b/test/common/router/retry_state_impl_test.cc index 99899fb3a6a1..92d8b6b70458 100644 --- a/test/common/router/retry_state_impl_test.cc +++ b/test/common/router/retry_state_impl_test.cc @@ -13,9 +13,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/router_ratelimit_test.cc b/test/common/router/router_ratelimit_test.cc index 5142ae43d6fc..e302f382c85a 100644 --- a/test/common/router/router_ratelimit_test.cc +++ b/test/common/router/router_ratelimit_test.cc @@ -19,9 +19,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/router_test.cc b/test/common/router/router_test.cc index 0903639555fe..467b2fa68aa8 100644 --- a/test/common/router/router_test.cc +++ b/test/common/router/router_test.cc @@ -27,6 +27,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AssertionFailure; using testing::AssertionResult; using testing::AssertionSuccess; @@ -39,7 +40,6 @@ using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/router_upstream_log_test.cc b/test/common/router/router_upstream_log_test.cc index d65e77eccec3..f10fd7f67017 100644 --- a/test/common/router/router_upstream_log_test.cc +++ b/test/common/router/router_upstream_log_test.cc @@ -22,11 +22,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/common/router/shadow_writer_impl_test.cc b/test/common/router/shadow_writer_impl_test.cc index 1f1b9c480cce..53f979e8826d 100644 --- a/test/common/router/shadow_writer_impl_test.cc +++ b/test/common/router/shadow_writer_impl_test.cc @@ -10,8 +10,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Router { diff --git a/test/common/runtime/runtime_impl_test.cc b/test/common/runtime/runtime_impl_test.cc index 6606e2b57bad..85ec22b011fd 100644 --- a/test/common/runtime/runtime_impl_test.cc +++ b/test/common/runtime/runtime_impl_test.cc @@ -14,11 +14,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnNew; -using testing::_; namespace Envoy { namespace Runtime { diff --git a/test/common/secret/BUILD b/test/common/secret/BUILD index c65489952a84..cbb7aff3e74d 100644 --- a/test/common/secret/BUILD +++ b/test/common/secret/BUILD @@ -15,9 +15,30 @@ envoy_cc_test( "//test/common/ssl/test_data:certs", ], deps = [ + "//source/common/secret:sds_api_lib", "//source/common/secret:secret_manager_impl_lib", + "//test/mocks/server:server_mocks", "//test/test_common:environment_lib", "//test/test_common:registry_lib", "//test/test_common:utility_lib", ], ) + +envoy_cc_test( + name = "sds_api_test", + srcs = ["sds_api_test.cc"], + data = [ + "//test/common/ssl/test_data:certs", + ], + deps = [ + "//source/common/secret:sds_api_lib", + "//test/mocks/grpc:grpc_mocks", + "//test/mocks/init:init_mocks", + "//test/mocks/secret:secret_mocks", + "//test/mocks/server:server_mocks", + "//test/test_common:environment_lib", + "//test/test_common:registry_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/service/discovery/v2:sds_cc", + ], +) diff --git a/test/common/secret/sds_api_test.cc b/test/common/secret/sds_api_test.cc new file mode 100644 index 000000000000..da000b022f5d --- /dev/null +++ b/test/common/secret/sds_api_test.cc @@ -0,0 +1,163 @@ +#include + +#include "envoy/api/v2/auth/cert.pb.h" +#include "envoy/common/exception.h" +#include "envoy/service/discovery/v2/sds.pb.h" + +#include "common/secret/sds_api.h" + +#include "test/mocks/grpc/mocks.h" +#include "test/mocks/init/mocks.h" +#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::_; +using ::testing::Invoke; +using ::testing::Return; + +namespace Envoy { +namespace Secret { +namespace { + +class SdsApiTest : public testing::Test {}; + +TEST_F(SdsApiTest, BasicTest) { + ::testing::InSequence s; + const envoy::service::discovery::v2::SdsDummy dummy; + NiceMock server; + NiceMock init_manager; + EXPECT_CALL(init_manager, registerTarget(_)); + + envoy::api::v2::core::ConfigSource config_source; + config_source.mutable_api_config_source()->set_api_type( + envoy::api::v2::core::ApiConfigSource::GRPC); + auto grpc_service = config_source.mutable_api_config_source()->add_grpc_services(); + auto google_grpc = grpc_service->mutable_google_grpc(); + google_grpc->set_target_uri("fake_address"); + google_grpc->set_stat_prefix("test"); + SdsApi sds_api(server.localInfo(), server.dispatcher(), server.random(), server.stats(), + server.clusterManager(), init_manager, config_source, "abc.com", []() {}); + + NiceMock* grpc_client{new NiceMock()}; + NiceMock* factory{new NiceMock()}; + EXPECT_CALL(server.cluster_manager_.async_client_manager_, factoryForGrpcService(_, _, _)) + .WillOnce(Invoke([factory](const envoy::api::v2::core::GrpcService&, Stats::Scope&, bool) { + return Grpc::AsyncClientFactoryPtr{factory}; + })); + EXPECT_CALL(*factory, create()).WillOnce(Invoke([grpc_client] { + return Grpc::AsyncClientPtr{grpc_client}; + })); + EXPECT_CALL(init_manager.initialized_, ready()); + init_manager.initialize(); +} + +TEST_F(SdsApiTest, SecretUpdateSuccess) { + NiceMock server; + NiceMock init_manager; + envoy::api::v2::core::ConfigSource config_source; + SdsApi sds_api(server.localInfo(), server.dispatcher(), server.random(), server.stats(), + server.clusterManager(), init_manager, config_source, "abc.com", []() {}); + + NiceMock secret_callback; + sds_api.addUpdateCallback(secret_callback); + + std::string yaml = + R"EOF( + name: "abc.com" + tls_certificate: + certificate_chain: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem" + )EOF"; + + Protobuf::RepeatedPtrField secret_resources; + auto secret_config = secret_resources.Add(); + MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), *secret_config); + EXPECT_CALL(secret_callback, onAddOrUpdateSecret()); + sds_api.onConfigUpdate(secret_resources, ""); + + const std::string cert_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem"; + EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)), + sds_api.secret()->certificateChain()); + + const std::string key_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem"; + EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(key_pem)), + sds_api.secret()->privateKey()); + + sds_api.removeUpdateCallback(secret_callback); +} + +TEST_F(SdsApiTest, EmptyResource) { + NiceMock server; + NiceMock init_manager; + envoy::api::v2::core::ConfigSource config_source; + SdsApi sds_api(server.localInfo(), server.dispatcher(), server.random(), server.stats(), + server.clusterManager(), init_manager, config_source, "abc.com", []() {}); + + Protobuf::RepeatedPtrField secret_resources; + + EXPECT_THROW_WITH_MESSAGE(sds_api.onConfigUpdate(secret_resources, ""), EnvoyException, + "Missing SDS resources for abc.com in onConfigUpdate()"); +} + +TEST_F(SdsApiTest, SecretUpdateWrongSize) { + NiceMock server; + NiceMock init_manager; + envoy::api::v2::core::ConfigSource config_source; + SdsApi sds_api(server.localInfo(), server.dispatcher(), server.random(), server.stats(), + server.clusterManager(), init_manager, config_source, "abc.com", []() {}); + + std::string yaml = + R"EOF( + name: "abc.com" + tls_certificate: + certificate_chain: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem" + )EOF"; + + Protobuf::RepeatedPtrField secret_resources; + auto secret_config_1 = secret_resources.Add(); + MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), *secret_config_1); + auto secret_config_2 = secret_resources.Add(); + MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), *secret_config_2); + + EXPECT_THROW_WITH_MESSAGE(sds_api.onConfigUpdate(secret_resources, ""), EnvoyException, + "Unexpected SDS secrets length: 2"); +} + +TEST_F(SdsApiTest, SecretUpdateWrongSecretName) { + NiceMock server; + NiceMock init_manager; + envoy::api::v2::core::ConfigSource config_source; + SdsApi sds_api(server.localInfo(), server.dispatcher(), server.random(), server.stats(), + server.clusterManager(), init_manager, config_source, "abc.com", []() {}); + + std::string yaml = + R"EOF( + name: "wrong.name.com" + tls_certificate: + certificate_chain: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem" + )EOF"; + + Protobuf::RepeatedPtrField secret_resources; + auto secret_config = secret_resources.Add(); + MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), *secret_config); + + EXPECT_THROW_WITH_MESSAGE(sds_api.onConfigUpdate(secret_resources, ""), EnvoyException, + "Unexpected SDS secret (expecting abc.com): wrong.name.com"); +} + +} // namespace +} // namespace Secret +} // namespace Envoy diff --git a/test/common/secret/secret_manager_impl_test.cc b/test/common/secret/secret_manager_impl_test.cc index bf27f559fd4f..f957d3c301ca 100644 --- a/test/common/secret/secret_manager_impl_test.cc +++ b/test/common/secret/secret_manager_impl_test.cc @@ -3,14 +3,19 @@ #include "envoy/api/v2/auth/cert.pb.h" #include "envoy/common/exception.h" +#include "common/secret/sds_api.h" #include "common/secret/secret_manager_impl.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/utility.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::Return; +using testing::ReturnRef; + namespace Envoy { namespace Secret { namespace { @@ -69,6 +74,51 @@ name: "abc.com" "Secret type not implemented"); } +TEST_F(SecretManagerImplTest, SdsDynamicSecretUpdateSuccess) { + Server::MockInstance server; + std::unique_ptr secret_manager(new SecretManagerImpl()); + + NiceMock secret_context; + + envoy::api::v2::core::ConfigSource config_source; + { + NiceMock local_info; + NiceMock dispatcher; + NiceMock random; + Stats::IsolatedStoreImpl stats; + NiceMock cluster_manager; + NiceMock init_manager; + EXPECT_CALL(secret_context, localInfo()).WillOnce(ReturnRef(local_info)); + EXPECT_CALL(secret_context, dispatcher()).WillOnce(ReturnRef(dispatcher)); + EXPECT_CALL(secret_context, random()).WillOnce(ReturnRef(random)); + EXPECT_CALL(secret_context, stats()).WillOnce(ReturnRef(stats)); + EXPECT_CALL(secret_context, clusterManager()).WillOnce(ReturnRef(cluster_manager)); + EXPECT_CALL(secret_context, initManager()).WillRepeatedly(Return(&init_manager)); + + auto secret_provider = + secret_manager->findOrCreateDynamicSecretProvider(config_source, "abc.com", secret_context); + std::string yaml = + R"EOF( +name: "abc.com" +tls_certificate: + certificate_chain: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem" + private_key: + filename: "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem" + )EOF"; + Protobuf::RepeatedPtrField secret_resources; + auto secret_config = secret_resources.Add(); + MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), *secret_config); + std::dynamic_pointer_cast(secret_provider)->onConfigUpdate(secret_resources, ""); + const std::string cert_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem"; + EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)), + secret_provider->secret()->certificateChain()); + const std::string key_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_key.pem"; + EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(key_pem)), + secret_provider->secret()->privateKey()); + } +} + } // namespace } // namespace Secret } // namespace Envoy diff --git a/test/common/ssl/BUILD b/test/common/ssl/BUILD index 70a45354264f..3d25e54a8e80 100644 --- a/test/common/ssl/BUILD +++ b/test/common/ssl/BUILD @@ -36,7 +36,6 @@ envoy_cc_test( "//test/mocks/buffer:buffer_mocks", "//test/mocks/network:network_mocks", "//test/mocks/runtime:runtime_mocks", - "//test/mocks/secret:secret_mocks", "//test/mocks/server:server_mocks", "//test/mocks/stats:stats_mocks", "//test/test_common:environment_lib", @@ -57,13 +56,13 @@ envoy_cc_test( ], deps = [ "//source/common/json:json_loader_lib", - "//source/common/secret:secret_manager_impl_lib", "//source/common/ssl:context_config_lib", "//source/common/ssl:context_lib", "//source/common/stats:isolated_store_lib", "//source/common/stats:stats_lib", "//test/mocks/runtime:runtime_mocks", "//test/mocks/secret:secret_mocks", + "//test/mocks/server:server_mocks", "//test/test_common:environment_lib", ], ) diff --git a/test/common/ssl/context_impl_test.cc b/test/common/ssl/context_impl_test.cc index 4c533ea17c19..70dcc0e9badc 100644 --- a/test/common/ssl/context_impl_test.cc +++ b/test/common/ssl/context_impl_test.cc @@ -2,7 +2,7 @@ #include #include "common/json/json_loader.h" -#include "common/secret/secret_manager_impl.h" +#include "common/secret/sds_api.h" #include "common/ssl/context_config_impl.h" #include "common/ssl/context_impl.h" #include "common/stats/isolated_store_impl.h" @@ -10,12 +10,14 @@ #include "test/common/ssl/ssl_certs_test.h" #include "test/mocks/runtime/mocks.h" #include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/utility.h" #include "gtest/gtest.h" using testing::NiceMock; +using testing::ReturnRef; namespace Envoy { namespace Ssl { @@ -81,7 +83,7 @@ TEST_F(SslContextImplTest, TestCipherSuites) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader, secret_manager_); + ClientContextConfigImpl cfg(*loader, factory_context_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -100,7 +102,7 @@ TEST_F(SslContextImplTest, TestExpiringCert) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader, secret_manager_); + ClientContextConfigImpl cfg(*loader, factory_context_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -123,7 +125,7 @@ TEST_F(SslContextImplTest, TestExpiredCert) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader, secret_manager_); + ClientContextConfigImpl cfg(*loader, factory_context_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -141,7 +143,7 @@ TEST_F(SslContextImplTest, TestGetCertInformation) { )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - ClientContextConfigImpl cfg(*loader, secret_manager_); + ClientContextConfigImpl cfg(*loader, factory_context_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -167,7 +169,7 @@ TEST_F(SslContextImplTest, TestGetCertInformation) { TEST_F(SslContextImplTest, TestNoCert) { Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString("{}"); - ClientContextConfigImpl cfg(*loader, secret_manager_); + ClientContextConfigImpl cfg(*loader, factory_context_); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -180,7 +182,6 @@ class SslServerContextImplTicketTest : public SslContextImplTest { public: static void loadConfig(ServerContextConfigImpl& cfg) { Runtime::MockLoader runtime; - NiceMock secret_manager; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; ServerContextSharedPtr server_ctx( @@ -196,15 +197,15 @@ class SslServerContextImplTicketTest : public SslContextImplTest { server_cert->mutable_private_key()->set_filename( TestEnvironment::substitute("{{ test_tmpdir }}/unittestkey.pem")); - NiceMock secret_manager; - ServerContextConfigImpl server_context_config(cfg, secret_manager); + NiceMock factory_context; + ServerContextConfigImpl server_context_config(cfg, factory_context); loadConfig(server_context_config); } static void loadConfigJson(const std::string& json) { Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - NiceMock secret_manager; - ServerContextConfigImpl cfg(*loader, secret_manager); + NiceMock factory_context; + ServerContextConfigImpl cfg(*loader, factory_context); loadConfig(cfg); } }; @@ -361,28 +362,28 @@ class ClientContextConfigImplTest : public SslCertsTest {}; // Validate that empty SNI (according to C string rules) fails config validation. TEST(ClientContextConfigImplTest, EmptyServerNameIndication) { envoy::api::v2::auth::UpstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; tls_context.set_sni(std::string("\000", 1)); EXPECT_THROW_WITH_MESSAGE( - ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + ClientContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, "SNI names containing NULL-byte are not allowed"); tls_context.set_sni(std::string("a\000b", 3)); EXPECT_THROW_WITH_MESSAGE( - ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + ClientContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, "SNI names containing NULL-byte are not allowed"); } // Validate that values other than a hex-encoded SHA-256 fail config validation. TEST(ClientContextConfigImplTest, InvalidCertificateHash) { envoy::api::v2::auth::UpstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; tls_context.mutable_common_tls_context() ->mutable_validation_context() // This is valid hex-encoded string, but it doesn't represent SHA-256 (80 vs 64 chars). ->add_verify_certificate_hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - ClientContextConfigImpl client_context_config(tls_context, secret_manager); + ClientContextConfigImpl client_context_config(tls_context, factory_context); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -393,12 +394,12 @@ TEST(ClientContextConfigImplTest, InvalidCertificateHash) { // Validate that values other than a base64-encoded SHA-256 fail config validation. TEST(ClientContextConfigImplTest, InvalidCertificateSpki) { envoy::api::v2::auth::UpstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; tls_context.mutable_common_tls_context() ->mutable_validation_context() // Not a base64-encoded string. ->add_verify_certificate_spki("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - ClientContextConfigImpl client_context_config(tls_context, secret_manager); + ClientContextConfigImpl client_context_config(tls_context, factory_context); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -410,14 +411,48 @@ TEST(ClientContextConfigImplTest, InvalidCertificateSpki) { // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ClientContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::UpstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; tls_context.mutable_common_tls_context()->add_tls_certificates(); tls_context.mutable_common_tls_context()->add_tls_certificates(); EXPECT_THROW_WITH_MESSAGE( - ClientContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + ClientContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, "Multiple TLS certificates are not supported for client contexts"); } +TEST(ClientContextConfigImplTest, TlsCertificatesAndSdsConfig) { + envoy::api::v2::auth::UpstreamTlsContext tls_context; + NiceMock factory_context; + tls_context.mutable_common_tls_context()->add_tls_certificates(); + tls_context.mutable_common_tls_context()->add_tls_certificate_sds_secret_configs(); + EXPECT_THROW_WITH_MESSAGE( + ClientContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, + "Multiple TLS certificates are not supported for client contexts"); +} + +TEST(ClientContextConfigImplTest, SecretNotReady) { + envoy::api::v2::auth::UpstreamTlsContext tls_context; + NiceMock local_info; + NiceMock dispatcher; + NiceMock random; + Stats::IsolatedStoreImpl stats; + NiceMock cluster_manager; + NiceMock init_manager; + NiceMock factory_context; + EXPECT_CALL(factory_context, localInfo()).WillOnce(ReturnRef(local_info)); + EXPECT_CALL(factory_context, dispatcher()).WillOnce(ReturnRef(dispatcher)); + EXPECT_CALL(factory_context, random()).WillOnce(ReturnRef(random)); + EXPECT_CALL(factory_context, stats()).WillOnce(ReturnRef(stats)); + EXPECT_CALL(factory_context, clusterManager()).WillOnce(ReturnRef(cluster_manager)); + EXPECT_CALL(factory_context, initManager()).WillRepeatedly(Return(&init_manager)); + auto sds_secret_configs = + tls_context.mutable_common_tls_context()->mutable_tls_certificate_sds_secret_configs()->Add(); + sds_secret_configs->set_name("abc.com"); + sds_secret_configs->mutable_sds_config(); + ClientContextConfigImpl client_context_config(tls_context, factory_context); + // When sds secret is not downloaded, config is not ready. + EXPECT_FALSE(client_context_config.isReady()); +} + TEST(ClientContextConfigImplTest, StaticTlsCertificates) { envoy::api::v2::auth::Secret secret_config; @@ -432,16 +467,15 @@ name: "abc.com" MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), secret_config); - std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); - secret_manager->addStaticSecret(secret_config); - envoy::api::v2::auth::UpstreamTlsContext tls_context; tls_context.mutable_common_tls_context() ->mutable_tls_certificate_sds_secret_configs() ->Add() ->set_name("abc.com"); - ClientContextConfigImpl client_context_config(tls_context, *secret_manager.get()); + NiceMock factory_context; + factory_context.secretManager().addStaticSecret(secret_config); + ClientContextConfigImpl client_context_config(tls_context, factory_context); const std::string cert_pem = "{{ test_rundir }}/test/common/ssl/test_data/selfsigned_cert.pem"; EXPECT_EQ(TestEnvironment::readFileToStringForTest(TestEnvironment::substitute(cert_pem)), @@ -465,9 +499,8 @@ name: "abc.com" MessageUtil::loadFromYaml(TestEnvironment::substitute(yaml), secret_config); - std::unique_ptr secret_manager(new Secret::SecretManagerImpl()); - - secret_manager->addStaticSecret(secret_config); + NiceMock factory_context; + factory_context.secretManager().addStaticSecret(secret_config); envoy::api::v2::auth::UpstreamTlsContext tls_context; tls_context.mutable_common_tls_context() @@ -476,8 +509,8 @@ name: "abc.com" ->set_name("missing"); EXPECT_THROW_WITH_MESSAGE( - ClientContextConfigImpl client_context_config(tls_context, *secret_manager.get()), - EnvoyException, "Static secret is not defined: missing"); + ClientContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, + "Unknown static secret: missing"); } // Multiple TLS certificates are not yet supported, but one is expected for @@ -485,23 +518,60 @@ name: "abc.com" // TODO(PiotrSikora): Support multiple TLS certificates. TEST(ServerContextConfigImplTest, MultipleTlsCertificates) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; EXPECT_THROW_WITH_MESSAGE( - ServerContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + ServerContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, "A single TLS certificate is required for server contexts"); tls_context.mutable_common_tls_context()->add_tls_certificates(); tls_context.mutable_common_tls_context()->add_tls_certificates(); EXPECT_THROW_WITH_MESSAGE( - ServerContextConfigImpl client_context_config(tls_context, secret_manager), EnvoyException, + ServerContextConfigImpl client_context_config(tls_context, factory_context), EnvoyException, "A single TLS certificate is required for server contexts"); } +TEST(ServerContextConfigImplTest, TlsCertificatesAndSdsConfig) { + envoy::api::v2::auth::DownstreamTlsContext tls_context; + NiceMock factory_context; + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl server_context_config(tls_context, factory_context), EnvoyException, + "A single TLS certificate is required for server contexts"); + tls_context.mutable_common_tls_context()->add_tls_certificates(); + tls_context.mutable_common_tls_context()->add_tls_certificate_sds_secret_configs(); + EXPECT_THROW_WITH_MESSAGE( + ServerContextConfigImpl server_context_config(tls_context, factory_context), EnvoyException, + "A single TLS certificate is required for server contexts"); +} + +TEST(ServerContextConfigImplTest, SecretNotReady) { + envoy::api::v2::auth::DownstreamTlsContext tls_context; + NiceMock local_info; + NiceMock dispatcher; + NiceMock random; + Stats::IsolatedStoreImpl stats; + NiceMock cluster_manager; + NiceMock init_manager; + NiceMock factory_context; + EXPECT_CALL(factory_context, localInfo()).WillOnce(ReturnRef(local_info)); + EXPECT_CALL(factory_context, dispatcher()).WillOnce(ReturnRef(dispatcher)); + EXPECT_CALL(factory_context, random()).WillOnce(ReturnRef(random)); + EXPECT_CALL(factory_context, stats()).WillOnce(ReturnRef(stats)); + EXPECT_CALL(factory_context, clusterManager()).WillOnce(ReturnRef(cluster_manager)); + EXPECT_CALL(factory_context, initManager()).WillRepeatedly(Return(&init_manager)); + auto sds_secret_configs = + tls_context.mutable_common_tls_context()->mutable_tls_certificate_sds_secret_configs()->Add(); + sds_secret_configs->set_name("abc.com"); + sds_secret_configs->mutable_sds_config(); + ServerContextConfigImpl server_context_config(tls_context, factory_context); + // When sds secret is not downloaded, config is not ready. + EXPECT_FALSE(server_context_config.isReady()); +} + // TlsCertificate messages must have a cert for servers. TEST(ServerContextImplTest, TlsCertificateNonEmpty) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; tls_context.mutable_common_tls_context()->add_tls_certificates(); - ServerContextConfigImpl client_context_config(tls_context, secret_manager); + ServerContextConfigImpl client_context_config(tls_context, factory_context); Runtime::MockLoader runtime; ContextManagerImpl manager(runtime); Stats::IsolatedStoreImpl store; @@ -514,7 +584,7 @@ TEST(ServerContextImplTest, TlsCertificateNonEmpty) { // Cannot ignore certificate expiration without a trusted CA. TEST(ServerContextConfigImplTest, InvalidIgnoreCertsNoCA) { envoy::api::v2::auth::DownstreamTlsContext tls_context; - NiceMock secret_manager; + NiceMock factory_context; envoy::api::v2::auth::CertificateValidationContext* server_validation_ctx = tls_context.mutable_common_tls_context()->mutable_validation_context(); @@ -522,7 +592,7 @@ TEST(ServerContextConfigImplTest, InvalidIgnoreCertsNoCA) { server_validation_ctx->set_allow_expired_certificate(true); EXPECT_THROW_WITH_MESSAGE( - ServerContextConfigImpl server_context_config(tls_context, secret_manager), EnvoyException, + ServerContextConfigImpl server_context_config(tls_context, factory_context), EnvoyException, "Certificate validity period is always ignored without trusted CA"); envoy::api::v2::auth::TlsCertificate* server_cert = @@ -534,19 +604,19 @@ TEST(ServerContextConfigImplTest, InvalidIgnoreCertsNoCA) { server_validation_ctx->set_allow_expired_certificate(false); - EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, secret_manager)); + EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, factory_context)); server_validation_ctx->set_allow_expired_certificate(true); EXPECT_THROW_WITH_MESSAGE( - ServerContextConfigImpl server_context_config(tls_context, secret_manager), EnvoyException, + ServerContextConfigImpl server_context_config(tls_context, factory_context), EnvoyException, "Certificate validity period is always ignored without trusted CA"); // But once you add a trusted CA, you should be able to create the context. server_validation_ctx->mutable_trusted_ca()->set_filename( TestEnvironment::substitute("{{ test_rundir }}/test/common/ssl/test_data/ca_cert.pem")); - EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, secret_manager)); + EXPECT_NO_THROW(ServerContextConfigImpl server_context_config(tls_context, factory_context)); } } // namespace Ssl diff --git a/test/common/ssl/ssl_certs_test.h b/test/common/ssl/ssl_certs_test.h index 37b85cad3f45..ad345ef1b2c2 100644 --- a/test/common/ssl/ssl_certs_test.h +++ b/test/common/ssl/ssl_certs_test.h @@ -1,6 +1,6 @@ #pragma once -#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "gtest/gtest.h" @@ -12,6 +12,6 @@ class SslCertsTest : public testing::Test { TestEnvironment::exec({TestEnvironment::runfilesPath("test/common/ssl/gen_unittest_certs.sh")}); } - testing::NiceMock secret_manager_; + testing::NiceMock factory_context_; }; } // namespace Envoy diff --git a/test/common/ssl/ssl_socket_test.cc b/test/common/ssl/ssl_socket_test.cc index 190d80471840..ad6946cf27f9 100644 --- a/test/common/ssl/ssl_socket_test.cc +++ b/test/common/ssl/ssl_socket_test.cc @@ -31,12 +31,12 @@ #include "gtest/gtest.h" #include "openssl/ssl.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::StrictMock; -using testing::_; namespace Envoy { namespace Ssl { @@ -51,10 +51,10 @@ void testUtil(const std::string& client_ctx_json, const std::string& server_ctx_ bool expect_success, const Network::Address::IpVersion version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - NiceMock secret_manager; + testing::NiceMock factory_context; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -67,7 +67,7 @@ void testUtil(const std::string& client_ctx_json, const std::string& server_ctx_ Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - auto client_cfg = std::make_unique(*client_ctx_loader, secret_manager); + auto client_cfg = std::make_unique(*client_ctx_loader, factory_context); Ssl::ClientSslSocketFactory client_ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( @@ -148,7 +148,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, const Network::Address::IpVersion version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - NiceMock secret_manager; + testing::NiceMock factory_context; ContextManagerImpl manager(runtime); std::string new_session = EMPTY_STRING; @@ -158,7 +158,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, std::vector server_names(filter_chain.filter_chain_match().server_names().begin(), filter_chain.filter_chain_match().server_names().end()); auto server_cfg = - std::make_unique(filter_chain.tls_context(), secret_manager); + std::make_unique(filter_chain.tls_context(), factory_context); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, server_names); @@ -169,7 +169,7 @@ const std::string testUtilV2(const envoy::api::v2::Listener& server_proto, Network::MockConnectionHandler connection_handler; Network::ListenerPtr listener = dispatcher.createListener(socket, callbacks, true, false); - auto client_cfg = std::make_unique(client_ctx_proto, secret_manager); + auto client_cfg = std::make_unique(client_ctx_proto, factory_context); ClientContextSharedPtr client_ctx(manager.createSslClientContext(stats_store, *client_cfg)); ClientSslSocketFactory client_ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( @@ -1538,7 +1538,7 @@ TEST_P(SslSocketTest, FlushCloseDuringHandshake) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager_); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -1596,7 +1596,7 @@ TEST_P(SslSocketTest, HalfClose) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager_); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -1617,7 +1617,7 @@ TEST_P(SslSocketTest, HalfClose) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - auto client_cfg = std::make_unique(*client_ctx_loader, secret_manager_); + auto client_cfg = std::make_unique(*client_ctx_loader, factory_context_); ClientSslSocketFactory client_ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -1669,7 +1669,7 @@ TEST_P(SslSocketTest, HalfClose) { TEST_P(SslSocketTest, ClientAuthMultipleCAs) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - NiceMock secret_manager; + testing::NiceMock factory_context; std::string server_ctx_json = R"EOF( { @@ -1680,7 +1680,7 @@ TEST_P(SslSocketTest, ClientAuthMultipleCAs) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -1700,7 +1700,7 @@ TEST_P(SslSocketTest, ClientAuthMultipleCAs) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - auto client_cfg = std::make_unique(*client_ctx_loader, secret_manager); + auto client_cfg = std::make_unique(*client_ctx_loader, factory_context); ClientSslSocketFactory ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -1757,13 +1757,15 @@ void testTicketSessionResumption(const std::string& server_ctx_json1, const Network::Address::IpVersion ip_version) { Stats::IsolatedStoreImpl stats_store; Runtime::MockLoader runtime; - NiceMock secret_manager; + testing::NiceMock factory_context; ContextManagerImpl manager(runtime); Json::ObjectSharedPtr server_ctx_loader1 = TestEnvironment::jsonLoadFromString(server_ctx_json1); Json::ObjectSharedPtr server_ctx_loader2 = TestEnvironment::jsonLoadFromString(server_ctx_json2); - auto server_cfg1 = std::make_unique(*server_ctx_loader1, secret_manager); - auto server_cfg2 = std::make_unique(*server_ctx_loader2, secret_manager); + auto server_cfg1 = + std::make_unique(*server_ctx_loader1, factory_context); + auto server_cfg2 = + std::make_unique(*server_ctx_loader2, factory_context); Ssl::ServerSslSocketFactory server_ssl_socket_factory1(std::move(server_cfg1), manager, stats_store, server_names1); Ssl::ServerSslSocketFactory server_ssl_socket_factory2(std::move(server_cfg2), manager, @@ -1780,7 +1782,7 @@ void testTicketSessionResumption(const std::string& server_ctx_json1, Network::ListenerPtr listener2 = dispatcher.createListener(socket2, callbacks, true, false); Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - auto client_cfg = std::make_unique(*client_ctx_loader, secret_manager); + auto client_cfg = std::make_unique(*client_ctx_loader, factory_context); ClientSslSocketFactory ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket1.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -2121,10 +2123,10 @@ TEST_P(SslSocketTest, ClientAuthCrossListenerSessionResumption) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager_); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context_); Json::ObjectSharedPtr server2_ctx_loader = TestEnvironment::jsonLoadFromString(server2_ctx_json); auto server2_cfg = - std::make_unique(*server2_ctx_loader, secret_manager_); + std::make_unique(*server2_ctx_loader, factory_context_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -2149,7 +2151,7 @@ TEST_P(SslSocketTest, ClientAuthCrossListenerSessionResumption) { )EOF"; Json::ObjectSharedPtr client_ctx_loader = TestEnvironment::jsonLoadFromString(client_ctx_json); - auto client_cfg = std::make_unique(*client_ctx_loader, secret_manager_); + auto client_cfg = std::make_unique(*client_ctx_loader, factory_context_); ClientSslSocketFactory ssl_socket_factory(std::move(client_cfg), manager, stats_store); Network::ClientConnectionPtr client_connection = dispatcher.createClientConnection( socket.localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -2236,7 +2238,7 @@ TEST_P(SslSocketTest, SslError) { )EOF"; Json::ObjectSharedPtr server_ctx_loader = TestEnvironment::jsonLoadFromString(server_ctx_json); - auto server_cfg = std::make_unique(*server_ctx_loader, secret_manager_); + auto server_cfg = std::make_unique(*server_ctx_loader, factory_context_); ContextManagerImpl manager(runtime); Ssl::ServerSslSocketFactory server_ssl_socket_factory(std::move(server_cfg), manager, stats_store, std::vector{}); @@ -2580,7 +2582,7 @@ class SslReadBufferLimitTest : public SslCertsTest, void initialize() { server_ctx_loader_ = TestEnvironment::jsonLoadFromString(server_ctx_json_); auto server_cfg = - std::make_unique(*server_ctx_loader_, secret_manager_); + std::make_unique(*server_ctx_loader_, factory_context_); manager_.reset(new ContextManagerImpl(runtime_)); server_ssl_socket_factory_.reset(new ServerSslSocketFactory( std::move(server_cfg), *manager_, stats_store_, std::vector{})); @@ -2589,7 +2591,7 @@ class SslReadBufferLimitTest : public SslCertsTest, client_ctx_loader_ = TestEnvironment::jsonLoadFromString(client_ctx_json_); auto client_cfg = - std::make_unique(*client_ctx_loader_, secret_manager_); + std::make_unique(*client_ctx_loader_, factory_context_); client_ssl_socket_factory_.reset( new ClientSslSocketFactory(std::move(client_cfg), *manager_, stats_store_)); diff --git a/test/common/stats/thread_local_store_test.cc b/test/common/stats/thread_local_store_test.cc index a32cc1bd4bb5..ce27b93452fa 100644 --- a/test/common/stats/thread_local_store_test.cc +++ b/test/common/stats/thread_local_store_test.cc @@ -17,12 +17,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Ref; using testing::Return; -using testing::_; namespace Envoy { namespace Stats { diff --git a/test/common/tcp/conn_pool_test.cc b/test/common/tcp/conn_pool_test.cc index 6b275d59c6fe..a3ba30df6331 100644 --- a/test/common/tcp/conn_pool_test.cc +++ b/test/common/tcp/conn_pool_test.cc @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -25,10 +26,21 @@ using testing::Property; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Tcp { +namespace { + +struct TestConnectionState : public ConnectionPool::ConnectionState { + TestConnectionState(int id, std::function on_destructor) + : id_(id), on_destructor_(on_destructor) {} + ~TestConnectionState() { on_destructor_(); } + + int id_; + std::function on_destructor_; +}; + +} // namespace /** * Mock callbacks used for conn pool testing. @@ -309,6 +321,9 @@ TEST_F(TcpConnPoolImplTest, VerifyBufferLimits) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test that upstream callback fire for assigned connections. + */ TEST_F(TcpConnPoolImplTest, UpstreamCallbacks) { Buffer::OwnedImpl buffer; @@ -343,6 +358,9 @@ TEST_F(TcpConnPoolImplTest, UpstreamCallbacks) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test that upstream callback close event fires for assigned connections. + */ TEST_F(TcpConnPoolImplTest, UpstreamCallbacksCloseEvent) { Buffer::OwnedImpl buffer; @@ -360,6 +378,9 @@ TEST_F(TcpConnPoolImplTest, UpstreamCallbacksCloseEvent) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test that a connection pool functions without upstream callbacks. + */ TEST_F(TcpConnPoolImplTest, NoUpstreamCallbacks) { Buffer::OwnedImpl buffer; @@ -400,6 +421,45 @@ TEST_F(TcpConnPoolImplTest, MultipleRequestAndResponse) { dispatcher_.clearDeferredDeleteList(); } +/** + * Tests ConnectionState assignment, lookup and destruction. + */ +TEST_F(TcpConnPoolImplTest, ConnectionStateLifecycle) { + InSequence s; + + bool state_destroyed = false; + + // Request 1 should kick off a new connection. + ActiveTestConn c1(*this, 0, ActiveTestConn::Type::CreateConnection); + + auto* state = new TestConnectionState(1, [&]() -> void { state_destroyed = true; }); + c1.callbacks_.conn_data_->setConnectionState(std::unique_ptr(state)); + + EXPECT_EQ(state, c1.callbacks_.conn_data_->connectionStateTyped()); + + EXPECT_CALL(conn_pool_, onConnReleasedForTest()); + c1.releaseConn(); + + EXPECT_FALSE(state_destroyed); + + // Request 2 should not. + ActiveTestConn c2(*this, 0, ActiveTestConn::Type::Immediate); + + EXPECT_EQ(state, c2.callbacks_.conn_data_->connectionStateTyped()); + + EXPECT_CALL(conn_pool_, onConnReleasedForTest()); + c2.releaseConn(); + + EXPECT_FALSE(state_destroyed); + + // Cause the connection to go away. + EXPECT_CALL(conn_pool_, onConnDestroyedForTest()); + conn_pool_.test_conns_[0].connection_->raiseEvent(Network::ConnectionEvent::RemoteClose); + dispatcher_.clearDeferredDeleteList(); + + EXPECT_TRUE(state_destroyed); +} + /** * Test when we overflow max pending requests. */ @@ -555,6 +615,9 @@ TEST_F(TcpConnPoolImplTest, DisconnectWhileBound) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test upstream disconnection of one request while another is pending. + */ TEST_F(TcpConnPoolImplTest, DisconnectWhilePending) { InSequence s; @@ -664,6 +727,9 @@ TEST_F(TcpConnPoolImplTest, MaxRequestsPerConnection) { EXPECT_EQ(1U, cluster_->stats_.upstream_cx_max_requests_.value()); } +/* + * Test that multiple connections can be assigned at once. + */ TEST_F(TcpConnPoolImplTest, ConcurrentConnections) { InSequence s; @@ -691,6 +757,61 @@ TEST_F(TcpConnPoolImplTest, ConcurrentConnections) { dispatcher_.clearDeferredDeleteList(); } +/** + * Tests ConnectionState lifecycle with multiple concurrent connections. + */ +TEST_F(TcpConnPoolImplTest, ConnectionStateWithConcurrentConnections) { + InSequence s; + + int state_destroyed = 0; + auto* s1 = new TestConnectionState(1, [&]() -> void { state_destroyed |= 1; }); + auto* s2 = new TestConnectionState(2, [&]() -> void { state_destroyed |= 2; }); + auto* s3 = new TestConnectionState(2, [&]() -> void { state_destroyed |= 4; }); + + cluster_->resource_manager_.reset( + new Upstream::ResourceManagerImpl(runtime_, "fake_key", 2, 1024, 1024, 1)); + ActiveTestConn c1(*this, 0, ActiveTestConn::Type::CreateConnection); + c1.callbacks_.conn_data_->setConnectionState(std::unique_ptr(s1)); + ActiveTestConn c2(*this, 1, ActiveTestConn::Type::CreateConnection); + c2.callbacks_.conn_data_->setConnectionState(std::unique_ptr(s2)); + ActiveTestConn c3(*this, 0, ActiveTestConn::Type::Pending); + + EXPECT_EQ(0, state_destroyed); + + // Finish c1, which gets c3 going. + EXPECT_CALL(conn_pool_, onConnReleasedForTest()); + conn_pool_.expectEnableUpstreamReady(); + c3.expectNewConn(); + c1.releaseConn(); + + conn_pool_.expectAndRunUpstreamReady(); + + // c3 now has the state set by c1. + EXPECT_EQ(s1, c3.callbacks_.conn_data_->connectionStateTyped()); + EXPECT_EQ(s2, c2.callbacks_.conn_data_->connectionStateTyped()); + + // replace c3's state + c3.callbacks_.conn_data_->setConnectionState(std::unique_ptr(s3)); + EXPECT_EQ(1, state_destroyed); + + EXPECT_CALL(conn_pool_, onConnReleasedForTest()).Times(2); + c2.releaseConn(); + c3.releaseConn(); + + EXPECT_EQ(1, state_destroyed); + + // Disconnect both connections. + EXPECT_CALL(conn_pool_, onConnDestroyedForTest()).Times(2); + conn_pool_.test_conns_[1].connection_->raiseEvent(Network::ConnectionEvent::RemoteClose); + conn_pool_.test_conns_[0].connection_->raiseEvent(Network::ConnectionEvent::RemoteClose); + dispatcher_.clearDeferredDeleteList(); + + EXPECT_EQ(7, state_destroyed); +} + +/** + * Tests that the DrainCallback is invoked when the number of connections goes to zero. + */ TEST_F(TcpConnPoolImplTest, DrainCallback) { InSequence s; ReadyWatcher drained; @@ -711,7 +832,9 @@ TEST_F(TcpConnPoolImplTest, DrainCallback) { dispatcher_.clearDeferredDeleteList(); } -// Test draining a connection pool that has a pending connection. +/** + * Test draining a connection pool that has a pending connection. + */ TEST_F(TcpConnPoolImplTest, DrainWhileConnecting) { InSequence s; ReadyWatcher drained; @@ -731,6 +854,9 @@ TEST_F(TcpConnPoolImplTest, DrainWhileConnecting) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test that the DrainCallback is invoked when a connection is closed. + */ TEST_F(TcpConnPoolImplTest, DrainOnClose) { ReadyWatcher drained; EXPECT_CALL(drained, ready()); @@ -754,6 +880,9 @@ TEST_F(TcpConnPoolImplTest, DrainOnClose) { dispatcher_.clearDeferredDeleteList(); } +/** + * Test that busy connections are closed when the connection pool is destroyed. + */ TEST_F(TcpConnPoolImplDestructorTest, TestBusyConnectionsAreClosed) { prepareConn(); @@ -762,6 +891,9 @@ TEST_F(TcpConnPoolImplDestructorTest, TestBusyConnectionsAreClosed) { conn_pool_.reset(); } +/** + * Test that ready connections are closed when the connection pool is destroyed. + */ TEST_F(TcpConnPoolImplDestructorTest, TestReadyConnectionsAreClosed) { prepareConn(); diff --git a/test/common/tcp_proxy/tcp_proxy_test.cc b/test/common/tcp_proxy/tcp_proxy_test.cc index 73568c61de74..3d810c8e9e56 100644 --- a/test/common/tcp_proxy/tcp_proxy_test.cc +++ b/test/common/tcp_proxy/tcp_proxy_test.cc @@ -26,6 +26,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::MatchesRegex; using testing::NiceMock; @@ -33,7 +34,6 @@ using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace TcpProxy { diff --git a/test/common/thread_local/thread_local_impl_test.cc b/test/common/thread_local/thread_local_impl_test.cc index 5726f4165895..0eb123a9ca5d 100644 --- a/test/common/thread_local/thread_local_impl_test.cc +++ b/test/common/thread_local/thread_local_impl_test.cc @@ -5,10 +5,10 @@ #include "gmock/gmock.h" +using testing::_; using testing::InSequence; using testing::Ref; using testing::ReturnPointee; -using testing::_; namespace Envoy { namespace ThreadLocal { diff --git a/test/common/tracing/http_tracer_impl_test.cc b/test/common/tracing/http_tracer_impl_test.cc index 1b6e2e61c670..6a9561bf9719 100644 --- a/test/common/tracing/http_tracer_impl_test.cc +++ b/test/common/tracing/http_tracer_impl_test.cc @@ -23,13 +23,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::Test; -using testing::_; namespace Envoy { namespace Tracing { diff --git a/test/common/upstream/cds_api_impl_test.cc b/test/common/upstream/cds_api_impl_test.cc index 574935c6ef26..6b3309c4f9e5 100644 --- a/test/common/upstream/cds_api_impl_test.cc +++ b/test/common/upstream/cds_api_impl_test.cc @@ -16,11 +16,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index a3700d53a10e..d2aca58d3feb 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -30,6 +30,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::Mock; @@ -39,7 +40,6 @@ using testing::Return; using testing::ReturnNew; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/eds_test.cc b/test/common/upstream/eds_test.cc index 8af7cd508cfe..7300a9eb8285 100644 --- a/test/common/upstream/eds_test.cc +++ b/test/common/upstream/eds_test.cc @@ -18,9 +18,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/hds_test.cc b/test/common/upstream/hds_test.cc index 1b419f633391..4c3332b27276 100644 --- a/test/common/upstream/hds_test.cc +++ b/test/common/upstream/hds_test.cc @@ -14,11 +14,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; using ::testing::AtLeast; diff --git a/test/common/upstream/health_checker_impl_test.cc b/test/common/upstream/health_checker_impl_test.cc index 111d2ac1f99b..1975164850bf 100644 --- a/test/common/upstream/health_checker_impl_test.cc +++ b/test/common/upstream/health_checker_impl_test.cc @@ -26,6 +26,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -36,7 +37,6 @@ using testing::Return; using testing::ReturnRef; using testing::SaveArg; using testing::WithArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/load_stats_reporter_test.cc b/test/common/upstream/load_stats_reporter_test.cc index 36be333d5b1d..9e2eada48351 100644 --- a/test/common/upstream/load_stats_reporter_test.cc +++ b/test/common/upstream/load_stats_reporter_test.cc @@ -11,11 +11,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; // The tests in this file provide just coverage over some corner cases in error handling. The test // for the happy path for LoadStatsReporter is provided in //test/integration:load_stats_reporter. diff --git a/test/common/upstream/logical_dns_cluster_test.cc b/test/common/upstream/logical_dns_cluster_test.cc index ca84b1a5de31..7ae43186c52b 100644 --- a/test/common/upstream/logical_dns_cluster_test.cc +++ b/test/common/upstream/logical_dns_cluster_test.cc @@ -24,9 +24,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/original_dst_cluster_test.cc b/test/common/upstream/original_dst_cluster_test.cc index d3816097ea59..da1d163776f7 100644 --- a/test/common/upstream/original_dst_cluster_test.cc +++ b/test/common/upstream/original_dst_cluster_test.cc @@ -25,12 +25,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/outlier_detection_impl_test.cc b/test/common/upstream/outlier_detection_impl_test.cc index 6538c98da35b..38b2e6dd9577 100644 --- a/test/common/upstream/outlier_detection_impl_test.cc +++ b/test/common/upstream/outlier_detection_impl_test.cc @@ -20,11 +20,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/ring_hash_lb_test.cc b/test/common/upstream/ring_hash_lb_test.cc index b8c3e6cdc820..c26d1b307def 100644 --- a/test/common/upstream/ring_hash_lb_test.cc +++ b/test/common/upstream/ring_hash_lb_test.cc @@ -15,9 +15,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/sds_test.cc b/test/common/upstream/sds_test.cc index af944aaa86b6..6226c2b7e121 100644 --- a/test/common/upstream/sds_test.cc +++ b/test/common/upstream/sds_test.cc @@ -28,6 +28,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -36,7 +37,6 @@ using testing::Return; using testing::ReturnRef; using testing::SaveArg; using testing::WithArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/subset_lb_test.cc b/test/common/upstream/subset_lb_test.cc index cdcf31bea3c2..b17de82617d7 100644 --- a/test/common/upstream/subset_lb_test.cc +++ b/test/common/upstream/subset_lb_test.cc @@ -22,11 +22,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::EndsWith; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index cbf04dbed544..921b32766469 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -31,11 +31,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ContainerEq; using testing::Invoke; using testing::NiceMock; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/config_test/config_test.cc b/test/config_test/config_test.cc index 98a0576b957b..22c84839c10d 100644 --- a/test/config_test/config_test.cc +++ b/test/config_test/config_test.cc @@ -18,11 +18,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace ConfigTest { diff --git a/test/exe/signals_test.cc b/test/exe/signals_test.cc index 4eaa3e150f3f..b4bd02158e53 100644 --- a/test/exe/signals_test.cc +++ b/test/exe/signals_test.cc @@ -124,4 +124,4 @@ TEST(Signals, HandlerTest) { SignalAction::sigHandler(SIGURG, &fake_si, nullptr); } -} // Envoy +} // namespace Envoy diff --git a/test/extensions/access_loggers/http_grpc/config_test.cc b/test/extensions/access_loggers/http_grpc/config_test.cc index b0aba3ba434b..b337fe4cf9d4 100644 --- a/test/extensions/access_loggers/http_grpc/config_test.cc +++ b/test/extensions/access_loggers/http_grpc/config_test.cc @@ -10,9 +10,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/access_loggers/http_grpc/grpc_access_log_impl_test.cc b/test/extensions/access_loggers/http_grpc/grpc_access_log_impl_test.cc index bfbb62bc7eeb..95cffa3e29a0 100644 --- a/test/extensions/access_loggers/http_grpc/grpc_access_log_impl_test.cc +++ b/test/extensions/access_loggers/http_grpc/grpc_access_log_impl_test.cc @@ -9,11 +9,11 @@ #include "test/mocks/thread_local/mocks.h" using namespace std::chrono_literals; +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/common/ext_authz/ext_authz_grpc_impl_test.cc b/test/extensions/filters/common/ext_authz/ext_authz_grpc_impl_test.cc index 6b6c5f825735..de17b1377978 100644 --- a/test/extensions/filters/common/ext_authz/ext_authz_grpc_impl_test.cc +++ b/test/extensions/filters/common/ext_authz/ext_authz_grpc_impl_test.cc @@ -13,6 +13,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Ref; using testing::Return; @@ -20,7 +21,6 @@ using testing::ReturnPointee; using testing::ReturnRef; using testing::WhenDynamicCastTo; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc b/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc index 93b6c12d3a65..bd021ca57716 100644 --- a/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc +++ b/test/extensions/filters/common/ext_authz/ext_authz_http_impl_test.cc @@ -14,6 +14,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Ref; using testing::Return; @@ -21,7 +22,6 @@ using testing::ReturnPointee; using testing::ReturnRef; using testing::WhenDynamicCastTo; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/common/lua/lua_test.cc b/test/extensions/filters/common/lua/lua_test.cc index df87cfec01fa..e3a837967071 100644 --- a/test/extensions/filters/common/lua/lua_test.cc +++ b/test/extensions/filters/common/lua/lua_test.cc @@ -6,9 +6,9 @@ #include "gmock/gmock.h" +using testing::_; using testing::InSequence; using testing::NiceMock; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/common/rbac/engine_impl_test.cc b/test/extensions/filters/common/rbac/engine_impl_test.cc index cf848847728c..5f86e7678513 100644 --- a/test/extensions/filters/common/rbac/engine_impl_test.cc +++ b/test/extensions/filters/common/rbac/engine_impl_test.cc @@ -8,10 +8,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Const; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/common/rbac/matchers_test.cc b/test/extensions/filters/common/rbac/matchers_test.cc index dae4eb73e07f..8aeae16c80f3 100644 --- a/test/extensions/filters/common/rbac/matchers_test.cc +++ b/test/extensions/filters/common/rbac/matchers_test.cc @@ -8,10 +8,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Const; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/buffer/buffer_filter_test.cc b/test/extensions/filters/http/buffer/buffer_filter_test.cc index c7479303c51a..38eb0a70ee90 100644 --- a/test/extensions/filters/http/buffer/buffer_filter_test.cc +++ b/test/extensions/filters/http/buffer/buffer_filter_test.cc @@ -16,12 +16,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::NiceMock; using testing::Return; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/buffer/config_test.cc b/test/extensions/filters/http/buffer/config_test.cc index 11842bc197e8..0616524dc518 100644 --- a/test/extensions/filters/http/buffer/config_test.cc +++ b/test/extensions/filters/http/buffer/config_test.cc @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::NiceMock; using testing::_; +using testing::NiceMock; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/cors/cors_filter_test.cc b/test/extensions/filters/http/cors/cors_filter_test.cc index 885f8830051b..246986831df9 100644 --- a/test/extensions/filters/http/cors/cors_filter_test.cc +++ b/test/extensions/filters/http/cors/cors_filter_test.cc @@ -9,6 +9,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::Invoke; @@ -16,7 +17,6 @@ using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/dynamo/dynamo_filter_test.cc b/test/extensions/filters/http/dynamo/dynamo_filter_test.cc index 5215f814eee4..f41e5a8eb9da 100644 --- a/test/extensions/filters/http/dynamo/dynamo_filter_test.cc +++ b/test/extensions/filters/http/dynamo/dynamo_filter_test.cc @@ -15,11 +15,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Property; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/dynamo/dynamo_utility_test.cc b/test/extensions/filters/http/dynamo/dynamo_utility_test.cc index f987bee21b83..83014009e7d8 100644 --- a/test/extensions/filters/http/dynamo/dynamo_utility_test.cc +++ b/test/extensions/filters/http/dynamo/dynamo_utility_test.cc @@ -7,9 +7,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/ext_authz/config_test.cc b/test/extensions/filters/http/ext_authz/config_test.cc index 4305e1ba3353..1adbf4a11e0d 100644 --- a/test/extensions/filters/http/ext_authz/config_test.cc +++ b/test/extensions/filters/http/ext_authz/config_test.cc @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/ext_authz/ext_authz_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_test.cc index 89fc15cacbf7..7926855e97ad 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_test.cc @@ -28,6 +28,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; @@ -36,7 +37,6 @@ using testing::ReturnRef; using testing::TestWithParam; using testing::Values; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/fault/config_test.cc b/test/extensions/filters/http/fault/config_test.cc index 34b9c6083139..55ff3fd376ef 100644 --- a/test/extensions/filters/http/fault/config_test.cc +++ b/test/extensions/filters/http/fault/config_test.cc @@ -7,8 +7,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/fault/fault_filter_test.cc b/test/extensions/filters/http/fault/fault_filter_test.cc index ec3e4066974a..127d38b32696 100644 --- a/test/extensions/filters/http/fault/fault_filter_test.cc +++ b/test/extensions/filters/http/fault/fault_filter_test.cc @@ -23,13 +23,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc b/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc index 5b96b1a9b090..13a14036a43f 100644 --- a/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc +++ b/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc @@ -11,11 +11,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/grpc_json_transcoder/grpc_json_transcoder_integration_test.cc b/test/extensions/filters/http/grpc_json_transcoder/grpc_json_transcoder_integration_test.cc index a4bc68362c24..9eb136c6b729 100644 --- a/test/extensions/filters/http/grpc_json_transcoder/grpc_json_transcoder_integration_test.cc +++ b/test/extensions/filters/http/grpc_json_transcoder/grpc_json_transcoder_integration_test.cc @@ -164,7 +164,8 @@ TEST_P(GrpcJsonTranscoderIntegrationTest, UnaryGet) { testTranscoding( Http::TestHeaderMapImpl{{":method", "GET"}, {":path", "/shelves"}, {":authority", "host"}}, "", {""}, {R"(shelves { id: 20 theme: "Children" } - shelves { id: 1 theme: "Foo" } )"}, Status(), + shelves { id: 1 theme: "Foo" } )"}, + Status(), Http::TestHeaderMapImpl{{":status", "200"}, {"content-type", "application/json"}, {"content-length", "69"}, diff --git a/test/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter_test.cc b/test/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter_test.cc index f388588a085e..6e8edc96cf95 100644 --- a/test/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter_test.cc +++ b/test/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter_test.cc @@ -21,12 +21,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; using Envoy::Protobuf::MethodDescriptor; diff --git a/test/extensions/filters/http/grpc_web/grpc_web_filter_test.cc b/test/extensions/filters/http/grpc_web/grpc_web_filter_test.cc index c36eb271448f..b7e355d215e4 100644 --- a/test/extensions/filters/http/grpc_web/grpc_web_filter_test.cc +++ b/test/extensions/filters/http/grpc_web/grpc_web_filter_test.cc @@ -17,12 +17,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Combine; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::Values; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/header_to_metadata/header_to_metadata_filter_test.cc b/test/extensions/filters/http/header_to_metadata/header_to_metadata_filter_test.cc index 308cae7cd358..715a2d45cc4c 100644 --- a/test/extensions/filters/http/header_to_metadata/header_to_metadata_filter_test.cc +++ b/test/extensions/filters/http/header_to_metadata/header_to_metadata_filter_test.cc @@ -9,8 +9,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::NiceMock; using testing::_; +using testing::NiceMock; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/health_check/config_test.cc b/test/extensions/filters/http/health_check/config_test.cc index a966cae896c8..b2b7b3393560 100644 --- a/test/extensions/filters/http/health_check/config_test.cc +++ b/test/extensions/filters/http/health_check/config_test.cc @@ -6,8 +6,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/health_check/health_check_test.cc b/test/extensions/filters/http/health_check/health_check_test.cc index aef501a25b03..cc6fdc5d5b4b 100644 --- a/test/extensions/filters/http/health_check/health_check_test.cc +++ b/test/extensions/filters/http/health_check/health_check_test.cc @@ -15,13 +15,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::DoAll; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/ip_tagging/ip_tagging_filter_test.cc b/test/extensions/filters/http/ip_tagging/ip_tagging_filter_test.cc index 2c2a95c7fa45..a349db9a1efa 100644 --- a/test/extensions/filters/http/ip_tagging/ip_tagging_filter_test.cc +++ b/test/extensions/filters/http/ip_tagging/ip_tagging_filter_test.cc @@ -14,9 +14,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/jwt_authn/authenticator_test.cc b/test/extensions/filters/http/jwt_authn/authenticator_test.cc index db411c32603d..02abd237488e 100644 --- a/test/extensions/filters/http/jwt_authn/authenticator_test.cc +++ b/test/extensions/filters/http/jwt_authn/authenticator_test.cc @@ -13,9 +13,9 @@ using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtAuthentication; using ::google::jwt_verify::Status; +using ::testing::_; using ::testing::Invoke; using ::testing::NiceMock; -using ::testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/jwt_authn/extractor_test.cc b/test/extensions/filters/http/jwt_authn/extractor_test.cc index d58acd3542d9..fe1937f3b71b 100644 --- a/test/extensions/filters/http/jwt_authn/extractor_test.cc +++ b/test/extensions/filters/http/jwt_authn/extractor_test.cc @@ -4,12 +4,12 @@ #include "test/test_common/utility.h" -using ::Envoy::Http::TestHeaderMapImpl; using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtAuthentication; +using ::Envoy::Http::TestHeaderMapImpl; +using ::testing::_; using ::testing::Invoke; using ::testing::NiceMock; -using ::testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/jwt_authn/filter_factory_test.cc b/test/extensions/filters/http/jwt_authn/filter_factory_test.cc index de5071941e7e..dfb2c94ff584 100644 --- a/test/extensions/filters/http/jwt_authn/filter_factory_test.cc +++ b/test/extensions/filters/http/jwt_authn/filter_factory_test.cc @@ -10,8 +10,8 @@ using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtAuthentication; using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtProvider; -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/jwt_authn/filter_test.cc b/test/extensions/filters/http/jwt_authn/filter_test.cc index 8d9c6a2c7760..80bbe941fb61 100644 --- a/test/extensions/filters/http/jwt_authn/filter_test.cc +++ b/test/extensions/filters/http/jwt_authn/filter_test.cc @@ -9,8 +9,8 @@ using ::envoy::config::filter::http::jwt_authn::v2alpha::JwtAuthentication; using ::google::jwt_verify::Status; -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/lua/lua_filter_test.cc b/test/extensions/filters/http/lua/lua_filter_test.cc index 0283baa92e33..5894fef3f66f 100644 --- a/test/extensions/filters/http/lua/lua_filter_test.cc +++ b/test/extensions/filters/http/lua/lua_filter_test.cc @@ -14,6 +14,7 @@ #include "gmock/gmock.h" +using testing::_; using testing::AtLeast; using testing::InSequence; using testing::Invoke; @@ -21,7 +22,6 @@ using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::StrEq; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/ratelimit/ratelimit_test.cc b/test/extensions/filters/http/ratelimit/ratelimit_test.cc index ba3ffd6e16f4..8d49e933ac4f 100644 --- a/test/extensions/filters/http/ratelimit/ratelimit_test.cc +++ b/test/extensions/filters/http/ratelimit/ratelimit_test.cc @@ -21,6 +21,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; @@ -28,7 +29,6 @@ using testing::Return; using testing::ReturnRef; using testing::SetArgReferee; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/rbac/config_test.cc b/test/extensions/filters/http/rbac/config_test.cc index 4fd404a237b5..6085958c1071 100644 --- a/test/extensions/filters/http/rbac/config_test.cc +++ b/test/extensions/filters/http/rbac/config_test.cc @@ -6,8 +6,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::NiceMock; using testing::_; +using testing::NiceMock; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 1b597ea7afb7..0fbf392bec61 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -10,10 +10,10 @@ #include "test/mocks/http/mocks.h" #include "test/mocks/network/mocks.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/http/squash/squash_filter_test.cc b/test/extensions/filters/http/squash/squash_filter_test.cc index 49cf2269f9b8..1144d46a2d87 100644 --- a/test/extensions/filters/http/squash/squash_filter_test.cc +++ b/test/extensions/filters/http/squash/squash_filter_test.cc @@ -16,10 +16,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; using Envoy::Protobuf::util::MessageDifferencer; diff --git a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc index 57916b0bb493..fa0cd1ebd2b9 100644 --- a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc +++ b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc @@ -28,13 +28,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/listener/tls_inspector/tls_inspector_benchmark.cc b/test/extensions/filters/listener/tls_inspector/tls_inspector_benchmark.cc index c4d23873317f..7abba1217293 100644 --- a/test/extensions/filters/listener/tls_inspector/tls_inspector_benchmark.cc +++ b/test/extensions/filters/listener/tls_inspector/tls_inspector_benchmark.cc @@ -14,6 +14,7 @@ #include "openssl/ssl.h" #include "testing/base/public/benchmark.h" +using testing::_; using testing::AtLeast; using testing::Invoke; using testing::NiceMock; @@ -21,7 +22,6 @@ using testing::Return; using testing::ReturnNew; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc b/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc index 0833711f39f4..67840cf2a84f 100644 --- a/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc +++ b/test/extensions/filters/listener/tls_inspector/tls_inspector_test.cc @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "openssl/ssl.h" +using testing::_; using testing::AtLeast; using testing::Eq; using testing::InSequence; @@ -19,7 +20,6 @@ using testing::Return; using testing::ReturnNew; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/client_ssl_auth/client_ssl_auth_test.cc b/test/extensions/filters/network/client_ssl_auth/client_ssl_auth_test.cc index 88bcb8f91337..516fb4998856 100644 --- a/test/extensions/filters/network/client_ssl_auth/client_ssl_auth_test.cc +++ b/test/extensions/filters/network/client_ssl_auth/client_ssl_auth_test.cc @@ -21,13 +21,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::Return; using testing::ReturnNew; using testing::ReturnRef; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/ext_authz/config_test.cc b/test/extensions/filters/network/ext_authz/config_test.cc index 453219de4ded..2d955119a1a7 100644 --- a/test/extensions/filters/network/ext_authz/config_test.cc +++ b/test/extensions/filters/network/ext_authz/config_test.cc @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/ext_authz/ext_authz_test.cc b/test/extensions/filters/network/ext_authz/ext_authz_test.cc index 633c875d8fe8..db8599cd0f09 100644 --- a/test/extensions/filters/network/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/network/ext_authz/ext_authz_test.cc @@ -22,13 +22,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/http_connection_manager/config_test.cc b/test/extensions/filters/network/http_connection_manager/config_test.cc index 1fc646bdba6f..37e720e18f2e 100644 --- a/test/extensions/filters/network/http_connection_manager/config_test.cc +++ b/test/extensions/filters/network/http_connection_manager/config_test.cc @@ -15,9 +15,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ContainerEq; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/mongo_proxy/proxy_test.cc b/test/extensions/filters/network/mongo_proxy/proxy_test.cc index a74144e26370..86bd5552c049 100644 --- a/test/extensions/filters/network/mongo_proxy/proxy_test.cc +++ b/test/extensions/filters/network/mongo_proxy/proxy_test.cc @@ -20,13 +20,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::Invoke; using testing::NiceMock; using testing::Property; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { @@ -221,7 +221,6 @@ TEST_F(MongoProxyFilterTest, Stats) { message->cursorId(1); message->documents().push_back(Bson::DocumentImpl::create()->addString("hello", "world")); filter_->callbacks_->decodeReply(std::move(message)); - })); filter_->onWrite(fake_data_, false); @@ -378,7 +377,6 @@ TEST_F(MongoProxyFilterTest, CallingFunctionStats) { message->cursorId(1); message->documents().push_back(Bson::DocumentImpl::create()->addString("hello", "world")); filter_->callbacks_->decodeReply(std::move(message)); - })); filter_->onWrite(fake_data_, false); } diff --git a/test/extensions/filters/network/ratelimit/ratelimit_test.cc b/test/extensions/filters/network/ratelimit/ratelimit_test.cc index dfd3a306b8b2..ec8aa55408e4 100644 --- a/test/extensions/filters/network/ratelimit/ratelimit_test.cc +++ b/test/extensions/filters/network/ratelimit/ratelimit_test.cc @@ -19,12 +19,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::WithArgs; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/rbac/config_test.cc b/test/extensions/filters/network/rbac/config_test.cc index b573dbf9f62b..e7ebabd2adf5 100644 --- a/test/extensions/filters/network/rbac/config_test.cc +++ b/test/extensions/filters/network/rbac/config_test.cc @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::NiceMock; using testing::_; +using testing::NiceMock; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/redis_proxy/command_splitter_impl_test.cc b/test/extensions/filters/network/redis_proxy/command_splitter_impl_test.cc index f9a401ac3252..85788f756bee 100644 --- a/test/extensions/filters/network/redis_proxy/command_splitter_impl_test.cc +++ b/test/extensions/filters/network/redis_proxy/command_splitter_impl_test.cc @@ -16,6 +16,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ByRef; using testing::DoAll; using testing::Eq; @@ -23,7 +24,6 @@ using testing::InSequence; using testing::Ref; using testing::Return; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/redis_proxy/conn_pool_impl_test.cc b/test/extensions/filters/network/redis_proxy/conn_pool_impl_test.cc index 2e91f821ddc2..432b4ca38611 100644 --- a/test/extensions/filters/network/redis_proxy/conn_pool_impl_test.cc +++ b/test/extensions/filters/network/redis_proxy/conn_pool_impl_test.cc @@ -15,6 +15,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Eq; using testing::InSequence; using testing::Invoke; @@ -22,7 +23,6 @@ using testing::Ref; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/redis_proxy/mocks.cc b/test/extensions/filters/network/redis_proxy/mocks.cc index 5cc170a32400..c3283870c80d 100644 --- a/test/extensions/filters/network/redis_proxy/mocks.cc +++ b/test/extensions/filters/network/redis_proxy/mocks.cc @@ -7,8 +7,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc b/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc index 64dfd5171442..e2ffcd6b8d79 100644 --- a/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc +++ b/test/extensions/filters/network/redis_proxy/proxy_filter_test.cc @@ -15,6 +15,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ByRef; using testing::DoAll; using testing::Eq; @@ -24,7 +25,6 @@ using testing::NiceMock; using testing::Ref; using testing::Return; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/thrift_proxy/BUILD b/test/extensions/filters/network/thrift_proxy/BUILD index e07767ba0963..ead7baef2ead 100644 --- a/test/extensions/filters/network/thrift_proxy/BUILD +++ b/test/extensions/filters/network/thrift_proxy/BUILD @@ -147,6 +147,20 @@ envoy_extension_cc_test( ], ) +envoy_extension_cc_test( + name = "header_transport_impl_test", + srcs = ["header_transport_impl_test.cc"], + extension_name = "envoy.filters.network.thrift_proxy", + deps = [ + ":mocks", + ":utility_lib", + "//source/extensions/filters/network/thrift_proxy:transport_lib", + "//test/mocks/buffer:buffer_mocks", + "//test/test_common:printers_lib", + "//test/test_common:utility_lib", + ], +) + envoy_extension_cc_test( name = "metadata_test", srcs = ["metadata_test.cc"], diff --git a/test/extensions/filters/network/thrift_proxy/config_test.cc b/test/extensions/filters/network/thrift_proxy/config_test.cc index 220ce5c3fddf..a1433cd6d554 100644 --- a/test/extensions/filters/network/thrift_proxy/config_test.cc +++ b/test/extensions/filters/network/thrift_proxy/config_test.cc @@ -14,38 +14,107 @@ namespace Extensions { namespace NetworkFilters { namespace ThriftProxy { -TEST(ThriftFilterConfigTest, ValidateFail) { - NiceMock context; - EXPECT_THROW(ThriftProxyFilterConfigFactory().createFilterFactoryFromProto( - envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy(), context), +namespace { + +std::vector +getTransportTypes() { + std::vector v; + int transport = envoy::config::filter::network::thrift_proxy::v2alpha1:: + ThriftProxy_TransportType_TransportType_MIN; + while (transport <= envoy::config::filter::network::thrift_proxy::v2alpha1:: + ThriftProxy_TransportType_TransportType_MAX) { + v.push_back(static_cast< + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_TransportType>( + transport)); + transport++; + } + return v; +} + +std::vector +getProtocolTypes() { + std::vector v; + int protocol = envoy::config::filter::network::thrift_proxy::v2alpha1:: + ThriftProxy_ProtocolType_ProtocolType_MIN; + while (protocol <= envoy::config::filter::network::thrift_proxy::v2alpha1:: + ThriftProxy_ProtocolType_ProtocolType_MAX) { + v.push_back(static_cast< + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_ProtocolType>( + protocol)); + protocol++; + } + return v; +} + +} // namespace + +class ThriftFilterConfigTestBase { +public: + void testConfig(envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy& config) { + Network::FilterFactoryCb cb; + EXPECT_NO_THROW({ cb = factory_.createFilterFactoryFromProto(config, context_); }); + + Network::MockConnection connection; + EXPECT_CALL(connection, addReadFilter(_)); + cb(connection); + } + + NiceMock context_; + ThriftProxyFilterConfigFactory factory_; +}; + +class ThriftFilterConfigTest : public ThriftFilterConfigTestBase, public testing::Test {}; + +class ThriftFilterTransportConfigTest + : public ThriftFilterConfigTestBase, + public testing::TestWithParam< + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_TransportType> {}; + +INSTANTIATE_TEST_CASE_P(TransportTypes, ThriftFilterTransportConfigTest, + testing::ValuesIn(getTransportTypes())); + +class ThriftFilterProtocolConfigTest + : public ThriftFilterConfigTestBase, + public testing::TestWithParam< + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy_ProtocolType> {}; + +INSTANTIATE_TEST_CASE_P(ProtocolTypes, ThriftFilterProtocolConfigTest, + testing::ValuesIn(getProtocolTypes())); + +TEST_F(ThriftFilterConfigTest, ValidateFail) { + EXPECT_THROW(factory_.createFilterFactoryFromProto( + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy(), context_), ProtoValidationException); } -TEST(ThriftFilterConfigTest, ValidProtoConfiguration) { +TEST_F(ThriftFilterConfigTest, ValidProtoConfiguration) { envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy config{}; + config.set_stat_prefix("my_stat_prefix"); + + testConfig(config); +} +TEST_P(ThriftFilterTransportConfigTest, ValidProtoConfiguration) { + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy config{}; config.set_stat_prefix("my_stat_prefix"); + config.set_transport(GetParam()); + testConfig(config); +} - NiceMock context; - ThriftProxyFilterConfigFactory factory; - Network::FilterFactoryCb cb = factory.createFilterFactoryFromProto(config, context); - Network::MockConnection connection; - EXPECT_CALL(connection, addReadFilter(_)); - cb(connection); +TEST_P(ThriftFilterProtocolConfigTest, ValidProtoConfiguration) { + envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy config{}; + config.set_stat_prefix("my_stat_prefix"); + config.set_protocol(GetParam()); + testConfig(config); } -TEST(ThriftFilterConfigTest, ThriftProxyWithEmptyProto) { - NiceMock context; - ThriftProxyFilterConfigFactory factory; +TEST_F(ThriftFilterConfigTest, ThriftProxyWithEmptyProto) { envoy::config::filter::network::thrift_proxy::v2alpha1::ThriftProxy config = *dynamic_cast( - factory.createEmptyConfigProto().get()); + factory_.createEmptyConfigProto().get()); config.set_stat_prefix("my_stat_prefix"); - Network::FilterFactoryCb cb = factory.createFilterFactoryFromProto(config, context); - Network::MockConnection connection; - EXPECT_CALL(connection, addReadFilter(_)); - cb(connection); + testConfig(config); } } // namespace ThriftProxy diff --git a/test/extensions/filters/network/thrift_proxy/conn_manager_test.cc b/test/extensions/filters/network/thrift_proxy/conn_manager_test.cc index 1710194965f6..049935796342 100644 --- a/test/extensions/filters/network/thrift_proxy/conn_manager_test.cc +++ b/test/extensions/filters/network/thrift_proxy/conn_manager_test.cc @@ -16,11 +16,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { @@ -426,6 +426,48 @@ TEST_F(ThriftConnectionManagerTest, OnDataHandlesProtocolErrorDuringMessageBegin EXPECT_EQ(1U, store_.counter("test.request_decoding_error").value()); } +TEST_F(ThriftConnectionManagerTest, OnDataHandlesTransportApplicationException) { + initializeFilter(); + addSeq(buffer_, { + 0x00, 0x00, 0x00, 0x64, // header: 100 bytes + 0x0f, 0xff, 0x00, 0x00, // magic, flags + 0x00, 0x00, 0x00, 0x01, // sequence id + 0x00, 0x01, 0x00, 0x02, // header size 4, binary proto, 2 transforms + 0x01, 0x02, 0x00, 0x00, // transforms: 1, 2; padding + }); + + std::string err = "Unknown transform 1"; + uint8_t len = 41 + err.length(); + addSeq(write_buffer_, { + 0x00, 0x00, 0x00, len, // header frame size + 0x0f, 0xff, 0x00, 0x00, // magic, flags + 0x00, 0x00, 0x00, 0x00, // sequence id 0 + 0x00, 0x01, 0x00, 0x00, // header size 4, binary, 0 transforms + 0x00, 0x00, // header padding + 0x80, 0x01, 0x00, 0x03, // binary, exception + 0x00, 0x00, 0x00, 0x00, // message name "" + 0x00, 0x00, 0x00, 0x00, // sequence id + 0x0b, 0x00, 0x01, // begin string field + }); + addInt32(write_buffer_, err.length()); + addString(write_buffer_, err); + addSeq(write_buffer_, { + 0x08, 0x00, 0x02, // begin i32 field + 0x00, 0x00, 0x00, 0x05, // missing result + 0x00, // stop field + }); + + EXPECT_CALL(filter_callbacks_.connection_, write(_, false)) + .WillOnce(Invoke([&](Buffer::Instance& buffer, bool) -> void { + EXPECT_EQ(bufferToString(write_buffer_), bufferToString(buffer)); + })); + EXPECT_CALL(filter_callbacks_.connection_, close(Network::ConnectionCloseType::FlushWrite)); + + EXPECT_EQ(filter_->onData(buffer_, false), Network::FilterStatus::StopIteration); + EXPECT_EQ(1U, store_.counter("test.request_decoding_error").value()); + EXPECT_EQ(0U, store_.gauge("test.request_active").value()); +} + TEST_F(ThriftConnectionManagerTest, OnEvent) { // No active calls { @@ -720,6 +762,46 @@ TEST_F(ThriftConnectionManagerTest, RequestAndResponseProtocolError) { EXPECT_EQ(1U, store_.counter("test.response_decoding_error").value()); } +TEST_F(ThriftConnectionManagerTest, RequestAndTransportApplicationException) { + initializeFilter(); + writeMessage(buffer_, TransportType::Header, ProtocolType::Binary, MessageType::Call, 0x0F); + + ThriftFilters::DecoderFilterCallbacks* callbacks{}; + EXPECT_CALL(*decoder_filter_, setDecoderFilterCallbacks(_)) + .WillOnce( + Invoke([&](ThriftFilters::DecoderFilterCallbacks& cb) -> void { callbacks = &cb; })); + + EXPECT_EQ(filter_->onData(buffer_, false), Network::FilterStatus::StopIteration); + EXPECT_EQ(1U, store_.counter("test.request_call").value()); + + // Response with unknown transform + addSeq(write_buffer_, { + 0x00, 0x00, 0x00, 0x64, // header: 100 bytes + 0x0f, 0xff, 0x00, 0x00, // magic, flags + 0x00, 0x00, 0x00, 0x01, // sequence id + 0x00, 0x01, 0x00, 0x02, // header size 4, binary proto, 2 transforms + 0x01, 0x02, 0x00, 0x00, // transforms: 1, 2; padding + }); + + callbacks->startUpstreamResponse(TransportType::Header, ProtocolType::Binary); + + EXPECT_CALL(filter_callbacks_.connection_.dispatcher_, deferredDelete_(_)).Times(1); + EXPECT_EQ(true, callbacks->upstreamData(write_buffer_)); + + filter_callbacks_.connection_.dispatcher_.clearDeferredDeleteList(); + + EXPECT_EQ(1U, store_.counter("test.request").value()); + EXPECT_EQ(1U, store_.counter("test.request_call").value()); + EXPECT_EQ(0U, store_.gauge("test.request_active").value()); + EXPECT_EQ(0U, store_.counter("test.response").value()); + EXPECT_EQ(0U, store_.counter("test.response_reply").value()); + EXPECT_EQ(0U, store_.counter("test.response_exception").value()); + EXPECT_EQ(0U, store_.counter("test.response_invalid_type").value()); + EXPECT_EQ(0U, store_.counter("test.response_success").value()); + EXPECT_EQ(0U, store_.counter("test.response_error").value()); + EXPECT_EQ(1U, store_.counter("test.response_decoding_error").value()); +} + TEST_F(ThriftConnectionManagerTest, PipelinedRequestAndResponse) { initializeFilter(); writeFramedBinaryMessage(buffer_, MessageType::Call, 0x01); diff --git a/test/extensions/filters/network/thrift_proxy/decoder_test.cc b/test/extensions/filters/network/thrift_proxy/decoder_test.cc index f18b0a7f6e43..40a7f318cbb9 100644 --- a/test/extensions/filters/network/thrift_proxy/decoder_test.cc +++ b/test/extensions/filters/network/thrift_proxy/decoder_test.cc @@ -12,6 +12,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::Combine; using testing::DoAll; @@ -29,7 +30,6 @@ using testing::Test; using testing::TestParamInfo; using testing::TestWithParam; using testing::Values; -using testing::_; namespace Envoy { namespace Extensions { @@ -781,6 +781,119 @@ TEST(DecoderTest, OnData) { EXPECT_TRUE(underflow); } +TEST(DecoderTest, OnDataWithProtocolHint) { + NiceMock* transport = new NiceMock(); + NiceMock* proto = new NiceMock(); + NiceMock callbacks; + StrictMock filter; + ON_CALL(callbacks, newDecoderFilter()).WillByDefault(ReturnRef(filter)); + + InSequence dummy; + Decoder decoder(TransportPtr{transport}, ProtocolPtr{proto}, callbacks); + Buffer::OwnedImpl buffer; + + EXPECT_CALL(*transport, decodeFrameStart(Ref(buffer), _)) + .WillOnce(Invoke([&](Buffer::Instance&, MessageMetadata& metadata) -> bool { + metadata.setFrameSize(100); + metadata.setProtocol(ProtocolType::Binary); + return true; + })); + EXPECT_CALL(*proto, type()).WillOnce(Return(ProtocolType::Auto)); + EXPECT_CALL(*proto, setType(ProtocolType::Binary)); + EXPECT_CALL(filter, transportBegin(_)) + .WillOnce(Invoke([&](MessageMetadataSharedPtr metadata) -> ThriftFilters::FilterStatus { + EXPECT_TRUE(metadata->hasFrameSize()); + EXPECT_EQ(100U, metadata->frameSize()); + + EXPECT_TRUE(metadata->hasProtocol()); + EXPECT_EQ(ProtocolType::Binary, metadata->protocol()); + + return ThriftFilters::FilterStatus::Continue; + })); + + EXPECT_CALL(*proto, readMessageBegin(Ref(buffer), _)) + .WillOnce(Invoke([&](Buffer::Instance&, MessageMetadata& metadata) -> bool { + metadata.setMethodName("name"); + metadata.setMessageType(MessageType::Call); + metadata.setSequenceId(100); + return true; + })); + EXPECT_CALL(filter, messageBegin(_)) + .WillOnce(Invoke([&](MessageMetadataSharedPtr metadata) -> ThriftFilters::FilterStatus { + EXPECT_TRUE(metadata->hasMethodName()); + EXPECT_TRUE(metadata->hasMessageType()); + EXPECT_TRUE(metadata->hasSequenceId()); + EXPECT_EQ("name", metadata->methodName()); + EXPECT_EQ(MessageType::Call, metadata->messageType()); + EXPECT_EQ(100U, metadata->sequenceId()); + return ThriftFilters::FilterStatus::Continue; + })); + + EXPECT_CALL(*proto, readStructBegin(Ref(buffer), _)).WillOnce(Return(true)); + EXPECT_CALL(filter, structBegin(absl::string_view())) + .WillOnce(Return(ThriftFilters::FilterStatus::Continue)); + + EXPECT_CALL(*proto, readFieldBegin(Ref(buffer), _, _, _)) + .WillOnce(DoAll(SetArgReferee<2>(FieldType::Stop), Return(true))); + EXPECT_CALL(*proto, readStructEnd(Ref(buffer))).WillOnce(Return(true)); + EXPECT_CALL(filter, structEnd()).WillOnce(Return(ThriftFilters::FilterStatus::Continue)); + + EXPECT_CALL(*proto, readMessageEnd(Ref(buffer))).WillOnce(Return(true)); + EXPECT_CALL(filter, messageEnd()).WillOnce(Return(ThriftFilters::FilterStatus::Continue)); + + EXPECT_CALL(*transport, decodeFrameEnd(Ref(buffer))).WillOnce(Return(true)); + EXPECT_CALL(filter, transportEnd()).WillOnce(Return(ThriftFilters::FilterStatus::Continue)); + + bool underflow = false; + EXPECT_EQ(ThriftFilters::FilterStatus::Continue, decoder.onData(buffer, underflow)); + EXPECT_TRUE(underflow); +} + +TEST(DecoderTest, OnDataWithInconsistentProtocolHint) { + NiceMock* transport = new NiceMock(); + NiceMock* proto = new NiceMock(); + NiceMock callbacks; + StrictMock filter; + ON_CALL(callbacks, newDecoderFilter()).WillByDefault(ReturnRef(filter)); + + InSequence dummy; + Decoder decoder(TransportPtr{transport}, ProtocolPtr{proto}, callbacks); + Buffer::OwnedImpl buffer; + + EXPECT_CALL(*transport, decodeFrameStart(Ref(buffer), _)) + .WillOnce(Invoke([&](Buffer::Instance&, MessageMetadata& metadata) -> bool { + metadata.setFrameSize(100); + metadata.setProtocol(ProtocolType::Binary); + return true; + })); + EXPECT_CALL(*proto, type()).WillRepeatedly(Return(ProtocolType::Compact)); + + bool underflow = false; + EXPECT_THROW_WITH_MESSAGE(decoder.onData(buffer, underflow), EnvoyException, + "transport reports protocol binary, but configured for compact"); +} + +TEST(DecoderTest, OnDataThrowsTransportAppException) { + NiceMock* transport = new NiceMock(); + NiceMock* proto = new NiceMock(); + NiceMock callbacks; + StrictMock filter; + ON_CALL(callbacks, newDecoderFilter()).WillByDefault(ReturnRef(filter)); + + InSequence dummy; + Decoder decoder(TransportPtr{transport}, ProtocolPtr{proto}, callbacks); + Buffer::OwnedImpl buffer; + + EXPECT_CALL(*transport, decodeFrameStart(Ref(buffer), _)) + .WillOnce(Invoke([&](Buffer::Instance&, MessageMetadata& metadata) -> bool { + metadata.setAppException(AppExceptionType::InvalidTransform, "unknown xform"); + return true; + })); + + bool underflow = false; + EXPECT_THROW_WITH_MESSAGE(decoder.onData(buffer, underflow), AppException, "unknown xform"); +} + TEST(DecoderTest, OnDataResumes) { NiceMock* transport = new NiceMock(); NiceMock* proto = new NiceMock(); diff --git a/test/extensions/filters/network/thrift_proxy/driver/client.py b/test/extensions/filters/network/thrift_proxy/driver/client.py index bbc1293cee55..c7134ce20ba8 100755 --- a/test/extensions/filters/network/thrift_proxy/driver/client.py +++ b/test/extensions/filters/network/thrift_proxy/driver/client.py @@ -79,6 +79,12 @@ def main(cfg, reqhandle, resphandle): transport, client_type=THeaderTransport.CLIENT_TYPE.HEADER, ) + if cfg.protocol == "binary": + transport.set_protocol_id(THeaderTransport.T_BINARY_PROTOCOL) + elif cfg.protocol == "compact": + transport.set_protocol_id(THeaderTransport.T_COMPACT_PROTOCOL) + else: + sys.exit("header transport cannot be used with protocol {0}".format(cfg.protocol)) else: sys.exit("unknown transport {0}".format(cfg.transport)) diff --git a/test/extensions/filters/network/thrift_proxy/driver/fbthrift/THeaderTransport.py b/test/extensions/filters/network/thrift_proxy/driver/fbthrift/THeaderTransport.py index cba5ec0651d9..76197ccf6e6e 100644 --- a/test/extensions/filters/network/thrift_proxy/driver/fbthrift/THeaderTransport.py +++ b/test/extensions/filters/network/thrift_proxy/driver/fbthrift/THeaderTransport.py @@ -658,5 +658,10 @@ def do_POST(self): # INFO:(zuercher): Added to simplify usage class THeaderTransportFactory: + def __init__(self, proto_id): + self.__proto_id = proto_id + def getTransport(self, trans): - return THeaderTransport(trans, client_type=CLIENT_TYPE.HEADER) + header_trans = THeaderTransport(trans, client_type=CLIENT_TYPE.HEADER) + header_trans.set_protocol_id(self.__proto_id) + return header_trans diff --git a/test/extensions/filters/network/thrift_proxy/driver/server.py b/test/extensions/filters/network/thrift_proxy/driver/server.py index 7ab9e862b4e9..e5e9cc3c52bc 100755 --- a/test/extensions/filters/network/thrift_proxy/driver/server.py +++ b/test/extensions/filters/network/thrift_proxy/driver/server.py @@ -133,7 +133,14 @@ def main(cfg): elif cfg.transport == "unframed": transport_factory = TTransport.TBufferedTransportFactory() elif cfg.transport == "header": - transport_factory = THeaderTransport.THeaderTransportFactory() + if cfg.protocol == "binary": + transport_factory = THeaderTransport.THeaderTransportFactory( + THeaderTransport.T_BINARY_PROTOCOL) + elif cfg.protocol == "compact": + transport_factory = THeaderTransport.THeaderTransportFactory( + THeaderTransport.T_COMPACT_PROTOCOL) + else: + sys.exit("header transport cannot be used with protocol {0}".format(cfg.protocol)) else: sys.exit("unknown transport {0}".format(cfg.transport)) diff --git a/test/extensions/filters/network/thrift_proxy/header_transport_impl_test.cc b/test/extensions/filters/network/thrift_proxy/header_transport_impl_test.cc new file mode 100644 index 000000000000..1bcc81120ce5 --- /dev/null +++ b/test/extensions/filters/network/thrift_proxy/header_transport_impl_test.cc @@ -0,0 +1,649 @@ +#include "envoy/common/exception.h" + +#include "common/buffer/buffer_impl.h" + +#include "extensions/filters/network/thrift_proxy/header_transport_impl.h" + +#include "test/extensions/filters/network/thrift_proxy/mocks.h" +#include "test/extensions/filters/network/thrift_proxy/utility.h" +#include "test/mocks/buffer/mocks.h" +#include "test/test_common/printers.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::NiceMock; +using testing::Return; + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace ThriftProxy { + +namespace { + +class MockBuffer : public Envoy::MockBuffer { +public: + MockBuffer() {} + ~MockBuffer() {} + + MOCK_CONST_METHOD0(length, uint64_t()); +}; + +MessageMetadata mkMessageMetadata(uint32_t num_headers) { + MessageMetadata metadata; + while (num_headers-- > 0) { + metadata.addHeader(Header("x", "y")); + } + return metadata; +} + +} // namespace + +TEST(HeaderTransportTest, Name) { + HeaderTransportImpl transport; + EXPECT_EQ(transport.name(), "header"); +} + +TEST(HeaderTransportTest, NotEnoughData) { + HeaderTransportImpl transport; + MessageMetadata metadata; + + // Empty buffer + { + Buffer::OwnedImpl buffer; + EXPECT_FALSE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + // Too short for minimum header + { + Buffer::OwnedImpl buffer; + addRepeated(buffer, 13, 0); + EXPECT_FALSE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + // Missing header data + { + Buffer::OwnedImpl buffer; + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // header size / 4 + addRepeated(buffer, 3, 0); + EXPECT_FALSE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } +} + +TEST(HeaderTransportTest, InvalidFrameSize) { + HeaderTransportImpl transport; + MessageMetadata metadata; + + { + Buffer::OwnedImpl buffer; + addInt32(buffer, -1); + addRepeated(buffer, 10, 0); + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid thrift header transport frame size -1"); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + { + Buffer::OwnedImpl buffer; + addInt32(buffer, 0x7fffffff); + addRepeated(buffer, 10, 0); + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid thrift header transport frame size 2147483647"); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } +} + +TEST(HeaderTransportTest, InvalidMagic) { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0123); + addRepeated(buffer, 8, 0); + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid thrift header transport magic 0123"); + EXPECT_THAT(metadata, IsEmptyMetadata()); +} + +TEST(HeaderTransportTest, InvalidHeaderSize) { + HeaderTransportImpl transport; + MessageMetadata metadata; + + // Minimum header size is 1 = 4 bytes + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 0); + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "no header data"); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + // Minimum header size is 1 = 4 bytes + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, -1); + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid thrift header transport header size -4 (ffff)"); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + // Max header size is 16384 = 65536 bytes + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 0x4001); + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid thrift header transport header size 65540 (4001)"); + EXPECT_THAT(metadata, IsEmptyMetadata()); + } + + // Header data extends past stated header size. + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // 4 bytes + addSeq(buffer, {0xFF, 0xFF, 0xFF, 0xFF, 0x1F}); // var int -1, exceeds header size + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "unable to read header transport protocol id: header too small"); + } + + // Partial var-int at end of header + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 0x100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // 4 bytes + addSeq(buffer, {0xFF, 0xFF, 0xFF, 0xFF}); // partial var int + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "unable to read header transport protocol id: header too small"); + } +} + +TEST(HeaderTransportTest, InvalidProto) { + HeaderTransportImpl transport; + MessageMetadata metadata; + + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {1, 0, 0, 0}); // 1 = json, 0 = num transforms, pad, pad + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "Unknown protocol 1"); + } + + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {3, 0, 0, 0}); // 3 = invalid proto, 0 = num transforms, pad, pad + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "Unknown protocol 3"); + } + + { + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 2); // size 8 + addSeq(buffer, {0xFF, 0xFF, 0xFF, 0xFF, 0x1F}); // -1 = invalid proto + addSeq(buffer, {0, 0, 0}); // 0 transforms and padding + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "Unknown protocol -1"); + } +} + +TEST(HeaderTransportTest, NoTransformsOrInfo) { + HeaderTransportImpl transport; + + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {0, 0, 0, 0}); // 0 = binary proto, 0 = num transforms, pad, pad + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(86U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Binary)); + EXPECT_THAT(metadata, HasSequenceId(1)); + EXPECT_THAT(metadata, HasNoHeaders()); + EXPECT_EQ(buffer.length(), 0); + } + + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 101); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 2); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {2, 0, 0, 0}); // 2 = compact proto, 0 = num transforms, pad, pad + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(87U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Compact)); + EXPECT_THAT(metadata, HasSequenceId(2)); + EXPECT_THAT(metadata, HasNoHeaders()); + } +} + +TEST(HeaderTransportTest, TransformErrors) { + MessageMetadata metadata; + + // Invalid number of transforms + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 2); // size 8 + addInt8(buffer, 0); // binary proto + addSeq(buffer, {0xFF, 0xFF, 0xFF, 0xFF, 0x1F}); // -1 = invalid num transforms + addSeq(buffer, {0, 0}); // padding + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid header transport transform count -1"); + } + + // Unknown transform ids + for (uint8_t xform_id = 1; xform_id < 5; xform_id++) { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {0, 1, xform_id, 0}); // 0 = binary proto, 1 = num transforms, xform id, pad + + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(86U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Binary)); + EXPECT_THAT(metadata, HasAppException(AppExceptionType::MissingResult, + fmt::format("Unknown transform {}", xform_id))); + } + + // Only the first of multiple errors is reported + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {0, 2, 1, 2}); // 0 = binary proto, 2 = num transforms, xform id 1, xform id 2 + + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(86U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Binary)); + EXPECT_THAT(metadata, HasAppException(AppExceptionType::MissingResult, "Unknown transform 1")); + } +} + +TEST(HeaderTransportTest, InvalidInfoBlock) { + // Unknown info block id + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 1); // size 4 + addSeq(buffer, {0, 0, 2, 0}); // 0 = binary proto, 0 = num transforms, 2 = unknown info id, pad + + // Unknown info id is ignored. + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(86U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Binary)); + EXPECT_THAT(metadata, HasSequenceId(1)); + EXPECT_THAT(metadata, HasNoHeaders()); + EXPECT_EQ(buffer.length(), 0); + } + + // Num headers info info block id 1 must be >= 0 + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 3); // size 12 + addSeq(buffer, {0, 0, 1}); // 0 = binary proto, 0 = num transforms, 1 key-value + addSeq(buffer, {0xFF, 0xFF, 0xFF, 0xFF, 0x1F}); // -1 headers + addSeq(buffer, {0, 0, 0, 0}); + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "invalid header transport header count -1"); + } + + // Header key length exceeds max allowed size + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 2); // size 8 + addSeq(buffer, {0, 0, 1, 1}); // 0 = binary proto, 0 = num transforms, 1 key-value, 1 = num kvs + addSeq(buffer, {0x80, 0x80, 0x40}); // var int 0x100000 + addInt8(buffer, 0); + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "header transport header key: value 1048576 exceeds max i16 (32767)"); + } + + // Header key extends past stated header size + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 2); // size 8 + addSeq(buffer, {0, 0, 1, 1}); // 0 = binary proto, 0 = num transforms, 1 key-value, 1 = num kvs + addInt8(buffer, 4); // exceeds specified header size + addString(buffer, "key_"); + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "unable to read header transport header key: header too small"); + } + + // Header key ends at stated header size (no value) + { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + + addInt32(buffer, 100); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 2); // size 8 + addSeq(buffer, {0, 0, 1, 1}); // 0 = binary proto, 0 = num transforms, 1 key-value, 1 = num kvs + addInt8(buffer, 3); // head ends with key, no room for value + addString(buffer, "abc"); + addInt8(buffer, 0); + + EXPECT_THROW_WITH_MESSAGE(transport.decodeFrameStart(buffer, metadata), EnvoyException, + "unable to read header transport header value: header too small"); + } +} + +TEST(HeaderTransportTest, InfoBlock) { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.addHeader(Header("not", "empty")); + + addInt32(buffer, 200); + addInt16(buffer, 0x0FFF); + addInt16(buffer, 0); + addInt32(buffer, 1); // sequence number + addInt16(buffer, 38); // size 152 + addSeq(buffer, {0, 0, 1, 3}); // 0 = binary proto, 0 = num transforms, 1 = key value, 3 = num kvs + addInt8(buffer, 3); + addString(buffer, "key"); + addInt8(buffer, 5); + addString(buffer, "value"); + addInt8(buffer, 4); + addString(buffer, "key2"); + addSeq(buffer, {0x80, 0x01}); // var int 128 + addString(buffer, std::string(128, 'x')); + addInt8(buffer, 0); // empty key + addInt8(buffer, 0); // empty value + addInt8(buffer, 0); // padding + + HeaderMap expected_headers{ + {"not", "empty"}, + {"key", "value"}, + {"key2", std::string(128, 'x')}, + {"", ""}, + }; + + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(38U)); + EXPECT_EQ(expected_headers, metadata.headers()); + EXPECT_EQ(buffer.length(), 0); +} + +TEST(HeaderTransportTest, DecodeFrameEnd) { + HeaderTransportImpl transport; + Buffer::OwnedImpl buffer; + EXPECT_TRUE(transport.decodeFrameEnd(buffer)); +} + +TEST(HeaderTransportImpl, TestEncodeFrame) { + HeaderTransportImpl transport; + + // No message + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + Buffer::OwnedImpl msg; + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "invalid thrift header transport message size 0"); + } + + // No protocol + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + Buffer::OwnedImpl msg; + msg.add("fake message"); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "missing header transport protocol"); + } + + // Illegal protocol + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Auto); + Buffer::OwnedImpl msg; + msg.add("fake message"); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "invalid header transport protocol auto"); + } + + // Message too large + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Binary); + + MockBuffer msg; + EXPECT_CALL(msg, length()).WillOnce(Return(0x40000000)); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "invalid thrift header transport frame size 1073741838"); + } + + // Too many headers + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata = mkMessageMetadata(32769); + metadata.setProtocol(ProtocolType::Binary); + + Buffer::OwnedImpl msg; + msg.add("fake message"); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "invalid thrift header transport too many headers 32769"); + } + + // Header string too large + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Binary); + metadata.addHeader(Header("key", std::string(32768, 'x'))); + + Buffer::OwnedImpl msg; + msg.add("fake message"); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "header string too long: 32768"); + } + + // Header info block too large + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Binary); + metadata.addHeader(Header("k1", std::string(16384, 'x'))); + metadata.addHeader(Header("k2", std::string(16384, 'x'))); + metadata.addHeader(Header("k3", std::string(16384, 'x'))); + metadata.addHeader(Header("k4", std::string(16384, 'x'))); + + Buffer::OwnedImpl msg; + msg.add("fake message"); + + EXPECT_THROW_WITH_MESSAGE(transport.encodeFrame(buffer, metadata, msg), EnvoyException, + "invalid thrift header transport header size 65568"); + } + + // Trivial frame with binary protocol + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Binary); + Buffer::OwnedImpl msg; + msg.add("fake message"); + + transport.encodeFrame(buffer, metadata, msg); + + EXPECT_EQ(0, msg.length()); + EXPECT_EQ(std::string("\0\0\0\x1a" + "\xf\xff\0\0" + "\0\0\0\0" + "\0\x1" + "\0\0\0\0" + "fake message", + 30), + buffer.toString()); + } + + // Trivial frame with compact protocol + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Compact); + metadata.setSequenceId(10); + Buffer::OwnedImpl msg; + msg.add("fake message"); + + transport.encodeFrame(buffer, metadata, msg); + + EXPECT_EQ(0, msg.length()); + EXPECT_EQ(std::string("\0\0\0\x1a" + "\xf\xff\0\0" + "\0\0\0\x0a" + "\0\x1" // header size = 4 + "\x2\0\0\0" // compact, no transforms, padding + "fake message", + 30), + buffer.toString()); + } + + // Frame with headers + { + Buffer::OwnedImpl buffer; + MessageMetadata metadata; + metadata.setProtocol(ProtocolType::Compact); + metadata.setSequenceId(10); + metadata.addHeader(Header("key", "value")); + metadata.addHeader(Header("", "")); + Buffer::OwnedImpl msg; + msg.add("fake message"); + + transport.encodeFrame(buffer, metadata, msg); + + EXPECT_EQ(0, msg.length()); + EXPECT_EQ(std::string("\0\0\0\x2a" + "\xf\xff\0\0" + "\0\0\0\x0a" + "\0\x5" // header size = 20 + "\x2\0" // compact, no transforms + "\x1\x2" // header info block, 2 headers + "\x3key\x5value" // first header + "\0\0" // second header + "\0\0\0\0" // padding + "fake message", + 46), + buffer.toString()); + } +} + +} // namespace ThriftProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/network/thrift_proxy/integration_test.cc b/test/extensions/filters/network/thrift_proxy/integration_test.cc index d64fb0e9438e..368c36130cbd 100644 --- a/test/extensions/filters/network/thrift_proxy/integration_test.cc +++ b/test/extensions/filters/network/thrift_proxy/integration_test.cc @@ -203,11 +203,12 @@ paramToString(const TestParamInfo>& p return fmt::format("{}{}", transport, protocol); } -INSTANTIATE_TEST_CASE_P( - TransportAndProtocol, ThriftConnManagerIntegrationTest, - Combine(Values(TransportNames::get().FRAMED, TransportNames::get().UNFRAMED), - Values(ProtocolNames::get().BINARY, ProtocolNames::get().COMPACT), Values(false, true)), - paramToString); +INSTANTIATE_TEST_CASE_P(TransportAndProtocol, ThriftConnManagerIntegrationTest, + Combine(Values(TransportNames::get().FRAMED, TransportNames::get().UNFRAMED, + TransportNames::get().HEADER), + Values(ProtocolNames::get().BINARY, ProtocolNames::get().COMPACT), + Values(false, true)), + paramToString); TEST_P(ThriftConnManagerIntegrationTest, Success) { initializeCall(CallResult::Success); diff --git a/test/extensions/filters/network/thrift_proxy/mocks.cc b/test/extensions/filters/network/thrift_proxy/mocks.cc index 85cdd7377a32..aae1a41e992b 100644 --- a/test/extensions/filters/network/thrift_proxy/mocks.cc +++ b/test/extensions/filters/network/thrift_proxy/mocks.cc @@ -2,10 +2,10 @@ #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/thrift_proxy/protocol_impl_test.cc b/test/extensions/filters/network/thrift_proxy/protocol_impl_test.cc index da9f0f90ed93..621f826c4687 100644 --- a/test/extensions/filters/network/thrift_proxy/protocol_impl_test.cc +++ b/test/extensions/filters/network/thrift_proxy/protocol_impl_test.cc @@ -342,6 +342,18 @@ TEST_F(AutoProtocolTest, Type) { EXPECT_EQ(proto.type(), ProtocolType::Auto); } +TEST_F(AutoProtocolTest, SetUnexpectedType) { + Buffer::OwnedImpl buffer; + AutoProtocolImpl proto; + resetMetadata(); + + addInt16(buffer, 0x0102); + + proto.setType(ProtocolType::Auto); + EXPECT_THROW_WITH_MESSAGE(proto.readMessageBegin(buffer, metadata_), EnvoyException, + "unknown thrift auto protocol message start 0102"); +} + } // namespace ThriftProxy } // namespace NetworkFilters } // namespace Extensions diff --git a/test/extensions/filters/network/thrift_proxy/router_test.cc b/test/extensions/filters/network/thrift_proxy/router_test.cc index d1a83977fe82..1822f6d9bb39 100644 --- a/test/extensions/filters/network/thrift_proxy/router_test.cc +++ b/test/extensions/filters/network/thrift_proxy/router_test.cc @@ -19,6 +19,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ContainsRegex; using testing::Invoke; using testing::NiceMock; @@ -28,7 +29,6 @@ using testing::ReturnRef; using testing::Test; using testing::TestWithParam; using testing::Values; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/filters/network/thrift_proxy/transport_impl_test.cc b/test/extensions/filters/network/thrift_proxy/transport_impl_test.cc index 93ddab8928a6..adf502ea96f7 100644 --- a/test/extensions/filters/network/thrift_proxy/transport_impl_test.cc +++ b/test/extensions/filters/network/thrift_proxy/transport_impl_test.cc @@ -131,6 +131,50 @@ TEST(AutoTransportTest, DecodeFrameStart) { EXPECT_EQ(transport.type(), TransportType::Unframed); EXPECT_EQ(buffer.length(), 8); } + + // Header transport + binary protocol + { + AutoTransportImpl transport; + Buffer::OwnedImpl buffer; + addInt32(buffer, 0xFF); + addInt16(buffer, 0x0FFF); // header magic + addInt16(buffer, 0x0000); + addInt32(buffer, 0xEE); // sequence id + addInt16(buffer, 1); + addInt32(buffer, 0); // protocol (binary), 0 transforms + padding + addInt16(buffer, 0x8001); + + MessageMetadata metadata; + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(241U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Binary)); + EXPECT_THAT(metadata, HasSequenceId(0xEE)); + EXPECT_EQ(transport.name(), "header(auto)"); + EXPECT_EQ(transport.type(), TransportType::Header); + EXPECT_EQ(buffer.length(), 2); + } + + // Header transport + compact protocol + { + AutoTransportImpl transport; + Buffer::OwnedImpl buffer; + addInt32(buffer, 0xFF); + addInt16(buffer, 0x0FFF); // header magic + addInt16(buffer, 0x0000); + addInt32(buffer, 0xEE); // sequence id + addInt16(buffer, 1); + addInt32(buffer, 0x02000000); // protocol (binary), 0 transforms + padding + addInt16(buffer, 0x8201); + + MessageMetadata metadata; + EXPECT_TRUE(transport.decodeFrameStart(buffer, metadata)); + EXPECT_THAT(metadata, HasFrameSize(241U)); + EXPECT_THAT(metadata, HasProtocol(ProtocolType::Compact)); + EXPECT_THAT(metadata, HasSequenceId(0xEE)); + EXPECT_EQ(transport.name(), "header(auto)"); + EXPECT_EQ(transport.type(), TransportType::Header); + EXPECT_EQ(buffer.length(), 2); + } } TEST(AutoTransportTest, DecodeFrameEnd) { diff --git a/test/extensions/health_checkers/redis/redis_test.cc b/test/extensions/health_checkers/redis/redis_test.cc index 015a7c08c9b5..a8759d4c90ab 100644 --- a/test/extensions/health_checkers/redis/redis_test.cc +++ b/test/extensions/health_checkers/redis/redis_test.cc @@ -7,6 +7,7 @@ #include "test/mocks/runtime/mocks.h" #include "test/mocks/upstream/mocks.h" +using testing::_; using testing::DoAll; using testing::InSequence; using testing::NiceMock; @@ -15,7 +16,6 @@ using testing::Return; using testing::ReturnRef; using testing::SaveArg; using testing::WithArg; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/stats_sinks/common/statsd/statsd_test.cc b/test/extensions/stats_sinks/common/statsd/statsd_test.cc index 82015050207f..36503764de5f 100644 --- a/test/extensions/stats_sinks/common/statsd/statsd_test.cc +++ b/test/extensions/stats_sinks/common/statsd/statsd_test.cc @@ -17,11 +17,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/stats_sinks/dog_statsd/config_test.cc b/test/extensions/stats_sinks/dog_statsd/config_test.cc index c54a1687772f..a8abc7f8205e 100644 --- a/test/extensions/stats_sinks/dog_statsd/config_test.cc +++ b/test/extensions/stats_sinks/dog_statsd/config_test.cc @@ -16,10 +16,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/stats_sinks/hystrix/config_test.cc b/test/extensions/stats_sinks/hystrix/config_test.cc index ec224c4ddb91..abcdcca16910 100644 --- a/test/extensions/stats_sinks/hystrix/config_test.cc +++ b/test/extensions/stats_sinks/hystrix/config_test.cc @@ -15,10 +15,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/stats_sinks/hystrix/hystrix_test.cc b/test/extensions/stats_sinks/hystrix/hystrix_test.cc index 5a7048346691..81be09a24aed 100644 --- a/test/extensions/stats_sinks/hystrix/hystrix_test.cc +++ b/test/extensions/stats_sinks/hystrix/hystrix_test.cc @@ -12,11 +12,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { 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 aba7183e3d0e..f2996770d3a2 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 @@ -6,11 +6,11 @@ #include "test/mocks/thread_local/mocks.h" using namespace std::chrono_literals; +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/stats_sinks/statsd/config_test.cc b/test/extensions/stats_sinks/statsd/config_test.cc index fc4eeee983c4..1c9e6ce118ac 100644 --- a/test/extensions/stats_sinks/statsd/config_test.cc +++ b/test/extensions/stats_sinks/statsd/config_test.cc @@ -17,10 +17,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/tracers/dynamic_ot/config_test.cc b/test/extensions/tracers/dynamic_ot/config_test.cc index 47764aca9308..d2c2077bcd7d 100644 --- a/test/extensions/tracers/dynamic_ot/config_test.cc +++ b/test/extensions/tracers/dynamic_ot/config_test.cc @@ -7,9 +7,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/tracers/lightstep/config_test.cc b/test/extensions/tracers/lightstep/config_test.cc index 3651224f2abd..3eb338d87dd2 100644 --- a/test/extensions/tracers/lightstep/config_test.cc +++ b/test/extensions/tracers/lightstep/config_test.cc @@ -5,9 +5,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/tracers/lightstep/lightstep_tracer_impl_test.cc b/test/extensions/tracers/lightstep/lightstep_tracer_impl_test.cc index fc1d0ba03496..2650ddc7df39 100644 --- a/test/extensions/tracers/lightstep/lightstep_tracer_impl_test.cc +++ b/test/extensions/tracers/lightstep/lightstep_tracer_impl_test.cc @@ -27,13 +27,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AtLeast; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::Test; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc b/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc index a52333cf848b..818cca0d9c87 100644 --- a/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc +++ b/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc @@ -24,12 +24,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::Test; -using testing::_; namespace Envoy { namespace Extensions { diff --git a/test/extensions/transport_sockets/alts/tsi_frame_protector_test.cc b/test/extensions/transport_sockets/alts/tsi_frame_protector_test.cc index 2604e837c8cd..d98217a9f537 100644 --- a/test/extensions/transport_sockets/alts/tsi_frame_protector_test.cc +++ b/test/extensions/transport_sockets/alts/tsi_frame_protector_test.cc @@ -11,12 +11,12 @@ namespace Extensions { namespace TransportSockets { namespace Alts { +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::SaveArg; using testing::Test; -using testing::_; using namespace std::string_literals; /** diff --git a/test/extensions/transport_sockets/alts/tsi_handshaker_test.cc b/test/extensions/transport_sockets/alts/tsi_handshaker_test.cc index 883462f77c04..611479298277 100644 --- a/test/extensions/transport_sockets/alts/tsi_handshaker_test.cc +++ b/test/extensions/transport_sockets/alts/tsi_handshaker_test.cc @@ -11,12 +11,12 @@ namespace Extensions { namespace TransportSockets { namespace Alts { +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::SaveArg; using testing::Test; -using testing::_; class MockTsiHandshakerCallbacks : public TsiHandshakerCallbacks { public: diff --git a/test/integration/BUILD b/test/integration/BUILD index 25534d61eec2..c2e3469ca85b 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -34,7 +34,7 @@ envoy_cc_test( "//source/extensions/transport_sockets/ssl:config", "//test/common/grpc:grpc_client_integration_lib", "//test/mocks/runtime:runtime_mocks", - "//test/mocks/secret:secret_mocks", + "//test/mocks/server:server_mocks", "//test/test_common:network_utility_lib", "//test/test_common:utility_lib", "@envoy_api//envoy/api/v2:cds_cc", @@ -462,6 +462,35 @@ envoy_cc_test( ], ) +envoy_cc_test( + name = "sds_dynamic_integration_test", + srcs = [ + "sds_dynamic_integration_test.cc", + ], + data = [ + "//test/config/integration/certs", + ], + deps = [ + ":http_integration_lib", + "//source/common/config:protobuf_link_hacks", + "//source/common/config:resources_lib", + "//source/common/event:dispatcher_includes", + "//source/common/event:dispatcher_lib", + "//source/common/network:connection_lib", + "//source/common/network:utility_lib", + "//source/common/ssl:context_config_lib", + "//source/common/ssl:context_lib", + "//source/extensions/filters/listener/tls_inspector:config", + "//source/extensions/transport_sockets/ssl:config", + "//test/common/grpc:grpc_client_integration_lib", + "//test/mocks/runtime:runtime_mocks", + "//test/mocks/secret:secret_mocks", + "//test/test_common:utility_lib", + "@envoy_api//envoy/config/transport_socket/capture/v2alpha:capture_cc", + "@envoy_api//envoy/data/tap/v2alpha:capture_cc", + ], +) + envoy_cc_test( name = "ssl_integration_test", srcs = [ @@ -567,7 +596,7 @@ envoy_cc_test( "//source/common/http:header_map_lib", "//source/extensions/filters/listener/tls_inspector:config", "//source/extensions/transport_sockets/ssl:config", - "//test/mocks/secret:secret_mocks", + "//test/mocks/server:server_mocks", "//test/test_common:utility_lib", ], ) diff --git a/test/integration/ads_integration_test.cc b/test/integration/ads_integration_test.cc index e2a96d260fe3..330fa426b63f 100644 --- a/test/integration/ads_integration_test.cc +++ b/test/integration/ads_integration_test.cc @@ -21,7 +21,7 @@ #include "test/integration/http_integration.h" #include "test/integration/utility.h" #include "test/mocks/runtime/mocks.h" -#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/network_utility.h" #include "test/test_common/utility.h" @@ -117,7 +117,7 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest, TestEnvironment::runfilesPath("test/config/integration/certs/upstreamcert.pem")); tls_cert->mutable_private_key()->set_filename( TestEnvironment::runfilesPath("test/config/integration/certs/upstreamkey.pem")); - auto cfg = std::make_unique(tls_context, secret_manager_); + auto cfg = std::make_unique(tls_context, factory_context_); static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); return std::make_unique( @@ -295,7 +295,7 @@ class AdsIntegrationTest : public AdsIntegrationBaseTest, return dynamic_cast(*message_ptr); } - testing::NiceMock secret_manager_; + testing::NiceMock factory_context_; Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; FakeStreamPtr ads_stream_; diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index e1bfbab9e51c..b284db4eac11 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -28,11 +28,11 @@ #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::HasSubstr; using testing::Invoke; using testing::Not; -using testing::_; namespace Envoy { @@ -79,7 +79,6 @@ IntegrationCodecClient::IntegrationCodecClient( connection_->addConnectionCallbacks(callbacks_); setCodecConnectionCallbacks(codec_callbacks_); dispatcher.run(Event::Dispatcher::RunType::Block); - EXPECT_TRUE(connected_); } void IntegrationCodecClient::flushWrite() { @@ -169,7 +168,7 @@ IntegrationCodecClientPtr HttpIntegrationTest::makeHttpConnection(uint32_t port) } IntegrationCodecClientPtr -HttpIntegrationTest::makeHttpConnection(Network::ClientConnectionPtr&& conn) { +HttpIntegrationTest::makeRawHttpConnection(Network::ClientConnectionPtr&& conn) { std::shared_ptr cluster{new NiceMock()}; Upstream::HostDescriptionConstSharedPtr host_description{Upstream::makeTestHostDescription( cluster, fmt::format("tcp://{}:80", Network::Test::getLoopbackAddressUrlString(version_)))}; @@ -177,6 +176,13 @@ HttpIntegrationTest::makeHttpConnection(Network::ClientConnectionPtr&& conn) { *dispatcher_, std::move(conn), host_description, downstream_protocol_)}; } +IntegrationCodecClientPtr +HttpIntegrationTest::makeHttpConnection(Network::ClientConnectionPtr&& conn) { + auto codec = makeRawHttpConnection(std::move(conn)); + EXPECT_TRUE(codec->connected()); + return codec; +} + HttpIntegrationTest::HttpIntegrationTest(Http::CodecClient::Type downstream_protocol, Network::Address::IpVersion version, const std::string& config) diff --git a/test/integration/http_integration.h b/test/integration/http_integration.h index 6d86ef8df5d7..b3f342ba5071 100644 --- a/test/integration/http_integration.h +++ b/test/integration/http_integration.h @@ -25,7 +25,8 @@ class IntegrationCodecClient : public Http::CodecClientProd { IntegrationStreamDecoderPtr makeHeaderOnlyRequest(const Http::HeaderMap& headers); IntegrationStreamDecoderPtr makeRequestWithBody(const Http::HeaderMap& headers, uint64_t body_size); - bool sawGoAway() { return saw_goaway_; } + bool sawGoAway() const { return saw_goaway_; } + bool connected() const { return connected_; } void sendData(Http::StreamEncoder& encoder, absl::string_view data, bool end_stream); void sendData(Http::StreamEncoder& encoder, Buffer::Instance& data, bool end_stream); void sendData(Http::StreamEncoder& encoder, uint64_t size, bool end_stream); @@ -81,6 +82,9 @@ class HttpIntegrationTest : public BaseIntegrationTest { protected: IntegrationCodecClientPtr makeHttpConnection(uint32_t port); + // Makes a http connection object without checking its connected state. + IntegrationCodecClientPtr makeRawHttpConnection(Network::ClientConnectionPtr&& conn); + // Makes a http connection object with asserting a connected state. IntegrationCodecClientPtr makeHttpConnection(Network::ClientConnectionPtr&& conn); // Sets downstream_protocol_ and alters the HTTP connection manager codec type in the diff --git a/test/integration/integration.cc b/test/integration/integration.cc index b91be75da80d..ab8754717eae 100644 --- a/test/integration/integration.cc +++ b/test/integration/integration.cc @@ -28,11 +28,11 @@ #include "gtest/gtest.h" +using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::Invoke; using testing::NiceMock; -using testing::_; namespace Envoy { diff --git a/test/integration/sds_dynamic_integration_test.cc b/test/integration/sds_dynamic_integration_test.cc new file mode 100644 index 000000000000..191a615240a2 --- /dev/null +++ b/test/integration/sds_dynamic_integration_test.cc @@ -0,0 +1,345 @@ +#include +#include + +#include "envoy/service/discovery/v2/sds.pb.h" + +#include "common/config/resources.h" +#include "common/event/dispatcher_impl.h" +#include "common/network/connection_impl.h" +#include "common/network/utility.h" +#include "common/ssl/context_config_impl.h" +#include "common/ssl/context_manager_impl.h" + +#include "test/common/grpc/grpc_client_integration.h" +#include "test/integration/http_integration.h" +#include "test/integration/server.h" +#include "test/integration/ssl_utility.h" +#include "test/mocks/init/mocks.h" +#include "test/mocks/runtime/mocks.h" +#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" +#include "test/test_common/network_utility.h" +#include "test/test_common/utility.h" + +#include "absl/strings/match.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "integration.h" +#include "utility.h" + +using testing::NiceMock; +using testing::Return; + +namespace Envoy { +namespace Ssl { + +// Hack to force linking of the service: https://github.com/google/protobuf/issues/4221. +const envoy::service::discovery::v2::SdsDummy _sds_dummy; + +// Sds integration base class with following support: +// * functions to create sds upstream, and send sds response +// * functions to create secret protobuf. +class SdsDynamicIntegrationBaseTest : public HttpIntegrationTest, + public Grpc::GrpcClientIntegrationParamTest { +public: + SdsDynamicIntegrationBaseTest() + : HttpIntegrationTest(Http::CodecClient::Type::HTTP1, ipVersion()) {} + +protected: + void createSdsStream(FakeUpstream& upstream) { + sds_upstream_ = &upstream; + AssertionResult result1 = sds_upstream_->waitForHttpConnection(*dispatcher_, sds_connection_); + RELEASE_ASSERT(result1, result1.message()); + + AssertionResult result2 = sds_connection_->waitForNewStream(*dispatcher_, sds_stream_); + RELEASE_ASSERT(result2, result2.message()); + sds_stream_->startGrpcStream(); + } + + envoy::api::v2::auth::Secret getServerSecret() { + envoy::api::v2::auth::Secret secret; + secret.set_name("server_cert"); + auto* tls_certificate = secret.mutable_tls_certificate(); + tls_certificate->mutable_certificate_chain()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/servercert.pem")); + tls_certificate->mutable_private_key()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/serverkey.pem")); + return secret; + } + + envoy::api::v2::auth::Secret getClientSecret() { + envoy::api::v2::auth::Secret secret; + secret.set_name("client_cert"); + auto* tls_certificate = secret.mutable_tls_certificate(); + tls_certificate->mutable_certificate_chain()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/clientcert.pem")); + tls_certificate->mutable_private_key()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/clientkey.pem")); + return secret; + } + + envoy::api::v2::auth::Secret getWrongSecret() { + envoy::api::v2::auth::Secret secret; + secret.set_name("wrong_cert"); + return secret; + } + + void sendSdsResponse(const envoy::api::v2::auth::Secret& secret) { + envoy::api::v2::DiscoveryResponse discovery_response; + discovery_response.set_version_info("1"); + discovery_response.set_type_url(Config::TypeUrl::get().Secret); + discovery_response.add_resources()->PackFrom(secret); + + sds_stream_->sendGrpcMessage(discovery_response); + } + + void cleanUpSdsConnection() { + ASSERT(sds_upstream_ != nullptr); + + // Don't ASSERT fail if an ADS reconnect ends up unparented. + sds_upstream_->set_allow_unexpected_disconnects(true); + AssertionResult result = sds_connection_->close(); + RELEASE_ASSERT(result, result.message()); + result = sds_connection_->waitForDisconnect(); + RELEASE_ASSERT(result, result.message()); + sds_connection_.reset(); + } + + void PrintServerCounters() { + std::cerr << "all counters" << std::endl; + for (const auto& c : test_server_->counters()) { + std::cerr << "counter: " << c->name() << ", value: " << c->value() << std::endl; + } + } + + Runtime::MockLoader runtime_; + Ssl::ContextManagerImpl context_manager_{runtime_}; + FakeHttpConnectionPtr sds_connection_; + FakeUpstream* sds_upstream_{}; + FakeStreamPtr sds_stream_; +}; + +// Downstream SDS integration test: static Listener with ssl cert from SDS +class SdsDynamicDownstreamIntegrationTest : public SdsDynamicIntegrationBaseTest { +public: + void initialize() override { + config_helper_.addConfigModifier([this](envoy::config::bootstrap::v2::Bootstrap& bootstrap) { + auto* common_tls_context = bootstrap.mutable_static_resources() + ->mutable_listeners(0) + ->mutable_filter_chains(0) + ->mutable_tls_context() + ->mutable_common_tls_context(); + common_tls_context->add_alpn_protocols("http/1.1"); + + auto* validation_context = common_tls_context->mutable_validation_context(); + validation_context->mutable_trusted_ca()->set_filename( + TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); + validation_context->add_verify_certificate_hash( + "E0:F3:C8:CE:5E:2E:A3:05:F0:70:1F:F5:12:E3:6E:2E:" + "97:92:82:84:A2:28:BC:F7:73:32:D3:39:30:A1:B6:FD"); + + // Modify the listener ssl cert to use SDS from sds_cluster + auto* secret_config = common_tls_context->add_tls_certificate_sds_secret_configs(); + secret_config->set_name("server_cert"); + auto* config_source = secret_config->mutable_sds_config(); + auto* api_config_source = config_source->mutable_api_config_source(); + api_config_source->set_api_type(envoy::api::v2::core::ApiConfigSource::GRPC); + auto* grpc_service = api_config_source->add_grpc_services(); + setGrpcService(*grpc_service, "sds_cluster", fake_upstreams_.back()->localAddress()); + + // Add a static sds cluster + auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); + sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + sds_cluster->set_name("sds_cluster"); + sds_cluster->mutable_http2_protocol_options(); + }); + + HttpIntegrationTest::initialize(); + client_ssl_ctx_ = createClientSslTransportSocketFactory(false, false, context_manager_); + } + + void createUpstreams() override { + HttpIntegrationTest::createUpstreams(); + // SDS upstream + fake_upstreams_.emplace_back( + new FakeUpstream(0, FakeHttpConnection::Type::HTTP2, version_, enable_half_close_)); + } + + void TearDown() override { + cleanUpSdsConnection(); + + client_ssl_ctx_.reset(); + cleanupUpstreamAndDownstream(); + fake_upstream_connection_.reset(); + codec_client_.reset(); + } + + Network::ClientConnectionPtr makeSslClientConnection() { + Network::Address::InstanceConstSharedPtr address = getSslAddress(version_, lookupPort("http")); + return dispatcher_->createClientConnection(address, Network::Address::InstanceConstSharedPtr(), + client_ssl_ctx_->createTransportSocket(), nullptr); + } + +private: + Network::TransportSocketFactoryPtr client_ssl_ctx_; +}; + +INSTANTIATE_TEST_CASE_P(IpVersionsClientType, SdsDynamicDownstreamIntegrationTest, + GRPC_CLIENT_INTEGRATION_PARAMS); + +// A test that SDS server send a good server secret for a static listener. +// The first ssl request should be OK. +TEST_P(SdsDynamicDownstreamIntegrationTest, BasicSuccess) { + pre_worker_start_test_steps_ = [this]() { + createSdsStream(*(fake_upstreams_[1])); + sendSdsResponse(getServerSecret()); + }; + initialize(); + + ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { + return makeSslClientConnection(); + }; + testRouterHeaderOnlyRequestAndResponse(true, &creator); +} + +// A test that SDS server send a bad secret for a static listener, +// The first ssl request should fail at connecting. +// then SDS send a good server secret, the second request should be OK. +TEST_P(SdsDynamicDownstreamIntegrationTest, WrongSecretFirst) { + pre_worker_start_test_steps_ = [this]() { + createSdsStream(*(fake_upstreams_[1])); + sendSdsResponse(getWrongSecret()); + }; + initialize(); + + codec_client_ = makeRawHttpConnection(makeSslClientConnection()); + // the connection state is not connected. + EXPECT_FALSE(codec_client_->connected()); + codec_client_->connection()->close(Network::ConnectionCloseType::NoFlush); + + sendSdsResponse(getServerSecret()); + + // Wait for ssl_context_updated_by_sds counter. + if (version_ == Network::Address::IpVersion::v4) { + test_server_->waitForCounterGe( + "listener.127.0.0.1_0.server_ssl_socket_factory.ssl_context_update_by_sds", 1); + } else { + test_server_->waitForCounterGe( + "listener.[__1]_0.server_ssl_socket_factory.ssl_context_update_by_sds", 1); + } + + ConnectionCreationFunction creator = [&]() -> Network::ClientConnectionPtr { + return makeSslClientConnection(); + }; + testRouterHeaderOnlyRequestAndResponse(true, &creator); +} + +// Upstream SDS integration test: a static cluster has ssl cert from SDS. +class SdsDynamicUpstreamIntegrationTest : public SdsDynamicIntegrationBaseTest { +public: + void initialize() override { + config_helper_.addConfigModifier([this](envoy::config::bootstrap::v2::Bootstrap& bootstrap) { + // add sds cluster first. + auto* sds_cluster = bootstrap.mutable_static_resources()->add_clusters(); + sds_cluster->MergeFrom(bootstrap.static_resources().clusters()[0]); + sds_cluster->set_name("sds_cluster"); + sds_cluster->mutable_http2_protocol_options(); + + // change the first cluster with ssl and sds. + auto* secret_config = bootstrap.mutable_static_resources() + ->mutable_clusters(0) + ->mutable_tls_context() + ->mutable_common_tls_context() + ->add_tls_certificate_sds_secret_configs(); + + secret_config->set_name("client_cert"); + auto* config_source = secret_config->mutable_sds_config(); + auto* api_config_source = config_source->mutable_api_config_source(); + api_config_source->set_api_type(envoy::api::v2::core::ApiConfigSource::GRPC); + auto* grpc_service = api_config_source->add_grpc_services(); + setGrpcService(*grpc_service, "sds_cluster", fake_upstreams_.back()->localAddress()); + }); + + HttpIntegrationTest::initialize(); + registerTestServerPorts({"http"}); + } + + void TearDown() override { + cleanUpSdsConnection(); + + cleanupUpstreamAndDownstream(); + fake_upstream_connection_.reset(); + codec_client_.reset(); + + test_server_.reset(); + fake_upstreams_.clear(); + } + + void createUpstreams() override { + // This is for backend with ssl + fake_upstreams_.emplace_back(new FakeUpstream(createUpstreamSslContext(context_manager_), 0, + FakeHttpConnection::Type::HTTP1, version_)); + // This is sds. + fake_upstreams_.emplace_back( + new FakeUpstream(0, FakeHttpConnection::Type::HTTP2, version_, enable_half_close_)); + } +}; + +INSTANTIATE_TEST_CASE_P(IpVersions, SdsDynamicUpstreamIntegrationTest, + GRPC_CLIENT_INTEGRATION_PARAMS); + +// To test a static cluster with sds. SDS send a good client secret first. +// The first request should work. +TEST_P(SdsDynamicUpstreamIntegrationTest, BasicSuccess) { + pre_worker_start_test_steps_ = [this]() { + createSdsStream(*(fake_upstreams_[1])); + sendSdsResponse(getClientSecret()); + }; + + initialize(); + fake_upstreams_[0]->set_allow_unexpected_disconnects(true); + + // There is a race condition here; there are two static clusters: + // backend cluster_0 with sds and sds_cluser. cluster_0 is created first, its init_manager + // is called so it issues a sds call, but fail since sds_cluster is not added yet. + // so cluster_0 is initialized with an empty secret. initialize() will not wait and will return. + // the testing request will be called, even though in the pre_workder_function, a good sds is + // send, the cluster will be updated with good secret, the testing request may fail if it is + // before context is updated. Hence, need to wait for context_update counter. + test_server_->waitForCounterGe( + "cluster.cluster_0.client_ssl_socket_factory.ssl_context_update_by_sds", 1); + + testRouterHeaderOnlyRequestAndResponse(true); +} + +// To test a static cluster with sds. SDS send a bad client secret first. +// The first request should fail with 503, then SDS sends a good client secret, +// the second request should work. +TEST_P(SdsDynamicUpstreamIntegrationTest, WrongSecretFirst) { + pre_worker_start_test_steps_ = [this]() { + createSdsStream(*(fake_upstreams_[1])); + sendSdsResponse(getWrongSecret()); + }; + initialize(); + fake_upstreams_[0]->set_allow_unexpected_disconnects(true); + + // Make a simple request, should get 503 + BufferingStreamDecoderPtr response = IntegrationUtil::makeSingleRequest( + lookupPort("http"), "GET", "/test/long/url", "", downstream_protocol_, version_); + ASSERT_TRUE(response->complete()); + EXPECT_STREQ("503", response->headers().Status()->value().c_str()); + + // To flush out the reset connection from the first request in upstream. + FakeRawConnectionPtr fake_upstream_connection; + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection)); + ASSERT_TRUE(fake_upstream_connection->waitForDisconnect()); + + sendSdsResponse(getClientSecret()); + test_server_->waitForCounterGe( + "cluster.cluster_0.client_ssl_socket_factory.ssl_context_update_by_sds", 1); + + testRouterHeaderOnlyRequestAndResponse(true); +} + +} // namespace Ssl +} // namespace Envoy diff --git a/test/integration/sds_static_integration_test.cc b/test/integration/sds_static_integration_test.cc index e3a24c3c4298..cc259d31ffe7 100644 --- a/test/integration/sds_static_integration_test.cc +++ b/test/integration/sds_static_integration_test.cc @@ -15,6 +15,7 @@ #include "test/mocks/init/mocks.h" #include "test/mocks/runtime/mocks.h" #include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/network_utility.h" #include "test/test_common/utility.h" @@ -68,8 +69,7 @@ class SdsStaticDownstreamIntegrationTest registerTestServerPorts({"http"}); - client_ssl_ctx_ = - createClientSslTransportSocketFactory(false, false, context_manager_, secret_manager_); + client_ssl_ctx_ = createClientSslTransportSocketFactory(false, false, context_manager_); } void TearDown() override { @@ -88,7 +88,6 @@ class SdsStaticDownstreamIntegrationTest private: Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; - NiceMock secret_manager_; Network::TransportSocketFactoryPtr client_ssl_ctx_; }; @@ -144,41 +143,13 @@ class SdsStaticUpstreamIntegrationTest } void createUpstreams() override { - fake_upstreams_.emplace_back( - new FakeUpstream(createUpstreamSslContext(), 0, FakeHttpConnection::Type::HTTP1, version_)); - } - - Network::TransportSocketFactoryPtr createUpstreamSslContext() { - envoy::api::v2::auth::DownstreamTlsContext tls_context; - auto* common_tls_context = tls_context.mutable_common_tls_context(); - common_tls_context->add_alpn_protocols("h2"); - common_tls_context->add_alpn_protocols("http/1.1"); - common_tls_context->mutable_deprecated_v1()->set_alt_alpn_protocols("http/1.1"); - - auto* validation_context = common_tls_context->mutable_validation_context(); - validation_context->mutable_trusted_ca()->set_filename( - TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); - validation_context->add_verify_certificate_hash( - "E0:F3:C8:CE:5E:2E:A3:05:F0:70:1F:F5:12:E3:6E:2E:" - "97:92:82:84:A2:28:BC:F7:73:32:D3:39:30:A1:B6:FD"); - - auto* tls_certificate = common_tls_context->add_tls_certificates(); - tls_certificate->mutable_certificate_chain()->set_filename( - TestEnvironment::runfilesPath("/test/config/integration/certs/servercert.pem")); - tls_certificate->mutable_private_key()->set_filename( - TestEnvironment::runfilesPath("/test/config/integration/certs/serverkey.pem")); - - auto cfg = std::make_unique(tls_context, secret_manager_); - - static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); - return std::make_unique( - std::move(cfg), context_manager_, *upstream_stats_store, std::vector{}); + fake_upstreams_.emplace_back(new FakeUpstream(createUpstreamSslContext(context_manager_), 0, + FakeHttpConnection::Type::HTTP1, version_)); } private: Runtime::MockLoader runtime_; Ssl::ContextManagerImpl context_manager_{runtime_}; - NiceMock secret_manager_; }; INSTANTIATE_TEST_CASE_P(IpVersions, SdsStaticUpstreamIntegrationTest, diff --git a/test/integration/ssl_integration_test.cc b/test/integration/ssl_integration_test.cc index 3ed603e9b37c..f72f0e7c518c 100644 --- a/test/integration/ssl_integration_test.cc +++ b/test/integration/ssl_integration_test.cc @@ -35,14 +35,10 @@ void SslIntegrationTest::initialize() { context_manager_.reset(new ContextManagerImpl(*runtime_)); registerTestServerPorts({"http"}); - client_ssl_ctx_plain_ = - createClientSslTransportSocketFactory(false, false, *context_manager_, secret_manager_); - client_ssl_ctx_alpn_ = - createClientSslTransportSocketFactory(true, false, *context_manager_, secret_manager_); - client_ssl_ctx_san_ = - createClientSslTransportSocketFactory(false, true, *context_manager_, secret_manager_); - client_ssl_ctx_alpn_san_ = - createClientSslTransportSocketFactory(true, true, *context_manager_, secret_manager_); + client_ssl_ctx_plain_ = createClientSslTransportSocketFactory(false, false, *context_manager_); + client_ssl_ctx_alpn_ = createClientSslTransportSocketFactory(true, false, *context_manager_); + client_ssl_ctx_san_ = createClientSslTransportSocketFactory(false, true, *context_manager_); + client_ssl_ctx_alpn_san_ = createClientSslTransportSocketFactory(true, true, *context_manager_); } void SslIntegrationTest::TearDown() { diff --git a/test/integration/ssl_integration_test.h b/test/integration/ssl_integration_test.h index 73f96c514a20..a883d3b9c3cb 100644 --- a/test/integration/ssl_integration_test.h +++ b/test/integration/ssl_integration_test.h @@ -32,7 +32,6 @@ class SslIntegrationTest : public HttpIntegrationTest, private: std::unique_ptr runtime_; std::unique_ptr context_manager_; - NiceMock secret_manager_; Network::TransportSocketFactoryPtr client_ssl_ctx_plain_; Network::TransportSocketFactoryPtr client_ssl_ctx_alpn_; diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index bb6ccb9f20b1..a5f7e71daa79 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -7,6 +7,7 @@ #include "common/ssl/ssl_socket.h" #include "test/integration/server.h" +#include "test/mocks/server/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/network_utility.h" @@ -14,8 +15,7 @@ namespace Envoy { namespace Ssl { Network::TransportSocketFactoryPtr -createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager, - Secret::SecretManager& secret_manager) { +createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager) { const std::string json_plain = R"EOF( { "ca_cert_file": "{{ test_rundir }}/test/config/integration/certs/cacert.pem", @@ -59,12 +59,41 @@ createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& conte target = san ? json_san : json_plain; } Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(target); - auto cfg = std::make_unique(*loader, secret_manager); + NiceMock mock_factory_ctx; + auto cfg = std::make_unique(*loader, mock_factory_ctx); static auto* client_stats_store = new Stats::TestIsolatedStoreImpl(); return Network::TransportSocketFactoryPtr{ new Ssl::ClientSslSocketFactory(std::move(cfg), context_manager, *client_stats_store)}; } +Network::TransportSocketFactoryPtr createUpstreamSslContext(ContextManager& context_manager) { + envoy::api::v2::auth::DownstreamTlsContext tls_context; + auto* common_tls_context = tls_context.mutable_common_tls_context(); + common_tls_context->add_alpn_protocols("h2"); + common_tls_context->add_alpn_protocols("http/1.1"); + common_tls_context->mutable_deprecated_v1()->set_alt_alpn_protocols("http/1.1"); + + auto* validation_context = common_tls_context->mutable_validation_context(); + validation_context->mutable_trusted_ca()->set_filename( + TestEnvironment::runfilesPath("test/config/integration/certs/cacert.pem")); + validation_context->add_verify_certificate_hash( + "E0:F3:C8:CE:5E:2E:A3:05:F0:70:1F:F5:12:E3:6E:2E:" + "97:92:82:84:A2:28:BC:F7:73:32:D3:39:30:A1:B6:FD"); + + auto* tls_certificate = common_tls_context->add_tls_certificates(); + tls_certificate->mutable_certificate_chain()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/servercert.pem")); + tls_certificate->mutable_private_key()->set_filename( + TestEnvironment::runfilesPath("/test/config/integration/certs/serverkey.pem")); + + NiceMock mock_factory_ctx; + auto cfg = std::make_unique(tls_context, mock_factory_ctx); + + static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); + return std::make_unique( + std::move(cfg), context_manager, *upstream_stats_store, std::vector{}); +} + Network::Address::InstanceConstSharedPtr getSslAddress(const Network::Address::IpVersion& version, int port) { std::string url = diff --git a/test/integration/ssl_utility.h b/test/integration/ssl_utility.h index d2ff42561bd4..268004dc756d 100644 --- a/test/integration/ssl_utility.h +++ b/test/integration/ssl_utility.h @@ -9,8 +9,8 @@ namespace Envoy { namespace Ssl { Network::TransportSocketFactoryPtr -createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager, - Secret::SecretManager& secret_manager); +createClientSslTransportSocketFactory(bool alpn, bool san, ContextManager& context_manager); +Network::TransportSocketFactoryPtr createUpstreamSslContext(ContextManager& context_manager); Network::Address::InstanceConstSharedPtr getSslAddress(const Network::Address::IpVersion& version, int port); diff --git a/test/integration/tcp_proxy_integration_test.cc b/test/integration/tcp_proxy_integration_test.cc index 4166a3beb0e2..c8ebe3c43921 100644 --- a/test/integration/tcp_proxy_integration_test.cc +++ b/test/integration/tcp_proxy_integration_test.cc @@ -12,10 +12,10 @@ #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::MatchesRegex; using testing::NiceMock; -using testing::_; namespace Envoy { namespace { @@ -383,8 +383,7 @@ void TcpProxySslIntegrationTest::setupConnections() { // Set up the SSl client. Network::Address::InstanceConstSharedPtr address = Ssl::getSslAddress(version_, lookupPort("tcp_proxy")); - context_ = - Ssl::createClientSslTransportSocketFactory(false, false, *context_manager_, secret_manager_); + context_ = Ssl::createClientSslTransportSocketFactory(false, false, *context_manager_); ssl_client_ = dispatcher_->createClientConnection(address, Network::Address::InstanceConstSharedPtr(), context_->createTransportSocket(), nullptr); diff --git a/test/integration/tcp_proxy_integration_test.h b/test/integration/tcp_proxy_integration_test.h index 9c75ee45fd92..b136c51c8bc5 100644 --- a/test/integration/tcp_proxy_integration_test.h +++ b/test/integration/tcp_proxy_integration_test.h @@ -41,7 +41,6 @@ class TcpProxySslIntegrationTest : public TcpProxyIntegrationTest { ConnectionStatusCallbacks connect_callbacks_; MockWatermarkBuffer* client_write_buffer_; std::shared_ptr payload_reader_; - testing::NiceMock secret_manager_; }; } // namespace diff --git a/test/integration/xfcc_integration_test.cc b/test/integration/xfcc_integration_test.cc index e4d7c0903979..0d81e51bfa8d 100644 --- a/test/integration/xfcc_integration_test.cc +++ b/test/integration/xfcc_integration_test.cc @@ -61,7 +61,7 @@ Network::TransportSocketFactoryPtr XfccIntegrationTest::createClientSslContext(b target = json_tls; } Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(target); - auto cfg = std::make_unique(*loader, secret_manager_); + auto cfg = std::make_unique(*loader, factory_context_); static auto* client_stats_store = new Stats::TestIsolatedStoreImpl(); return Network::TransportSocketFactoryPtr{ new Ssl::ClientSslSocketFactory(std::move(cfg), *context_manager_, *client_stats_store)}; @@ -76,7 +76,7 @@ Network::TransportSocketFactoryPtr XfccIntegrationTest::createUpstreamSslContext )EOF"; Json::ObjectSharedPtr loader = TestEnvironment::jsonLoadFromString(json); - auto cfg = std::make_unique(*loader, secret_manager_); + auto cfg = std::make_unique(*loader, factory_context_); static Stats::Scope* upstream_stats_store = new Stats::TestIsolatedStoreImpl(); return std::make_unique( std::move(cfg), *context_manager_, *upstream_stats_store, std::vector{}); diff --git a/test/integration/xfcc_integration_test.h b/test/integration/xfcc_integration_test.h index e762b1720f41..d8302ea05816 100644 --- a/test/integration/xfcc_integration_test.h +++ b/test/integration/xfcc_integration_test.h @@ -6,7 +6,7 @@ #include "test/integration/http_integration.h" #include "test/integration/server.h" #include "test/mocks/runtime/mocks.h" -#include "test/mocks/secret/mocks.h" +#include "test/mocks/server/mocks.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -56,7 +56,7 @@ class XfccIntegrationTest : public HttpIntegrationTest, Network::TransportSocketFactoryPtr client_tls_ssl_ctx_; Network::TransportSocketFactoryPtr client_mtls_ssl_ctx_; Network::TransportSocketFactoryPtr upstream_ssl_ctx_; - testing::NiceMock secret_manager_; + testing::NiceMock factory_context_; }; } // namespace Xfcc } // namespace Envoy diff --git a/test/mocks/access_log/mocks.cc b/test/mocks/access_log/mocks.cc index 70784ddada35..6f7edb0232aa 100644 --- a/test/mocks/access_log/mocks.cc +++ b/test/mocks/access_log/mocks.cc @@ -3,9 +3,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace AccessLog { diff --git a/test/mocks/api/mocks.cc b/test/mocks/api/mocks.cc index 6373bf33d661..2a577efed115 100644 --- a/test/mocks/api/mocks.cc +++ b/test/mocks/api/mocks.cc @@ -6,8 +6,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Return; using testing::_; +using testing::Return; namespace Envoy { namespace Api { diff --git a/test/mocks/event/mocks.cc b/test/mocks/event/mocks.cc index 402d25b17a87..59d724f85e4d 100644 --- a/test/mocks/event/mocks.cc +++ b/test/mocks/event/mocks.cc @@ -3,12 +3,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnNew; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Event { diff --git a/test/mocks/http/mocks.cc b/test/mocks/http/mocks.cc index eeac8a672369..5527abab5ee9 100644 --- a/test/mocks/http/mocks.cc +++ b/test/mocks/http/mocks.cc @@ -6,11 +6,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Http { diff --git a/test/mocks/init/mocks.cc b/test/mocks/init/mocks.cc index c8ddb6b96ca9..ce0cb291ebca 100644 --- a/test/mocks/init/mocks.cc +++ b/test/mocks/init/mocks.cc @@ -5,8 +5,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Init { diff --git a/test/mocks/network/mocks.cc b/test/mocks/network/mocks.cc index 31fba7361201..43ade3273e44 100644 --- a/test/mocks/network/mocks.cc +++ b/test/mocks/network/mocks.cc @@ -13,12 +13,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Network { diff --git a/test/mocks/request_info/mocks.cc b/test/mocks/request_info/mocks.cc index e034c1e82d5c..868422743c68 100644 --- a/test/mocks/request_info/mocks.cc +++ b/test/mocks/request_info/mocks.cc @@ -5,11 +5,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace RequestInfo { diff --git a/test/mocks/router/mocks.cc b/test/mocks/router/mocks.cc index e4afcf3d5343..643f191d70db 100644 --- a/test/mocks/router/mocks.cc +++ b/test/mocks/router/mocks.cc @@ -5,12 +5,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Router { diff --git a/test/mocks/runtime/mocks.cc b/test/mocks/runtime/mocks.cc index 956b5474e597..56f299b4d389 100644 --- a/test/mocks/runtime/mocks.cc +++ b/test/mocks/runtime/mocks.cc @@ -3,9 +3,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Return; using testing::ReturnArg; -using testing::_; namespace Envoy { namespace Runtime { diff --git a/test/mocks/secret/BUILD b/test/mocks/secret/BUILD index e01f07aaae59..43fc682bb7da 100644 --- a/test/mocks/secret/BUILD +++ b/test/mocks/secret/BUILD @@ -13,7 +13,9 @@ envoy_cc_mock( srcs = ["mocks.cc"], hdrs = ["mocks.h"], deps = [ + "//include/envoy/secret:secret_callbacks_interface", "//include/envoy/secret:secret_manager_interface", + "//include/envoy/server:transport_socket_config_interface", "//include/envoy/ssl:tls_certificate_config_interface", "//source/common/secret:secret_provider_impl_lib", ], diff --git a/test/mocks/secret/mocks.cc b/test/mocks/secret/mocks.cc index 48b788874a66..7461830a5693 100644 --- a/test/mocks/secret/mocks.cc +++ b/test/mocks/secret/mocks.cc @@ -2,8 +2,8 @@ #include "common/secret/secret_provider_impl.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace Secret { @@ -17,5 +17,9 @@ MockSecretManager::MockSecretManager() { MockSecretManager::~MockSecretManager() {} +MockSecretCallbacks::MockSecretCallbacks() {} + +MockSecretCallbacks::~MockSecretCallbacks() {} + } // namespace Secret } // namespace Envoy diff --git a/test/mocks/secret/mocks.h b/test/mocks/secret/mocks.h index 212cc8985cbb..739b940fccfe 100644 --- a/test/mocks/secret/mocks.h +++ b/test/mocks/secret/mocks.h @@ -1,6 +1,7 @@ #pragma once #include "envoy/secret/secret_manager.h" +#include "envoy/server/transport_socket_config.h" #include "envoy/ssl/tls_certificate_config.h" #include "gmock/gmock.h" @@ -20,6 +21,17 @@ class MockSecretManager : public SecretManager { MOCK_METHOD1(createInlineTlsCertificateProvider, TlsCertificateConfigProviderSharedPtr( const envoy::api::v2::auth::TlsCertificate& tls_certificate)); + MOCK_METHOD3(findOrCreateDynamicSecretProvider, + TlsCertificateConfigProviderSharedPtr( + const envoy::api::v2::core::ConfigSource&, const std::string&, + Server::Configuration::TransportSocketFactoryContext&)); +}; + +class MockSecretCallbacks : public SecretCallbacks { +public: + MockSecretCallbacks(); + ~MockSecretCallbacks(); + MOCK_METHOD0(onAddOrUpdateSecret, void()); }; } // namespace Secret diff --git a/test/mocks/server/mocks.cc b/test/mocks/server/mocks.cc index 65c55ba9f6e7..72628f6ab835 100644 --- a/test/mocks/server/mocks.cc +++ b/test/mocks/server/mocks.cc @@ -7,13 +7,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnNew; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Server { @@ -164,7 +164,9 @@ MockFactoryContext::MockFactoryContext() : singleton_manager_(new Singleton::Man MockFactoryContext::~MockFactoryContext() {} -MockTransportSocketFactoryContext::MockTransportSocketFactoryContext() {} +MockTransportSocketFactoryContext::MockTransportSocketFactoryContext() + : secret_manager_(new Secret::SecretManagerImpl()) {} + MockTransportSocketFactoryContext::~MockTransportSocketFactoryContext() {} MockListenerFactoryContext::MockListenerFactoryContext() {} diff --git a/test/mocks/server/mocks.h b/test/mocks/server/mocks.h index 3058a6cb0e2c..d984db2fe8bd 100644 --- a/test/mocks/server/mocks.h +++ b/test/mocks/server/mocks.h @@ -425,14 +425,19 @@ class MockTransportSocketFactoryContext : public TransportSocketFactoryContext { MockTransportSocketFactoryContext(); ~MockTransportSocketFactoryContext(); + Secret::SecretManager& secretManager() override { return *(secret_manager_.get()); } + MOCK_METHOD0(sslContextManager, Ssl::ContextManager&()); MOCK_CONST_METHOD0(statsScope, Stats::Scope&()); MOCK_METHOD0(clusterManager, Upstream::ClusterManager&()); - MOCK_METHOD0(secretManager, Secret::SecretManager&()); MOCK_METHOD0(localInfo, const LocalInfo::LocalInfo&()); MOCK_METHOD0(dispatcher, Event::Dispatcher&()); MOCK_METHOD0(random, Envoy::Runtime::RandomGenerator&()); MOCK_METHOD0(stats, Stats::Store&()); + MOCK_METHOD1(setInitManager, void(Init::Manager&)); + MOCK_METHOD0(initManager, Init::Manager*()); + + std::unique_ptr secret_manager_; }; class MockListenerFactoryContext : public virtual MockFactoryContext, diff --git a/test/mocks/stats/mocks.cc b/test/mocks/stats/mocks.cc index 9ec20c8dec6c..d2269d308f73 100644 --- a/test/mocks/stats/mocks.cc +++ b/test/mocks/stats/mocks.cc @@ -3,12 +3,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Stats { diff --git a/test/mocks/tcp/mocks.cc b/test/mocks/tcp/mocks.cc index 1374d415dea7..d9ffcc2f79e7 100644 --- a/test/mocks/tcp/mocks.cc +++ b/test/mocks/tcp/mocks.cc @@ -4,9 +4,9 @@ using testing::ReturnRef; +using testing::_; using testing::Invoke; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Tcp { diff --git a/test/mocks/tcp/mocks.h b/test/mocks/tcp/mocks.h index 3fb969f088b2..8abd46bf6188 100644 --- a/test/mocks/tcp/mocks.h +++ b/test/mocks/tcp/mocks.h @@ -44,6 +44,10 @@ class MockConnectionData : public ConnectionData { // Tcp::ConnectionPool::ConnectionData MOCK_METHOD0(connection, Network::ClientConnection&()); MOCK_METHOD1(addUpstreamCallbacks, void(ConnectionPool::UpstreamCallbacks&)); + void setConnectionState(ConnectionStatePtr&& state) override { setConnectionState_(state); } + MOCK_METHOD0(connectionState, ConnectionPool::ConnectionState*()); + + MOCK_METHOD1(setConnectionState_, void(ConnectionPool::ConnectionStatePtr& state)); // If set, invoked in ~MockConnectionData, which indicates that the connection pool // caller has relased a connection. diff --git a/test/mocks/thread_local/mocks.cc b/test/mocks/thread_local/mocks.cc index 6c40f98875f0..cfabd7a7f52f 100644 --- a/test/mocks/thread_local/mocks.cc +++ b/test/mocks/thread_local/mocks.cc @@ -3,8 +3,8 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -using testing::Invoke; using testing::_; +using testing::Invoke; namespace Envoy { namespace ThreadLocal { diff --git a/test/mocks/upstream/cluster_info.cc b/test/mocks/upstream/cluster_info.cc index b0b45f0f26b3..da27d7c4357a 100644 --- a/test/mocks/upstream/cluster_info.cc +++ b/test/mocks/upstream/cluster_info.cc @@ -3,11 +3,11 @@ #include "common/network/raw_buffer_socket.h" #include "common/upstream/upstream_impl.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/mocks/upstream/host.cc b/test/mocks/upstream/host.cc index 71d7df2efe9d..6bd306c87aae 100644 --- a/test/mocks/upstream/host.cc +++ b/test/mocks/upstream/host.cc @@ -2,10 +2,10 @@ #include "common/network/utility.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/mocks/upstream/mocks.cc b/test/mocks/upstream/mocks.cc index b487c0b16fc1..5be57cff244c 100644 --- a/test/mocks/upstream/mocks.cc +++ b/test/mocks/upstream/mocks.cc @@ -8,12 +8,12 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Upstream { diff --git a/test/server/connection_handler_test.cc b/test/server/connection_handler_test.cc index b40ee8ad1e5b..746aae1dba44 100644 --- a/test/server/connection_handler_test.cc +++ b/test/server/connection_handler_test.cc @@ -14,13 +14,13 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::ByRef; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Server { @@ -90,7 +90,6 @@ TEST_F(ConnectionHandlerTest, RemoveListener) { [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { listener_callbacks = &cb; return listener; - })); TestListener* test_listener = addListener(1, true, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); @@ -127,7 +126,6 @@ TEST_F(ConnectionHandlerTest, DestroyCloseConnections) { [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { listener_callbacks = &cb; return listener; - })); TestListener* test_listener = addListener(1, true, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); @@ -153,7 +151,6 @@ TEST_F(ConnectionHandlerTest, CloseDuringFilterChainCreate) { [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { listener_callbacks = &cb; return listener; - })); TestListener* test_listener = addListener(1, true, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); @@ -182,7 +179,6 @@ TEST_F(ConnectionHandlerTest, CloseConnectionOnEmptyFilterChain) { [&](Network::Socket&, Network::ListenerCallbacks& cb, bool, bool) -> Network::Listener* { listener_callbacks = &cb; return listener; - })); TestListener* test_listener = addListener(1, true, false, "test_listener"); EXPECT_CALL(test_listener->socket_, localAddress()); diff --git a/test/server/drain_manager_impl_test.cc b/test/server/drain_manager_impl_test.cc index 207e3d6debaf..29ba7fd65991 100644 --- a/test/server/drain_manager_impl_test.cc +++ b/test/server/drain_manager_impl_test.cc @@ -7,10 +7,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Return; using testing::SaveArg; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/hot_restart_impl_test.cc b/test/server/hot_restart_impl_test.cc index c5ed4e40fd6e..b9a2d6b5cea1 100644 --- a/test/server/hot_restart_impl_test.cc +++ b/test/server/hot_restart_impl_test.cc @@ -12,12 +12,12 @@ #include "absl/strings/string_view.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::Return; using testing::ReturnRef; using testing::WithArg; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/http/admin_test.cc b/test/server/http/admin_test.cc index f237fc30ff86..def04abb45d2 100644 --- a/test/server/http/admin_test.cc +++ b/test/server/http/admin_test.cc @@ -26,6 +26,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::HasSubstr; using testing::InSequence; using testing::Invoke; @@ -34,7 +35,6 @@ using testing::Ref; using testing::Return; using testing::ReturnPointee; using testing::ReturnRef; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/init_manager_impl_test.cc b/test/server/init_manager_impl_test.cc index 530e67df30cd..afaa2e44a017 100644 --- a/test/server/init_manager_impl_test.cc +++ b/test/server/init_manager_impl_test.cc @@ -5,9 +5,9 @@ #include "gmock/gmock.h" +using testing::_; using testing::InSequence; using testing::Invoke; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/lds_api_test.cc b/test/server/lds_api_test.cc index 906cfd920d22..7c39a8235e30 100644 --- a/test/server/lds_api_test.cc +++ b/test/server/lds_api_test.cc @@ -11,11 +11,11 @@ #include "gmock/gmock.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::Return; using testing::Throw; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/listener_manager_impl_test.cc b/test/server/listener_manager_impl_test.cc index 4c113784eddf..aba15f05284c 100644 --- a/test/server/listener_manager_impl_test.cc +++ b/test/server/listener_manager_impl_test.cc @@ -26,13 +26,13 @@ #include "absl/strings/match.h" #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::NiceMock; using testing::Return; using testing::ReturnRef; using testing::Throw; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/overload_manager_impl_test.cc b/test/server/overload_manager_impl_test.cc index 3d3b5f37cabc..a4c8fd67794b 100644 --- a/test/server/overload_manager_impl_test.cc +++ b/test/server/overload_manager_impl_test.cc @@ -15,9 +15,9 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::NiceMock; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/server_test.cc b/test/server/server_test.cc index a682d3184ae6..b6726ed75ca5 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -12,6 +12,7 @@ #include "gtest/gtest.h" +using testing::_; using testing::HasSubstr; using testing::InSequence; using testing::Invoke; @@ -20,7 +21,6 @@ using testing::Property; using testing::Ref; using testing::SaveArg; using testing::StrictMock; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/server/worker_impl_test.cc b/test/server/worker_impl_test.cc index 6a73bf302cff..50a2d7fff083 100644 --- a/test/server/worker_impl_test.cc +++ b/test/server/worker_impl_test.cc @@ -9,13 +9,13 @@ #include "gtest/gtest.h" +using testing::_; using testing::InSequence; using testing::Invoke; using testing::InvokeWithoutArgs; using testing::NiceMock; using testing::Return; using testing::Throw; -using testing::_; namespace Envoy { namespace Server { diff --git a/test/test_common/utility.h b/test/test_common/utility.h index c27d4be9319f..3300c44678c0 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -25,11 +25,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +using testing::_; using testing::AssertionFailure; using testing::AssertionResult; using testing::AssertionSuccess; using testing::Invoke; -using testing::_; namespace Envoy { #define EXPECT_THROW_WITH_MESSAGE(statement, expected_exception, message) \ diff --git a/tools/check_format.py b/tools/check_format.py index 5cd498832baa..c9e8fc243535 100755 --- a/tools/check_format.py +++ b/tools/check_format.py @@ -23,7 +23,7 @@ GOOGLE_PROTOBUF_WHITELIST = ("ci/prebuilt", "source/common/protobuf", "api/test") REPOSITORIES_BZL = "bazel/repositories.bzl" -CLANG_FORMAT_PATH = os.getenv("CLANG_FORMAT", "clang-format-5.0") +CLANG_FORMAT_PATH = os.getenv("CLANG_FORMAT", "clang-format-6.0") BUILDIFIER_PATH = os.getenv("BUILDIFIER_BIN", "$GOPATH/bin/buildifier") ENVOY_BUILD_FIXER_PATH = os.path.join( os.path.dirname(os.path.abspath(sys.argv[0])), "envoy_build_fixer.py")