From 2c7edc491b6e5b0e4a9fa76b5f3aa647f41eb1af Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 14 Dec 2023 08:42:32 -0500 Subject: [PATCH 001/126] mobile: adding some more lifetime tests (#31313) Signed-off-by: Alyssa Wilk --- .../integration/client_integration_test.cc | 59 +++++++++++++++++-- test/integration/autonomous_upstream.cc | 13 +++- test/integration/autonomous_upstream.h | 3 + 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 61e4f326be56..a524b6d8cfc7 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -142,7 +142,7 @@ class ClientIntegrationTest void basicTest(); void trickleTest(); - void explicitFlowControlWithCancels(); + void explicitFlowControlWithCancels(uint32_t body_size = 1000); static std::string protocolToString(Http::CodecType type) { if (type == Http::CodecType::HTTP3) { @@ -344,8 +344,9 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { ASSERT_EQ(num_requests, cc_.on_complete_calls); } -void ClientIntegrationTest::explicitFlowControlWithCancels() { - default_request_headers_.addCopy(AutonomousStream::RESPONSE_SIZE_BYTES, std::to_string(1000)); +void ClientIntegrationTest::explicitFlowControlWithCancels(uint32_t body_size) { + default_request_headers_.addCopy(AutonomousStream::RESPONSE_SIZE_BYTES, + std::to_string(body_size)); uint32_t num_requests = 100; std::vector prototype_streams; @@ -405,6 +406,12 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancels) { explicitFlowControlWithCancels(); } +TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancelsAfterComplete) { + explicit_flow_control_ = true; + initialize(); + explicitFlowControlWithCancels(100); +} + TEST_P(ClientIntegrationTest, ClearTextNotPermitted) { if (getCodecType() != Http::CodecType::HTTP1) { return; @@ -500,6 +507,17 @@ TEST_P(ClientIntegrationTest, BasicNon2xx) { ASSERT_EQ(cc_.on_complete_calls, 1); } +TEST_P(ClientIntegrationTest, InvalidDomain) { + initialize(); + + default_request_headers_.setHost("www.doesnotexist.com"); + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_error_calls, 1); + ASSERT_EQ(cc_.on_headers_calls, 0); +} + TEST_P(ClientIntegrationTest, BasicReset) { initialize(); @@ -512,7 +530,40 @@ TEST_P(ClientIntegrationTest, BasicReset) { ASSERT_EQ(cc_.on_headers_calls, 0); } -TEST_P(ClientIntegrationTest, BasicCancel) { +TEST_P(ClientIntegrationTest, CancelBeforeRequestHeadersSent) { + autonomous_upstream_ = false; + initialize(); + ConditionalInitializer headers_callback; + + stream_->cancel(); + + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_cancel_calls, 1); +} + +TEST_P(ClientIntegrationTest, CancelAfterRequestHeadersSent) { + initialize(); + + default_request_headers_.addCopy(AutonomousStream::RESPOND_AFTER_REQUEST_HEADERS, "yes"); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), false); + stream_->cancel(); + terminal_callback_.waitReady(); + ASSERT_EQ(cc_.on_cancel_calls, 1); +} + +TEST_P(ClientIntegrationTest, CancelAfterRequestComplete) { + autonomous_upstream_ = false; + initialize(); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + stream_->cancel(); + terminal_callback_.waitReady(); + ASSERT_EQ(cc_.on_cancel_calls, 1); +} + +TEST_P(ClientIntegrationTest, CancelDuringResponse) { autonomous_upstream_ = false; initialize(); ConditionalInitializer headers_callback; diff --git a/test/integration/autonomous_upstream.cc b/test/integration/autonomous_upstream.cc index 97b714e29233..94ae18094589 100644 --- a/test/integration/autonomous_upstream.cc +++ b/test/integration/autonomous_upstream.cc @@ -24,6 +24,7 @@ const char AutonomousStream::RESET_AFTER_REQUEST[] = "reset_after_request"; const char AutonomousStream::CLOSE_AFTER_RESPONSE[] = "close_after_response"; const char AutonomousStream::NO_TRAILERS[] = "no_trailers"; const char AutonomousStream::NO_END_STREAM[] = "no_end_stream"; +const char AutonomousStream::RESPOND_AFTER_REQUEST_HEADERS[] = "respond_after_request_headers"; AutonomousStream::AutonomousStream(FakeHttpConnection& parent, Http::ResponseEncoder& encoder, AutonomousUpstream& upstream, bool allow_incomplete_streams) @@ -36,10 +37,20 @@ AutonomousStream::~AutonomousStream() { } } +void AutonomousStream::decodeHeaders(Http::RequestHeaderMapSharedPtr&& headers, bool end_stream) { + bool send_response = !headers->get(Http::LowerCaseString(RESPOND_AFTER_REQUEST_HEADERS)).empty(); + FakeStream::decodeHeaders(std::move(headers), end_stream); + + if (send_response) { + absl::MutexLock lock(&lock_); + sendResponse(); + } +} + // By default, automatically send a response when the request is complete. void AutonomousStream::setEndStream(bool end_stream) { FakeStream::setEndStream(end_stream); - if (end_stream) { + if (end_stream && headers_->get(Http::LowerCaseString(RESPOND_AFTER_REQUEST_HEADERS)).empty()) { sendResponse(); } } diff --git a/test/integration/autonomous_upstream.h b/test/integration/autonomous_upstream.h index 9ee0c857c4c5..4d1dd9671bd7 100644 --- a/test/integration/autonomous_upstream.h +++ b/test/integration/autonomous_upstream.h @@ -27,12 +27,15 @@ class AutonomousStream : public FakeStream { static const char NO_END_STREAM[]; // Closes the underlying connection after a given response is sent. static const char CLOSE_AFTER_RESPONSE[]; + // Send the response after the request headers are received. + static const char RESPOND_AFTER_REQUEST_HEADERS[]; AutonomousStream(FakeHttpConnection& parent, Http::ResponseEncoder& encoder, AutonomousUpstream& upstream, bool allow_incomplete_streams); ~AutonomousStream() override; void setEndStream(bool set) ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) override; + void decodeHeaders(Http::RequestHeaderMapSharedPtr&& headers, bool end_stream) override; private: AutonomousUpstream& upstream_; From f7ef1eeca94f714f0d48af3dd8a43757dc63d770 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Thu, 14 Dec 2023 11:40:05 -0500 Subject: [PATCH 002/126] tls: Account for a change in BoringSSL verify depth semantics (#31287) Prior to OpenSSL 1.1.0, the certificate depth limit in OpenSSL omitted the leaf but included the trust anchor. That is, if your chain was Leaf, Intermediate, Root, any depth limit of 2 or more allowed the certificate. OpenSSL 1.1.0 included d9b8b89bec4480de3a10bdaf9425db371c19145b, which was described as a cleanup change to X509_verify_cert. However, this change the semantics of the depth limit to omit *both* the leaf and trust anchor. So the example above was accepted also at depth limit 1. This is also why common.proto had a comment about different semantics between the libraries. BoringSSL originally forked a little before 1.0.2, so it had the older OpenSSL behavior. Now that the new behavior has been in OpenSSL upstream for a while, BoringSSL plans to match the new behavior in https://boringssl-review.googlesource.com/c/boringssl/+/64707/ This change makes Envoy compatible with BoringSSLs before and after that change. When BORINGSSL_API_VERSION is new enough, we adjust the value before passing it in, to preserve the original semantics. I'm assuming here that Envoy would prefer to maintain its existing semantics, rather than change the test expectation. I've also removed the comment about backend-specific behavior difference. Supposing Envoy prefers to maintain existing semantics, any OpenSSL port of Envoy should similarly adjust the value on OpenSSL 1.1.0 and up. Along the way, fix an overflow. maxVerifyDepth is a uint32_t, but the OpenSSL API takes an int. When we exceed INT_MAX, saturate the cast. Signed-off-by: David Benjamin --- .../extensions/transport_sockets/tls/v3/common.proto | 10 ++++------ .../tls/cert_validator/default_validator.cc | 12 +++++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/api/envoy/extensions/transport_sockets/tls/v3/common.proto b/api/envoy/extensions/transport_sockets/tls/v3/common.proto index 753dcb49ba02..d244adcdf549 100644 --- a/api/envoy/extensions/transport_sockets/tls/v3/common.proto +++ b/api/envoy/extensions/transport_sockets/tls/v3/common.proto @@ -536,12 +536,10 @@ message CertificateValidationContext { bool only_verify_leaf_cert_crl = 14; // Defines maximum depth of a certificate chain accepted in verification, the default limit is 100, though this can be system-dependent. - // This number does not include the leaf, so a depth of 1 allows the leaf and one CA certificate. If a trusted issuer appears in the chain, - // but in a depth larger than configured, the certificate validation will fail. - // See `BoringSSL SSL_CTX_set_verify_depth `_ - // If you use OpenSSL, its behavior is different from BoringSSL, this will define a limit on the number of certificates between the end-entity and trust-anchor certificates. - // Neither the end-entity nor the trust-anchor certificates count against depth. - // See `OpenSSL SSL set_verify_depth `_. + // This number does not include the leaf but includes the trust anchor, so a depth of 1 allows the leaf and one CA certificate. If a trusted issuer + // appears in the chain, but in a depth larger than configured, the certificate validation will fail. + // This matches the semantics of ``SSL_CTX_set_verify_depth`` in OpenSSL 1.0.x and older versions of BoringSSL. It differs from ``SSL_CTX_set_verify_depth`` + // in OpenSSL 1.1.x and newer versions of BoringSSL in that the trust anchor is included. // Trusted issues are specified by setting :ref:`trusted_ca ` google.protobuf.UInt32Value max_verify_depth = 16 [(validate.rules).uint32 = {lte: 100}]; } diff --git a/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc b/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc index ffd5f94c6126..138578d1b839 100644 --- a/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc +++ b/source/extensions/transport_sockets/tls/cert_validator/default_validator.cc @@ -1,6 +1,8 @@ #include "source/extensions/transport_sockets/tls/cert_validator/default_validator.h" +#include #include +#include #include #include #include @@ -530,7 +532,15 @@ void DefaultCertValidator::addClientValidationContext(SSL_CTX* ctx, bool require } // Set the verify_depth if (config_->maxVerifyDepth().has_value()) { - SSL_CTX_set_verify_depth(ctx, config_->maxVerifyDepth().value()); + uint32_t max_verify_depth = std::min(config_->maxVerifyDepth().value(), uint32_t{INT_MAX}); +#if BORINGSSL_API_VERSION >= 29 + // Older BoringSSLs behave like OpenSSL 1.0.x and exclude the leaf from the + // depth but include the trust anchor. Newer BoringSSLs match OpenSSL 1.1.x + // and later in excluding both the leaf and trust anchor. `maxVerifyDepth` + // documents the older behavior, so adjust the value to match. + max_verify_depth = max_verify_depth > 0 ? max_verify_depth - 1 : 0; +#endif + SSL_CTX_set_verify_depth(ctx, static_cast(max_verify_depth)); } } From 6d5d7550cf0a91e609fc4b1bf7a1494e1a0b7a59 Mon Sep 17 00:00:00 2001 From: Tony Allen Date: Thu, 14 Dec 2023 10:34:31 -0800 Subject: [PATCH 003/126] test: Add a LB simulation test to validate selection probabilities (#30818) Signed-off-by: Kuat Yessenov Signed-off-by: Tony Allen Co-authored-by: Kuat Yessenov --- .../load_balancing/load_balancers.rst | 7 +- .../upstream/load_balancer_simulation_test.cc | 136 ++++++++++++++---- 2 files changed, 116 insertions(+), 27 deletions(-) diff --git a/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst b/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst index e99fe65b231c..3dac22ac4519 100644 --- a/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst +++ b/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst @@ -36,9 +36,10 @@ same or different weights. host which has the fewest active requests (`Mitzenmacher et al. `_ has shown that this approach is nearly as good as an O(N) full scan). This is also known as P2C (power of two - choices). The P2C load balancer has the property that a host with the highest number of active - requests in the cluster will never receive new requests. It will be allowed to drain until it is - less than or equal to all of the other hosts. + choices). The P2C load balancer has the property that host weights will decrease as the number of + active requests on those hosts increases. P2C selection is particularly useful for load + balancer implementations due to its resistance to + [herding behavior](https://en.wikipedia.org/wiki/Thundering_herd_problem). * *all weights not equal*: If two or more hosts in the cluster have different load balancing weights, the load balancer shifts into a mode where it uses a weighted round robin schedule in which weights are dynamically adjusted based on the host's request load at the time of selection. diff --git a/test/common/upstream/load_balancer_simulation_test.cc b/test/common/upstream/load_balancer_simulation_test.cc index 22c1f175b44d..1ec475438a88 100644 --- a/test/common/upstream/load_balancer_simulation_test.cc +++ b/test/common/upstream/load_balancer_simulation_test.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -41,27 +42,58 @@ static HostSharedPtr newTestHost(Upstream::ClusterInfoConstSharedPtr cluster, envoy::config::core::v3::UNKNOWN, time_source)}; } -// Simulate weighted LR load balancer. -TEST(DISABLED_LeastRequestLoadBalancerWeightTest, Weight) { - const uint64_t num_hosts = 4; - const uint64_t weighted_subset_percent = 50; - const uint64_t weight = 2; // weighted_subset_percent of hosts will have this weight. - const uint64_t active_requests = 3; // weighted_subset_percent will have this active requests. +// Defines parameters for LeastRequestLoadBalancerWeightTest cases. +struct LRLBTestParams { + // The total number of hosts. + uint64_t num_hosts; + + // Number of hosts that are part of the subset. + uint64_t num_subset_hosts; + + // The weight assigned to each subset host. + uint64_t weight; + + // The number of active requests each subset host will be loaded with. + uint64_t active_request_count; + + // An unordered collection of expected selection probabilities for the hosts. The test will simply + // sort the expected and observed selection probabilities and verify each element is within some + // expected tolerance. Therefore, the vector does not need to be sorted. + std::vector expected_selection_probs; +}; + +void leastRequestLBWeightTest(LRLBTestParams params) { + constexpr uint64_t num_requests = 100000; + + // Observed selection probabilities must be within tolerance_pct of the expected to pass the test. + // The expected range is [0,100). + constexpr double tolerance_pct = 1.0; + + // Validate params. + ASSERT_GT(params.num_hosts, 0); + ASSERT_LE(params.num_subset_hosts, params.num_hosts); + ASSERT_GT(params.weight, 0); + ASSERT_EQ(params.expected_selection_probs.size(), params.num_hosts); + ASSERT_LT(tolerance_pct, 100); + ASSERT_GE(tolerance_pct, 0); - PrioritySetImpl priority_set; - std::shared_ptr info_{new NiceMock()}; NiceMock time_source_; HostVector hosts; - for (uint64_t i = 0; i < num_hosts; i++) { - const bool should_weight = i < num_hosts * (weighted_subset_percent / 100.0); - hosts.push_back(makeTestHost(info_, fmt::format("tcp://10.0.{}.{}:6379", i / 256, i % 256), - time_source_, should_weight ? weight : 1)); + absl::node_hash_map host_hits; + std::shared_ptr info{new NiceMock()}; + for (uint64_t i = 0; i < params.num_hosts; i++) { + const bool should_weight = i < params.num_subset_hosts; + auto hostPtr = makeTestHost(info, fmt::format("tcp://10.0.{}.{}:6379", i / 256, i % 256), + time_source_, should_weight ? params.weight : 1); + host_hits[hostPtr] = 0; + hosts.push_back(hostPtr); if (should_weight) { - hosts.back()->stats().rq_active_.set(active_requests); + hosts.back()->stats().rq_active_.set(params.active_request_count); } } HostVectorConstSharedPtr updated_hosts{new HostVector(hosts)}; HostsPerLocalitySharedPtr updated_locality_hosts{new HostsPerLocalityImpl(hosts)}; + PrioritySetImpl priority_set; priority_set.updateHosts( 0, updateHostsParams(updated_hosts, updated_locality_hosts, @@ -81,26 +113,82 @@ TEST(DISABLED_LeastRequestLoadBalancerWeightTest, Weight) { priority_set, nullptr, lb_stats, runtime, random, common_config, least_request_lb_config, *time_source}; - absl::node_hash_map host_hits; - const uint64_t total_requests = 100; - for (uint64_t i = 0; i < total_requests; i++) { + for (uint64_t i = 0; i < num_requests; i++) { host_hits[lb_.chooseHost(nullptr)]++; } - absl::node_hash_map weight_to_percent; + std::vector observed_pcts; for (const auto& host : host_hits) { - std::cout << fmt::format("url:{}, weight:{}, hits:{}, percent_of_total:{}\n", - host.first->address()->asString(), host.first->weight(), host.second, - (static_cast(host.second) / total_requests) * 100); - weight_to_percent[host.first->weight()] += - (static_cast(host.second) / total_requests) * 100; + observed_pcts.push_back((static_cast(host.second) / num_requests) * 100); } - for (const auto& weight : weight_to_percent) { - std::cout << fmt::format("weight:{}, percent:{}\n", weight.first, weight.second); + std::sort(observed_pcts.begin(), observed_pcts.end()); + std::sort(params.expected_selection_probs.begin(), params.expected_selection_probs.end()); + ASSERT_EQ(observed_pcts.size(), params.expected_selection_probs.size()); + for (uint64_t i = 0; i < observed_pcts.size(); i++) { + EXPECT_NEAR(params.expected_selection_probs[i], observed_pcts[i], tolerance_pct); } } +// Simulate weighted LR load balancer and verify expected selection probabilities. +TEST(LeastRequestLoadBalancerWeightTest, Weight) { + LRLBTestParams params; + + // No active requests or weight differences. This should look like uniform random LB. + params.num_hosts = 3; + params.num_subset_hosts = 1; + params.active_request_count = 0; + params.expected_selection_probs = {33.333, 33.333, 33.333}; + params.weight = 1; + leastRequestLBWeightTest(params); + + // Single host (out of 3) with lots of in-flight requests. Given that P2C will choose 2 hosts and + // take the one with higher weight, the only circumstance that the host with many in-flight + // requests will be picked is if P2C selects it twice. + params.num_hosts = 3; + params.num_subset_hosts = 1; + params.active_request_count = 10; + params.expected_selection_probs = {44.45, 44.45, 11.1}; + params.weight = 1; + leastRequestLBWeightTest(params); + + // Same as above, but with 2 hosts. The busy host will only be chosen if P2C picks it for both + // selections. + params.num_hosts = 2; + params.num_subset_hosts = 1; + params.active_request_count = 10; + params.expected_selection_probs = {25, 75}; + params.weight = 1; + leastRequestLBWeightTest(params); + + // Heterogeneous weights with no active requests. This should behave identically to weighted + // round-robin. + params.num_hosts = 2; + params.num_subset_hosts = 1; + params.active_request_count = 0; + params.expected_selection_probs = {66.66, 33.33}; + params.weight = 2; + leastRequestLBWeightTest(params); + + // Same as above, but we'll scale the subset's weight with active requests. With a default + // active_request_bias of 1.0, the subset host with a single active request will be cut in half, + // making both hosts have an identical weight. + params.num_hosts = 2; + params.num_subset_hosts = 1; + params.active_request_count = 1; + params.expected_selection_probs = {50, 50}; + params.weight = 2; + leastRequestLBWeightTest(params); + + // Same as above, but with 3 hosts. + params.num_hosts = 3; + params.num_subset_hosts = 1; + params.active_request_count = 1; + params.expected_selection_probs = {33.3, 33.3, 33.3}; + params.weight = 2; + leastRequestLBWeightTest(params); +} + /** * This test is for simulation only and should not be run as part of unit tests. */ From 432a03bce9e22b1c8c415ba94d9b0049b576a991 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 10:59:55 +0000 Subject: [PATCH 004/126] build(deps): bump distroless/base-nossl-debian12 from `8a0cabc` to `8c957f0` in /ci (#31389) build(deps): bump distroless/base-nossl-debian12 in /ci Bumps distroless/base-nossl-debian12 from `8a0cabc` to `8c957f0`. --- updated-dependencies: - dependency-name: distroless/base-nossl-debian12 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index adb525bbd469..9902045cbf4f 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -58,7 +58,7 @@ COPY --chown=0:0 --chmod=755 \ # STAGE: envoy-distroless -FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:8a0cabc3a404dfe80725874f4be24ba716c1115693f3a33bdc9565173e84bdfa AS envoy-distroless +FROM gcr.io/distroless/base-nossl-debian12:nonroot@sha256:8c957f0c06030921ee439d028b5778dd1cee9e095092833fe8e4ee795d3a2298 AS envoy-distroless EXPOSE 10000 ENTRYPOINT ["/usr/local/bin/envoy"] CMD ["-c", "/etc/envoy/envoy.yaml"] From ade6a2bc55557b329d40e165f088748b6d1bd07b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:24:49 +0000 Subject: [PATCH 005/126] build(deps): bump actions/download-artifact from 3 to 4 (#31385) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/envoy-windows.yml | 2 +- .github/workflows/mobile-release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/envoy-windows.yml b/.github/workflows/envoy-windows.yml index 21d9a992da25..90ccb62a0616 100644 --- a/.github/workflows/envoy-windows.yml +++ b/.github/workflows/envoy-windows.yml @@ -100,7 +100,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ needs.load.outputs.repo_ref }} - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: windows.release - run: | diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 05c093364cfa..684ddfa6eb8d 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -83,7 +83,7 @@ jobs: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: envoy_android_aar_sources path: . @@ -202,7 +202,7 @@ jobs: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: envoy_xds_android_aar_sources path: . From b435805297075c135a21665d8786eae424d75b43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:25:19 +0000 Subject: [PATCH 006/126] build(deps): bump actions/upload-artifact from 3 to 4 (#31386) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/mobile-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 684ddfa6eb8d..1085df0107b3 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -64,7 +64,7 @@ jobs: bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-sources.jar \ bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-javadoc.jar working-directory: mobile - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: envoy_android_aar_sources path: mobile/envoy_android_aar_sources.tar.gz @@ -183,7 +183,7 @@ jobs: bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-sources.jar \ bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-javadoc.jar working-directory: mobile - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: envoy_xds_android_aar_sources path: mobile/envoy_xds_android_aar_sources.tar.gz From a9978b4bfb94fd44292712fc1fcef5d360c9f7b9 Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 15 Dec 2023 13:33:29 +0000 Subject: [PATCH 007/126] bazel/deps: Shift edenhill/kakfa dep -> confluentinc (#31393) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- tools/dependency/BUILD | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index a988835a5247..4d8f68f5f28f 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1323,17 +1323,17 @@ REPOSITORY_LOCATIONS_SPEC = dict( edenhill_librdkafka = dict( project_name = "Kafka (C/C++ client)", project_desc = "C/C++ client for Apache Kafka (open-source distributed event streaming platform)", - project_url = "https://github.com/edenhill/librdkafka", + project_url = "https://github.com/confluentinc/librdkafka", version = "2.3.0", sha256 = "2d49c35c77eeb3d42fa61c43757fcbb6a206daa560247154e60642bcdcc14d12", strip_prefix = "librdkafka-{version}", - urls = ["https://github.com/edenhill/librdkafka/archive/v{version}.tar.gz"], + urls = ["https://github.com/confluentinc/librdkafka/archive/v{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.filters.network.kafka_mesh"], release_date = "2023-10-25", cpe = "N/A", license = "librdkafka", - license_url = "https://github.com/edenhill/librdkafka/blob/v{version}/LICENSE", + license_url = "https://github.com/confluentinc/librdkafka/blob/v{version}/LICENSE", ), kafka_server_binary = dict( project_name = "Kafka (server binary)", diff --git a/tools/dependency/BUILD b/tools/dependency/BUILD index ff0467298b73..634594c6901a 100644 --- a/tools/dependency/BUILD +++ b/tools/dependency/BUILD @@ -23,10 +23,23 @@ config_setting( }, ) +# Currently we are unable to check for the libdrdkafka dep +# this is a workaround to just exclude it from checks for now +# which is sub-optimal as it also excludes it from CVE scanning +# https://github.com/envoyproxy/envoy/issues/31394 +envoy_genjson( + name = "filtered-dependencies", + filter = """ + .[0] + | del(.edenhill_librdkafka) + """, + srcs = ["//bazel:all_repository_locations"], +) + envoy_entry_point( name = "check", args = [ - "--repository_locations=$(location //bazel:all_repository_locations)", + "--repository_locations=$(location :filtered-dependencies)", "--cve_config=$(location :cve.yaml)", ] + select({ ":preloaded_cve_data": ["--cve_data=$(location :cve_data)"], @@ -34,7 +47,7 @@ envoy_entry_point( }), data = [ ":cve.yaml", - "//bazel:all_repository_locations", + ":filtered-dependencies", ] + select({ ":preloaded_cve_data": [":cve_data"], "//conditions:default": [], From c1e70f70cc8cc71ad917eebed523639c24bc397e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:35:52 +0000 Subject: [PATCH 008/126] build(deps): bump mysql from `6057dec` to `ceb9891` in /examples/mysql (#31390) Bumps mysql from `6057dec` to `ceb9891`. --- updated-dependencies: - dependency-name: mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/mysql/Dockerfile-mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mysql/Dockerfile-mysql b/examples/mysql/Dockerfile-mysql index 9c06218bbacb..ab835ddc7df2 100644 --- a/examples/mysql/Dockerfile-mysql +++ b/examples/mysql/Dockerfile-mysql @@ -1 +1 @@ -FROM mysql:8.2.0@sha256:6057dec95d87a0d7880d9cfc9b3d9292f9c11473a5104b906402a2b73396e377 +FROM mysql:8.2.0@sha256:ceb98918916bd5261b3e9866ac8271d75d276b8a4db56f1dc190770342a77a9b From 2ee74db308b7be541b6f82b8bae958a865792dc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:36:20 +0000 Subject: [PATCH 009/126] build(deps): bump postgres from `a2282ad` to `1f703fa` in /examples/shared/postgres (#31388) build(deps): bump postgres in /examples/shared/postgres Bumps postgres from `a2282ad` to `1f703fa`. --- updated-dependencies: - dependency-name: postgres dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/postgres/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/postgres/Dockerfile b/examples/shared/postgres/Dockerfile index cfafff48b15a..0dfd66a86702 100644 --- a/examples/shared/postgres/Dockerfile +++ b/examples/shared/postgres/Dockerfile @@ -1,3 +1,3 @@ -FROM postgres:latest@sha256:a2282ad0db623c27f03bab803975c9e3942a24e974f07142d5d69b6b8eaaf9e2 +FROM postgres:latest@sha256:1f703fadc8993f74b82a2706712e61208b1f2bc1658f286c5b68970bbf09f0ae COPY docker-healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["docker-healthcheck.sh"] From 54a46aa1538d42498226ada5d76fbeeea4b9ecbf Mon Sep 17 00:00:00 2001 From: phlax Date: Fri, 15 Dec 2023 14:16:02 +0000 Subject: [PATCH 010/126] bazel/updater: Use workaround to filter deps + format fix (#31397) Signed-off-by: Ryan Northey --- bazel/BUILD | 2 +- tools/dependency/BUILD | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bazel/BUILD b/bazel/BUILD index 9b431e41d01d..37eafa57eda1 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -891,7 +891,7 @@ cc_library( updater( name = "update", data = ["//tools/dependency:check"], - dependencies = ":repository_locations", + dependencies = "//tools/dependency:filtered-dependencies", post_script = ":version_update_post.sh", pydict = True, tags = ["skip_on_windows"], diff --git a/tools/dependency/BUILD b/tools/dependency/BUILD index 634594c6901a..ba2106cdac2a 100644 --- a/tools/dependency/BUILD +++ b/tools/dependency/BUILD @@ -29,11 +29,11 @@ config_setting( # https://github.com/envoyproxy/envoy/issues/31394 envoy_genjson( name = "filtered-dependencies", + srcs = ["//bazel:all_repository_locations"], filter = """ .[0] | del(.edenhill_librdkafka) """, - srcs = ["//bazel:all_repository_locations"], ) envoy_entry_point( From e449aac831e3f1780d149878444ccd7e45f23dd5 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Fri, 15 Dec 2023 14:57:24 +0000 Subject: [PATCH 011/126] Revert "build(deps): bump actions/download-artifact from 3 to 4 (#31385)" This reverts commit ade6a2bc55557b329d40e165f088748b6d1bd07b. Signed-off-by: Ryan Northey --- .github/workflows/envoy-windows.yml | 2 +- .github/workflows/mobile-release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/envoy-windows.yml b/.github/workflows/envoy-windows.yml index 90ccb62a0616..21d9a992da25 100644 --- a/.github/workflows/envoy-windows.yml +++ b/.github/workflows/envoy-windows.yml @@ -100,7 +100,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ needs.load.outputs.repo_ref }} - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v3 with: name: windows.release - run: | diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 1085df0107b3..b5e04430c18a 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -83,7 +83,7 @@ jobs: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v3 with: name: envoy_android_aar_sources path: . @@ -202,7 +202,7 @@ jobs: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v3 with: name: envoy_xds_android_aar_sources path: . From 07f0f470c30771dfcc6fb6b140f0c75c6b31e653 Mon Sep 17 00:00:00 2001 From: Ryan Northey Date: Fri, 15 Dec 2023 14:57:40 +0000 Subject: [PATCH 012/126] Revert "build(deps): bump actions/upload-artifact from 3 to 4 (#31386)" This reverts commit b435805297075c135a21665d8786eae424d75b43. Signed-off-by: Ryan Northey --- .github/workflows/mobile-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index b5e04430c18a..05c093364cfa 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -64,7 +64,7 @@ jobs: bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-sources.jar \ bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-javadoc.jar working-directory: mobile - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v3 with: name: envoy_android_aar_sources path: mobile/envoy_android_aar_sources.tar.gz @@ -183,7 +183,7 @@ jobs: bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-sources.jar \ bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-javadoc.jar working-directory: mobile - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v3 with: name: envoy_xds_android_aar_sources path: mobile/envoy_xds_android_aar_sources.tar.gz From c4de046f896375806c7d2405ebeda09c484bfb29 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Fri, 15 Dec 2023 10:25:18 -0500 Subject: [PATCH 013/126] mobile: Add an RTDS integration test with dfp_mixed_scheme (#31364) As part of this change, a new test Runtime was added: TestScopedStaticReloadableFeaturesRuntime. It should be used in build environments, like Envoy Mobile, where the admin layer is not available (which is required by TestScopedRuntime). Signed-off-by: Ali Beyad --- mobile/test/common/integration/BUILD | 1 + .../integration/rtds_integration_test.cc | 111 ++++++++++-------- test/test_common/test_runtime.h | 49 +++++++- 3 files changed, 110 insertions(+), 51 deletions(-) diff --git a/mobile/test/common/integration/BUILD b/mobile/test/common/integration/BUILD index fbfb3f83e1ab..35dd44d664d4 100644 --- a/mobile/test/common/integration/BUILD +++ b/mobile/test/common/integration/BUILD @@ -52,6 +52,7 @@ envoy_cc_test( deps = [ ":xds_integration_test_lib", "@envoy//test/test_common:environment_lib", + "@envoy//test/test_common:test_runtime_lib", "@envoy//test/test_common:utility_lib", "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/service/runtime/v3:pkg_cc_proto", diff --git a/mobile/test/common/integration/rtds_integration_test.cc b/mobile/test/common/integration/rtds_integration_test.cc index 14e42ae55456..96cde1310d73 100644 --- a/mobile/test/common/integration/rtds_integration_test.cc +++ b/mobile/test/common/integration/rtds_integration_test.cc @@ -3,6 +3,7 @@ #include "test/common/integration/xds_integration_test.h" #include "test/test_common/environment.h" +#include "test/test_common/test_runtime.h" #include "test/test_common/utility.h" #include "gtest/gtest.h" @@ -34,6 +35,59 @@ class RtdsIntegrationTest : public XdsIntegrationTest { } void SetUp() override { initialize(); } + + void runReloadTest() { + // Send a request on the data plane. + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + terminal_callback_.waitReady(); + + EXPECT_EQ(cc_.on_headers_calls, 1); + EXPECT_EQ(cc_.status, "200"); + EXPECT_EQ(cc_.on_data_calls, 2); + EXPECT_EQ(cc_.on_complete_calls, 1); + EXPECT_EQ(cc_.on_cancel_calls, 0); + EXPECT_EQ(cc_.on_error_calls, 0); + EXPECT_EQ(cc_.on_header_consumed_bytes_from_response, 27); + EXPECT_EQ(cc_.on_complete_received_byte_count, 67); + // Check that the Runtime config is from the static layer. + EXPECT_FALSE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); + + const std::string load_success_counter = "runtime.load_success"; + uint64_t load_success_value = getCounterValue(load_success_counter); + // Send a RTDS request and get back the RTDS response. + EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Runtime, "", {"some_rtds_resource"}, + {"some_rtds_resource"}, {}, true)); + + envoy::service::runtime::v3::Runtime some_rtds_resource; + some_rtds_resource.set_name("some_rtds_resource"); + auto* static_layer = some_rtds_resource.mutable_layer(); + (*static_layer->mutable_fields())["envoy.reloadable_features.test_feature_false"] + .set_bool_value(true); + + sendDiscoveryResponse( + Config::TypeUrl::get().Runtime, {some_rtds_resource}, {some_rtds_resource}, {}, "1"); + // Wait until the RTDS updates from the DiscoveryResponse have been applied. + ASSERT_TRUE(waitForCounterGe(load_success_counter, load_success_value + 1)); + + // Verify that the Runtime config values are from the RTDS response. + EXPECT_TRUE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); + + load_success_value = getCounterValue(load_success_counter); + EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Runtime, "", {"some_rtds_resource"}, + {"some_rtds_resource"}, {})); + (*static_layer->mutable_fields())["envoy.reloadable_features.test_feature_false"] + .set_bool_value(false); + + // Send another response with Resource wrapper. + sendDiscoveryResponse( + Config::TypeUrl::get().Runtime, {some_rtds_resource}, {some_rtds_resource}, {}, "2", + {{"test", ProtobufWkt::Any()}}); + // Wait until the RTDS updates from the DiscoveryResponse have been applied. + ASSERT_TRUE(waitForCounterGe(load_success_counter, load_success_value + 1)); + + // Verify that the Runtime config values are from the RTDS response. + EXPECT_FALSE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); + } }; INSTANTIATE_TEST_SUITE_P( @@ -43,55 +97,14 @@ INSTANTIATE_TEST_SUITE_P( // Envoy Mobile's xDS APIs only support state-of-the-world, not delta. testing::Values(Grpc::SotwOrDelta::Sotw, Grpc::SotwOrDelta::UnifiedSotw))); -TEST_P(RtdsIntegrationTest, RtdsReload) { - // Send a request on the data plane. - stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); - terminal_callback_.waitReady(); - - EXPECT_EQ(cc_.on_headers_calls, 1); - EXPECT_EQ(cc_.status, "200"); - EXPECT_EQ(cc_.on_data_calls, 2); - EXPECT_EQ(cc_.on_complete_calls, 1); - EXPECT_EQ(cc_.on_cancel_calls, 0); - EXPECT_EQ(cc_.on_error_calls, 0); - EXPECT_EQ(cc_.on_header_consumed_bytes_from_response, 27); - EXPECT_EQ(cc_.on_complete_received_byte_count, 67); - // Check that the Runtime config is from the static layer. - EXPECT_FALSE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); - - const std::string load_success_counter = "runtime.load_success"; - uint64_t load_success_value = getCounterValue(load_success_counter); - // Send a RTDS request and get back the RTDS response. - EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Runtime, "", {"some_rtds_resource"}, - {"some_rtds_resource"}, {}, true)); - - envoy::service::runtime::v3::Runtime some_rtds_resource; - some_rtds_resource.set_name("some_rtds_resource"); - auto* static_layer = some_rtds_resource.mutable_layer(); - (*static_layer->mutable_fields())["envoy.reloadable_features.test_feature_false"].set_bool_value( - true); - sendDiscoveryResponse( - Config::TypeUrl::get().Runtime, {some_rtds_resource}, {some_rtds_resource}, {}, "1"); - // Wait until the RTDS updates from the DiscoveryResponse have been applied. - ASSERT_TRUE(waitForCounterGe(load_success_counter, load_success_value + 1)); - - // Verify that the Runtime config values are from the RTDS response. - EXPECT_TRUE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); - - load_success_value = getCounterValue(load_success_counter); - EXPECT_TRUE(compareDiscoveryRequest(Config::TypeUrl::get().Runtime, "", {"some_rtds_resource"}, - {"some_rtds_resource"}, {})); - (*static_layer->mutable_fields())["envoy.reloadable_features.test_feature_false"].set_bool_value( - false); - // Send another response with Resource wrapper. - sendDiscoveryResponse( - Config::TypeUrl::get().Runtime, {some_rtds_resource}, {some_rtds_resource}, {}, "2", - {{"test", ProtobufWkt::Any()}}); - // Wait until the RTDS updates from the DiscoveryResponse have been applied. - ASSERT_TRUE(waitForCounterGe(load_success_counter, load_success_value + 1)); - - // Verify that the Runtime config values are from the RTDS response. - EXPECT_FALSE(Runtime::runtimeFeatureEnabled("envoy.reloadable_features.test_feature_false")); +TEST_P(RtdsIntegrationTest, RtdsReloadWithDfpMixedScheme) { + TestScopedStaticReloadableFeaturesRuntime scoped_runtime({{"dfp_mixed_scheme", true}}); + runReloadTest(); +} + +TEST_P(RtdsIntegrationTest, RtdsReloadWithoutDfpMixedScheme) { + TestScopedStaticReloadableFeaturesRuntime scoped_runtime({{"dfp_mixed_scheme", false}}); + runReloadTest(); } } // namespace diff --git a/test/test_common/test_runtime.h b/test/test_common/test_runtime.h index b332f52737d1..f270948f3f13 100644 --- a/test/test_common/test_runtime.h +++ b/test/test_common/test_runtime.h @@ -7,8 +7,17 @@ // TestScopedRuntime scoped_runtime; // scoped_runtime.mergeValues( // {{"envoy.reloadable_features.test_feature_true", "false"}}); - -#pragma once +// +// TestScopedRuntime depends on the admin interface being compiled into the binary. +// For build options where the admin interface is not available (particularly, Envoy Mobile), use +// TestScopedStaticReloadableFeaturesRuntime. As the name suggests, it only works with reloadable +// features: +// +// TestScopedStaticReloadableFeaturesRuntime scoped_runtime( +// {{"dfp_mixed_cache", false}, {"always_use_v6", true}}); +// +// This will translate to envoy.reloadable_features.dfp_mixed_cache being set to false and +// envoy.reloadable_features.always_use_v6 being set to true in the static runtime layer. #include "envoy/config/bootstrap/v3/bootstrap.pb.h" @@ -58,6 +67,42 @@ class TestScopedRuntime { std::unique_ptr runtime_; }; +class TestScopedStaticReloadableFeaturesRuntime { +public: + TestScopedStaticReloadableFeaturesRuntime(const std::vector>& values) + : api_(Api::createApiForTest()) { + envoy::config::bootstrap::v3::LayeredRuntime config; + // Set up runtime. + auto* runtime = config.add_layers(); + runtime->set_name("test_static_layer_test_runtime"); + ProtobufWkt::Struct envoy_layer; + ProtobufWkt::Struct& runtime_values = + *(*envoy_layer.mutable_fields())["envoy"].mutable_struct_value(); + ProtobufWkt::Struct& flags = + *(*runtime_values.mutable_fields())["reloadable_features"].mutable_struct_value(); + for (const auto& [key, value] : values) { + (*flags.mutable_fields())[key].set_bool_value(value); + } + runtime->mutable_static_layer()->MergeFrom(envoy_layer); + + Runtime::LoaderPtr runtime_ptr = std::make_unique( + dispatcher_, tls_, config, local_info_, store_, generator_, validation_visitor_, *api_); + // This will ignore values set in test, but just use flag defaults! + runtime_ = std::move(runtime_ptr); + } + +protected: + absl::FlagSaver saver_; + Event::MockDispatcher dispatcher_; + testing::NiceMock tls_; + Stats::TestUtil::TestStore store_; + Random::MockRandomGenerator generator_; + Api::ApiPtr api_; + testing::NiceMock local_info_; + testing::NiceMock validation_visitor_; + std::unique_ptr runtime_; +}; + class TestDeprecatedV2Api : public TestScopedRuntime { public: TestDeprecatedV2Api() { allowDeprecatedV2(); } From 22083273a1e0880fc3e4928e040d4382693038a5 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:02:38 -0700 Subject: [PATCH 014/126] deps: Bump `com_github_rules_proto_grpc` -> 4.6.0 (#31399) Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 4d8f68f5f28f..5e38448c5c24 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -390,13 +390,13 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Protobuf and gRPC rules for Bazel", project_desc = "Bazel rules for building Protobuf and gRPC code and libraries from proto_library targets", project_url = "https://github.com/rules-proto-grpc/rules_proto_grpc", - version = "4.5.0", - sha256 = "9ba7299c5eb6ec45b6b9a0ceb9916d0ab96789ac8218269322f0124c0c0d24e2", + version = "4.6.0", + sha256 = "2a0860a336ae836b54671cbbe0710eec17c64ef70c4c5a88ccfd47ea6e3739bd", strip_prefix = "rules_proto_grpc-{version}", urls = ["https://github.com/rules-proto-grpc/rules_proto_grpc/releases/download/{version}/rules_proto_grpc-{version}.tar.gz"], use_category = ["dataplane_ext"], extensions = ["envoy.transport_sockets.alts"], - release_date = "2023-09-12", + release_date = "2023-12-14", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/rules-proto-grpc/rules_proto_grpc/blob/{version}/LICENSE", From 163a62629d36f021d85c43c53c2ff175e7b0ec82 Mon Sep 17 00:00:00 2001 From: yanjunxiang-google <78807980+yanjunxiang-google@users.noreply.github.com> Date: Fri, 15 Dec 2023 19:12:45 -0500 Subject: [PATCH 015/126] Implementing drop_overload stats reporting in load report service API (#31384) --------- Signed-off-by: Yanjun Xiang --- source/common/upstream/load_stats_reporter.cc | 9 +++ .../upstream/load_stats_reporter_test.cc | 20 +++++++ .../load_stats_integration_test.cc | 59 ++++++++++++++++++- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/source/common/upstream/load_stats_reporter.cc b/source/common/upstream/load_stats_reporter.cc index 386f79b6be99..a06d85c40ded 100644 --- a/source/common/upstream/load_stats_reporter.cc +++ b/source/common/upstream/load_stats_reporter.cc @@ -123,6 +123,14 @@ void LoadStatsReporter::sendLoadStatsRequest() { } cluster_stats->set_total_dropped_requests( cluster.info()->loadReportStats().upstream_rq_dropped_.latch()); + const uint64_t drop_overload_count = + cluster.info()->loadReportStats().upstream_rq_drop_overload_.latch(); + if (drop_overload_count > 0) { + auto* dropped_request = cluster_stats->add_dropped_requests(); + dropped_request->set_category("drop_overload"); + dropped_request->set_dropped_count(drop_overload_count); + } + const auto now = time_source_.monotonicTime().time_since_epoch(); const auto measured_interval = now - cluster_name_and_timestamp.second; cluster_stats->mutable_load_report_interval()->MergeFrom( @@ -214,6 +222,7 @@ void LoadStatsReporter::startLoadReportPeriod() { } } cluster.info()->loadReportStats().upstream_rq_dropped_.latch(); + cluster.info()->loadReportStats().upstream_rq_drop_overload_.latch(); }; if (message_->send_all_clusters()) { for (const auto& p : all_clusters.active_clusters_) { diff --git a/test/common/upstream/load_stats_reporter_test.cc b/test/common/upstream/load_stats_reporter_test.cc index 429cea9b4182..1997e2d324c5 100644 --- a/test/common/upstream/load_stats_reporter_test.cc +++ b/test/common/upstream/load_stats_reporter_test.cc @@ -73,6 +73,12 @@ class LoadStatsReporterTest : public testing::Test { load_stats_reporter_->onReceiveMessage(std::move(response)); } + void setDropOverload(envoy::config::endpoint::v3::ClusterStats& cluster_stats, uint64_t count) { + auto* dropped_request = cluster_stats.add_dropped_requests(); + dropped_request->set_category("drop_overload"); + dropped_request->set_dropped_count(count); + } + Event::SimulatedTimeSystem time_system_; NiceMock cm_; Event::MockDispatcher dispatcher_; @@ -132,12 +138,14 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { deliverLoadStatsResponse({"foo"}); // Initial stats report for foo on timer tick. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(5); + foo_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(7); time_system_.setMonotonicTime(std::chrono::microseconds(4)); { envoy::config::endpoint::v3::ClusterStats foo_cluster_stats; foo_cluster_stats.set_cluster_name("foo"); foo_cluster_stats.set_cluster_service_name("bar"); foo_cluster_stats.set_total_dropped_requests(5); + setDropOverload(foo_cluster_stats, 7); foo_cluster_stats.mutable_load_report_interval()->MergeFrom( Protobuf::util::TimeUtil::MicrosecondsToDuration(1)); expectSendMessage({foo_cluster_stats}); @@ -148,6 +156,7 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { // Some traffic on foo/bar in between previous request and next response. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(5); // Start reporting on bar. time_system_.setMonotonicTime(std::chrono::microseconds(6)); @@ -155,6 +164,7 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { // Stats report foo/bar on timer tick. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(3); time_system_.setMonotonicTime(std::chrono::microseconds(28)); { envoy::config::endpoint::v3::ClusterStats foo_cluster_stats; @@ -166,6 +176,7 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { envoy::config::endpoint::v3::ClusterStats bar_cluster_stats; bar_cluster_stats.set_cluster_name("bar"); bar_cluster_stats.set_total_dropped_requests(1); + setDropOverload(bar_cluster_stats, 3); bar_cluster_stats.mutable_load_report_interval()->MergeFrom( Protobuf::util::TimeUtil::MicrosecondsToDuration(22)); expectSendMessage({bar_cluster_stats, foo_cluster_stats}); @@ -176,17 +187,20 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { // Some traffic on foo/bar in between previous request and next response. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(1); // Stop reporting on foo. deliverLoadStatsResponse({"bar"}); // Stats report for bar on timer tick. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(5); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(5); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(7); time_system_.setMonotonicTime(std::chrono::microseconds(33)); { envoy::config::endpoint::v3::ClusterStats bar_cluster_stats; bar_cluster_stats.set_cluster_name("bar"); bar_cluster_stats.set_total_dropped_requests(6); + setDropOverload(bar_cluster_stats, 8); bar_cluster_stats.mutable_load_report_interval()->MergeFrom( Protobuf::util::TimeUtil::MicrosecondsToDuration(5)); expectSendMessage({bar_cluster_stats}); @@ -196,25 +210,31 @@ TEST_F(LoadStatsReporterTest, ExistingClusters) { // Some traffic on foo/bar in between previous request and next response. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + foo_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(8); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(3); // Start tracking foo again, we should forget earlier history for foo. time_system_.setMonotonicTime(std::chrono::microseconds(43)); deliverLoadStatsResponse({"foo", "bar"}); // Stats report foo/bar on timer tick. foo_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + foo_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(9); bar_cluster.info_->load_report_stats_.upstream_rq_dropped_.add(1); + bar_cluster.info_->load_report_stats_.upstream_rq_drop_overload_.add(4); time_system_.setMonotonicTime(std::chrono::microseconds(47)); { envoy::config::endpoint::v3::ClusterStats foo_cluster_stats; foo_cluster_stats.set_cluster_name("foo"); foo_cluster_stats.set_cluster_service_name("bar"); foo_cluster_stats.set_total_dropped_requests(1); + setDropOverload(foo_cluster_stats, 9); foo_cluster_stats.mutable_load_report_interval()->MergeFrom( Protobuf::util::TimeUtil::MicrosecondsToDuration(4)); envoy::config::endpoint::v3::ClusterStats bar_cluster_stats; bar_cluster_stats.set_cluster_name("bar"); bar_cluster_stats.set_total_dropped_requests(2); + setDropOverload(bar_cluster_stats, 7); bar_cluster_stats.mutable_load_report_interval()->MergeFrom( Protobuf::util::TimeUtil::MicrosecondsToDuration(14)); expectSendMessage({bar_cluster_stats, foo_cluster_stats}); diff --git a/test/integration/load_stats_integration_test.cc b/test/integration/load_stats_integration_test.cc index 4dd11637cc98..668cdb0fcf52 100644 --- a/test/integration/load_stats_integration_test.cc +++ b/test/integration/load_stats_integration_test.cc @@ -191,6 +191,20 @@ class LoadStatsIntegrationTest : public Grpc::GrpcClientIntegrationParamTest, cluster_stats->set_total_dropped_requests(cluster_stats->total_dropped_requests() + local_cluster_stats.total_dropped_requests()); + if (local_cluster_stats.dropped_requests().size() > 0) { + const uint64_t local_drop_count = local_cluster_stats.dropped_requests(0).dropped_count(); + if (local_drop_count > 0) { + envoy::config::endpoint::v3::ClusterStats::DroppedRequests* drop_request; + if (cluster_stats->dropped_requests().size() > 0) { + drop_request = cluster_stats->mutable_dropped_requests(0); + drop_request->set_dropped_count(drop_request->dropped_count() + local_drop_count); + } else { + drop_request = cluster_stats->add_dropped_requests(); + drop_request->set_dropped_count(local_drop_count); + } + drop_request->set_category("drop_overload"); + } + } for (int i = 0; i < local_cluster_stats.upstream_locality_stats_size(); ++i) { const auto& local_upstream_locality_stats = local_cluster_stats.upstream_locality_stats(i); @@ -243,7 +257,7 @@ class LoadStatsIntegrationTest : public Grpc::GrpcClientIntegrationParamTest, ABSL_MUST_USE_RESULT AssertionResult waitForLoadStatsRequest(const std::vector& expected_locality_stats, - uint64_t dropped = 0) { + uint64_t dropped = 0, bool drop_overload_test = false) { Event::TestTimeSystem::RealTimeBound bound(TestUtility::DefaultTimeout); Protobuf::RepeatedPtrField expected_cluster_stats; if (!expected_locality_stats.empty() || dropped != 0) { @@ -253,6 +267,11 @@ class LoadStatsIntegrationTest : public Grpc::GrpcClientIntegrationParamTest, cluster_stats->set_cluster_service_name("service_name_0"); if (dropped > 0) { cluster_stats->set_total_dropped_requests(dropped); + if (drop_overload_test) { + auto* drop_request = cluster_stats->add_dropped_requests(); + drop_request->set_category("drop_overload"); + drop_request->set_dropped_count(dropped); + } } std::copy( expected_locality_stats.begin(), expected_locality_stats.end(), @@ -368,6 +387,19 @@ class LoadStatsIntegrationTest : public Grpc::GrpcClientIntegrationParamTest, cleanupUpstreamAndDownstream(); } + void updateDropOverloadConfig() { + envoy::config::endpoint::v3::ClusterLoadAssignment cluster_load_assignment; + cluster_load_assignment.set_cluster_name("service_name_0"); + // Config drop_overload to drop 100% requests. + auto* policy = cluster_load_assignment.mutable_policy(); + auto* drop_overload = policy->add_drop_overloads(); + drop_overload->set_category("drop_overload"); + auto* drop_percentage = drop_overload->mutable_drop_percentage(); + drop_percentage->set_numerator(100); + drop_percentage->set_denominator(envoy::type::v3::FractionalPercent::HUNDRED); + eds_helper_.setEdsAndWait({cluster_load_assignment}, *test_server_); + } + static constexpr uint32_t upstream_endpoints_ = 5; IntegrationStreamDecoderPtr response_; @@ -646,5 +678,30 @@ TEST_P(LoadStatsIntegrationTest, Dropped) { cleanupLoadStatsConnection(); } +// Validate the load reports for dropped requests due to drop_overload make sense. +TEST_P(LoadStatsIntegrationTest, DropOverloadDropped) { + initialize(); + waitForLoadStatsStream(); + ASSERT_TRUE(waitForLoadStatsRequest({})); + loadstats_stream_->startGrpcStream(); + updateClusterLoadAssignment({{0}}, {}, {}, {}); + updateDropOverloadConfig(); + + requestLoadStatsResponse({"cluster_0"}); + initiateClientConnection(); + ASSERT_TRUE(response_->waitForEndStream()); + ASSERT_TRUE(response_->complete()); + EXPECT_EQ("503", response_->headers().getStatusValue()); + cleanupUpstreamAndDownstream(); + + ASSERT_TRUE(waitForLoadStatsRequest({}, 1, true)); + + EXPECT_EQ(1, test_server_->counter("load_reporter.requests")->value()); + EXPECT_LE(2, test_server_->counter("load_reporter.responses")->value()); + EXPECT_EQ(0, test_server_->counter("load_reporter.errors")->value()); + + cleanupLoadStatsConnection(); +} + } // namespace } // namespace Envoy From 3a6bfbb9e12ec911acfefdb174caef49482daf6e Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Sun, 17 Dec 2023 14:27:19 -0500 Subject: [PATCH 016/126] mobile/ci: Disable the Mobile Traffic Director workflow (#31417) Until https://github.com/envoyproxy/envoy/issues/31416 is resolved. Signed-off-by: Ali Beyad --- .github/workflows/mobile-traffic_director.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mobile-traffic_director.yml b/.github/workflows/mobile-traffic_director.yml index 8522956a41e7..79459cef6e6f 100644 --- a/.github/workflows/mobile-traffic_director.yml +++ b/.github/workflows/mobile-traffic_director.yml @@ -4,9 +4,9 @@ permissions: contents: read on: - schedule: - # Once a day at midnight. - - cron: '0 0 * * *' + # Disabled scheduled runs until https://github.com/envoyproxy/envoy/issues/31416 is resolved. + # schedule: + # - cron: '0 0 * * *' # Allows manual triggering in the UI. Makes it easier to test. workflow_dispatch: From eda5d9a636c9d5c966ce05c92f385fba229a331a Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 18 Dec 2023 08:15:22 +0000 Subject: [PATCH 017/126] deps: Rename edenhill -> confluentinc (#31398) Signed-off-by: Ryan Northey --- bazel/foreign_cc/BUILD | 2 +- bazel/repositories.bzl | 2 +- bazel/repository_locations.bzl | 2 +- .../kafka/filters/network/source/mesh/upstream_kafka_client.h | 2 +- .../filters/network/source/mesh/upstream_kafka_consumer_impl.cc | 2 +- tools/dependency/BUILD | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index afbf34164cb2..eb9c9e81d2c4 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -85,7 +85,7 @@ configure_make( name = "librdkafka_build", configure_in_place = True, configure_options = ["--disable-ssl --disable-gssapi --disable-zstd --disable-curl && cp Makefile.config src/.. && cp config.h src/.."], - lib_source = "@edenhill_librdkafka//:all", + lib_source = "@confluentinc_librdkafka//:all", out_static_libs = [ "librdkafka.a", "librdkafka++.a", diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 925c97a64eb1..4affb6bb757f 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -1413,7 +1413,7 @@ filegroup( # This archive provides Kafka C/CPP client used by mesh filter to communicate with upstream # Kafka clusters. external_http_archive( - name = "edenhill_librdkafka", + name = "confluentinc_librdkafka", build_file_content = BUILD_ALL_CONTENT, # (adam.kotwasinski) librdkafka bundles in cJSON, which is also bundled in by libvppinfra. # For now, let's just drop this dependency from Kafka, as it's used only for monitoring. diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 5e38448c5c24..5674ac4e62cb 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1320,7 +1320,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( license = "Apache-2.0", license_url = "https://github.com/apache/kafka/blob/{version}/LICENSE", ), - edenhill_librdkafka = dict( + confluentinc_librdkafka = dict( project_name = "Kafka (C/C++ client)", project_desc = "C/C++ client for Apache Kafka (open-source distributed event streaming platform)", project_url = "https://github.com/confluentinc/librdkafka", diff --git a/contrib/kafka/filters/network/source/mesh/upstream_kafka_client.h b/contrib/kafka/filters/network/source/mesh/upstream_kafka_client.h index f034f7da4f42..bb883e5c8b2e 100644 --- a/contrib/kafka/filters/network/source/mesh/upstream_kafka_client.h +++ b/contrib/kafka/filters/network/source/mesh/upstream_kafka_client.h @@ -69,7 +69,7 @@ class KafkaProducer { // Theoretically we do not need to do this and leave it all to destructor, but then closing N // producers would require doing that in sequence, while we can optimize it somewhat (so we just // wait for the slowest one). - // See https://github.com/edenhill/librdkafka/issues/2972 + // See https://github.com/confluentinc/librdkafka/issues/2972 virtual void markFinished() PURE; }; diff --git a/contrib/kafka/filters/network/source/mesh/upstream_kafka_consumer_impl.cc b/contrib/kafka/filters/network/source/mesh/upstream_kafka_consumer_impl.cc index a6ba7a3e1d71..0c0a6cd66463 100644 --- a/contrib/kafka/filters/network/source/mesh/upstream_kafka_consumer_impl.cc +++ b/contrib/kafka/filters/network/source/mesh/upstream_kafka_consumer_impl.cc @@ -133,7 +133,7 @@ std::vector RichKafkaConsumer::receiveRecordBatch() { // XXX (adam.kotwasinski) There could be something more present in the consumer, // and we could drain it (at least a little) in the next commits. - // See: https://github.com/edenhill/librdkafka/discussions/3897 + // See: https://github.com/confluentinc/librdkafka/discussions/3897 return {inbound_record}; } else { // Nothing extraordinary (timeout because there is nothing upstream), diff --git a/tools/dependency/BUILD b/tools/dependency/BUILD index ba2106cdac2a..661adb959c42 100644 --- a/tools/dependency/BUILD +++ b/tools/dependency/BUILD @@ -32,7 +32,7 @@ envoy_genjson( srcs = ["//bazel:all_repository_locations"], filter = """ .[0] - | del(.edenhill_librdkafka) + | del(.confluentinc_librdkafka) """, ) From cb6b341dc21ae7d0131e0a86262df0b093ec1fce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 08:20:34 +0000 Subject: [PATCH 018/126] build(deps): bump envoy-dependency-check from 0.1.11 to 0.1.12 in /tools/base (#31421) build(deps): bump envoy-dependency-check in /tools/base Bumps [envoy-dependency-check](https://github.com/envoyproxy/toolshed) from 0.1.11 to 0.1.12. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/compare/0.1.11...0.1.12) --- updated-dependencies: - dependency-name: envoy-dependency-check dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 4e94594bb203..cfeb32a97fb4 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -482,9 +482,9 @@ envoy-code-check==0.5.8 \ --hash=sha256:03f32588cc9ed98ab6703cbca6f81df1527db71c3a0f962be6a6084ded40d528 \ --hash=sha256:2b12c51098c78d393823cf055a54e9308c37321d769041f01a2f35b04074d6f3 # via -r requirements.in -envoy-dependency-check==0.1.11 \ - --hash=sha256:1c4e9f238787bda6d1270452538b361b3f33be3866640373161b70ac9c98c740 \ - --hash=sha256:3318930cf8632b3e9d0bfbd724f148c8eeb2b3e20784d92f62e16c6c706ba511 +envoy-dependency-check==0.1.12 \ + --hash=sha256:4673cb4cf9c0e2c55b2a0e0b39df3b8df9993d6524c6edb9527d3c8fb1ec24e2 \ + --hash=sha256:7443e530a2a9155d1e114b8a99d9355bbbe73005b0c96ee653907912ae368f3c # via -r requirements.in envoy-distribution-distrotest==0.0.10 \ --hash=sha256:83e912c48da22eb3e514fc1142247d33eb7ed0d59e94eca2ffbd178a26fbf808 \ From abd322f844d6716263945a3c2274021f26a79500 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 18 Dec 2023 10:28:57 +0000 Subject: [PATCH 019/126] examples: Bump `debian` -> bookworm (#31373) Signed-off-by: Ryan Northey --- examples/shared/golang/Dockerfile | 6 +++--- examples/shared/node/Dockerfile | 2 +- examples/shared/python/Dockerfile | 4 ++-- examples/shared/websocket/Dockerfile | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/shared/golang/Dockerfile b/examples/shared/golang/Dockerfile index accda6beda05..9af123412189 100644 --- a/examples/shared/golang/Dockerfile +++ b/examples/shared/golang/Dockerfile @@ -1,9 +1,9 @@ -FROM debian:bullseye-slim@sha256:5aab272aa24713622bfac9dba239bc7488d9979b0d82d19a9dffccd99292154d as os-base +FROM debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 as os-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache -FROM golang:1.21.5-bullseye@sha256:ca78a56712ab89487123b3af2b30052824653730e7ff25271d2f3037153bc0df as golang-base +FROM golang:1.21.5-bookworm@sha256:2d3b13c2a6368032e9697e64e7c923184e6e3be03cf01eadff27de124114e64e as golang-base FROM golang-base as golang-control-plane-builder @@ -19,7 +19,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ apt-get -qq update \ - && apt-get -qq install --no-install-recommends -y netcat + && apt-get -qq install --no-install-recommends -y netcat-traditional COPY --from=golang-control-plane-builder /go/go-control-plane/bin/example /usr/local/bin/example diff --git a/examples/shared/node/Dockerfile b/examples/shared/node/Dockerfile index 25609994371a..6981d22f3072 100644 --- a/examples/shared/node/Dockerfile +++ b/examples/shared/node/Dockerfile @@ -1,4 +1,4 @@ -FROM node:21.4-bullseye-slim@sha256:3afb93c631e692edb893a403d25f9b4cae4b03748244cc9804c31dd957235682 as node-base +FROM node:21.4-bookworm-slim@sha256:3a3b69c7013ac1233d4570f14108572e3f6dac3e2cefa8ef63be2885f702d033 as node-base FROM node-base as node-http-auth diff --git a/examples/shared/python/Dockerfile b/examples/shared/python/Dockerfile index 5c697831d6ce..09c4b5708cc3 100644 --- a/examples/shared/python/Dockerfile +++ b/examples/shared/python/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11.5-slim-bullseye@sha256:9f35f3a6420693c209c11bba63dcf103d88e47ebe0b205336b5168c122967edf as python-base +FROM python:3.11.5-slim-bookworm@sha256:edaf703dce209d774af3ff768fc92b1e3b60261e7602126276f9ceb0e3a96874 as python-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache ARG PYTHON_REQUIREMENTS_FILE=aiohttp/requirements.txt @@ -21,7 +21,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ pip3 install --require-hashes -qr /tmp/requirements.txt \ && apt-get -qq update \ - && apt-get -qq install -y --no-install-recommends netcat \ + && apt-get -qq install -y --no-install-recommends netcat-traditional \ && mkdir /code HEALTHCHECK \ --interval=1s \ diff --git a/examples/shared/websocket/Dockerfile b/examples/shared/websocket/Dockerfile index 370b67eba36b..8b934519a2ae 100644 --- a/examples/shared/websocket/Dockerfile +++ b/examples/shared/websocket/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bullseye-slim@sha256:5aab272aa24713622bfac9dba239bc7488d9979b0d82d19a9dffccd99292154d as websocket-base +FROM debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 as websocket-base ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ From 503d2727353b40d6cebf00512d1901096a5a79f7 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 18 Dec 2023 10:30:11 +0000 Subject: [PATCH 020/126] github/actions: Bump toolshed actions -> 0.2.18 (#31425) Signed-off-by: Ryan Northey --- .github/workflows/_cache.yml | 8 ++++---- .github/workflows/_finish.yml | 8 ++++---- .github/workflows/_load.yml | 10 +++++----- .github/workflows/_request.yml | 10 +++++----- .github/workflows/_run.yml | 16 ++++++++-------- .github/workflows/_stage_publish.yml | 8 ++++---- .github/workflows/_stage_verify.yml | 8 ++++---- .github/workflows/_start.yml | 10 +++++----- .github/workflows/codeql-push.yml | 2 +- .github/workflows/command.yml | 6 +++--- .github/workflows/envoy-dependency.yml | 18 +++++++++--------- .github/workflows/envoy-release.yml | 16 ++++++++-------- .github/workflows/envoy-sync.yml | 4 ++-- .github/workflows/mobile-android_build.yml | 12 ++++++------ .github/workflows/mobile-ios_build.yml | 4 ++-- 15 files changed, 70 insertions(+), 70 deletions(-) diff --git a/.github/workflows/_cache.yml b/.github/workflows/_cache.yml index 905e3438724c..4461da055193 100644 --- a/.github/workflows/_cache.yml +++ b/.github/workflows/_cache.yml @@ -39,20 +39,20 @@ jobs: docker: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 id: appauth name: Appauth (mutex lock) with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.18 id: docker name: Prime Docker cache (${{ inputs.image-tag }}) with: image-tag: ${{ inputs.image-tag }} lock-token: ${{ steps.appauth.outputs.token }} lock-repository: ${{ inputs.lock-repository }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: data name: Cache data with: @@ -60,7 +60,7 @@ jobs: input: | cached: ${{ steps.docker.outputs.cached }} key: ${{ inputs.image-tag }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.18 name: Summary with: json: ${{ steps.data.outputs.value }} diff --git a/.github/workflows/_finish.yml b/.github/workflows/_finish.yml index 8af0051e148c..c7a9ddf9bc1a 100644 --- a/.github/workflows/_finish.yml +++ b/.github/workflows/_finish.yml @@ -36,7 +36,7 @@ jobs: actions: read contents: read steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 name: Incoming data id: needs with: @@ -87,7 +87,7 @@ jobs: summary: "Check has finished", text: $text}}}} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 name: Print summary with: input: ${{ toJSON(steps.needs.outputs.value).summary-title }} @@ -95,13 +95,13 @@ jobs: "## \(.)" options: -Rr output-path: GITHUB_STEP_SUMMARY - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 name: Update check with: action: update diff --git a/.github/workflows/_load.yml b/.github/workflows/_load.yml index 6bf63709805b..44c595bfb756 100644 --- a/.github/workflows/_load.yml +++ b/.github/workflows/_load.yml @@ -91,7 +91,7 @@ jobs: # Handle any failure in triggering job # Remove any `checks` we dont care about # Prepare a check request - - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.18 name: Load env id: data with: @@ -102,13 +102,13 @@ jobs: GH_TOKEN: ${{ github.token }} # Update the check - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 name: Update check if: ${{ fromJSON(steps.data.outputs.data).data.check.action == 'RUN' }} with: @@ -116,7 +116,7 @@ jobs: checks: ${{ toJSON(fromJSON(steps.data.outputs.data).checks) }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 name: Print request summary with: input: | @@ -136,7 +136,7 @@ jobs: | $summary.summary as $summary | "${{ inputs.template-request-summary }}" - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: request-output name: Load request with: diff --git a/.github/workflows/_request.yml b/.github/workflows/_request.yml index 9e9812986ba7..454f917a7f1a 100644 --- a/.github/workflows/_request.yml +++ b/.github/workflows/_request.yml @@ -40,14 +40,14 @@ jobs: env: ${{ steps.data.outputs.value }} config: ${{ steps.config.outputs.config }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 id: checkout name: Checkout Envoy repository with: @@ -60,7 +60,7 @@ jobs: # *ALL* variables collected should be treated as untrusted and should be sanitized before # use - name: Generate environment variables from commit - uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.18 id: env with: branch-name: ${{ steps.checkout.outputs.branch-name }} @@ -71,7 +71,7 @@ jobs: vars: ${{ toJSON(vars) }} - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.18 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} @@ -87,7 +87,7 @@ jobs: target-branch: ${{ fromJSON(steps.env.outputs.data).request.target-branch }} - name: Environment data - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: data with: input: | diff --git a/.github/workflows/_run.yml b/.github/workflows/_run.yml index ec667d75f92f..b4e23f7f56cf 100644 --- a/.github/workflows/_run.yml +++ b/.github/workflows/_run.yml @@ -91,7 +91,7 @@ on: summary-post: type: string default: | - - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.18 with: context: %{{ inputs.context }} steps-pre: @@ -152,7 +152,7 @@ jobs: name: ${{ inputs.command }} ${{ inputs.target }} timeout-minutes: ${{ inputs.timeout-minutes }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: started name: Create timestamp with: @@ -160,7 +160,7 @@ jobs: filter: | now # This controls which input vars are exposed to the run action (and related steps) - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 name: Context id: context with: @@ -181,11 +181,11 @@ jobs: | . * {$config, $check} - if: ${{ inputs.cache-build-image }} name: Restore Docker cache ${{ inputs.cache-build-image && format('({0})', inputs.cache-build-image) || '' }} - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.18 with: image_tag: ${{ inputs.cache-build-image }} - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 id: appauth name: Appauth if: ${{ inputs.trusted }} @@ -196,7 +196,7 @@ jobs: # - the workaround is to allow the token to be passed through. token: ${{ github.token }} token-ok: true - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 id: checkout name: Checkout Envoy repository with: @@ -213,7 +213,7 @@ jobs: token: ${{ inputs.trusted && steps.appauth.outputs.token || github.token }} # This is currently only use by mobile-docs and can be removed once they are updated to the newer website - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 id: checkout-extra name: Checkout extra repository (for publishing) if: ${{ inputs.checkout-extra }} @@ -221,7 +221,7 @@ jobs: config: ${{ inputs.checkout-extra }} ssh-key: ${{ inputs.trusted && inputs.ssh-key-extra || '' }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 name: Run CI ${{ inputs.command }} ${{ inputs.target }} with: args: ${{ inputs.args != '--' && inputs.args || inputs.target }} diff --git a/.github/workflows/_stage_publish.yml b/.github/workflows/_stage_publish.yml index 38f3a413bae8..e0fadbf2aa25 100644 --- a/.github/workflows/_stage_publish.yml +++ b/.github/workflows/_stage_publish.yml @@ -63,7 +63,7 @@ jobs: export ENVOY_PUBLISH_DRY_RUN=${{ (fromJSON(inputs.request).request.version.dev || ! inputs.trusted) && 1 || '' }} steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 with: options: -Rr input: >- @@ -80,7 +80,7 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)/\($path)" - - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.18 with: url: %{{ steps.url.outputs.value }} path: %{{ runner.temp }}/release.signed @@ -98,12 +98,12 @@ jobs: needs: - publish steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.18 with: ref: main repository: ${{ fromJSON(inputs.request).request.version.dev && 'envoyproxy/envoy-website' || 'envoyproxy/archive' }} diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index 7592e81cf444..f320faeb6a8f 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -50,7 +50,7 @@ jobs: rbe: false steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 with: options: -Rr input: >- @@ -66,15 +66,15 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)" - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 with: url: %{{ steps.url.outputs.value }}/docker/envoy.tar variant: dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 with: url: %{{ steps.url.outputs.value }}/docker/envoy-contrib.tar variant: contrib-dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 with: url: %{{ steps.url.outputs.value }}/docker/envoy-google-vrp.tar variant: google-vrp-dev diff --git a/.github/workflows/_start.yml b/.github/workflows/_start.yml index 399223cc63c8..c7a1760679ad 100644 --- a/.github/workflows/_start.yml +++ b/.github/workflows/_start.yml @@ -54,7 +54,7 @@ jobs: start: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 id: check-config name: Prepare check data with: @@ -77,13 +77,13 @@ jobs: | .skipped.output.summary = "${{ inputs.skipped-summary }}" | .skipped.output.text = "" - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 name: Start checks id: checks with: @@ -94,7 +94,7 @@ jobs: ${{ fromJSON(inputs.env).summary.summary }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.18 name: Summary with: collapse-open: true @@ -118,7 +118,7 @@ jobs: output-path: GITHUB_STEP_SUMMARY title: Checks started/skipped - - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.18 name: Save env id: data with: diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 8c335d4706a6..94ba6261013f 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Pre-cleanup - uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.18 with: to_remove: | /usr/local/lib/android diff --git a/.github/workflows/command.yml b/.github/workflows/command.yml index 64a95ee27218..4ea970e4fcda 100644 --- a/.github/workflows/command.yml +++ b/.github/workflows/command.yml @@ -27,7 +27,7 @@ jobs: && github.actor != 'dependabot[bot]' }} steps: - - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.18 name: Parse command from comment id: command with: @@ -36,14 +36,14 @@ jobs: ^/(retest) # /retest - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 if: ${{ steps.command.outputs.command == 'retest' }} id: appauth-retest name: Appauth (retest) with: key: ${{ secrets.ENVOY_CI_APP_KEY }} app_id: ${{ secrets.ENVOY_CI_APP_ID }} - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.18 if: ${{ steps.command.outputs.command == 'retest' }} name: Retest with: diff --git a/.github/workflows/envoy-dependency.yml b/.github/workflows/envoy-dependency.yml index a250415ef4b7..589f858d58ed 100644 --- a/.github/workflows/envoy-dependency.yml +++ b/.github/workflows/envoy-dependency.yml @@ -50,16 +50,16 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 with: token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.18 id: update name: Update dependency (${{ inputs.dependency }}) with: @@ -92,13 +92,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.18 name: Upload diff with: name: ${{ inputs.dependency }}-${{ steps.update.outputs.output }} - name: Create a PR if: ${{ inputs.pr }} - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 with: base: main body: | @@ -129,11 +129,11 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 id: checkout name: Checkout Envoy repository with: @@ -175,7 +175,7 @@ jobs: - name: Check Docker SHAs id: build-images - uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.18 with: images: | sha: envoyproxy/envoy-build-ubuntu:${{ steps.build-tools.outputs.tag }} @@ -204,7 +204,7 @@ jobs: name: Update SHAs working-directory: envoy - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 with: base: main body: Created by Envoy dependency bot diff --git a/.github/workflows/envoy-release.yml b/.github/workflows/envoy-release.yml index 5988bffda5ec..80c6e2c04b7f 100644 --- a/.github/workflows/envoy-release.yml +++ b/.github/workflows/envoy-release.yml @@ -55,7 +55,7 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} @@ -77,10 +77,10 @@ jobs: name: Check changelog summary - if: ${{ inputs.author }} name: Validate signoff email - uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.18 with: email: ${{ inputs.author }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 name: Create release with: source: | @@ -105,7 +105,7 @@ jobs: name: Release version id: release - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 with: base: ${{ github.ref_name }} commit: false @@ -130,13 +130,13 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} committer-name: ${{ env.COMMITTER_NAME }} committer-email: ${{ env.COMMITTER_EMAIL }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 name: Sync version histories with: command: >- @@ -146,7 +146,7 @@ jobs: -- --signoff="${{ env.COMMITTER_NAME }} <${{ env.COMMITTER_EMAIL }}>" - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 with: append-commit-message: true base: ${{ github.ref_name }} @@ -176,7 +176,7 @@ jobs: name: Create release branch steps: - name: Checkout repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.17 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml index dbde1a0e6574..d5af50330a1a 100644 --- a/.github/workflows/envoy-sync.yml +++ b/.github/workflows/envoy-sync.yml @@ -28,12 +28,12 @@ jobs: - data-plane-api - mobile-website steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.18 with: repository: "envoyproxy/${{ matrix.downstream }}" ref: main diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 9aae18f203c0..8a6df4e37ddb 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -75,9 +75,9 @@ jobs: target: kotlin-hello-world runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.18 steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 with: apk: bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity @@ -104,7 +104,7 @@ jobs: target: ${{ matrix.target }} runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.18 steps-post: ${{ matrix.steps-post }} timeout-minutes: 50 trusted: ${{ fromJSON(needs.load.outputs.trusted) }} @@ -115,7 +115,7 @@ jobs: include: - name: java-hello-world steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 with: apk: bazel-bin/examples/java/hello_world/hello_envoy.apk app: io.envoyproxy.envoymobile.helloenvoy/.MainActivity @@ -134,7 +134,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/baseline:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 with: apk: bazel-bin/test/kotlin/apps/baseline/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoybaselinetest/.MainActivity @@ -149,7 +149,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/experimental:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 with: apk: bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index 227be825be9b..aa1be794333b 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -86,7 +86,7 @@ jobs: ./ci/mac_ci_setup.sh ./bazelw shutdown steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.18 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} @@ -127,7 +127,7 @@ jobs: source: | ./ci/mac_ci_setup.sh steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.17 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.18 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} From b18ea4488a540aaab4979aea7ebeb252b77d4fe7 Mon Sep 17 00:00:00 2001 From: phlax Date: Mon, 18 Dec 2023 10:30:26 +0000 Subject: [PATCH 021/126] deps/tooling: Add CI paths (#31400) Signed-off-by: Ryan Northey --- .github/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/config.yml b/.github/config.yml index ffa12f151beb..d31ac8c2ce6e 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -325,6 +325,8 @@ run: - .bazelversion - .github/config.yml - .github/dependabot.yml + - bazel/BUILD + - tools/dependency/* - "**/*.bzl" - "**/requirements.txt" - "**/go.mod" From 56f88a1761c7076004d5500c8aca06c4a51fc4ec Mon Sep 17 00:00:00 2001 From: yanavlasov Date: Mon, 18 Dec 2023 16:00:29 -0500 Subject: [PATCH 022/126] build: Remove decommissioned (in v5.x) bazel attribute (#31434) Remove decommissioned (in v5.x) bazel attribute Signed-off-by: Yan Avlasov --- api/bazel/cc_proto_descriptor_library/builddefs.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/api/bazel/cc_proto_descriptor_library/builddefs.bzl b/api/bazel/cc_proto_descriptor_library/builddefs.bzl index 53e312002646..2da95d00a063 100644 --- a/api/bazel/cc_proto_descriptor_library/builddefs.bzl +++ b/api/bazel/cc_proto_descriptor_library/builddefs.bzl @@ -332,7 +332,6 @@ cc_proto_descriptor_library_aspect = aspect( attr_aspects = ["deps"], fragments = ["cpp"], toolchains = use_cpp_toolchain(), - incompatible_use_toolchain_transition = True, ) cc_proto_descriptor_library = rule( From 7e834d7123f38e4f607b8fa94b13167f0992de1f Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 19 Dec 2023 12:36:05 +0800 Subject: [PATCH 023/126] accesslog: support node in cel (#31319) Commit Message: with this patch, it's able send `xds.node.id` or `xds.node.metadata[xxx]` with command `%(CEL(xds.node.id))%`, this's useful when send log with OpenTelemetry sink. Additional Description: tests and release notes will be added if this's right forward. Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: --- changelogs/current.yaml | 3 +++ .../access_loggers/filters/cel/cel.cc | 11 ++++++----- .../extensions/access_loggers/filters/cel/cel.h | 4 +++- .../access_loggers/filters/cel/config.cc | 1 + .../extensions/filters/common/expr/context.cc | 4 ++++ source/extensions/filters/common/expr/context.h | 7 +++++-- .../extensions/filters/common/expr/evaluator.cc | 17 +++++++++++------ .../extensions/filters/common/expr/evaluator.h | 11 ++++++++--- source/extensions/formatter/cel/cel.cc | 14 +++++++++----- source/extensions/formatter/cel/cel.h | 8 ++++++-- .../matching/http/cel_input/cel_input.h | 1 + .../rate_limit_descriptors/expr/config.cc | 2 +- test/extensions/filters/common/expr/BUILD | 1 + .../filters/common/expr/context_test.cc | 9 ++++++++- .../filters/common/expr/evaluator_fuzz_test.cc | 2 +- test/extensions/formatter/cel/cel_test.cc | 8 ++++++++ 16 files changed, 76 insertions(+), 27 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index eee40903099a..7a51dd282778 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -302,5 +302,8 @@ new_features: - area: access_log change: | Added new access log command operator ``%EMIT_TIME%`` to get the time when the log entry is emitted. +- area: access_log + change: | + Added support for node data in ``%CEL%`` formatter. deprecated: diff --git a/source/extensions/access_loggers/filters/cel/cel.cc b/source/extensions/access_loggers/filters/cel/cel.cc index 2dba1b18e80e..20f80b70e2a0 100644 --- a/source/extensions/access_loggers/filters/cel/cel.cc +++ b/source/extensions/access_loggers/filters/cel/cel.cc @@ -9,17 +9,18 @@ namespace CEL { namespace Expr = Envoy::Extensions::Filters::Common::Expr; CELAccessLogExtensionFilter::CELAccessLogExtensionFilter( - Expr::BuilderInstanceSharedPtr builder, const google::api::expr::v1alpha1::Expr& input_expr) - : builder_(builder), parsed_expr_(input_expr) { + const ::Envoy::LocalInfo::LocalInfo& local_info, Expr::BuilderInstanceSharedPtr builder, + const google::api::expr::v1alpha1::Expr& input_expr) + : local_info_(local_info), builder_(builder), parsed_expr_(input_expr) { compiled_expr_ = Expr::createExpression(builder_->builder(), parsed_expr_); } bool CELAccessLogExtensionFilter::evaluate(const Formatter::HttpFormatterContext& log_context, const StreamInfo::StreamInfo& stream_info) const { Protobuf::Arena arena; - auto eval_status = - Expr::evaluate(*compiled_expr_, arena, stream_info, &log_context.requestHeaders(), - &log_context.responseHeaders(), &log_context.responseTrailers()); + auto eval_status = Expr::evaluate(*compiled_expr_, arena, &local_info_, stream_info, + &log_context.requestHeaders(), &log_context.responseHeaders(), + &log_context.responseTrailers()); if (!eval_status.has_value() || eval_status.value().IsError()) { return false; } diff --git a/source/extensions/access_loggers/filters/cel/cel.h b/source/extensions/access_loggers/filters/cel/cel.h index 3fe63981a951..74247d5187d6 100644 --- a/source/extensions/access_loggers/filters/cel/cel.h +++ b/source/extensions/access_loggers/filters/cel/cel.h @@ -19,13 +19,15 @@ namespace CEL { class CELAccessLogExtensionFilter : public AccessLog::Filter { public: - CELAccessLogExtensionFilter(Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr, + CELAccessLogExtensionFilter(const ::Envoy::LocalInfo::LocalInfo& local_info, + Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr, const google::api::expr::v1alpha1::Expr&); bool evaluate(const Formatter::HttpFormatterContext& log_context, const StreamInfo::StreamInfo& stream_info) const override; private: + const ::Envoy::LocalInfo::LocalInfo& local_info_; Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr builder_; const google::api::expr::v1alpha1::Expr parsed_expr_; Extensions::Filters::Common::Expr::ExpressionPtr compiled_expr_; diff --git a/source/extensions/access_loggers/filters/cel/config.cc b/source/extensions/access_loggers/filters/cel/config.cc index c8ce15d00b48..9a1a1be32435 100644 --- a/source/extensions/access_loggers/filters/cel/config.cc +++ b/source/extensions/access_loggers/filters/cel/config.cc @@ -33,6 +33,7 @@ Envoy::AccessLog::FilterPtr CELAccessLogExtensionFilterFactory::createFilter( } return std::make_unique( + context.serverFactoryContext().localInfo(), Extensions::Filters::Common::Expr::getBuilder(context.serverFactoryContext()), parse_status.value().expr()); #else diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc index 748e46b5643e..a40fdd735e5d 100644 --- a/source/extensions/filters/common/expr/context.cc +++ b/source/extensions/filters/common/expr/context.cc @@ -385,6 +385,10 @@ absl::optional XDSWrapper::operator[](CelValue key) const { const absl::string_view filter_chain_name = filter_chain_info.has_value() ? filter_chain_info->name() : absl::string_view{}; return CelValue::CreateStringView(filter_chain_name); + } else if (value == Node) { + if (local_info_) { + return CelProtoWrapper::CreateMessage(&local_info_->node(), &arena_); + } } return {}; } diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h index 4fd159046b90..0308671984f8 100644 --- a/source/extensions/filters/common/expr/context.h +++ b/source/extensions/filters/common/expr/context.h @@ -89,6 +89,7 @@ constexpr absl::string_view RouteName = "route_name"; constexpr absl::string_view RouteMetadata = "route_metadata"; constexpr absl::string_view UpstreamHostMetadata = "upstream_host_metadata"; constexpr absl::string_view FilterChainName = "filter_chain_name"; +constexpr absl::string_view Node = "node"; class WrapperFieldValues { public: @@ -232,12 +233,14 @@ class FilterStateWrapper : public BaseWrapper { class XDSWrapper : public BaseWrapper { public: - XDSWrapper(Protobuf::Arena& arena, const StreamInfo::StreamInfo& info) - : BaseWrapper(arena), info_(info) {} + XDSWrapper(Protobuf::Arena& arena, const StreamInfo::StreamInfo& info, + const LocalInfo::LocalInfo* local_info) + : BaseWrapper(arena), info_(info), local_info_(local_info) {} absl::optional operator[](CelValue key) const override; private: const StreamInfo::StreamInfo& info_; + const LocalInfo::LocalInfo* local_info_; }; } // namespace Expr diff --git a/source/extensions/filters/common/expr/evaluator.cc b/source/extensions/filters/common/expr/evaluator.cc index f7f965e9b3b9..a6eec90a949a 100644 --- a/source/extensions/filters/common/expr/evaluator.cc +++ b/source/extensions/filters/common/expr/evaluator.cc @@ -64,23 +64,26 @@ absl::optional StreamActivation::FindValue(absl::string_view name, return CelValue::CreateMap( Protobuf::Arena::Create(arena, *arena, info.filterState())); case ActivationToken::XDS: - return CelValue::CreateMap(Protobuf::Arena::Create(arena, *arena, info)); - }; + return CelValue::CreateMap( + Protobuf::Arena::Create(arena, *arena, info, local_info_)); + } return {}; } void StreamActivation::resetActivation() const { + local_info_ = nullptr; activation_info_ = nullptr; activation_request_headers_ = nullptr; activation_response_headers_ = nullptr; activation_response_trailers_ = nullptr; } -ActivationPtr createActivation(const StreamInfo::StreamInfo& info, +ActivationPtr createActivation(const LocalInfo::LocalInfo* local_info, + const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap* request_headers, const Http::ResponseHeaderMap* response_headers, const Http::ResponseTrailerMap* response_trailers) { - return std::make_unique(info, request_headers, response_headers, + return std::make_unique(local_info, info, request_headers, response_headers, response_trailers); } @@ -131,11 +134,13 @@ ExpressionPtr createExpression(Builder& builder, const google::api::expr::v1alph } absl::optional evaluate(const Expression& expr, Protobuf::Arena& arena, + const LocalInfo::LocalInfo* local_info, const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap* request_headers, const Http::ResponseHeaderMap* response_headers, const Http::ResponseTrailerMap* response_trailers) { - auto activation = createActivation(info, request_headers, response_headers, response_trailers); + auto activation = + createActivation(local_info, info, request_headers, response_headers, response_trailers); auto eval_status = expr.Evaluate(*activation, &arena); if (!eval_status.ok()) { return {}; @@ -147,7 +152,7 @@ absl::optional evaluate(const Expression& expr, Protobuf::Arena& arena bool matches(const Expression& expr, const StreamInfo::StreamInfo& info, const Http::RequestHeaderMap& headers) { Protobuf::Arena arena; - auto eval_status = Expr::evaluate(expr, arena, info, &headers, nullptr, nullptr); + auto eval_status = Expr::evaluate(expr, arena, nullptr, info, &headers, nullptr, nullptr); if (!eval_status.has_value()) { return false; } diff --git a/source/extensions/filters/common/expr/evaluator.h b/source/extensions/filters/common/expr/evaluator.h index 656a9c7e676f..e250469298fe 100644 --- a/source/extensions/filters/common/expr/evaluator.h +++ b/source/extensions/filters/common/expr/evaluator.h @@ -26,11 +26,13 @@ using ExpressionPtr = std::unique_ptr; // Base class for the context used by the CEL evaluator to look up attributes. class StreamActivation : public google::api::expr::runtime::BaseActivation { public: - StreamActivation(const StreamInfo::StreamInfo& info, + StreamActivation(const ::Envoy::LocalInfo::LocalInfo* local_info, + const StreamInfo::StreamInfo& info, const ::Envoy::Http::RequestHeaderMap* request_headers, const ::Envoy::Http::ResponseHeaderMap* response_headers, const ::Envoy::Http::ResponseTrailerMap* response_trailers) - : activation_info_(&info), activation_request_headers_(request_headers), + : local_info_(local_info), activation_info_(&info), + activation_request_headers_(request_headers), activation_response_headers_(response_headers), activation_response_trailers_(response_trailers) {} @@ -44,6 +46,7 @@ class StreamActivation : public google::api::expr::runtime::BaseActivation { protected: void resetActivation() const; + mutable const ::Envoy::LocalInfo::LocalInfo* local_info_{nullptr}; mutable const StreamInfo::StreamInfo* activation_info_{nullptr}; mutable const ::Envoy::Http::RequestHeaderMap* activation_request_headers_{nullptr}; mutable const ::Envoy::Http::ResponseHeaderMap* activation_response_headers_{nullptr}; @@ -52,7 +55,8 @@ class StreamActivation : public google::api::expr::runtime::BaseActivation { // Creates an activation providing the common context attributes. // The activation lazily creates wrappers during an evaluation using the evaluation arena. -ActivationPtr createActivation(const StreamInfo::StreamInfo& info, +ActivationPtr createActivation(const ::Envoy::LocalInfo::LocalInfo* local_info, + const StreamInfo::StreamInfo& info, const ::Envoy::Http::RequestHeaderMap* request_headers, const ::Envoy::Http::ResponseHeaderMap* response_headers, const ::Envoy::Http::ResponseTrailerMap* response_trailers); @@ -84,6 +88,7 @@ ExpressionPtr createExpression(Builder& builder, const google::api::expr::v1alph // Evaluates an expression for a request. The arena is used to hold intermediate computational // results and potentially the final value. absl::optional evaluate(const Expression& expr, Protobuf::Arena& arena, + const ::Envoy::LocalInfo::LocalInfo* local_info, const StreamInfo::StreamInfo& info, const ::Envoy::Http::RequestHeaderMap* request_headers, const ::Envoy::Http::ResponseHeaderMap* response_headers, diff --git a/source/extensions/formatter/cel/cel.cc b/source/extensions/formatter/cel/cel.cc index 74160a6651bb..ffee3e8c73ff 100644 --- a/source/extensions/formatter/cel/cel.cc +++ b/source/extensions/formatter/cel/cel.cc @@ -15,10 +15,12 @@ namespace Formatter { namespace Expr = Filters::Common::Expr; -CELFormatter::CELFormatter(Expr::BuilderInstanceSharedPtr expr_builder, +CELFormatter::CELFormatter(const ::Envoy::LocalInfo::LocalInfo& local_info, + Expr::BuilderInstanceSharedPtr expr_builder, const google::api::expr::v1alpha1::Expr& input_expr, absl::optional& max_length) - : expr_builder_(expr_builder), parsed_expr_(input_expr), max_length_(max_length) { + : local_info_(local_info), expr_builder_(expr_builder), parsed_expr_(input_expr), + max_length_(max_length) { compiled_expr_ = Expr::createExpression(expr_builder_->builder(), parsed_expr_); } @@ -26,8 +28,9 @@ absl::optional CELFormatter::formatWithContext(const Envoy::Formatter::HttpFormatterContext& context, const StreamInfo::StreamInfo& stream_info) const { Protobuf::Arena arena; - auto eval_status = Expr::evaluate(*compiled_expr_, arena, stream_info, &context.requestHeaders(), - &context.responseHeaders(), &context.responseTrailers()); + auto eval_status = + Expr::evaluate(*compiled_expr_, arena, &local_info_, stream_info, &context.requestHeaders(), + &context.responseHeaders(), &context.responseTrailers()); if (!eval_status.has_value() || eval_status.value().IsError()) { return absl::nullopt; } @@ -60,7 +63,8 @@ CELFormatterCommandParser::parse(const std::string& command, const std::string& parse_status.status().ToString()); } - return std::make_unique(expr_builder_, parse_status.value().expr(), max_length); + return std::make_unique(local_info_, expr_builder_, parse_status.value().expr(), + max_length); } return nullptr; diff --git a/source/extensions/formatter/cel/cel.h b/source/extensions/formatter/cel/cel.h index b1135f5ffe03..2c5a600a3397 100644 --- a/source/extensions/formatter/cel/cel.h +++ b/source/extensions/formatter/cel/cel.h @@ -14,7 +14,8 @@ namespace Formatter { class CELFormatter : public ::Envoy::Formatter::FormatterProvider { public: - CELFormatter(Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr, + CELFormatter(const ::Envoy::LocalInfo::LocalInfo& local_info, + Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr, const google::api::expr::v1alpha1::Expr&, absl::optional&); absl::optional @@ -24,6 +25,7 @@ class CELFormatter : public ::Envoy::Formatter::FormatterProvider { const StreamInfo::StreamInfo&) const override; private: + const ::Envoy::LocalInfo::LocalInfo& local_info_; Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr expr_builder_; const google::api::expr::v1alpha1::Expr parsed_expr_; const absl::optional max_length_; @@ -33,12 +35,14 @@ class CELFormatter : public ::Envoy::Formatter::FormatterProvider { class CELFormatterCommandParser : public ::Envoy::Formatter::CommandParser { public: CELFormatterCommandParser(Server::Configuration::CommonFactoryContext& context) - : expr_builder_(Extensions::Filters::Common::Expr::getBuilder(context)){}; + : local_info_(context.localInfo()), + expr_builder_(Extensions::Filters::Common::Expr::getBuilder(context)){}; ::Envoy::Formatter::FormatterProviderPtr parse(const std::string& command, const std::string& subcommand, absl::optional& max_length) const override; private: + const ::Envoy::LocalInfo::LocalInfo& local_info_; Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr expr_builder_; }; diff --git a/source/extensions/matching/http/cel_input/cel_input.h b/source/extensions/matching/http/cel_input/cel_input.h index 324d2fd264cd..d1d718a4705b 100644 --- a/source/extensions/matching/http/cel_input/cel_input.h +++ b/source/extensions/matching/http/cel_input/cel_input.h @@ -43,6 +43,7 @@ class HttpCelDataInput : public Matcher::DataInput activation = Extensions::Filters::Common::Expr::createActivation( + nullptr, // TODO: pass local_info to CEL activation. data.streamInfo(), maybe_request_headers.ptr(), maybe_response_headers.ptr(), maybe_response_trailers.ptr()); diff --git a/source/extensions/rate_limit_descriptors/expr/config.cc b/source/extensions/rate_limit_descriptors/expr/config.cc index a50dec82f0f2..e6e4b8044a59 100644 --- a/source/extensions/rate_limit_descriptors/expr/config.cc +++ b/source/extensions/rate_limit_descriptors/expr/config.cc @@ -36,7 +36,7 @@ class ExpressionDescriptor : public RateLimit::DescriptorProducer { const Http::RequestHeaderMap& headers, const StreamInfo::StreamInfo& info) const override { ProtobufWkt::Arena arena; - const auto result = Filters::Common::Expr::evaluate(*compiled_expr_.get(), arena, info, + const auto result = Filters::Common::Expr::evaluate(*compiled_expr_.get(), arena, nullptr, info, &headers, nullptr, nullptr); if (!result.has_value() || result.value().IsError()) { // If result is an error and if skip_if_error is true skip this descriptor, diff --git a/test/extensions/filters/common/expr/BUILD b/test/extensions/filters/common/expr/BUILD index aff36a60b926..ddda2980b9b8 100644 --- a/test/extensions/filters/common/expr/BUILD +++ b/test/extensions/filters/common/expr/BUILD @@ -24,6 +24,7 @@ envoy_extension_cc_test( "//source/extensions/clusters/original_dst:original_dst_cluster_lib", "//source/extensions/filters/common/expr:cel_state_lib", "//source/extensions/filters/common/expr:context_lib", + "//test/mocks/local_info:local_info_mocks", "//test/mocks/network:network_mocks", "//test/mocks/router:router_mocks", "//test/mocks/ssl:ssl_mocks", diff --git a/test/extensions/filters/common/expr/context_test.cc b/test/extensions/filters/common/expr/context_test.cc index 180116b8ac56..0c4f449d9ba2 100644 --- a/test/extensions/filters/common/expr/context_test.cc +++ b/test/extensions/filters/common/expr/context_test.cc @@ -7,6 +7,7 @@ #include "source/extensions/filters/common/expr/cel_state.h" #include "source/extensions/filters/common/expr/context.h" +#include "test/mocks/local_info/mocks.h" #include "test/mocks/network/mocks.h" #include "test/mocks/router/mocks.h" #include "test/mocks/ssl/mocks.h" @@ -829,6 +830,7 @@ TEST(Context, FilterStateAttributes) { } TEST(Context, XDSAttributes) { + NiceMock local_info; NiceMock info; std::shared_ptr> cluster_info( new NiceMock()); @@ -847,7 +849,7 @@ TEST(Context, XDSAttributes) { info.downstream_connection_info_provider_->setFilterChainInfo(filter_chain_info); Protobuf::Arena arena; - XDSWrapper wrapper(arena, info); + XDSWrapper wrapper(arena, info, &local_info); { const auto value = wrapper[CelValue::CreateStringView(ClusterName)]; @@ -893,6 +895,11 @@ TEST(Context, XDSAttributes) { const auto value = wrapper[CelValue::CreateInt64(5)]; EXPECT_FALSE(value.has_value()); } + { + const auto value = wrapper[CelValue::CreateStringView(Node)]; + EXPECT_TRUE(value.has_value()); + ASSERT_TRUE(value.value().IsMessage()); + } } } // namespace diff --git a/test/extensions/filters/common/expr/evaluator_fuzz_test.cc b/test/extensions/filters/common/expr/evaluator_fuzz_test.cc index 2446fb4a8ac3..a09c51bb4a2a 100644 --- a/test/extensions/filters/common/expr/evaluator_fuzz_test.cc +++ b/test/extensions/filters/common/expr/evaluator_fuzz_test.cc @@ -44,7 +44,7 @@ DEFINE_PROTO_FUZZER(const test::extensions::filters::common::expr::EvaluatorTest // Evaluate the CEL expression. Protobuf::Arena arena; - Expr::evaluate(*expr, arena, *stream_info, &request_headers, &response_headers, + Expr::evaluate(*expr, arena, nullptr, *stream_info, &request_headers, &response_headers, &response_trailers); } catch (const CelException& e) { ENVOY_LOG_MISC(debug, "CelException: {}", e.what()); diff --git a/test/extensions/formatter/cel/cel_test.cc b/test/extensions/formatter/cel/cel_test.cc index f3680af88c4b..2ada1036d0b5 100644 --- a/test/extensions/formatter/cel/cel_test.cc +++ b/test/extensions/formatter/cel/cel_test.cc @@ -34,6 +34,14 @@ class CELFormatterTest : public ::testing::Test { }; #ifdef USE_CEL_PARSER +TEST_F(CELFormatterTest, TestNodeId) { + auto cel_parser = std::make_unique(context_.server_factory_context_); + absl::optional max_length = absl::nullopt; + auto formatter = cel_parser->parse("CEL", "xds.node.id", max_length); + EXPECT_THAT(formatter->formatValueWithContext(formatter_context_, stream_info_), + ProtoEq(ValueUtil::stringValue("node_name"))); +} + TEST_F(CELFormatterTest, TestFormatValue) { auto cel_parser = std::make_unique(context_.server_factory_context_); absl::optional max_length = absl::nullopt; From f27ed961a8c023c046599a090d7c549ddf65a86d Mon Sep 17 00:00:00 2001 From: code Date: Tue, 19 Dec 2023 23:12:57 +0800 Subject: [PATCH 024/126] docs: update route specified filter chain related docs (#31158) * route: allow empty FilterConfig in the route configuration Signed-off-by: wbpcode * change log Signed-off-by: wbpcode * more detailed change log Signed-off-by: wbpcode * fix test Signed-off-by: wbpcode * minor update Signed-off-by: wbpcode * Update changelogs/current.yaml Co-authored-by: Adi (Suissa) Peleg Signed-off-by: code * revert code change and update docs Signed-off-by: wbpcode * docs update Signed-off-by: wbpcode * Update docs/root/intro/arch_overview/http/http_filters.rst Co-authored-by: Adi (Suissa) Peleg Signed-off-by: code * Update docs/root/intro/arch_overview/http/http_filters.rst Co-authored-by: Adi (Suissa) Peleg Signed-off-by: code * Update docs/root/intro/arch_overview/http/http_filters.rst Co-authored-by: Adi (Suissa) Peleg Signed-off-by: code * minor update Signed-off-by: wbpcode --------- Signed-off-by: wbpcode Signed-off-by: code Co-authored-by: Adi (Suissa) Peleg --- .../config/route/v3/route_components.proto | 2 + .../v3/http_connection_manager.proto | 10 +-- .../intro/arch_overview/http/http_filters.rst | 67 +++++++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/api/envoy/config/route/v3/route_components.proto b/api/envoy/config/route/v3/route_components.proto index 0fb1e4244ea8..1e2b486d288b 100644 --- a/api/envoy/config/route/v3/route_components.proto +++ b/api/envoy/config/route/v3/route_components.proto @@ -2417,6 +2417,8 @@ message FilterConfig { bool is_optional = 2; // If true, the filter is disabled in the route or virtual host and the ``config`` field is ignored. + // See :ref:`route based filter chain ` + // for more details. // // .. note:: // diff --git a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto index 55c6f1aa5b1d..7a92259eb43b 100644 --- a/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto +++ b/api/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto @@ -1172,14 +1172,8 @@ message HttpFilter { // If true, the filter is disabled by default and must be explicitly enabled by setting // per filter configuration in the route configuration. - // - // A disabled filter will be treated as enabled in the following cases: - // - // 1. Valid per filter configuration is configured in the ``typed_per_filter_config`` of route config. - // 2. :ref:`FilterConfig ` is configured in the - // ``typed_per_filter_config`` of route config and the - // :ref:`disabled of FilterConfig ` - // is set to false. + // See :ref:`route based filter chain ` + // for more details. // // Terminal filters (e.g. ``envoy.filters.http.router``) cannot be marked as disabled. bool disabled = 7; diff --git a/docs/root/intro/arch_overview/http/http_filters.rst b/docs/root/intro/arch_overview/http/http_filters.rst index 1137cffa5dc4..5486ff37402c 100644 --- a/docs/root/intro/arch_overview/http/http_filters.rst +++ b/docs/root/intro/arch_overview/http/http_filters.rst @@ -148,3 +148,70 @@ the filter config name. Use of per filter config map is filter specific. See the :ref:`HTTP filter documentation ` for if and how it is utilized for every filter. + +.. _arch_overview_http_filters_route_based_filter_chain: + +Route based filter chain +------------------------ + +There is support for having different filter chains for different routes. There are two different modes for this: + +* Disabling a filter in the filter chain for specific routes. +* Overriding a filter in the filter chain that is disabled by default and enabling it for specific + routes. + +By default, the filter chain is the same for all routes and all filters are enabled. However, a filter +can be disabled for specific routes by using the :ref:`FilterConfig ` +and setting the :ref:`disabled field ` in the +per filter config map in the route configuration. See the +:ref:`Route specific config ` section for more details. + +For example, given following http filter config: + +.. code-block:: yaml + + http_filters: + - name: buffer + typed_config: { ... } + - name: lua + typed_config: { ... } + +Both the ``buffer`` and ``lua`` filters are enabled by default. If we want to disable the ``buffer`` filter +for a specific route, we can set the per filter config map in the route configuration: + +.. code-block:: yaml + + typed_per_filter_config: + buffer: + "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig + disabled: true + +In addition, we can set a filter to be disabled by default by setting the :ref:`disabled field +` +in the HttpFilter configuration and then enable it for specific routes if needed. + +For example, given following http filter config: + +.. code-block:: yaml + + http_filters: + - name: buffer + typed_config: { ... } + disabled: true + - name: lua + typed_config: { ... } + disabled: true + +Both the ``buffer`` and ``lua`` filters are disabled by default. If we want to enable one of them +for a specific route, we can set per filter config map in the route configuration: + +.. code-block:: yaml + + typed_per_filter_config: + lua: + "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.LuaPerRoute + name: my_lua_script + + +Legitimate route-specific configuration for filter (like the above ``lua`` filter) is valid way to +enable the filter for the route. From ac52d65ad4dc639820c2c9bb7e09eb4a98449130 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:41:42 +0000 Subject: [PATCH 025/126] deps: Bump `proxy_wasm_cpp_sdk` -> 921039a (#31430) Signed-off-by: Ryan Northey Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 5674ac4e62cb..5fdba9b412bf 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1363,8 +1363,8 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "WebAssembly for Proxies (C++ SDK)", project_desc = "WebAssembly for Proxies (C++ SDK)", project_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-sdk", - version = "e30535b7c0cd3126e6401bc3769063a74bbb37be", - sha256 = "94e474ebea782225821224734ed5992fa749301e12e06b6520b8b4d4e1c05ffc", + version = "921039ae983ce053bf5cba78a85a3c08ff9791e5", + sha256 = "a11adfe4e6346d3318ff72643aa5569dc8439d7e8927ed148f93226fa255cc7a", strip_prefix = "proxy-wasm-cpp-sdk-{version}", urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], @@ -1380,7 +1380,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.wasm.runtime.wavm", "envoy.wasm.runtime.wasmtime", ], - release_date = "2022-03-15", + release_date = "2023-05-01", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/blob/{version}/LICENSE", From ff991f3454b426bfec49c752d1e7ffbafa9fdd76 Mon Sep 17 00:00:00 2001 From: Kuat Date: Tue, 19 Dec 2023 08:57:23 -0800 Subject: [PATCH 026/126] stream info: add listener info (#31365) Commit Message: Expose listener info in stream info. Additional Description: Add relevant accessors in the access log and CEL attributes. Risk Level: low Testing: added Docs Changes: yes Release Notes: yes Fixes: #24303 --- .../formatter/metadata/v3/metadata.proto | 1 + changelogs/current.yaml | 9 ++++++++ .../arch_overview/advanced/attributes.rst | 19 ++++++++------- envoy/network/listener.h | 6 +++-- envoy/network/socket.h | 12 ++++++++++ source/common/http/filter_manager.h | 3 +++ source/common/listener_manager/BUILD | 1 + .../active_stream_listener_base.cc | 1 + .../common/listener_manager/listener_impl.h | 9 ++++---- .../listener_manager/listener_manager_impl.cc | 2 +- source/common/network/BUILD | 1 + source/common/network/socket_impl.h | 8 +++++++ .../extensions/filters/common/expr/context.cc | 10 ++++++++ .../extensions/filters/common/expr/context.h | 2 ++ .../extensions/formatter/metadata/metadata.cc | 23 +++++++++++++++++++ source/server/BUILD | 1 + source/server/admin/BUILD | 1 + source/server/admin/admin.cc | 3 ++- source/server/admin/admin.h | 5 ++-- source/server/admin/admin_factory_context.h | 5 ++-- source/server/api_listener_impl.cc | 1 + source/server/config_validation/BUILD | 1 + source/server/config_validation/server.cc | 3 ++- source/server/factory_context_impl.cc | 12 ++++------ source/server/factory_context_impl.h | 9 +++----- .../active_internal_listener_test.cc | 9 +++++--- .../proxy_protocol_regression_test.cc | 9 +++++--- .../filters/common/expr/context_test.cc | 19 +++++++++++++++ .../common/fuzz/listener_filter_fuzzer.cc | 3 ++- .../common/fuzz/listener_filter_fuzzer.h | 6 +++-- .../proxy_protocol/proxy_protocol_test.cc | 18 ++++++++++----- .../formatter/metadata/metadata_test.cc | 17 ++++++++++++++ test/integration/fake_upstream.h | 9 +++++--- test/mocks/network/mocks.cc | 3 ++- test/mocks/network/mocks.h | 4 ++-- test/server/admin/BUILD | 1 + .../admin/admin_factory_context_test.cc | 4 +++- test/server/admin/admin_test.cc | 2 +- test/server/connection_handler_test.cc | 14 +++++++---- 39 files changed, 205 insertions(+), 61 deletions(-) diff --git a/api/envoy/extensions/formatter/metadata/v3/metadata.proto b/api/envoy/extensions/formatter/metadata/v3/metadata.proto index 90f6094b3c27..bf79f76741b5 100644 --- a/api/envoy/extensions/formatter/metadata/v3/metadata.proto +++ b/api/envoy/extensions/formatter/metadata/v3/metadata.proto @@ -21,6 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // * CLUSTER // * ROUTE // * UPSTREAM_HOST +// * LISTENER // // See :ref:`here ` for more information on access log configuration. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 7a51dd282778..9114296017ab 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -303,7 +303,16 @@ new_features: change: | Added new access log command operator ``%EMIT_TIME%`` to get the time when the log entry is emitted. - area: access_log + change: | + Added support for listener metadata in ``%METADATA%`` formatter. +- area: attributes + change: | + Added support for listener metadata and listener direction in XDS attributes. +- area: attributes change: | Added support for node data in ``%CEL%`` formatter. deprecated: +- area: wasm + change: | + Wasm-specific configuration attributes are deprecated in favor of ``xds`` attributes. diff --git a/docs/root/intro/arch_overview/advanced/attributes.rst b/docs/root/intro/arch_overview/advanced/attributes.rst index 840bebfebf82..aabbf41ce368 100644 --- a/docs/root/intro/arch_overview/advanced/attributes.rst +++ b/docs/root/intro/arch_overview/advanced/attributes.rst @@ -177,8 +177,11 @@ following attributes: :header: Attribute, Type, Description :widths: 1, 1, 4 + xds.node, :ref:`Node`, Local node description xds.cluster_name, string, Upstream cluster name xds.cluster_metadata, :ref:`Metadata`, Upstream cluster metadata + xds.listener_direction, int, Enumeration value of the :ref:`listener traffic direction` + xds.listener_metadata, :ref:`Metadata`, Listener metadata xds.route_name, string, Route name xds.route_metadata, :ref:`Metadata`, Route metadata xds.upstream_host_metadata, :ref:`Metadata`, Upstream host metadata @@ -197,14 +200,14 @@ In addition to all above, the following extra attributes are available to Wasm e plugin_name, string, Plugin name plugin_root_id, string, Plugin root ID plugin_vm_id, string, Plugin VM ID - node, :ref:`Node`, Local node description - cluster_name, string, Upstream cluster name - cluster_metadata, :ref:`Metadata`, Upstream cluster metadata - listener_direction, int, Enumeration value of the :ref:`listener traffic direction` - listener_metadata, :ref:`Metadata`, Listener metadata - route_name, string, Route name - route_metadata, :ref:`Metadata`, Route metadata - upstream_host_metadata, :ref:`Metadata`, Upstream host metadata + node, :ref:`Node`, Local node description. DEPRECATED: please use `xds` attributes. + cluster_name, string, Upstream cluster name. DEPRECATED: please use `xds` attributes. + cluster_metadata, :ref:`Metadata`, Upstream cluster metadata. DEPRECATED: please use `xds` attributes. + listener_direction, int, Enumeration value of the :ref:`listener traffic direction`. DEPRECATED: please use `xds` attributes. + listener_metadata, :ref:`Metadata`, Listener metadata. DEPRECATED: please use `xds` attributes. + route_name, string, Route name. DEPRECATED: please use `xds` attributes. + route_metadata, :ref:`Metadata`, Route metadata. DEPRECATED: please use `xds` attributes. + upstream_host_metadata, :ref:`Metadata`, Upstream host metadata. DEPRECATED: please use `xds` attributes. Path expressions ---------------- diff --git a/envoy/network/listener.h b/envoy/network/listener.h index 8c742cf5dcd9..117fb0fa4871 100644 --- a/envoy/network/listener.h +++ b/envoy/network/listener.h @@ -164,6 +164,8 @@ class ListenerInfo { virtual bool isQuic() const PURE; }; +using ListenerInfoConstSharedPtr = std::shared_ptr; + /** * A configuration for an individual listener. */ @@ -238,9 +240,9 @@ class ListenerConfig { virtual const std::string& name() const PURE; /** - * @return ListenerInfo& description of the listener. + * @return ListenerInfoConstSharedPtr& description of the listener. */ - virtual const ListenerInfo& listenerInfo() const PURE; + virtual const ListenerInfoConstSharedPtr& listenerInfo() const PURE; /** * @return the UDP configuration for the listener IFF it is a UDP listener. diff --git a/envoy/network/socket.h b/envoy/network/socket.h index b59f09871c80..b83d0f213047 100644 --- a/envoy/network/socket.h +++ b/envoy/network/socket.h @@ -176,6 +176,8 @@ class FilterChainInfo { virtual absl::string_view name() const PURE; }; +class ListenerInfo; + using FilterChainInfoConstSharedPtr = std::shared_ptr; /** @@ -253,6 +255,11 @@ class ConnectionInfoProvider { * @return the filter chain info provider backing this socket. */ virtual OptRef filterChainInfo() const PURE; + + /** + * @return the listener info backing this socket. + */ + virtual OptRef listenerInfo() const PURE; }; class ConnectionInfoSetter : public ConnectionInfoProvider { @@ -324,6 +331,11 @@ class ConnectionInfoSetter : public ConnectionInfoProvider { * @param filter_chain_info the filter chain info provider backing this socket. */ virtual void setFilterChainInfo(FilterChainInfoConstSharedPtr filter_chain_info) PURE; + + /** + * @param listener_info the listener info provider backing this socket. + */ + virtual void setListenerInfo(std::shared_ptr listener_info) PURE; }; using ConnectionInfoSetterSharedPtr = std::shared_ptr; diff --git a/source/common/http/filter_manager.h b/source/common/http/filter_manager.h index a1499f0ea4d5..42c02e594d23 100644 --- a/source/common/http/filter_manager.h +++ b/source/common/http/filter_manager.h @@ -617,6 +617,9 @@ class OverridableRemoteConnectionInfoSetterStreamInfo : public StreamInfo::Strea OptRef filterChainInfo() const override { return StreamInfoImpl::downstreamAddressProvider().filterChainInfo(); } + OptRef listenerInfo() const override { + return StreamInfoImpl::downstreamAddressProvider().listenerInfo(); + } private: Network::Address::InstanceConstSharedPtr overridden_downstream_remote_address_; diff --git a/source/common/listener_manager/BUILD b/source/common/listener_manager/BUILD index bced882ff9d3..3c682e02966f 100644 --- a/source/common/listener_manager/BUILD +++ b/source/common/listener_manager/BUILD @@ -24,6 +24,7 @@ envoy_cc_library( ":connection_handler_lib", ":filter_chain_manager_lib", ":lds_api_lib", + ":listener_info_lib", "//envoy/access_log:access_log_interface", "//envoy/config:typed_metadata_interface", "//envoy/network:connection_interface", diff --git a/source/common/listener_manager/active_stream_listener_base.cc b/source/common/listener_manager/active_stream_listener_base.cc index e7f74c14b1f6..42a6f413da58 100644 --- a/source/common/listener_manager/active_stream_listener_base.cc +++ b/source/common/listener_manager/active_stream_listener_base.cc @@ -51,6 +51,7 @@ void ActiveStreamListenerBase::newConnection(Network::ConnectionSocketPtr&& sock return; } + socket->connectionInfoProvider().setListenerInfo(config_->listenerInfo()); socket->connectionInfoProvider().setFilterChainInfo( std::make_shared(filter_chain->name())); diff --git a/source/common/listener_manager/listener_impl.h b/source/common/listener_manager/listener_impl.h index af3650ebb841..9bb5b8702411 100644 --- a/source/common/listener_manager/listener_impl.h +++ b/source/common/listener_manager/listener_impl.h @@ -119,6 +119,8 @@ class ListenSocketFactoryImpl : public Network::ListenSocketFactory, // TODO(mattklein123): Consider getting rid of pre-worker start and post-worker start code by // initializing all listeners after workers are started. +class ListenerImpl; + /** * The common functionality shared by PerListenerFilterFactoryContexts and * PerFilterChainFactoryFactoryContexts. @@ -143,13 +145,12 @@ class ListenerFactoryContextBaseImpl final : public Server::FactoryContextImplBa return nullptr; } Server::DrainManager& drainManager(); + friend class ListenerImpl; private: const Server::DrainManagerPtr drain_manager_; }; -class ListenerImpl; - // TODO(lambdai): Strip the interface since ListenerFactoryContext only need to support // ListenerFilterChain creation. e.g, Is listenerMetaData() required? Is it required only at // listener update or during the lifetime of listener? @@ -315,9 +316,9 @@ class ListenerImpl final : public Network::ListenerConfig, } Init::Manager& initManager() override; bool ignoreGlobalConnLimit() const override { return ignore_global_conn_limit_; } - const Network::ListenerInfo& listenerInfo() const override { + const Network::ListenerInfoConstSharedPtr& listenerInfo() const override { ASSERT(listener_factory_context_ != nullptr); - return listener_factory_context_->listenerInfo(); + return listener_factory_context_->listener_factory_context_base_->listener_info_; } void ensureSocketOptions(Network::Socket::OptionsSharedPtr& options) { diff --git a/source/common/listener_manager/listener_manager_impl.cc b/source/common/listener_manager/listener_manager_impl.cc index 8de2641edc52..c503efd8ccf0 100644 --- a/source/common/listener_manager/listener_manager_impl.cc +++ b/source/common/listener_manager/listener_manager_impl.cc @@ -993,7 +993,7 @@ void ListenerManagerImpl::stopListeners(StopListenersType stop_listeners_type, stop_listeners_type_ = stop_listeners_type; for (Network::ListenerConfig& listener : listeners()) { if (stop_listeners_type != StopListenersType::InboundOnly || - listener.listenerInfo().direction() == envoy::config::core::v3::INBOUND) { + listener.listenerInfo()->direction() == envoy::config::core::v3::INBOUND) { ENVOY_LOG(debug, "begin stop listener: name={}", listener.name()); auto existing_warming_listener = getListenerByName(warming_listeners_, listener.name()); // Destroy a warming listener directly. diff --git a/source/common/network/BUILD b/source/common/network/BUILD index e9fef1bf4cda..f91ba321c879 100644 --- a/source/common/network/BUILD +++ b/source/common/network/BUILD @@ -274,6 +274,7 @@ envoy_cc_library( srcs = ["socket_impl.cc"], hdrs = ["socket_impl.h"], deps = [ + "//envoy/network:listener_interface", "//envoy/network:socket_interface", "//envoy/network:socket_interface_interface", "//source/common/api:os_sys_calls_lib", diff --git a/source/common/network/socket_impl.h b/source/common/network/socket_impl.h index 62cdc572c2ff..2becca95532d 100644 --- a/source/common/network/socket_impl.h +++ b/source/common/network/socket_impl.h @@ -1,5 +1,6 @@ #pragma once +#include "envoy/network/listener.h" #include "envoy/network/socket.h" #include "envoy/network/socket_interface.h" @@ -79,6 +80,12 @@ class ConnectionInfoSetterImpl : public ConnectionInfoSetter { void setFilterChainInfo(FilterChainInfoConstSharedPtr filter_chain_info) override { filter_chain_info_ = std::move(filter_chain_info); } + OptRef listenerInfo() const override { + return makeOptRefFromPtr(listener_info_.get()); + } + void setListenerInfo(ListenerInfoConstSharedPtr listener_info) override { + listener_info_ = std::move(listener_info); + } private: Address::InstanceConstSharedPtr local_address_; @@ -93,6 +100,7 @@ class ConnectionInfoSetterImpl : public ConnectionInfoSetter { std::string ja3_hash_; absl::optional round_trip_time_; FilterChainInfoConstSharedPtr filter_chain_info_; + ListenerInfoConstSharedPtr listener_info_; }; class SocketImpl : public virtual Socket { diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc index a40fdd735e5d..a609e8be884a 100644 --- a/source/extensions/filters/common/expr/context.cc +++ b/source/extensions/filters/common/expr/context.cc @@ -385,6 +385,16 @@ absl::optional XDSWrapper::operator[](CelValue key) const { const absl::string_view filter_chain_name = filter_chain_info.has_value() ? filter_chain_info->name() : absl::string_view{}; return CelValue::CreateStringView(filter_chain_name); + } else if (value == ListenerMetadata) { + const auto listener_info = info_.downstreamAddressProvider().listenerInfo(); + if (listener_info) { + return CelProtoWrapper::CreateMessage(&listener_info->metadata(), &arena_); + } + } else if (value == ListenerDirection) { + const auto listener_info = info_.downstreamAddressProvider().listenerInfo(); + if (listener_info) { + return CelValue::CreateInt64(listener_info->direction()); + } } else if (value == Node) { if (local_info_) { return CelProtoWrapper::CreateMessage(&local_info_->node(), &arena_); diff --git a/source/extensions/filters/common/expr/context.h b/source/extensions/filters/common/expr/context.h index 0308671984f8..ff1f127373cf 100644 --- a/source/extensions/filters/common/expr/context.h +++ b/source/extensions/filters/common/expr/context.h @@ -89,6 +89,8 @@ constexpr absl::string_view RouteName = "route_name"; constexpr absl::string_view RouteMetadata = "route_metadata"; constexpr absl::string_view UpstreamHostMetadata = "upstream_host_metadata"; constexpr absl::string_view FilterChainName = "filter_chain_name"; +constexpr absl::string_view ListenerMetadata = "listener_metadata"; +constexpr absl::string_view ListenerDirection = "listener_direction"; constexpr absl::string_view Node = "node"; class WrapperFieldValues { diff --git a/source/extensions/formatter/metadata/metadata.cc b/source/extensions/formatter/metadata/metadata.cc index 873912edadb4..4bf5b939c7c9 100644 --- a/source/extensions/formatter/metadata/metadata.cc +++ b/source/extensions/formatter/metadata/metadata.cc @@ -29,6 +29,23 @@ class RouteMetadataFormatter : public ::Envoy::Formatter::MetadataFormatter { }) {} }; +// Metadata formatter for listener metadata. +class ListenerMetadataFormatter : public ::Envoy::Formatter::MetadataFormatter { +public: + ListenerMetadataFormatter(const std::string& filter_namespace, + const std::vector& path, absl::optional max_length) + : ::Envoy::Formatter::MetadataFormatter( + filter_namespace, path, max_length, + [](const StreamInfo::StreamInfo& stream_info) + -> const envoy::config::core::v3::Metadata* { + const auto listener_info = stream_info.downstreamAddressProvider().listenerInfo(); + if (listener_info) { + return &listener_info->metadata(); + } + return nullptr; + }) {} +}; + // Constructor registers all types of supported metadata along with the // handlers accessing the required metadata type. MetadataFormatterCommandParser::MetadataFormatterCommandParser() { @@ -55,6 +72,12 @@ MetadataFormatterCommandParser::MetadataFormatterCommandParser() { return std::make_unique<::Envoy::Formatter::UpstreamHostMetadataFormatter>(filter_namespace, path, max_length); }; + + metadata_formatter_providers_["LISTENER"] = [](const std::string& filter_namespace, + const std::vector& path, + absl::optional max_length) { + return std::make_unique(filter_namespace, path, max_length); + }; } ::Envoy::Formatter::FormatterProviderPtr diff --git a/source/server/BUILD b/source/server/BUILD index 6cdecb25bd94..82e7eeb9a56b 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -341,6 +341,7 @@ envoy_cc_library( "//source/common/config:utility_lib", "//source/common/init:manager_lib", "//source/common/init:target_lib", + "//source/common/listener_manager:listener_info_lib", "//source/common/network:utility_lib", "//source/common/stream_info:stream_info_lib", "//source/extensions/filters/network/http_connection_manager:config", diff --git a/source/server/admin/BUILD b/source/server/admin/BUILD index 3870114d680c..3913191068d4 100644 --- a/source/server/admin/BUILD +++ b/source/server/admin/BUILD @@ -79,6 +79,7 @@ envoy_cc_library( "//source/common/http:header_map_lib", "//source/common/http:headers_lib", "//source/common/http:utility_lib", + "//source/common/listener_manager:listener_info_lib", "//source/common/listener_manager:listener_manager_lib", "//source/common/memory:utils_lib", "//source/common/network:connection_balancer_lib", diff --git a/source/server/admin/admin.cc b/source/server/admin/admin.cc index ab1f97d90037..9a40639a60c7 100644 --- a/source/server/admin/admin.cc +++ b/source/server/admin/admin.cc @@ -108,7 +108,8 @@ Http::HeaderValidatorFactoryPtr createHeaderValidatorFactory( AdminImpl::AdminImpl(const std::string& profile_path, Server::Instance& server, bool ignore_global_conn_limit) - : server_(server), factory_context_(server), + : server_(server), listener_info_(std::make_shared()), + factory_context_(server, listener_info_), request_id_extension_(Extensions::RequestId::UUIDRequestIDExtension::defaultInstance( server_.api().randomGenerator())), profile_path_(profile_path), stats_(Http::ConnectionManagerImpl::generateStats( diff --git a/source/server/admin/admin.h b/source/server/admin/admin.h index a83d9f2682d2..c77be2b2b92b 100644 --- a/source/server/admin/admin.h +++ b/source/server/admin/admin.h @@ -389,8 +389,8 @@ class AdminImpl : public Admin, Stats::Scope& listenerScope() override { return scope_; } uint64_t listenerTag() const override { return 0; } const std::string& name() const override { return name_; } - const Network::ListenerInfo& listenerInfo() const override { - return parent_.factoryContext().listenerInfo(); + const Network::ListenerInfoConstSharedPtr& listenerInfo() const override { + return parent_.listener_info_; } Network::UdpListenerConfigOptRef udpListenerConfig() override { return {}; } Network::InternalListenerConfigOptRef internalListenerConfig() override { return {}; } @@ -449,6 +449,7 @@ class AdminImpl : public Admin, }; Server::Instance& server_; + const Network::ListenerInfoConstSharedPtr listener_info_; AdminFactoryContext factory_context_; Http::RequestIDExtensionSharedPtr request_id_extension_; std::list access_logs_; diff --git a/source/server/admin/admin_factory_context.h b/source/server/admin/admin_factory_context.h index 4e55dd04c81b..ab38ff179748 100644 --- a/source/server/admin/admin_factory_context.h +++ b/source/server/admin/admin_factory_context.h @@ -10,10 +10,11 @@ namespace Server { class AdminFactoryContext final : public FactoryContextImplBase { public: - AdminFactoryContext(Envoy::Server::Instance& server) + AdminFactoryContext(Envoy::Server::Instance& server, + const Network::ListenerInfoConstSharedPtr& listener_info) : FactoryContextImplBase(server, server.messageValidationContext().staticValidationVisitor(), server.stats().createScope(""), - server.stats().createScope("listener.admin.")) {} + server.stats().createScope("listener.admin."), listener_info) {} Init::Manager& initManager() override { // Reuse the server init manager to avoid creating a new one for this special listener. diff --git a/source/server/api_listener_impl.cc b/source/server/api_listener_impl.cc index 48bbe8236739..d947a0549c7a 100644 --- a/source/server/api_listener_impl.cc +++ b/source/server/api_listener_impl.cc @@ -5,6 +5,7 @@ #include "envoy/stats/scope.h" #include "source/common/http/conn_manager_impl.h" +#include "source/common/listener_manager/listener_info_impl.h" #include "source/common/network/resolver_impl.h" #include "source/common/protobuf/utility.h" #include "source/extensions/filters/network/http_connection_manager/config.h" diff --git a/source/server/config_validation/BUILD b/source/server/config_validation/BUILD index f4006850893b..eba39b9bc6d2 100644 --- a/source/server/config_validation/BUILD +++ b/source/server/config_validation/BUILD @@ -90,6 +90,7 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/config:utility_lib", "//source/common/grpc:common_lib", + "//source/common/listener_manager:listener_info_lib", "//source/common/local_info:local_info_lib", "//source/common/protobuf:utility_lib", "//source/common/quic:quic_stat_names_lib", diff --git a/source/server/config_validation/server.cc b/source/server/config_validation/server.cc index 664462c7ec2a..f8d6e31813d6 100644 --- a/source/server/config_validation/server.cc +++ b/source/server/config_validation/server.cc @@ -8,6 +8,7 @@ #include "source/common/config/utility.h" #include "source/common/config/well_known_names.h" #include "source/common/event/real_time_system.h" +#include "source/common/listener_manager/listener_info_impl.h" #include "source/common/local_info/local_info_impl.h" #include "source/common/protobuf/utility.h" #include "source/common/singleton/manager_impl.h" @@ -112,7 +113,7 @@ void ValidationInstance::initialize(const Options& options, dispatcher(), *stats().rootScope(), threadLocal(), bootstrap_.overload_manager(), messageValidationContext().staticValidationVisitor(), *api_, options_); Configuration::InitialImpl initial_config(bootstrap_); - AdminFactoryContext factory_context(*this); + AdminFactoryContext factory_context(*this, std::make_shared()); initial_config.initAdminAccessLog(bootstrap_, factory_context); admin_ = std::make_unique(initial_config.admin().address()); listener_manager_ = Config::Utility::getAndCheckFactoryByName( diff --git a/source/server/factory_context_impl.cc b/source/server/factory_context_impl.cc index e1a295588633..63232e6c5f38 100644 --- a/source/server/factory_context_impl.cc +++ b/source/server/factory_context_impl.cc @@ -6,12 +6,10 @@ namespace Server { FactoryContextImplBase::FactoryContextImplBase( Server::Instance& server, ProtobufMessage::ValidationVisitor& validation_visitor, Stats::ScopeSharedPtr scope, Stats::ScopeSharedPtr listener_scope, - ListenerInfoConstSharedPtr listener_info) + const Network::ListenerInfoConstSharedPtr& listener_info) : server_(server), validation_visitor_(validation_visitor), scope_(std::move(scope)), - listener_scope_(std::move(listener_scope)), listener_info_(std::move(listener_info)) { - if (listener_info_ == nullptr) { - listener_info_ = std::make_shared(); - } + listener_scope_(std::move(listener_scope)), listener_info_(listener_info) { + ASSERT(listener_info_ != nullptr); } Configuration::ServerFactoryContext& FactoryContextImplBase::serverFactoryContext() const { @@ -39,9 +37,9 @@ FactoryContextImpl::FactoryContextImpl(Server::Instance& server, Network::DrainDecision& drain_decision, Stats::ScopeSharedPtr scope, Stats::ScopeSharedPtr listener_scope, - ListenerInfoConstSharedPtr listener_info) + const Network::ListenerInfoConstSharedPtr& listener_info) : FactoryContextImplBase(server, server.messageValidationContext().staticValidationVisitor(), - std::move(scope), std::move(listener_scope), std::move(listener_info)), + std::move(scope), std::move(listener_scope), listener_info), drain_decision_(drain_decision) {} Init::Manager& FactoryContextImpl::initManager() { return server_.initManager(); } diff --git a/source/server/factory_context_impl.h b/source/server/factory_context_impl.h index bd9fcdafafa7..fd476a148d04 100644 --- a/source/server/factory_context_impl.h +++ b/source/server/factory_context_impl.h @@ -4,19 +4,16 @@ #include "envoy/server/instance.h" #include "source/common/config/metadata.h" -#include "source/common/listener_manager/listener_info_impl.h" namespace Envoy { namespace Server { -using ListenerInfoConstSharedPtr = std::shared_ptr; - class FactoryContextImplBase : virtual public Configuration::FactoryContext { public: FactoryContextImplBase(Server::Instance& server, ProtobufMessage::ValidationVisitor& validation_visitor, Stats::ScopeSharedPtr scope, Stats::ScopeSharedPtr listener_scope, - ListenerInfoConstSharedPtr listener_info = nullptr); + const Network::ListenerInfoConstSharedPtr& listener_info); // Configuration::FactoryContext Configuration::ServerFactoryContext& serverFactoryContext() const override; @@ -34,7 +31,7 @@ class FactoryContextImplBase : virtual public Configuration::FactoryContext { Stats::ScopeSharedPtr scope_; // Listener scope with the listener prefix. Stats::ScopeSharedPtr listener_scope_; - ListenerInfoConstSharedPtr listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; /** @@ -44,7 +41,7 @@ class FactoryContextImpl : public FactoryContextImplBase { public: FactoryContextImpl(Server::Instance& server, Network::DrainDecision& drain_decision, Stats::ScopeSharedPtr scope, Stats::ScopeSharedPtr listener_scope, - ListenerInfoConstSharedPtr listener_info); + const Network::ListenerInfoConstSharedPtr& listener_info); // Configuration::FactoryContext Init::Manager& initManager() override; diff --git a/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc b/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc index d92082c6d101..d739f795d5a8 100644 --- a/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc +++ b/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc @@ -271,7 +271,8 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable() : connection_balancer), access_logs_({access_log}), inline_filter_chain_manager_(filter_chain_manager), - init_manager_(nullptr), ignore_global_conn_limit_(ignore_global_conn_limit) { + init_manager_(nullptr), ignore_global_conn_limit_(ignore_global_conn_limit), + listener_info_(std::make_shared>()) { socket_factories_.emplace_back(std::make_unique()); ON_CALL(*socket_, socketType()).WillByDefault(Return(socket_type)); } @@ -323,7 +324,9 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable> inline_filter_chain_manager_; std::unique_ptr init_manager_; const bool ignore_global_conn_limit_; - testing::NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; using TestListenerPtr = std::unique_ptr; diff --git a/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc b/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc index 5b1eab44a883..ee5732e61735 100644 --- a/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc +++ b/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc @@ -46,7 +46,8 @@ class ProxyProtocolRegressionTest : public testing::TestWithParam>()) { socket_factories_.emplace_back(std::make_unique()); EXPECT_CALL(*static_cast(socket_factories_[0].get()), socketType()) @@ -85,7 +86,9 @@ class ProxyProtocolRegressionTest : public testing::TestWithParam init_manager_; NiceMock runtime_; testing::NiceMock random_; - testing::NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; // Parameterize the listener socket address version. diff --git a/test/extensions/filters/common/expr/context_test.cc b/test/extensions/filters/common/expr/context_test.cc index 0c4f449d9ba2..556424e8c3cc 100644 --- a/test/extensions/filters/common/expr/context_test.cc +++ b/test/extensions/filters/common/expr/context_test.cc @@ -848,6 +848,13 @@ TEST(Context, XDSAttributes) { filter_chain_info->filter_chain_name_ = "fake_filter_chain_name"; info.downstream_connection_info_provider_->setFilterChainInfo(filter_chain_info); + auto listener_info = std::make_shared>(); + envoy::config::core::v3::Metadata listener_metadata; + EXPECT_CALL(*listener_info, metadata()).WillRepeatedly(ReturnRef(listener_metadata)); + EXPECT_CALL(*listener_info, direction()) + .WillRepeatedly(Return(envoy::config::core::v3::TrafficDirection::OUTBOUND)); + info.downstream_connection_info_provider_->setListenerInfo(listener_info); + Protobuf::Arena arena; XDSWrapper wrapper(arena, info, &local_info); @@ -887,6 +894,18 @@ TEST(Context, XDSAttributes) { ASSERT_TRUE(value.value().IsString()); EXPECT_EQ(chain_name, value.value().StringOrDie().value()); } + { + const auto value = wrapper[CelValue::CreateStringView(ListenerMetadata)]; + EXPECT_TRUE(value.has_value()); + ASSERT_TRUE(value.value().IsMessage()); + EXPECT_EQ(&listener_metadata, value.value().MessageOrDie()); + } + { + const auto value = wrapper[CelValue::CreateStringView(ListenerDirection)]; + EXPECT_TRUE(value.has_value()); + ASSERT_TRUE(value.value().IsInt64()); + EXPECT_EQ(2, value.value().Int64OrDie()); + } { const auto value = wrapper[CelValue::CreateStringView(XDS)]; EXPECT_FALSE(value.has_value()); diff --git a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc index 1f4ab5ede664..428577783279 100644 --- a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc +++ b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc @@ -34,7 +34,8 @@ ListenerFilterWithDataFuzzer::ListenerFilterWithDataFuzzer() Network::Test::getCanonicalLoopbackAddress(Network::Address::IpVersion::v4))), connection_handler_(new Server::ConnectionHandlerImpl(*dispatcher_, absl::nullopt)), name_("proxy"), filter_chain_(Network::Test::createEmptyFilterChainWithRawBufferSockets()), - init_manager_(nullptr) { + init_manager_(nullptr), + listener_info_(std::make_shared>()) { socket_factories_.emplace_back(std::make_unique()); EXPECT_CALL(*static_cast(socket_factories_[0].get()), socketType()) diff --git a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h index e386400e5e22..f72a794a65df 100644 --- a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h +++ b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h @@ -63,7 +63,9 @@ class ListenerFilterWithDataFuzzer : public Network::ListenerConfig, const std::string& name() const override { return name_; } Network::UdpListenerConfigOptRef udpListenerConfig() override { return {}; } Network::InternalListenerConfigOptRef internalListenerConfig() override { return {}; } - const Network::ListenerInfo& listenerInfo() const override { return listener_info_; } + const Network::ListenerInfoConstSharedPtr& listenerInfo() const override { + return listener_info_; + } Network::ConnectionBalancer& connectionBalancer(const Network::Address::Instance&) override { return connection_balancer_; } @@ -114,7 +116,7 @@ class ListenerFilterWithDataFuzzer : public Network::ListenerConfig, const std::vector empty_access_logs_; std::unique_ptr init_manager_; bool connection_established_{}; - NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; } // namespace ListenerFilters 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 943a67a708e5..af16be2cff70 100644 --- a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc +++ b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc @@ -65,7 +65,8 @@ class ProxyProtocolTest : public testing::TestWithParam>()) { socket_factories_.emplace_back(std::make_unique()); EXPECT_CALL(*static_cast(socket_factories_[0].get()), socketType()) @@ -101,7 +102,9 @@ class ProxyProtocolTest : public testing::TestWithParam empty_access_logs_; std::unique_ptr init_manager_; - NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; // Parameterize the listener socket address version. @@ -1969,7 +1972,8 @@ class WildcardProxyProtocolTest : public testing::TestWithParamconnectionInfoProvider().localAddress()->ip()->port())), connection_handler_(new Server::ConnectionHandlerImpl(*dispatcher_, absl::nullopt)), name_("proxy"), filter_chain_(Network::Test::createEmptyFilterChainWithRawBufferSockets()), - init_manager_(nullptr) { + init_manager_(nullptr), + listener_info_(std::make_shared>()) { socket_factories_.emplace_back(std::make_unique()); EXPECT_CALL(*static_cast(socket_factories_[0].get()), socketType()) @@ -2014,7 +2018,9 @@ class WildcardProxyProtocolTest : public testing::TestWithParam empty_access_logs_; std::unique_ptr init_manager_; - NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; // Parameterize the listener socket address version. diff --git a/test/extensions/formatter/metadata/metadata_test.cc b/test/extensions/formatter/metadata/metadata_test.cc index d16492dca24b..a265a5ac9d26 100644 --- a/test/extensions/formatter/metadata/metadata_test.cc +++ b/test/extensions/formatter/metadata/metadata_test.cc @@ -129,6 +129,23 @@ TEST_F(MetadataFormatterTest, NonExistentRouteMetadata) { getTestMetadataFormatter("ROUTE")->formatWithContext(formatter_context_, stream_info_)); } +// Test that METADATA(LISTENER accesses stream_info listener metadata. +TEST_F(MetadataFormatterTest, ListenerMetadata) { + auto listener_info = std::make_shared>(); + EXPECT_CALL(*listener_info, metadata()).WillRepeatedly(testing::ReturnRef(*metadata_)); + stream_info_.downstream_connection_info_provider_->setListenerInfo(listener_info); + EXPECT_EQ( + "test_value", + getTestMetadataFormatter("LISTENER")->formatWithContext(formatter_context_, stream_info_)); +} + +// Test that METADATA(LISTENER handles no listener info. +TEST_F(MetadataFormatterTest, NoListenerMetadata) { + EXPECT_EQ( + "-", + getTestMetadataFormatter("LISTENER")->formatWithContext(formatter_context_, stream_info_)); +} + } // namespace Formatter } // namespace Extensions } // namespace Envoy diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index 91da42ea6dc3..0fd9bf07da94 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -856,7 +856,8 @@ class FakeUpstream : Logger::Loggable, }; FakeListener(FakeUpstream& parent, bool is_quic = false) - : parent_(parent), name_("fake_upstream"), init_manager_(nullptr) { + : parent_(parent), name_("fake_upstream"), init_manager_(nullptr), + listener_info_(std::make_shared>()) { if (is_quic) { #if defined(ENVOY_ENABLE_QUIC) udp_listener_config_.listener_factory_ = std::make_unique( @@ -898,7 +899,9 @@ class FakeUpstream : Logger::Loggable, const std::vector& accessLogs() const override { return empty_access_logs_; } - const Network::ListenerInfo& listenerInfo() const override { return listener_info_; } + const Network::ListenerInfoConstSharedPtr& listenerInfo() const override { + return listener_info_; + } ResourceLimit& openConnections() override { return connection_resource_; } uint32_t tcpBacklogSize() const override { return ENVOY_TCP_BACKLOG_SIZE; } uint32_t maxConnectionsToAcceptPerSocketEvent() const override { @@ -918,7 +921,7 @@ class FakeUpstream : Logger::Loggable, BasicResourceLimitImpl connection_resource_; const std::vector empty_access_logs_; std::unique_ptr init_manager_; - testing::NiceMock listener_info_; + const Network::ListenerInfoConstSharedPtr listener_info_; }; void threadRoutine(); diff --git a/test/mocks/network/mocks.cc b/test/mocks/network/mocks.cc index e2b8cd9267ba..1525608d43e8 100644 --- a/test/mocks/network/mocks.cc +++ b/test/mocks/network/mocks.cc @@ -33,7 +33,8 @@ MockUdpListenerConfig::MockUdpListenerConfig(uint32_t concurrency) MockUdpListenerConfig::~MockUdpListenerConfig() = default; MockListenerConfig::MockListenerConfig() - : socket_(std::make_shared>()) { + : socket_(std::make_shared>()), + listener_info_(std::make_shared>()) { socket_factories_.emplace_back(std::make_unique()); ON_CALL(*this, filterChainFactory()).WillByDefault(ReturnRef(filter_chain_factory_)); ON_CALL(*this, listenSocketFactories()).WillByDefault(ReturnRef(socket_factories_)); diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 8bfcc4aea5db..283bb4377df7 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -503,12 +503,12 @@ class MockListenerConfig : public ListenerConfig { return empty_access_logs_; } - const Network::ListenerInfo& listenerInfo() const override { return listener_info_; } + const ListenerInfoConstSharedPtr& listenerInfo() const override { return listener_info_; } testing::NiceMock filter_chain_factory_; std::vector socket_factories_; SocketSharedPtr socket_; - testing::NiceMock listener_info_; + ListenerInfoConstSharedPtr listener_info_; Stats::IsolatedStoreImpl store_; std::string name_; const std::vector empty_access_logs_; diff --git a/test/server/admin/BUILD b/test/server/admin/BUILD index 1efe0ee5e1ac..8e7c6ecce89f 100644 --- a/test/server/admin/BUILD +++ b/test/server/admin/BUILD @@ -25,6 +25,7 @@ envoy_cc_test( name = "admin_factory_context_test", srcs = ["admin_factory_context_test.cc"], deps = [ + "//source/common/listener_manager:listener_info_lib", "//source/server/admin:admin_factory_context", "//test/mocks/server:instance_mocks", ], diff --git a/test/server/admin/admin_factory_context_test.cc b/test/server/admin/admin_factory_context_test.cc index 2caef4098ae9..4a0bf5d9f459 100644 --- a/test/server/admin/admin_factory_context_test.cc +++ b/test/server/admin/admin_factory_context_test.cc @@ -1,3 +1,4 @@ +#include "source/common/listener_manager/listener_info_impl.h" #include "source/server/admin/admin_factory_context.h" #include "test/mocks/server/instance.h" @@ -10,8 +11,9 @@ namespace { TEST(AdminFactoryContextTest, AdminFactoryContextTest) { testing::NiceMock server; + const auto listener_info = std::make_shared(); - AdminFactoryContext context(server); + AdminFactoryContext context(server, listener_info); context.serverFactoryContext(); context.getTransportSocketFactoryContext(); diff --git a/test/server/admin/admin_test.cc b/test/server/admin/admin_test.cc index f5805ccefb00..c60a94323741 100644 --- a/test/server/admin/admin_test.cc +++ b/test/server/admin/admin_test.cc @@ -355,7 +355,7 @@ TEST_P(AdminInstanceTest, Overrides) { peer.listener().name(); peer.listener().udpListenerConfig(); - peer.listener().listenerInfo().direction(); + peer.listener().listenerInfo()->direction(); peer.listener().tcpBacklogSize(); } diff --git a/test/server/connection_handler_test.cc b/test/server/connection_handler_test.cc index 91dd0094686a..30612ed4f9c5 100644 --- a/test/server/connection_handler_test.cc +++ b/test/server/connection_handler_test.cc @@ -94,7 +94,8 @@ class ConnectionHandlerTest : public testing::Test, name_(name), listener_filters_timeout_(listener_filters_timeout), continue_on_listener_filters_timeout_(continue_on_listener_filters_timeout), access_logs_({access_log}), inline_filter_chain_manager_(filter_chain_manager), - init_manager_(nullptr), ignore_global_conn_limit_(ignore_global_conn_limit) { + init_manager_(nullptr), ignore_global_conn_limit_(ignore_global_conn_limit), + listener_info_(std::make_shared>()) { for (int i = 0; i < num_of_socket_factories; i++) { socket_factories_.emplace_back(std::make_unique()); sockets_.emplace_back(std::make_shared>()); @@ -105,7 +106,10 @@ class ConnectionHandlerTest : public testing::Test, udp_listener_config_->listener_factory_ = std::make_unique(1); udp_listener_config_->writer_factory_ = std::make_unique(); - ON_CALL(listener_info_, direction()).WillByDefault(Return(direction_)); + ON_CALL(*static_cast( + const_cast(listener_info_.get())), + direction()) + .WillByDefault(Return(direction_)); } struct UdpListenerConfigImpl : public Network::UdpListenerConfig { @@ -160,7 +164,9 @@ class ConnectionHandlerTest : public testing::Test, const std::string& name() const override { return name_; } Network::UdpListenerConfigOptRef udpListenerConfig() override { return *udp_listener_config_; } Network::InternalListenerConfigOptRef internalListenerConfig() override { return {}; } - const Network::ListenerInfo& listenerInfo() const override { return listener_info_; } + const Network::ListenerInfoConstSharedPtr& listenerInfo() const override { + return listener_info_; + } void setDirection(envoy::config::core::v3::TrafficDirection direction) { direction_ = direction; } @@ -197,7 +203,7 @@ class ConnectionHandlerTest : public testing::Test, const bool ignore_global_conn_limit_; envoy::config::core::v3::TrafficDirection direction_; absl::flat_hash_map udp_listener_callback_map_{}; - NiceMock listener_info_; + Network::ListenerInfoConstSharedPtr listener_info_; }; class TestListener : public TestListenerBase { From dddfcfbd135cd4737965f1c3c84001e0ed86c8e3 Mon Sep 17 00:00:00 2001 From: "dependency-envoy[bot]" <148525496+dependency-envoy[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:12:35 +0000 Subject: [PATCH 027/126] deps: Bump `proxy_wasm_cpp_host` -> e200fee (#31451) * deps: Bump `proxy_wasm_cpp_host` -> e200fee Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 5fdba9b412bf..7c4d5ca49dfb 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1389,8 +1389,8 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "WebAssembly for Proxies (C++ host implementation)", project_desc = "WebAssembly for Proxies (C++ host implementation)", project_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host", - version = "5d76116c449d6892b298b7ae79a84ef1cf5752bf", - sha256 = "a5825a1a5bbd5b0178c6189b227d5cf4370ac713a883b41f6a54edd768a03cb7", + version = "e200fee8af40918c41f3275cff090993e3b26940", + sha256 = "9711411b3b8d48a3ee9278f44824ce569c1fdd491183255f568f2b938360e964", strip_prefix = "proxy-wasm-cpp-host-{version}", urls = ["https://github.com/proxy-wasm/proxy-wasm-cpp-host/archive/{version}.tar.gz"], use_category = ["dataplane_ext"], @@ -1406,7 +1406,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( "envoy.wasm.runtime.wavm", "envoy.wasm.runtime.wasmtime", ], - release_date = "2023-06-01", + release_date = "2023-12-19", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/proxy-wasm/proxy-wasm-cpp-host/blob/{version}/LICENSE", From 483ecb2d4055b42a806f0a1003243ba62c86cf3a Mon Sep 17 00:00:00 2001 From: Jacob Bohanon Date: Tue, 19 Dec 2023 18:29:59 -0500 Subject: [PATCH 028/126] set_metadata: allow setting typed metadata (#31244) Signed-off-by: Jacob Bohanon --- .../filters/http/set_metadata/v3/BUILD | 5 +- .../http/set_metadata/v3/set_metadata.proto | 36 +- changelogs/current.yaml | 13 + .../http/http_filters/set_metadata_filter.rst | 23 +- .../filters/http/set_metadata/config.cc | 10 +- .../http/set_metadata/set_metadata_filter.cc | 78 +++- .../http/set_metadata/set_metadata_filter.h | 33 +- .../filters/http/set_metadata/config_test.cc | 42 +- .../set_metadata/set_metadata_filter_test.cc | 362 ++++++++++++++++-- 9 files changed, 537 insertions(+), 65 deletions(-) diff --git a/api/envoy/extensions/filters/http/set_metadata/v3/BUILD b/api/envoy/extensions/filters/http/set_metadata/v3/BUILD index 29ebf0741406..cd8fcbbc5e0d 100644 --- a/api/envoy/extensions/filters/http/set_metadata/v3/BUILD +++ b/api/envoy/extensions/filters/http/set_metadata/v3/BUILD @@ -5,5 +5,8 @@ load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") licenses(["notice"]) # Apache 2 api_proto_package( - deps = ["@com_github_cncf_xds//udpa/annotations:pkg"], + deps = [ + "//envoy/annotations:pkg", + "@com_github_cncf_xds//udpa/annotations:pkg", + ], ) diff --git a/api/envoy/extensions/filters/http/set_metadata/v3/set_metadata.proto b/api/envoy/extensions/filters/http/set_metadata/v3/set_metadata.proto index a50a1d4fad95..e3dc67392752 100644 --- a/api/envoy/extensions/filters/http/set_metadata/v3/set_metadata.proto +++ b/api/envoy/extensions/filters/http/set_metadata/v3/set_metadata.proto @@ -2,8 +2,10 @@ syntax = "proto3"; package envoy.extensions.filters.http.set_metadata.v3; +import "google/protobuf/any.proto"; import "google/protobuf/struct.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "validate/validate.proto"; @@ -19,13 +21,41 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // [#extension: envoy.filters.http.set_metadata] -message Config { +message Metadata { // The metadata namespace. string metadata_namespace = 1 [(validate.rules).string = {min_len: 1}]; - // The value to update the namespace with. See + // Allow the filter to overwrite or merge with an existing value in the namespace. + bool allow_overwrite = 2; + + // The value to place at the namespace. If ``allow_overwrite``, this will + // overwrite or merge with any existing values in that namespace. See + // :ref:`the filter documentation ` for + // more information on how this value is merged with potentially existing + // ones if ``allow_overwrite`` is configured. Only one of ``value`` and + // ``typed_value`` may be set. + google.protobuf.Struct value = 3; + + // The value to place at the namespace. If ``allow_overwrite``, this will + // overwrite any existing values in that namespace. Only one of ``value`` and + // ``typed_value`` may be set. + google.protobuf.Any typed_value = 4; +} + +message Config { + // The metadata namespace. + // This field is deprecated; please use ``metadata`` as replacement. + string metadata_namespace = 1 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; + + // The untyped value to update the dynamic metadata namespace with. See // :ref:`the filter documentation ` for // more information on how this value is merged with potentially existing // ones. - google.protobuf.Struct value = 2; + // This field is deprecated; please use ``metadata`` as replacement. + google.protobuf.Struct value = 2 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; + + // Defines changes to be made to dynamic metadata. + repeated Metadata metadata = 3; } diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 9114296017ab..50b21469c601 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -311,8 +311,21 @@ new_features: - area: attributes change: | Added support for node data in ``%CEL%`` formatter. +- area: set_metadata + change: | + Added support for injecting typed and untyped dynamic metadata with this filter, also adds the ability + to add multiple namespaces with one filter and config to overwrite existing metadata is opt-in. + :ref:`untyped_metadata ` + may now be used to configure the ``set_metadata`` filter. deprecated: - area: wasm change: | Wasm-specific configuration attributes are deprecated in favor of ``xds`` attributes. +- area: set_metadata + change: | + :ref:`metadata_namespace ` + and :ref:`value ` + are deprecated. Please use the new field + :ref:`untyped_metadata ` + to configure static metadata to inject. diff --git a/docs/root/configuration/http/http_filters/set_metadata_filter.rst b/docs/root/configuration/http/http_filters/set_metadata_filter.rst index 7d0b3c1ba7bb..fde69d5a5031 100644 --- a/docs/root/configuration/http/http_filters/set_metadata_filter.rst +++ b/docs/root/configuration/http/http_filters/set_metadata_filter.rst @@ -8,13 +8,14 @@ Set Metadata This filters adds or updates dynamic metadata with static data. -Dynamic metadata values are updated with the following scheme. If a key -does not exists, it's just copied into the current metadata. If the key exists -but has a different type, it is replaced by the new value. Otherwise: +Dynamic metadata values are updated with the following rules. If a key does not exist, it is copied into the current metadata. If the key exists, then following rules will be used: - * for scalar values (null, string, number, boolean) are replaced with the new value - * for lists: new values are added to the current list - * for structures: recursively apply this scheme +* if :ref:`typed metadata value ` is used, it will overwrite existing values iff :ref:`allow_overwrite ` is set to true, otherwise nothing is done. +* if :ref:`untyped metadata value ` is used and ``allow_overwrite`` is set to true, or if deprecated :ref:`value ` field is used, the values are updated with the following scheme: + - existing value with different type: the existing value is replaced. + - scalar values (null, string, number, boolean): the existing value is replaced. + - lists: new values are appended to the current list. + - structures: recursively apply this scheme. For instance, if the namespace already contains this structure: @@ -50,4 +51,12 @@ After applying this filter, the namespace will contain: Statistics ---------- -Currently, this filter generates no statistics. +The ``set_metadata`` filter outputs statistics in the ``http..set_metadata.`` namespace. The :ref:`stat prefix +` comes from the +owning HTTP connection manager. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + overwrite_denied, Counter, Total number of denied attempts to overwrite an existing metadata value diff --git a/source/extensions/filters/http/set_metadata/config.cc b/source/extensions/filters/http/set_metadata/config.cc index 4989e41b2c18..2c17079e280d 100644 --- a/source/extensions/filters/http/set_metadata/config.cc +++ b/source/extensions/filters/http/set_metadata/config.cc @@ -16,8 +16,9 @@ namespace SetMetadataFilter { Http::FilterFactoryCb SetMetadataConfig::createFilterFactoryFromProtoTyped( const envoy::extensions::filters::http::set_metadata::v3::Config& proto_config, - const std::string&, Server::Configuration::FactoryContext&) { - ConfigSharedPtr filter_config(std::make_shared(proto_config)); + const std::string& stats_prefix, Server::Configuration::FactoryContext& context) { + ConfigSharedPtr filter_config( + std::make_shared(proto_config, context.scope(), stats_prefix)); return [filter_config](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter( @@ -27,8 +28,9 @@ Http::FilterFactoryCb SetMetadataConfig::createFilterFactoryFromProtoTyped( Http::FilterFactoryCb SetMetadataConfig::createFilterFactoryFromProtoWithServerContextTyped( const envoy::extensions::filters::http::set_metadata::v3::Config& proto_config, - const std::string&, Server::Configuration::ServerFactoryContext&) { - ConfigSharedPtr filter_config(std::make_shared(proto_config)); + const std::string& stats_prefix, Server::Configuration::ServerFactoryContext& server_context) { + ConfigSharedPtr filter_config( + std::make_shared(proto_config, server_context.scope(), stats_prefix)); return [filter_config](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter( diff --git a/source/extensions/filters/http/set_metadata/set_metadata_filter.cc b/source/extensions/filters/http/set_metadata/set_metadata_filter.cc index 8d824a3190e7..129fba5af7d2 100644 --- a/source/extensions/filters/http/set_metadata/set_metadata_filter.cc +++ b/source/extensions/filters/http/set_metadata/set_metadata_filter.cc @@ -13,9 +13,34 @@ namespace Extensions { namespace HttpFilters { namespace SetMetadataFilter { -Config::Config(const envoy::extensions::filters::http::set_metadata::v3::Config& proto_config) { - namespace_ = proto_config.metadata_namespace(); - value_ = proto_config.value(); +Config::Config(const envoy::extensions::filters::http::set_metadata::v3::Config& proto_config, + Stats::Scope& scope, const std::string& stats_prefix) + : stats_(generateStats(stats_prefix, scope)) { + if (proto_config.has_value() && !proto_config.metadata_namespace().empty()) { + UntypedMetadataEntry deprecated_api_val{true, proto_config.metadata_namespace(), + proto_config.value()}; + untyped_.emplace_back(deprecated_api_val); + } + + for (const auto& metadata : proto_config.metadata()) { + if (metadata.has_value()) { + UntypedMetadataEntry untyped_entry{metadata.allow_overwrite(), metadata.metadata_namespace(), + metadata.value()}; + untyped_.emplace_back(untyped_entry); + } else if (metadata.has_typed_value()) { + TypedMetadataEntry typed_entry{metadata.allow_overwrite(), metadata.metadata_namespace(), + metadata.typed_value()}; + typed_.emplace_back(typed_entry); + } else { + ENVOY_LOG(warn, "set_metadata filter configuration contains metadata entries without value " + "or typed_value"); + } + } +} + +FilterStats Config::generateStats(const std::string& prefix, Stats::Scope& scope) { + std::string final_prefix = prefix + "set_metadata."; + return {ALL_SET_METADATA_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix))}; } SetMetadataFilter::SetMetadataFilter(const ConfigSharedPtr config) : config_(config) {} @@ -23,13 +48,48 @@ SetMetadataFilter::SetMetadataFilter(const ConfigSharedPtr config) : config_(con SetMetadataFilter::~SetMetadataFilter() = default; Http::FilterHeadersStatus SetMetadataFilter::decodeHeaders(Http::RequestHeaderMap&, bool) { - const absl::string_view metadata_namespace = config_->metadataNamespace(); - auto& metadata = *decoder_callbacks_->streamInfo().dynamicMetadata().mutable_filter_metadata(); - ProtobufWkt::Struct& org_fields = - metadata[toStdStringView(metadata_namespace)]; // NOLINT(std::string_view) - const ProtobufWkt::Struct& to_merge = config_->value(); - StructUtil::update(org_fields, to_merge); + // Add configured untyped metadata. + if (!config_->untyped().empty()) { + auto& mut_untyped_metadata = + *decoder_callbacks_->streamInfo().dynamicMetadata().mutable_filter_metadata(); + + for (const auto& entry : config_->untyped()) { + if (!mut_untyped_metadata.contains(entry.metadata_namespace)) { + // Insert the new entry. + mut_untyped_metadata[entry.metadata_namespace] = entry.value; + } else if (entry.allow_overwrite) { + // Get the existing metadata at this key for merging. + ProtobufWkt::Struct& orig_fields = mut_untyped_metadata[entry.metadata_namespace]; + const auto& to_merge = entry.value; + + // Merge the new metadata into the existing metadata. + StructUtil::update(orig_fields, to_merge); + } else { + // The entry exists, and we are not allowed to overwrite -- emit a stat. + config_->stats().overwrite_denied_.inc(); + } + } + } + + // Add configured typed metadata. + if (!config_->typed().empty()) { + auto& mut_typed_metadata = + *decoder_callbacks_->streamInfo().dynamicMetadata().mutable_typed_filter_metadata(); + + for (const auto& entry : config_->typed()) { + if (!mut_typed_metadata.contains(entry.metadata_namespace)) { + // Insert the new entry. + mut_typed_metadata[entry.metadata_namespace] = entry.value; + } else if (entry.allow_overwrite) { + // Overwrite the existing typed metadata at this key. + mut_typed_metadata[entry.metadata_namespace] = entry.value; + } else { + // The entry exists, and we are not allowed to overwrite -- emit a stat. + config_->stats().overwrite_denied_.inc(); + } + } + } return Http::FilterHeadersStatus::Continue; } diff --git a/source/extensions/filters/http/set_metadata/set_metadata_filter.h b/source/extensions/filters/http/set_metadata/set_metadata_filter.h index 8611980117f2..e293690a32ab 100644 --- a/source/extensions/filters/http/set_metadata/set_metadata_filter.h +++ b/source/extensions/filters/http/set_metadata/set_metadata_filter.h @@ -5,28 +5,51 @@ #include #include "envoy/extensions/filters/http/set_metadata/v3/set_metadata.pb.h" +#include "envoy/stats/stats_macros.h" #include "source/common/common/logger.h" #include "source/extensions/filters/http/common/pass_through_filter.h" #include "absl/strings/string_view.h" +#include "absl/types/variant.h" namespace Envoy { namespace Extensions { namespace HttpFilters { namespace SetMetadataFilter { +#define ALL_SET_METADATA_FILTER_STATS(COUNTER) COUNTER(overwrite_denied) + +struct FilterStats { + ALL_SET_METADATA_FILTER_STATS(GENERATE_COUNTER_STRUCT) +}; + +struct UntypedMetadataEntry { + bool allow_overwrite{}; + std::string metadata_namespace; + ProtobufWkt::Struct value; +}; +struct TypedMetadataEntry { + bool allow_overwrite{}; + std::string metadata_namespace; + ProtobufWkt::Any value; +}; class Config : public ::Envoy::Router::RouteSpecificFilterConfig, public Logger::Loggable { public: - Config(const envoy::extensions::filters::http::set_metadata::v3::Config& config); + Config(const envoy::extensions::filters::http::set_metadata::v3::Config& config, + Stats::Scope& scope, const std::string& stats_prefix); - absl::string_view metadataNamespace() const { return namespace_; } - const ProtobufWkt::Struct& value() { return value_; } + const std::vector& untyped() { return untyped_; } + const std::vector& typed() { return typed_; } + const FilterStats& stats() const { return stats_; } private: - std::string namespace_; - ProtobufWkt::Struct value_; + static FilterStats generateStats(const std::string& prefix, Stats::Scope& scope); + + std::vector untyped_; + std::vector typed_; + FilterStats stats_; }; using ConfigSharedPtr = std::shared_ptr; diff --git a/test/extensions/filters/http/set_metadata/config_test.cc b/test/extensions/filters/http/set_metadata/config_test.cc index bca4cf7f579a..f54552002155 100644 --- a/test/extensions/filters/http/set_metadata/config_test.cc +++ b/test/extensions/filters/http/set_metadata/config_test.cc @@ -22,12 +22,21 @@ using SetMetadataProtoConfig = envoy::extensions::filters::http::set_metadata::v TEST(SetMetadataFilterConfigTest, SimpleConfig) { const std::string yaml = R"EOF( -metadata_namespace: thenamespace -value: - mynumber: 20 - mylist: ["b"] - tags: - mytag1: 1 +metadata: +- metadata_namespace: thenamespace + value: + mynumber: 20 + mylist: ["b"] + tags: + mytag1: 1 + allow_overwrite: true +- metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + allow_overwrite: true )EOF"; SetMetadataProtoConfig proto_config; @@ -45,12 +54,21 @@ metadata_namespace: thenamespace TEST(SetMetadataFilterConfigTest, SimpleConfigServerContext) { const std::string yaml = R"EOF( -metadata_namespace: thenamespace -value: - mynumber: 20 - mylist: ["b"] - tags: - mytag1: 1 +metadata: +- metadata_namespace: thenamespace + value: + mynumber: 20 + mylist: ["b"] + tags: + mytag1: 1 + allow_overwrite: true +- metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + allow_overwrite: true )EOF"; SetMetadataProtoConfig proto_config; diff --git a/test/extensions/filters/http/set_metadata/set_metadata_filter_test.cc b/test/extensions/filters/http/set_metadata/set_metadata_filter_test.cc index 32fb9318b800..5ada203e0d78 100644 --- a/test/extensions/filters/http/set_metadata/set_metadata_filter_test.cc +++ b/test/extensions/filters/http/set_metadata/set_metadata_filter_test.cc @@ -18,42 +18,50 @@ namespace Extensions { namespace HttpFilters { namespace SetMetadataFilter { -class SetMetadataIntegrationTest : public testing::Test { +using FilterSharedPtr = std::shared_ptr; + +class SetMetadataFilterTest : public testing::Test { public: - SetMetadataIntegrationTest() = default; + SetMetadataFilterTest() = default; void runFilter(envoy::config::core::v3::Metadata& metadata, const std::string& yaml_config) { - envoy::extensions::filters::http::set_metadata::v3::Config ext_config; - TestUtility::loadFromYaml(yaml_config, ext_config); - auto config = std::make_shared(ext_config); - auto filter = std::make_shared(config); + envoy::extensions::filters::http::set_metadata::v3::Config proto_config; + TestUtility::loadFromYaml(yaml_config, proto_config); + config_ = std::make_shared(proto_config, *stats_store_.rootScope(), ""); + filter_ = std::make_shared(config_); Http::TestRequestHeaderMapImpl headers; NiceMock decoder_callbacks; NiceMock req_info; - filter->setDecoderFilterCallbacks(decoder_callbacks); + filter_->setDecoderFilterCallbacks(decoder_callbacks); EXPECT_CALL(decoder_callbacks, streamInfo()).WillRepeatedly(ReturnRef(req_info)); EXPECT_CALL(req_info, dynamicMetadata()).WillRepeatedly(ReturnRef(metadata)); - EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter->decodeHeaders(headers, true)); + EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers, true)); Buffer::OwnedImpl buffer; - EXPECT_EQ(Http::FilterDataStatus::Continue, filter->decodeData(buffer, true)); - filter->onDestroy(); + EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(buffer, true)); + filter_->onDestroy(); } - void checkKeyInt(const ProtobufWkt::Struct& s, const char* key, int val) { + void checkKeyInt(const ProtobufWkt::Struct& s, std::string key, int val) { const auto& fields = s.fields(); const auto it = fields.find(key); - ASSERT_TRUE(it != fields.end()); + ASSERT_NE(it, fields.end()); const auto& pbval = it->second; ASSERT_EQ(pbval.kind_case(), ProtobufWkt::Value::kNumberValue); EXPECT_EQ(pbval.number_value(), val); } + + ConfigSharedPtr config_; + FilterSharedPtr filter_; + +private: + NiceMock stats_store_; }; -TEST_F(SetMetadataIntegrationTest, TestTagsHeaders) { +TEST_F(SetMetadataFilterTest, DeprecatedSimple) { const std::string yaml_config = R"EOF( metadata_namespace: thenamespace value: @@ -64,19 +72,19 @@ TEST_F(SetMetadataIntegrationTest, TestTagsHeaders) { envoy::config::core::v3::Metadata metadata; runFilter(metadata, yaml_config); - // Verify that `metadata` contains `{"thenamespace": {"tags": {"mytag0": 1}}}` + // Verify that `metadata` contains `{"thenamespace": {"tags": {"mytag0": 1}}}`. const auto& filter_metadata = metadata.filter_metadata(); const auto it_namespace = filter_metadata.find("thenamespace"); - ASSERT_TRUE(it_namespace != filter_metadata.end()); + ASSERT_NE(it_namespace, filter_metadata.end()); const auto& fields = it_namespace->second.fields(); const auto it_tags = fields.find("tags"); - ASSERT_TRUE(it_tags != fields.end()); + ASSERT_NE(it_tags, fields.end()); const auto& tags = it_tags->second; ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); checkKeyInt(tags.struct_value(), "mytag0", 1); } -TEST_F(SetMetadataIntegrationTest, TestTagsHeadersUpdate) { +TEST_F(SetMetadataFilterTest, DeprecatedWithMerge) { envoy::config::core::v3::Metadata metadata; { @@ -105,17 +113,17 @@ TEST_F(SetMetadataIntegrationTest, TestTagsHeadersUpdate) { } // Verify that `metadata` contains: - // ``{"thenamespace": {number: 20, mylist: ["a","b"], "tags": {"mytag0": 1, "mytag1": 1}}}`` + // ``{"thenamespace": {number: 20, mylist: ["a","b"], "tags": {"mytag0": 1, "mytag1": 1}}}``. const auto& filter_metadata = metadata.filter_metadata(); const auto it_namespace = filter_metadata.find("thenamespace"); - ASSERT_TRUE(it_namespace != filter_metadata.end()); - const auto& namespace_ = it_namespace->second; + ASSERT_NE(it_namespace, filter_metadata.end()); + const auto& namespaced_md = it_namespace->second; - checkKeyInt(namespace_, "mynumber", 20); + checkKeyInt(namespaced_md, "mynumber", 20); - const auto& fields = namespace_.fields(); + const auto& fields = namespaced_md.fields(); const auto it_mylist = fields.find("mylist"); - ASSERT_TRUE(it_mylist != fields.end()); + ASSERT_NE(it_mylist, fields.end()); const auto& mylist = it_mylist->second; ASSERT_EQ(mylist.kind_case(), ProtobufWkt::Value::kListValue); const auto& vals = mylist.list_value().values(); @@ -126,7 +134,7 @@ TEST_F(SetMetadataIntegrationTest, TestTagsHeadersUpdate) { EXPECT_EQ(vals[1].string_value(), "b"); const auto it_tags = fields.find("tags"); - ASSERT_TRUE(it_tags != fields.end()); + ASSERT_NE(it_tags, fields.end()); const auto& tags = it_tags->second; ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); const auto& tags_struct = tags.struct_value(); @@ -135,6 +143,312 @@ TEST_F(SetMetadataIntegrationTest, TestTagsHeadersUpdate) { checkKeyInt(tags_struct, "mytag1", 1); } +TEST_F(SetMetadataFilterTest, UntypedSimple) { + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + value: + tags: + mytag0: 1 + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains `{"thenamespace": {"tags": {"mytag0": 1}}}`. + const auto& filter_metadata = metadata.filter_metadata(); + const auto it_namespace = filter_metadata.find("thenamespace"); + ASSERT_NE(it_namespace, filter_metadata.end()); + const auto& fields = it_namespace->second.fields(); + const auto it_tags = fields.find("tags"); + ASSERT_NE(it_tags, fields.end()); + const auto& tags = it_tags->second; + ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); + checkKeyInt(tags.struct_value(), "mytag0", 1); +} + +TEST_F(SetMetadataFilterTest, TypedSimple) { + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains our typed Config. + const auto& typed_metadata = metadata.typed_filter_metadata(); + const auto it_namespace2 = typed_metadata.find("thenamespace"); + ASSERT_NE(typed_metadata.end(), it_namespace2); + const auto any_val = it_namespace2->second; + ASSERT_EQ("type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config", + any_val.type_url()); + envoy::extensions::filters::http::set_metadata::v3::Config test_cfg; + ASSERT_TRUE(any_val.UnpackTo(&test_cfg)); + EXPECT_EQ("foo_namespace", test_cfg.metadata_namespace()); +} + +TEST_F(SetMetadataFilterTest, UntypedWithAllowOverwrite) { + envoy::config::core::v3::Metadata metadata; + + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + value: + mynumber: 10 + mylist: ["a"] + tags: + mytag0: 1 + - metadata_namespace: thenamespace + value: + mynumber: 20 + mylist: ["b"] + tags: + mytag1: 1 + allow_overwrite: true + )EOF"; + + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains: + // ``{"thenamespace": {number: 20, mylist: ["a","b"], "tags": {"mytag0": 1, "mytag1": 1}}}``. + const auto& filter_metadata = metadata.filter_metadata(); + const auto it_namespace = filter_metadata.find("thenamespace"); + ASSERT_NE(it_namespace, filter_metadata.end()); + const auto& namespaced_md = it_namespace->second; + + checkKeyInt(namespaced_md, "mynumber", 20); + + const auto& fields = namespaced_md.fields(); + const auto it_mylist = fields.find("mylist"); + ASSERT_NE(it_mylist, fields.end()); + const auto& mylist = it_mylist->second; + ASSERT_EQ(mylist.kind_case(), ProtobufWkt::Value::kListValue); + const auto& vals = mylist.list_value().values(); + ASSERT_EQ(vals.size(), 2); + ASSERT_EQ(vals[0].kind_case(), ProtobufWkt::Value::kStringValue); + EXPECT_EQ(vals[0].string_value(), "a"); + ASSERT_EQ(vals[1].kind_case(), ProtobufWkt::Value::kStringValue); + EXPECT_EQ(vals[1].string_value(), "b"); + + const auto it_tags = fields.find("tags"); + ASSERT_NE(it_tags, fields.end()); + const auto& tags = it_tags->second; + ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); + const auto& tags_struct = tags.struct_value(); + + checkKeyInt(tags_struct, "mytag0", 1); + checkKeyInt(tags_struct, "mytag1", 1); +} + +TEST_F(SetMetadataFilterTest, UntypedWithNoAllowOverwrite) { + envoy::config::core::v3::Metadata metadata; + + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + value: + mynumber: 10 + mylist: ["a"] + tags: + mytag0: 1 + - metadata_namespace: thenamespace + value: + mynumber: 20 + mylist: ["b"] + tags: + mytag1: 1 + )EOF"; + + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains: + // ``{"thenamespace": {number: 10, mylist: ["a"], "tags": {"mytag0": 1}}}``. + const auto& filter_metadata = metadata.filter_metadata(); + const auto it_namespace = filter_metadata.find("thenamespace"); + ASSERT_NE(it_namespace, filter_metadata.end()); + const auto& namespaced_md = it_namespace->second; + + checkKeyInt(namespaced_md, "mynumber", 10); + + const auto& fields = namespaced_md.fields(); + const auto it_mylist = fields.find("mylist"); + ASSERT_NE(it_mylist, fields.end()); + const auto& mylist = it_mylist->second; + ASSERT_EQ(mylist.kind_case(), ProtobufWkt::Value::kListValue); + const auto& vals = mylist.list_value().values(); + ASSERT_EQ(vals.size(), 1); + ASSERT_EQ(vals[0].kind_case(), ProtobufWkt::Value::kStringValue); + EXPECT_EQ(vals[0].string_value(), "a"); + + const auto it_tags = fields.find("tags"); + ASSERT_NE(it_tags, fields.end()); + const auto& tags = it_tags->second; + ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); + const auto& tags_struct = tags.struct_value(); + + checkKeyInt(tags_struct, "mytag0", 1); + EXPECT_EQ(1, config_->stats().overwrite_denied_.value()); +} + +TEST_F(SetMetadataFilterTest, TypedWithAllowOverwrite) { + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: bat_namespace + value: + bat: baz + allow_overwrite: true + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains our typed Config. + const auto& typed_metadata = metadata.typed_filter_metadata(); + const auto it_namespace2 = typed_metadata.find("thenamespace"); + ASSERT_NE(typed_metadata.end(), it_namespace2); + const auto any_val = it_namespace2->second; + ASSERT_EQ("type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config", + any_val.type_url()); + envoy::extensions::filters::http::set_metadata::v3::Config test_cfg; + ASSERT_TRUE(any_val.UnpackTo(&test_cfg)); + EXPECT_EQ("bat_namespace", test_cfg.metadata_namespace()); + ASSERT_TRUE(test_cfg.has_value()); + EXPECT_TRUE(test_cfg.value().fields().contains("bat")); +} + +TEST_F(SetMetadataFilterTest, TypedWithNoAllowOverwrite) { + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: bat_namespace + value: + bat: baz + allow_overwrite: false + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains our typed Config. + const auto& typed_metadata = metadata.typed_filter_metadata(); + const auto it_namespace2 = typed_metadata.find("thenamespace"); + ASSERT_NE(typed_metadata.end(), it_namespace2); + const auto any_val = it_namespace2->second; + ASSERT_EQ("type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config", + any_val.type_url()); + envoy::extensions::filters::http::set_metadata::v3::Config test_cfg; + ASSERT_TRUE(any_val.UnpackTo(&test_cfg)); + EXPECT_EQ("foo_namespace", test_cfg.metadata_namespace()); + ASSERT_TRUE(test_cfg.has_value()); + EXPECT_TRUE(test_cfg.value().fields().contains("foo")); + EXPECT_EQ(1, config_->stats().overwrite_denied_.value()); +} + +TEST_F(SetMetadataFilterTest, UntypedWithDeprecated) { + const std::string yaml_config = R"EOF( + metadata_namespace: thenamespace + value: + tags: + mytag0: 0 + metadata: + - metadata_namespace: thenamespace + value: + tags: + mytag0: 1 + allow_overwrite: true + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains `{"thenamespace": {"tags": {"mytag0": 1}}}`. + const auto& filter_metadata = metadata.filter_metadata(); + const auto it_namespace = filter_metadata.find("thenamespace"); + ASSERT_NE(it_namespace, filter_metadata.end()); + const auto& fields = it_namespace->second.fields(); + const auto it_tags = fields.find("tags"); + ASSERT_NE(it_tags, fields.end()); + const auto& tags = it_tags->second; + ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); + checkKeyInt(tags.struct_value(), "mytag0", 1); +} + +TEST_F(SetMetadataFilterTest, TypedWithDeprecated) { + const std::string yaml_config = R"EOF( + metadata_namespace: thenamespace + value: + tags: + mytag0: 0 + metadata: + - metadata_namespace: thenamespace + typed_value: + '@type': type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config + metadata_namespace: foo_namespace + value: + foo: bar + )EOF"; + + envoy::config::core::v3::Metadata metadata; + runFilter(metadata, yaml_config); + + // Verify that `metadata` contains `{"thenamespace": {"tags": {"mytag0": 0}}}`. + const auto& untyped_metadata = metadata.filter_metadata(); + const auto it_namespace = untyped_metadata.find("thenamespace"); + ASSERT_NE(untyped_metadata.end(), it_namespace); + const auto& fields = it_namespace->second.fields(); + const auto it_tags = fields.find("tags"); + ASSERT_NE(it_tags, fields.end()); + const auto& tags = it_tags->second; + ASSERT_EQ(tags.kind_case(), ProtobufWkt::Value::kStructValue); + checkKeyInt(tags.struct_value(), "mytag0", 0); + + // Verify that `metadata` contains our typed Config. + const auto& typed_metadata = metadata.typed_filter_metadata(); + const auto it_namespace2 = typed_metadata.find("thenamespace"); + ASSERT_NE(typed_metadata.end(), it_namespace2); + const auto any_val = it_namespace2->second; + ASSERT_EQ("type.googleapis.com/envoy.extensions.filters.http.set_metadata.v3.Config", + any_val.type_url()); + envoy::extensions::filters::http::set_metadata::v3::Config test_cfg; + ASSERT_TRUE(any_val.UnpackTo(&test_cfg)); + EXPECT_EQ("foo_namespace", test_cfg.metadata_namespace()); +} + +TEST_F(SetMetadataFilterTest, LogsErrorWhenNoValueConfigured) { + const std::string yaml_config = R"EOF( + metadata: + - metadata_namespace: thenamespace + )EOF"; + envoy::config::core::v3::Metadata metadata; + EXPECT_LOG_CONTAINS( + "warn", + "set_metadata filter configuration contains metadata entries without value or typed_value", + runFilter(metadata, yaml_config)); +} + } // namespace SetMetadataFilter } // namespace HttpFilters } // namespace Extensions From 9dbcc4fa41e920cefa0c6367477e3eef233afa01 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 20 Dec 2023 07:51:41 +0800 Subject: [PATCH 029/126] tracing: bring Inline header support back (#31141) * possible way Signed-off-by: wbpcode * minor update Signed-off-by: wbpcode * cleanup unnecessary interface Signed-off-by: wbpcode * fix format Signed-off-by: wbpcode * new tests and fix tests Signed-off-by: wbpcode * fix building Signed-off-by: wbpcode * fix test Signed-off-by: wbpcode * fix test Signed-off-by: wbpcode * fix tests Signed-off-by: wbpcode * improve coverage rate Signed-off-by: wbpcode * try to improve coverage ratio Signed-off-by: wbpcode * refactor interface of http header map and trace context Signed-off-by: wbpcode * fix test Signed-off-by: wbpcode * fix building Signed-off-by: wbpcode * fix building Signed-off-by: wbpcode * fix test of validators Signed-off-by: wbpcode * fix test of tracers Signed-off-by: wbpcode * fix test of router Signed-off-by: wbpcode * fix test of tracing Signed-off-by: wbpcode * revert unexpected change of mobile Signed-off-by: wbpcode * fix gcc compile Signed-off-by: wbpcode --------- Signed-off-by: wbpcode --- .../filters/network/source/tracing.cc | 12 +- .../filters/network/source/tracing.h | 8 +- envoy/http/BUILD | 1 - envoy/http/header_map.h | 4 +- envoy/tracing/BUILD | 4 + envoy/tracing/custom_tag.h | 2 +- envoy/tracing/trace_context.h | 36 ++-- source/common/grpc/async_client_impl.cc | 3 +- .../common/grpc/google_async_client_impl.cc | 3 +- source/common/http/async_client_impl.cc | 6 +- source/common/http/conn_manager_impl.cc | 3 +- source/common/http/header_map_impl.cc | 66 ------- source/common/http/header_map_impl.h | 12 -- source/common/http/header_utility.cc | 4 +- source/common/router/upstream_request.cc | 5 +- source/common/tracing/BUILD | 17 ++ source/common/tracing/custom_tag_impl.cc | 5 +- source/common/tracing/custom_tag_impl.h | 3 +- source/common/tracing/http_tracer_impl.cc | 5 +- source/common/tracing/http_tracer_impl.h | 54 ++++++ source/common/tracing/trace_context_impl.cc | 97 ++++++++++ source/common/tracing/trace_context_impl.h | 75 ++++++++ source/common/tracing/tracer_impl.cc | 2 +- source/extensions/access_loggers/grpc/BUILD | 1 + .../grpc/grpc_access_log_utils.cc | 4 +- .../envoy_default/header_validator.cc | 2 +- .../envoy_default/http1_header_validator.cc | 2 +- .../envoy_default/http2_header_validator.cc | 2 +- .../envoy_default/path_normalizer.cc | 4 +- source/extensions/tracers/common/ot/BUILD | 1 + .../common/ot/opentracing_driver_impl.cc | 16 +- source/extensions/tracers/datadog/BUILD | 1 + .../extensions/tracers/datadog/dict_util.cc | 3 +- source/extensions/tracers/datadog/span.cc | 2 +- .../opencensus/opencensus_tracer_impl.cc | 52 +++--- source/extensions/tracers/opentelemetry/BUILD | 1 + .../opentelemetry/opentelemetry_tracer_impl.h | 8 - .../opentelemetry/span_context_extractor.cc | 15 +- .../opentelemetry/span_context_extractor.h | 9 + .../tracers/opentelemetry/tracer.cc | 15 +- .../skywalking/skywalking_tracer_impl.cc | 2 +- .../extensions/tracers/skywalking/tracer.cc | 6 +- source/extensions/tracers/skywalking/tracer.h | 3 +- source/extensions/tracers/xray/tracer.cc | 10 +- source/extensions/tracers/xray/tracer.h | 6 +- .../tracers/xray/xray_tracer_impl.cc | 4 +- .../tracers/zipkin/span_context_extractor.cc | 15 +- .../tracers/zipkin/zipkin_core_constants.h | 13 +- .../tracers/zipkin/zipkin_tracer_impl.cc | 13 +- test/common/http/header_map_impl_test.cc | 83 --------- test/common/router/config_impl_test.cc | 4 +- test/common/tracing/BUILD | 11 ++ test/common/tracing/http_tracer_impl_test.cc | 52 ++++++ .../common/tracing/trace_context_impl_test.cc | 166 ++++++++++++++++++ test/common/tracing/tracer_impl_test.cc | 10 +- .../udp/udp_proxy/udp_proxy_filter_test.cc | 2 +- .../http1_header_validator_test.cc | 10 +- .../http2_header_validator_test.cc | 40 ++--- .../http_common_validation_test.cc | 16 +- .../path_normalizer_fuzz_test.cc | 29 +-- .../envoy_default/path_normalizer_test.cc | 52 +++--- .../common/ot/opentracing_driver_impl_test.cc | 2 +- .../tracers/datadog/agent_http_client_test.cc | 30 ++-- .../tracers/opencensus/tracer_test.cc | 9 +- .../opentelemetry_tracer_impl_test.cc | 21 ++- .../span_context_extractor_test.cc | 31 ++-- test/extensions/tracers/xray/tracer_test.cc | 4 +- .../tracers/xray/xray_tracer_impl_test.cc | 10 +- .../zipkin/span_context_extractor_test.cc | 81 +++++---- .../tracers/zipkin/zipkin_tracer_impl_test.cc | 112 ++++++------ .../filters/invalid_header_filter.cc | 6 +- test/test_common/BUILD | 1 + test/test_common/utility.h | 46 +---- 73 files changed, 890 insertions(+), 575 deletions(-) create mode 100644 source/common/tracing/trace_context_impl.cc create mode 100644 source/common/tracing/trace_context_impl.h create mode 100644 test/common/tracing/trace_context_impl_test.cc diff --git a/contrib/generic_proxy/filters/network/source/tracing.cc b/contrib/generic_proxy/filters/network/source/tracing.cc index 26ed71eec117..10d0d7bd4af4 100644 --- a/contrib/generic_proxy/filters/network/source/tracing.cc +++ b/contrib/generic_proxy/filters/network/source/tracing.cc @@ -10,19 +10,13 @@ absl::string_view TraceContextBridge::host() const { return request_.host(); } absl::string_view TraceContextBridge::path() const { return request_.path(); } absl::string_view TraceContextBridge::method() const { return request_.method(); } void TraceContextBridge::forEach(IterateCallback callback) const { request_.forEach(callback); } -absl::optional TraceContextBridge::getByKey(absl::string_view key) const { +absl::optional TraceContextBridge::get(absl::string_view key) const { return request_.get(key); } -void TraceContextBridge::setByKey(absl::string_view key, absl::string_view val) { +void TraceContextBridge::set(absl::string_view key, absl::string_view val) { request_.set(key, val); } -void TraceContextBridge::setByReferenceKey(absl::string_view key, absl::string_view val) { - request_.set(key, val); -} -void TraceContextBridge::setByReference(absl::string_view key, absl::string_view val) { - request_.set(key, val); -} -void TraceContextBridge::removeByKey(absl::string_view key) { request_.erase(key); } +void TraceContextBridge::remove(absl::string_view key) { request_.erase(key); } } // namespace GenericProxy } // namespace NetworkFilters diff --git a/contrib/generic_proxy/filters/network/source/tracing.h b/contrib/generic_proxy/filters/network/source/tracing.h index 334871ec8051..986bd8fe3dc6 100644 --- a/contrib/generic_proxy/filters/network/source/tracing.h +++ b/contrib/generic_proxy/filters/network/source/tracing.h @@ -22,11 +22,9 @@ class TraceContextBridge : public Tracing::TraceContext { absl::string_view path() const override; absl::string_view method() const override; void forEach(IterateCallback callback) const override; - absl::optional getByKey(absl::string_view key) const override; - void setByKey(absl::string_view key, absl::string_view val) override; - void setByReferenceKey(absl::string_view key, absl::string_view val) override; - void setByReference(absl::string_view key, absl::string_view val) override; - void removeByKey(absl::string_view key) override; + absl::optional get(absl::string_view key) const override; + void set(absl::string_view key, absl::string_view val) override; + void remove(absl::string_view key) override; private: StreamRequest& request_; diff --git a/envoy/http/BUILD b/envoy/http/BUILD index 6da0f1c308bc..ba992698b4ee 100644 --- a/envoy/http/BUILD +++ b/envoy/http/BUILD @@ -140,7 +140,6 @@ envoy_cc_library( deps = [ ":header_formatter_interface", "//envoy/common:union_string", - "//envoy/tracing:trace_context_interface", "//source/common/common:assert_lib", "//source/common/common:hash_lib", ], diff --git a/envoy/http/header_map.h b/envoy/http/header_map.h index c4eb4ea915ca..0e95b6db91dd 100644 --- a/envoy/http/header_map.h +++ b/envoy/http/header_map.h @@ -13,7 +13,6 @@ #include "envoy/common/pure.h" #include "envoy/common/union_string.h" #include "envoy/http/header_formatter.h" -#include "envoy/tracing/trace_context.h" #include "source/common/common/assert.h" #include "source/common/common/hash.h" @@ -728,8 +727,7 @@ class RequestOrResponseHeaderMap : public HeaderMap { // Request headers. class RequestHeaderMap : public RequestOrResponseHeaderMap, - public CustomInlineHeaderBase, - public Tracing::TraceContext { + public CustomInlineHeaderBase { public: INLINE_REQ_STRING_HEADERS(DEFINE_INLINE_STRING_HEADER) INLINE_REQ_NUMERIC_HEADERS(DEFINE_INLINE_NUMERIC_HEADER) diff --git a/envoy/tracing/BUILD b/envoy/tracing/BUILD index 29c2776504ba..3e2e9c9f5281 100644 --- a/envoy/tracing/BUILD +++ b/envoy/tracing/BUILD @@ -43,6 +43,10 @@ envoy_cc_library( envoy_cc_library( name = "trace_context_interface", hdrs = ["trace_context.h"], + deps = [ + "//envoy/common:optref_lib", + "//envoy/http:header_map_interface", + ], ) envoy_cc_library( diff --git a/envoy/tracing/custom_tag.h b/envoy/tracing/custom_tag.h index f930fe0527e2..51968026e8dd 100644 --- a/envoy/tracing/custom_tag.h +++ b/envoy/tracing/custom_tag.h @@ -16,7 +16,7 @@ namespace Tracing { * The context for the custom tag to obtain the tag value. */ struct CustomTagContext { - const TraceContext* trace_context; + const TraceContext& trace_context; const StreamInfo::StreamInfo& stream_info; }; diff --git a/envoy/tracing/trace_context.h b/envoy/tracing/trace_context.h index 0f551db3a778..fb2bd7eafba7 100644 --- a/envoy/tracing/trace_context.h +++ b/envoy/tracing/trace_context.h @@ -3,7 +3,9 @@ #include #include +#include "envoy/common/optref.h" #include "envoy/common/pure.h" +#include "envoy/http/header_map.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -11,6 +13,8 @@ namespace Envoy { namespace Tracing { +class TraceContextHandler; + /** * Protocol-independent abstraction for traceable stream. It hides the differences between different * protocol and provides tracer driver with common methods for obtaining and setting the tracing @@ -66,7 +70,7 @@ class TraceContext { * @param key The context key of string view type. * @return The optional context value of string_view type. */ - virtual absl::optional getByKey(absl::string_view key) const PURE; + virtual absl::optional get(absl::string_view key) const PURE; /** * Set new tracing context key/value pair. @@ -74,33 +78,25 @@ class TraceContext { * @param key The context key of string view type. * @param val The context value of string view type. */ - virtual void setByKey(absl::string_view key, absl::string_view val) PURE; + virtual void set(absl::string_view key, absl::string_view val) PURE; /** - * Set new tracing context key/value pair. The key MUST point to data that will live beyond - * the lifetime of any traceable stream that using the string. + * Removes the following key and its associated values from the tracing + * context. * - * @param key The context key of string view type. - * @param val The context value of string view type. + * @param key The key to remove if it exists. */ - virtual void setByReferenceKey(absl::string_view key, absl::string_view val) PURE; + virtual void remove(absl::string_view key) PURE; - /** - * Set new tracing context key/value pair. Both key and val MUST point to data that will live - * beyond the lifetime of any traceable stream that using the string. - * - * @param key The context key of string view type. - * @param val The context value of string view type. - */ - virtual void setByReference(absl::string_view key, absl::string_view val) PURE; +private: + friend class TraceContextHandler; /** - * Removes the following key and its associated values from the tracing - * context. - * - * @param key The key to remove if it exists. + * Optional HTTP request headers map. This is valid for HTTP protocol or any protocol that + * that provides HTTP request headers. */ - virtual void removeByKey(absl::string_view key) PURE; + virtual OptRef requestHeaders() { return {}; }; + virtual OptRef requestHeaders() const { return {}; }; }; } // namespace Tracing diff --git a/source/common/grpc/async_client_impl.cc b/source/common/grpc/async_client_impl.cc index 93e779554556..962d68ae3705 100644 --- a/source/common/grpc/async_client_impl.cc +++ b/source/common/grpc/async_client_impl.cc @@ -255,7 +255,8 @@ void AsyncRequestImpl::cancel() { } void AsyncRequestImpl::onCreateInitialMetadata(Http::RequestHeaderMap& metadata) { - current_span_->injectContext(metadata, nullptr); + Tracing::HttpTraceContext trace_context(metadata); + current_span_->injectContext(trace_context, nullptr); callbacks_.onCreateInitialMetadata(metadata); } diff --git a/source/common/grpc/google_async_client_impl.cc b/source/common/grpc/google_async_client_impl.cc index 326319585a73..eea658811b45 100644 --- a/source/common/grpc/google_async_client_impl.cc +++ b/source/common/grpc/google_async_client_impl.cc @@ -463,7 +463,8 @@ void GoogleAsyncRequestImpl::cancel() { } void GoogleAsyncRequestImpl::onCreateInitialMetadata(Http::RequestHeaderMap& metadata) { - current_span_->injectContext(metadata, nullptr); + Tracing::HttpTraceContext trace_context(metadata); + current_span_->injectContext(trace_context, nullptr); callbacks_.onCreateInitialMetadata(metadata); } diff --git a/source/common/http/async_client_impl.cc b/source/common/http/async_client_impl.cc index 04ca4bb217d4..0ec47e45e26c 100644 --- a/source/common/http/async_client_impl.cc +++ b/source/common/http/async_client_impl.cc @@ -280,7 +280,8 @@ AsyncRequestSharedImpl::AsyncRequestSharedImpl(AsyncClientImpl& parent, } void AsyncRequestImpl::initialize() { - child_span_->injectContext(request_->headers(), nullptr); + Tracing::HttpTraceContext trace_context(request_->headers()); + child_span_->injectContext(trace_context, nullptr); sendHeaders(request_->headers(), request_->body().length() == 0); if (request_->body().length() != 0) { // It's possible this will be a no-op due to a local response synchronously generated in @@ -291,7 +292,8 @@ void AsyncRequestImpl::initialize() { } void AsyncOngoingRequestImpl::initialize() { - child_span_->injectContext(*request_headers_, nullptr); + Tracing::HttpTraceContext trace_context(*request_headers_); + child_span_->injectContext(trace_context, nullptr); sendHeaders(*request_headers_, false); } diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 6d438d46fae3..c219d9699c47 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -1442,8 +1442,9 @@ void ConnectionManagerImpl::ActiveStream::traceRequest() { ConnectionManagerImpl::chargeTracingStats(tracing_decision.reason, connection_manager_.config_.tracingStats()); + Tracing::HttpTraceContext trace_context(*request_headers_); active_span_ = connection_manager_.tracer().startSpan( - *this, *request_headers_, filter_manager_.streamInfo(), tracing_decision); + *this, trace_context, filter_manager_.streamInfo(), tracing_decision); if (!active_span_) { return; diff --git a/source/common/http/header_map_impl.cc b/source/common/http/header_map_impl.cc index f38f09a2cd6e..1431e66ffe6b 100644 --- a/source/common/http/header_map_impl.cc +++ b/source/common/http/header_map_impl.cc @@ -26,11 +26,6 @@ constexpr absl::string_view DelimiterForInlineHeaders{","}; constexpr absl::string_view DelimiterForInlineCookies{"; "}; const static int kMinHeadersForLazyMap = 3; // Optimal hard-coded value based on benchmarks. -bool validatedLowerCaseString(absl::string_view str) { - auto lower_case_str = LowerCaseString(str); - return lower_case_str == str; -} - absl::string_view delimiterByHeader(const LowerCaseString& key) { if (key == Http::Headers::get().Cookie) { return DelimiterForInlineCookies; @@ -531,66 +526,5 @@ HeaderMapImplUtility::getAllHeaderMapImplInfo() { return ret; } -absl::string_view RequestHeaderMapImpl::protocol() const { return getProtocolValue(); } - -absl::string_view RequestHeaderMapImpl::host() const { return getHostValue(); } - -absl::string_view RequestHeaderMapImpl::path() const { return getPathValue(); } - -absl::string_view RequestHeaderMapImpl::method() const { return getMethodValue(); } - -void RequestHeaderMapImpl::forEach(Tracing::TraceContext::IterateCallback callback) const { - HeaderMapImpl::iterate([cb = std::move(callback)](const HeaderEntry& entry) { - if (cb(entry.key().getStringView(), entry.value().getStringView())) { - return HeaderMap::Iterate::Continue; - } - return HeaderMap::Iterate::Break; - }); -} - -absl::optional RequestHeaderMapImpl::getByKey(absl::string_view key) const { - ASSERT(validatedLowerCaseString(key)); - auto result = const_cast(this)->getExisting(key); - - if (result.empty()) { - return absl::nullopt; - } - return result[0]->value().getStringView(); -} - -void RequestHeaderMapImpl::setByKey(absl::string_view key, absl::string_view val) { - ASSERT(validatedLowerCaseString(key)); - HeaderMapImpl::removeExisting(key); - - HeaderString new_key; - new_key.setCopy(key); - HeaderString new_val; - new_val.setCopy(val); - - HeaderMapImpl::insertByKey(std::move(new_key), std::move(new_val)); -} - -void RequestHeaderMapImpl::setByReferenceKey(absl::string_view key, absl::string_view val) { - ASSERT(validatedLowerCaseString(key)); - HeaderMapImpl::removeExisting(key); - - HeaderString new_val; - new_val.setCopy(val); - - HeaderMapImpl::insertByKey(HeaderString(key), std::move(new_val)); -} - -void RequestHeaderMapImpl::setByReference(absl::string_view key, absl::string_view val) { - ASSERT(validatedLowerCaseString(key)); - HeaderMapImpl::removeExisting(key); - - HeaderMapImpl::insertByKey(HeaderString(key), HeaderString(val)); -} - -void RequestHeaderMapImpl::removeByKey(absl::string_view key) { - ASSERT(validatedLowerCaseString(key)); - HeaderMapImpl::removeExisting(key); -} - } // namespace Http } // namespace Envoy diff --git a/source/common/http/header_map_impl.h b/source/common/http/header_map_impl.h index 75056a740745..df7c911e93de 100644 --- a/source/common/http/header_map_impl.h +++ b/source/common/http/header_map_impl.h @@ -491,18 +491,6 @@ class RequestHeaderMapImpl final : public TypedHeaderMapImpl, INLINE_REQ_RESP_STRING_HEADERS(DEFINE_INLINE_HEADER_STRING_FUNCS) INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_INLINE_HEADER_NUMERIC_FUNCS) - // Tracing::TraceContext - absl::string_view protocol() const override; - absl::string_view host() const override; - absl::string_view path() const override; - absl::string_view method() const override; - void forEach(Tracing::TraceContext::IterateCallback callback) const override; - absl::optional getByKey(absl::string_view key) const override; - void setByKey(absl::string_view key, absl::string_view val) override; - void setByReferenceKey(absl::string_view key, absl::string_view val) override; - void setByReference(absl::string_view key, absl::string_view val) override; - void removeByKey(absl::string_view key) override; - protected: // NOTE: Because inline_headers_ is a variable size member, it must be the last member in the // most derived class. This forces the definition of the following three functions to also be diff --git a/source/common/http/header_utility.cc b/source/common/http/header_utility.cc index 5ffc055d7ceb..f83084ac9ece 100644 --- a/source/common/http/header_utility.cc +++ b/source/common/http/header_utility.cc @@ -650,12 +650,12 @@ std::string HeaderUtility::addEncodingToAcceptEncoding(absl::string_view accept_ } bool HeaderUtility::isStandardConnectRequest(const Http::RequestHeaderMap& headers) { - return headers.method() == Http::Headers::get().MethodValues.Connect && + return headers.getMethodValue() == Http::Headers::get().MethodValues.Connect && headers.getProtocolValue().empty(); } bool HeaderUtility::isExtendedH2ConnectRequest(const Http::RequestHeaderMap& headers) { - return headers.method() == Http::Headers::get().MethodValues.Connect && + return headers.getMethodValue() == Http::Headers::get().MethodValues.Connect && !headers.getProtocolValue().empty(); } diff --git a/source/common/router/upstream_request.cc b/source/common/router/upstream_request.cc index d26c375932e2..5a27efd3e11c 100644 --- a/source/common/router/upstream_request.cc +++ b/source/common/router/upstream_request.cc @@ -109,13 +109,14 @@ UpstreamRequest::UpstreamRequest(RouterFilterInterface& parent, // The router checks that the connection pool is non-null before creating the upstream request. auto upstream_host = conn_pool_->host(); + Tracing::HttpTraceContext trace_context(*parent_.downstreamHeaders()); if (span_ != nullptr) { - span_->injectContext(*parent_.downstreamHeaders(), upstream_host); + span_->injectContext(trace_context, upstream_host); } else { // No independent child span for current upstream request then inject the parent span's tracing // context into the request headers. // The injectContext() of the parent span may be called repeatedly when the request is retried. - parent_.callbacks()->activeSpan().injectContext(*parent_.downstreamHeaders(), upstream_host); + parent_.callbacks()->activeSpan().injectContext(trace_context, upstream_host); } stream_info_.setUpstreamInfo(std::make_shared()); diff --git a/source/common/tracing/BUILD b/source/common/tracing/BUILD index b59a5612b590..b0c1132467b6 100644 --- a/source/common/tracing/BUILD +++ b/source/common/tracing/BUILD @@ -38,6 +38,7 @@ envoy_cc_library( "http_tracer_impl.h", ], deps = [ + ":trace_context_lib", ":tracer_lib", "//envoy/tracing:tracer_interface", "//source/common/formatter:substitution_formatter_lib", @@ -100,6 +101,21 @@ envoy_cc_library( ], ) +envoy_cc_library( + name = "trace_context_lib", + srcs = [ + "trace_context_impl.cc", + ], + hdrs = [ + "trace_context_impl.h", + ], + deps = [ + "//envoy/http:header_map_interface", + "//envoy/tracing:trace_context_interface", + "//source/common/http:header_map_lib", + ], +) + envoy_cc_library( name = "custom_tag_lib", srcs = [ @@ -109,6 +125,7 @@ envoy_cc_library( "custom_tag_impl.h", ], deps = [ + ":trace_context_lib", "//envoy/router:router_interface", "//envoy/tracing:custom_tag_interface", "//source/common/config:metadata_lib", diff --git a/source/common/tracing/custom_tag_impl.cc b/source/common/tracing/custom_tag_impl.cc index 5d34282c6041..3b9c8e5fc0a6 100644 --- a/source/common/tracing/custom_tag_impl.cc +++ b/source/common/tracing/custom_tag_impl.cc @@ -49,11 +49,8 @@ RequestHeaderCustomTag::RequestHeaderCustomTag( default_value_(request_header.default_value()) {} absl::string_view RequestHeaderCustomTag::value(const CustomTagContext& ctx) const { - if (ctx.trace_context == nullptr) { - return default_value_; - } // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially populate all header values. - const auto entry = ctx.trace_context->getByKey(name_); + const auto entry = name_.get(ctx.trace_context); return entry.value_or(default_value_); } diff --git a/source/common/tracing/custom_tag_impl.h b/source/common/tracing/custom_tag_impl.h index ec141da2778b..f17ffc3ab16c 100644 --- a/source/common/tracing/custom_tag_impl.h +++ b/source/common/tracing/custom_tag_impl.h @@ -4,6 +4,7 @@ #include "envoy/type/tracing/v3/custom_tag.pb.h" #include "source/common/config/metadata.h" +#include "source/common/tracing/trace_context_impl.h" namespace Envoy { namespace Tracing { @@ -51,7 +52,7 @@ class RequestHeaderCustomTag : public CustomTagBase { absl::string_view value(const CustomTagContext& ctx) const override; private: - const Http::LowerCaseString name_; + const Tracing::TraceContextHandler name_; const std::string default_value_; }; diff --git a/source/common/tracing/http_tracer_impl.cc b/source/common/tracing/http_tracer_impl.cc index e55153de6613..cd2cd817cfc8 100644 --- a/source/common/tracing/http_tracer_impl.cc +++ b/source/common/tracing/http_tracer_impl.cc @@ -239,7 +239,10 @@ void HttpTracerUtility::setCommonTags(Span& span, const StreamInfo::StreamInfo& span.setTag(Tracing::Tags::get().Error, Tracing::Tags::get().True); } - CustomTagContext ctx{stream_info.getRequestHeaders(), stream_info}; + ReadOnlyHttpTraceContext trace_context{stream_info.getRequestHeaders() != nullptr + ? *stream_info.getRequestHeaders() + : *Http::StaticEmptyHeaders::get().request_headers}; + CustomTagContext ctx{trace_context, stream_info}; if (const CustomTagMap* custom_tag_map = tracing_config.customTags(); custom_tag_map) { for (const auto& it : *custom_tag_map) { it.second->applySpan(span, ctx); diff --git a/source/common/tracing/http_tracer_impl.h b/source/common/tracing/http_tracer_impl.h index 47b3eb9ab7e2..25ce607f2e0c 100644 --- a/source/common/tracing/http_tracer_impl.h +++ b/source/common/tracing/http_tracer_impl.h @@ -17,6 +17,60 @@ namespace Envoy { namespace Tracing { +template class HttpTraceContextBase : public TraceContext { +public: + static_assert(std::is_same::type, Http::RequestHeaderMap>::value, + "T must be Http::RequestHeaderMap or const Http::RequestHeaderMap"); + + HttpTraceContextBase(T& request_headers) : request_headers_(request_headers) {} + + absl::string_view protocol() const override { return request_headers_.getProtocolValue(); } + absl::string_view host() const override { return request_headers_.getHostValue(); } + absl::string_view path() const override { return request_headers_.getPathValue(); } + absl::string_view method() const override { return request_headers_.getMethodValue(); } + void forEach(IterateCallback callback) const override { + request_headers_.iterate([cb = std::move(callback)](const Http::HeaderEntry& entry) { + if (cb(entry.key().getStringView(), entry.value().getStringView())) { + return Http::HeaderMap::Iterate::Continue; + } + return Http::HeaderMap::Iterate::Break; + }); + } + absl::optional get(absl::string_view key) const override { + Http::LowerCaseString lower_key{std::string(key)}; + const auto entry = request_headers_.get(lower_key); + if (!entry.empty()) { + return entry[0]->value().getStringView(); + } + return absl::nullopt; + } + void set(absl::string_view, absl::string_view) override {} + void remove(absl::string_view) override {} + OptRef requestHeaders() const override { return request_headers_; }; + OptRef requestHeaders() override { return {}; }; + +protected: + T& request_headers_; +}; + +// Read only http trace context that could be constructed from const Http::RequestHeaderMap. +// This is mainly used for custom tag extraction. +using ReadOnlyHttpTraceContext = HttpTraceContextBase; + +class HttpTraceContext : public HttpTraceContextBase { +public: + using HttpTraceContextBase::HttpTraceContextBase; + + void set(absl::string_view key, absl::string_view value) override { + request_headers_.setCopy(Http::LowerCaseString(std::string(key)), value); + } + void remove(absl::string_view key) override { + request_headers_.remove(Http::LowerCaseString(std::string(key))); + } + OptRef requestHeaders() const override { return request_headers_; }; + OptRef requestHeaders() override { return request_headers_; }; +}; + class HttpTracerUtility { public: /** diff --git a/source/common/tracing/trace_context_impl.cc b/source/common/tracing/trace_context_impl.cc new file mode 100644 index 000000000000..5eb4075dac59 --- /dev/null +++ b/source/common/tracing/trace_context_impl.cc @@ -0,0 +1,97 @@ +#include "source/common/tracing/trace_context_impl.h" + +#include "source/common/http/header_map_impl.h" + +namespace Envoy { +namespace Tracing { + +TraceContextHandler::TraceContextHandler(absl::string_view key) : key_(key) { + // This will force the header map to be finalized in unit tests and do nothing in prod ( + // where the header map is already finalized when the server is initializing). + Http::TypedHeaderMapImpl::inlineHeadersSize(); + + handle_ = Http::CustomInlineHeaderRegistry::getInlineHeader< + Http::CustomInlineHeaderRegistry::Type::RequestHeaders>(key_); +} + +void TraceContextHandler::set(TraceContext& trace_context, absl::string_view value) const { + // Will dynamic_cast be better? + auto header_map = trace_context.requestHeaders(); + if (!header_map.has_value()) { + trace_context.set(key_, value); + return; + } + + if (handle_.has_value()) { + header_map->setInline(handle_.value(), value); + } else { + header_map->setCopy(key_, value); + } +} + +void TraceContextHandler::setRefKey(TraceContext& trace_context, absl::string_view value) const { + auto header_map = trace_context.requestHeaders(); + if (!header_map.has_value()) { + trace_context.set(key_, value); + return; + } + + if (handle_.has_value()) { + header_map->setInline(handle_.value(), value); + } else { + header_map->setReferenceKey(key_, value); + } +} + +void TraceContextHandler::setRef(TraceContext& trace_context, absl::string_view value) const { + auto header_map = trace_context.requestHeaders(); + if (!header_map.has_value()) { + trace_context.set(key_, value); + return; + } + + if (handle_.has_value()) { + header_map->setReferenceInline(handle_.value(), value); + } else { + header_map->setReference(key_, value); + } +} + +absl::optional +TraceContextHandler::get(const TraceContext& trace_context) const { + auto header_map = trace_context.requestHeaders(); + if (!header_map.has_value()) { + return trace_context.get(key_); + } + + if (handle_.has_value()) { + auto* entry = header_map->getInline(handle_.value()); + if (entry == nullptr) { + return absl::nullopt; + } + return entry->value().getStringView(); + } else { + auto results = header_map->get(key_); + if (results.empty()) { + return absl::nullopt; + } + return results[0]->value().getStringView(); + } +} + +void TraceContextHandler::remove(TraceContext& trace_context) const { + auto header_map = trace_context.requestHeaders(); + if (!header_map.has_value()) { + trace_context.remove(key_); + return; + } + + if (handle_.has_value()) { + header_map->removeInline(handle_.value()); + } else { + header_map->remove(key_); + } +} + +} // namespace Tracing +} // namespace Envoy diff --git a/source/common/tracing/trace_context_impl.h b/source/common/tracing/trace_context_impl.h new file mode 100644 index 000000000000..8ee2c4aeb83f --- /dev/null +++ b/source/common/tracing/trace_context_impl.h @@ -0,0 +1,75 @@ +#pragma once + +#include "envoy/http/header_map.h" +#include "envoy/tracing/trace_context.h" + +namespace Envoy { +namespace Tracing { + +using InlineHandle = Http::CustomInlineHeaderRegistry::Handle< + Http::CustomInlineHeaderRegistry::Type::RequestHeaders>; + +/** + * A handler class for trace context. This class could be used to set, get and erase the key/value + * pair in the trace context. This handler is optimized for HTTP to support reference semantics and + * inline header. If HTTP header is used as the trace context and the key is registered in the + * custom inline header registry, then inline handle will be used to improve the performance. + */ +class TraceContextHandler { +public: + /** + * Construct a handler with the given key. Note that the key will be lowercase and copied. + * @param key the key of the handler. + */ + TraceContextHandler(absl::string_view key); + + /** + * Get the key of the handler. + * @return absl::string_view the key of the handler. Note that the key is lowercase. + */ + const Http::LowerCaseString& key() const { return key_; } + + /** + * Erase the key/value pair from the trace context. + * @param trace_context the trace context to erase the key/value pair. + */ + void remove(TraceContext& trace_context) const; + + /** + * Get the value from the trace context by the key. + * @param trace_context the trace context to get the value. + * @return absl::optional the value of the key. If the key is not found, then + * absl::nullopt will be returned. + */ + absl::optional get(const TraceContext& trace_context) const; + + /* + * Set the key/value pair in the trace context. + * @param trace_context the trace context to set the key/value pair. + * @param value the value to set. + */ + void set(TraceContext& trace_context, absl::string_view value) const; + + /** + * Set the key/value pair in the trace context. This method should only be used when the handler + * has longer lifetime than current stream. + * @param trace_context the trace context to set the key/value pair. + * @param value the value to set. + */ + void setRefKey(TraceContext& trace_context, absl::string_view value) const; + + /** + * Set the key/value pair in the trace context. This method should only be used when both the + * handler and the value have longer lifetime than current stream. + * @param trace_context the trace context to set the key/value pair. + * @param value the value to set. + */ + void setRef(TraceContext& trace_context, absl::string_view value) const; + +private: + const Http::LowerCaseString key_; + absl::optional handle_; +}; + +} // namespace Tracing +} // namespace Envoy diff --git a/source/common/tracing/tracer_impl.cc b/source/common/tracing/tracer_impl.cc index 01ee929bbd35..8205d0d2f8cd 100644 --- a/source/common/tracing/tracer_impl.cc +++ b/source/common/tracing/tracer_impl.cc @@ -125,7 +125,7 @@ void TracerUtility::finalizeSpan(Span& span, const TraceContext& trace_context, } // Custom tag from configuration. - CustomTagContext ctx{&trace_context, stream_info}; + CustomTagContext ctx{trace_context, stream_info}; if (const CustomTagMap* custom_tag_map = tracing_config.customTags(); custom_tag_map) { for (const auto& it : *custom_tag_map) { it.second->applySpan(span, ctx); diff --git a/source/extensions/access_loggers/grpc/BUILD b/source/extensions/access_loggers/grpc/BUILD index 9be93daf2aa3..976ada1ba7c5 100644 --- a/source/extensions/access_loggers/grpc/BUILD +++ b/source/extensions/access_loggers/grpc/BUILD @@ -52,6 +52,7 @@ envoy_cc_library( "//source/common/stream_info:stream_info_lib", "//source/common/stream_info:utility_lib", "//source/common/tracing:custom_tag_lib", + "//source/common/tracing:http_tracer_lib", "@envoy_api//envoy/data/accesslog/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/access_loggers/grpc/v3:pkg_cc_proto", ], diff --git a/source/extensions/access_loggers/grpc/grpc_access_log_utils.cc b/source/extensions/access_loggers/grpc/grpc_access_log_utils.cc index aece740263c4..c9f08685f94a 100644 --- a/source/extensions/access_loggers/grpc/grpc_access_log_utils.cc +++ b/source/extensions/access_loggers/grpc/grpc_access_log_utils.cc @@ -8,6 +8,7 @@ #include "source/common/network/utility.h" #include "source/common/stream_info/utility.h" #include "source/common/tracing/custom_tag_impl.h" +#include "source/common/tracing/http_tracer_impl.h" namespace Envoy { namespace Extensions { @@ -310,7 +311,8 @@ void Utility::extractCommonAccessLogProperties( } } - Tracing::CustomTagContext ctx{&request_header, stream_info}; + Tracing::ReadOnlyHttpTraceContext trace_context(request_header); + Tracing::CustomTagContext ctx{trace_context, stream_info}; for (const auto& custom_tag : config.custom_tags()) { const auto tag_applier = Tracing::CustomTagUtility::createCustomTag(custom_tag); tag_applier->applyLog(common_access_log, ctx); diff --git a/source/extensions/http/header_validators/envoy_default/header_validator.cc b/source/extensions/http/header_validators/envoy_default/header_validator.cc index e492dd1ee88a..f0104cd9e0dc 100644 --- a/source/extensions/http/header_validators/envoy_default/header_validator.cc +++ b/source/extensions/http/header_validators/envoy_default/header_validator.cc @@ -473,7 +473,7 @@ void HeaderValidator::encodeAdditionalCharactersInPath( 0b11111111111111111111111111111111, }; - absl::string_view path = header_map.path(); + absl::string_view path = header_map.getPathValue(); // Check if URL path contains any characters in the kCharactersToEncode set auto char_to_encode = path.begin(); for (; char_to_encode != path.end() && !testCharInTable(kCharactersToEncode, *char_to_encode); diff --git a/source/extensions/http/header_validators/envoy_default/http1_header_validator.cc b/source/extensions/http/header_validators/envoy_default/http1_header_validator.cc index cf29b3e612b4..fbcf08a4624f 100644 --- a/source/extensions/http/header_validators/envoy_default/http1_header_validator.cc +++ b/source/extensions/http/header_validators/envoy_default/http1_header_validator.cc @@ -216,7 +216,7 @@ ValidationResult Http1HeaderValidator::validateRequestHeaders(const RequestHeade // parse the :path form and compare the authority component of the path against the :authority // header. auto is_connect_method = ::Envoy::Http::HeaderUtility::isConnect(header_map); - auto is_options_method = header_map.method() == header_values_.MethodValues.Options; + auto is_options_method = header_map.getMethodValue() == header_values_.MethodValues.Options; if (!is_connect_method && path.empty()) { // The :path is required for non-CONNECT requests. diff --git a/source/extensions/http/header_validators/envoy_default/http2_header_validator.cc b/source/extensions/http/header_validators/envoy_default/http2_header_validator.cc index e67ad1f4e0e4..b552159046ff 100644 --- a/source/extensions/http/header_validators/envoy_default/http2_header_validator.cc +++ b/source/extensions/http/header_validators/envoy_default/http2_header_validator.cc @@ -232,7 +232,7 @@ Http2HeaderValidator::validateRequestHeaders(const ::Envoy::Http::RequestHeaderM // HTTP/2 requests. const bool is_standard_connect_request = HeaderUtility::isStandardConnectRequest(header_map); const bool is_extended_connect_request = HeaderUtility::isExtendedH2ConnectRequest(header_map); - auto is_options_request = header_map.method() == header_values_.MethodValues.Options; + auto is_options_request = header_map.getMethodValue() == header_values_.MethodValues.Options; bool path_is_empty = path.empty(); bool path_is_asterisk = path == "*"; bool path_is_absolute = !path_is_empty && path.at(0) == '/'; diff --git a/source/extensions/http/header_validators/envoy_default/path_normalizer.cc b/source/extensions/http/header_validators/envoy_default/path_normalizer.cc index 7674d3808d62..9e8713c3aa8b 100644 --- a/source/extensions/http/header_validators/envoy_default/path_normalizer.cc +++ b/source/extensions/http/header_validators/envoy_default/path_normalizer.cc @@ -177,9 +177,9 @@ PathNormalizer::normalizePathUri(RequestHeaderMap& header_map) const { // asterisk-form = "*" // // TODO(#23887) - potentially separate path normalization into multiple independent operations. - const auto original_path = header_map.path(); + const auto original_path = header_map.getPathValue(); if (original_path == "*" && - header_map.method() == ::Envoy::Http::Headers::get().MethodValues.Options) { + header_map.getMethodValue() == ::Envoy::Http::Headers::get().MethodValues.Options) { // asterisk-form, only valid for OPTIONS request return PathNormalizationResult::success(); } diff --git a/source/extensions/tracers/common/ot/BUILD b/source/extensions/tracers/common/ot/BUILD index c07fd828a0d7..2612bf77a461 100644 --- a/source/extensions/tracers/common/ot/BUILD +++ b/source/extensions/tracers/common/ot/BUILD @@ -28,5 +28,6 @@ envoy_cc_library( "//source/common/json:json_loader_lib", "//source/common/tracing:common_values_lib", "//source/common/tracing:null_span_lib", + "//source/common/tracing:trace_context_lib", ], ) diff --git a/source/extensions/tracers/common/ot/opentracing_driver_impl.cc b/source/extensions/tracers/common/ot/opentracing_driver_impl.cc index e802f29e1295..7d1050e76ac8 100644 --- a/source/extensions/tracers/common/ot/opentracing_driver_impl.cc +++ b/source/extensions/tracers/common/ot/opentracing_driver_impl.cc @@ -10,6 +10,7 @@ #include "source/common/http/header_map_impl.h" #include "source/common/tracing/common_values.h" #include "source/common/tracing/null_span_impl.h" +#include "source/common/tracing/trace_context_impl.h" namespace Envoy { namespace Extensions { @@ -22,6 +23,10 @@ Http::RegisterCustomInlineHeader Set(opentracing::string_view key, opentracing::string_view value) const override { Http::LowerCaseString lowercase_key{{key.data(), key.size()}}; - trace_context_.setByKey(lowercase_key, {value.data(), value.size()}); + trace_context_.set(lowercase_key, {value.data(), value.size()}); return {}; } @@ -57,7 +62,7 @@ class OpenTracingHeadersReader : public opentracing::HTTPHeadersReader { opentracing::expected LookupKey(opentracing::string_view key) const override { Http::LowerCaseString lowercase_key{{key.data(), key.size()}}; - const auto entry = trace_context_.getByKey(lowercase_key); + const auto entry = trace_context_.get(lowercase_key); if (entry.has_value()) { return opentracing::string_view{entry.value().data(), entry.value().length()}; } else { @@ -120,9 +125,8 @@ void OpenTracingSpan::injectContext(Tracing::TraceContext& trace_context, return; } const std::string current_span_context = oss.str(); - trace_context.setByReferenceKey( - Http::CustomHeaders::get().OtSpanContext, - Base64::encode(current_span_context.c_str(), current_span_context.length())); + otSpanContextHeader().setRefKey( + trace_context, Base64::encode(current_span_context.c_str(), current_span_context.length())); } else { // Inject the context using the tracer's standard header format. const OpenTracingHeadersWriter writer{trace_context}; @@ -161,7 +165,7 @@ Tracing::SpanPtr OpenTracingDriver::startSpan(const Tracing::Config& config, std::unique_ptr active_span; std::unique_ptr parent_span_ctx; - const auto entry = trace_context.getByKey(Http::CustomHeaders::get().OtSpanContext); + const auto entry = otSpanContextHeader().get(trace_context); if (propagation_mode == PropagationMode::SingleHeader && entry.has_value()) { opentracing::expected> parent_span_ctx_maybe; std::string parent_context = Base64::decode(std::string(entry.value())); diff --git a/source/extensions/tracers/datadog/BUILD b/source/extensions/tracers/datadog/BUILD index 43c0f6f2c0e7..5fa018ef5c9a 100644 --- a/source/extensions/tracers/datadog/BUILD +++ b/source/extensions/tracers/datadog/BUILD @@ -44,6 +44,7 @@ envoy_cc_library( "//source/common/config:utility_lib", "//source/common/http:async_client_utility_lib", "//source/common/tracing:null_span_lib", + "//source/common/tracing:trace_context_lib", "//source/common/upstream:cluster_update_tracker_lib", "//source/common/version:version_lib", "//source/extensions/tracers/common:factory_base_lib", diff --git a/source/extensions/tracers/datadog/dict_util.cc b/source/extensions/tracers/datadog/dict_util.cc index 79e7f61173e2..7932e7e8779f 100644 --- a/source/extensions/tracers/datadog/dict_util.cc +++ b/source/extensions/tracers/datadog/dict_util.cc @@ -3,6 +3,7 @@ #include #include "envoy/http/header_map.h" +#include "envoy/tracing/trace_context.h" #include "absl/strings/str_join.h" @@ -61,7 +62,7 @@ TraceContextReader::TraceContextReader(const Tracing::TraceContext& context) : c datadog::tracing::Optional TraceContextReader::lookup(datadog::tracing::StringView key) const { - return context_.getByKey(key); + return context_.get(key); } void TraceContextReader::visit( diff --git a/source/extensions/tracers/datadog/span.cc b/source/extensions/tracers/datadog/span.cc index d02741915218..4e9bcc77c895 100644 --- a/source/extensions/tracers/datadog/span.cc +++ b/source/extensions/tracers/datadog/span.cc @@ -23,7 +23,7 @@ class TraceContextWriter : public datadog::tracing::DictWriter { explicit TraceContextWriter(Tracing::TraceContext& context) : context_(context) {} void set(datadog::tracing::StringView key, datadog::tracing::StringView value) override { - context_.setByKey(key, value); + context_.set(key, value); } private: diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc index d75449825f1b..5c4ea0b4dfba 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc @@ -7,6 +7,7 @@ #include "source/common/common/base64.h" #include "source/common/common/empty_string.h" +#include "source/common/tracing/trace_context_impl.h" #include "absl/strings/str_cat.h" #include "google/devtools/cloudtrace/v2/tracing.grpc.pb.h" @@ -41,13 +42,13 @@ namespace { class ConstantValues { public: - const Http::LowerCaseString TRACEPARENT{"traceparent"}; - const Http::LowerCaseString GRPC_TRACE_BIN{"grpc-trace-bin"}; - const Http::LowerCaseString X_CLOUD_TRACE_CONTEXT{"x-cloud-trace-context"}; - const Http::LowerCaseString X_B3_TRACEID{"x-b3-traceid"}; - const Http::LowerCaseString X_B3_SPANID{"x-b3-spanid"}; - const Http::LowerCaseString X_B3_SAMPLED{"x-b3-sampled"}; - const Http::LowerCaseString X_B3_FLAGS{"x-b3-flags"}; + const Tracing::TraceContextHandler TRACEPARENT{"traceparent"}; + const Tracing::TraceContextHandler GRPC_TRACE_BIN{"grpc-trace-bin"}; + const Tracing::TraceContextHandler X_CLOUD_TRACE_CONTEXT{"x-cloud-trace-context"}; + const Tracing::TraceContextHandler X_B3_TRACEID{"x-b3-traceid"}; + const Tracing::TraceContextHandler X_B3_SPANID{"x-b3-spanid"}; + const Tracing::TraceContextHandler X_B3_SAMPLED{"x-b3-sampled"}; + const Tracing::TraceContextHandler X_B3_FLAGS{"x-b3-flags"}; }; using Constants = ConstSingleton; @@ -96,7 +97,7 @@ startSpanHelper(const std::string& name, bool traced, const Tracing::TraceContex bool found = false; switch (incoming) { case OpenCensusConfig::TRACE_CONTEXT: { - const auto entry = trace_context.getByKey(Constants::get().TRACEPARENT); + const auto entry = Constants::get().TRACEPARENT.get(trace_context); if (entry.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. @@ -105,7 +106,7 @@ startSpanHelper(const std::string& name, bool traced, const Tracing::TraceContex break; } case OpenCensusConfig::GRPC_TRACE_BIN: { - const auto entry = trace_context.getByKey(Constants::get().GRPC_TRACE_BIN); + const auto entry = Constants::get().GRPC_TRACE_BIN.get(trace_context); if (entry.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. @@ -115,7 +116,7 @@ startSpanHelper(const std::string& name, bool traced, const Tracing::TraceContex break; } case OpenCensusConfig::CLOUD_TRACE_CONTEXT: { - const auto entry = trace_context.getByKey(Constants::get().X_CLOUD_TRACE_CONTEXT); + const auto entry = Constants::get().X_CLOUD_TRACE_CONTEXT.get(trace_context); if (entry.has_value()) { found = true; // This is an implicitly untrusted header, so only the first value is used. @@ -129,19 +130,19 @@ startSpanHelper(const std::string& name, bool traced, const Tracing::TraceContex absl::string_view b3_span_id; absl::string_view b3_sampled; absl::string_view b3_flags; - const auto h_b3_trace_id = trace_context.getByKey(Constants::get().X_B3_TRACEID); + const auto h_b3_trace_id = Constants::get().X_B3_TRACEID.get(trace_context); if (h_b3_trace_id.has_value()) { b3_trace_id = h_b3_trace_id.value(); } - const auto h_b3_span_id = trace_context.getByKey(Constants::get().X_B3_SPANID); + const auto h_b3_span_id = Constants::get().X_B3_SPANID.get(trace_context); if (h_b3_span_id.has_value()) { b3_span_id = h_b3_span_id.value(); } - const auto h_b3_sampled = trace_context.getByKey(Constants::get().X_B3_SAMPLED); + const auto h_b3_sampled = Constants::get().X_B3_SAMPLED.get(trace_context); if (h_b3_sampled.has_value()) { b3_sampled = h_b3_sampled.value(); } - const auto h_b3_flags = trace_context.getByKey(Constants::get().X_B3_FLAGS); + const auto h_b3_flags = Constants::get().X_B3_FLAGS.get(trace_context); if (h_b3_flags.has_value()) { b3_flags = h_b3_flags.value(); } @@ -209,27 +210,26 @@ void Span::injectContext(Tracing::TraceContext& trace_context, for (const auto& outgoing : oc_config_.outgoing_trace_context()) { switch (outgoing) { case OpenCensusConfig::TRACE_CONTEXT: - trace_context.setByReferenceKey(Constants::get().TRACEPARENT, - ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); + Constants::get().TRACEPARENT.setRefKey( + trace_context, ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); break; case OpenCensusConfig::GRPC_TRACE_BIN: { std::string val = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); val = Base64::encode(val.data(), val.size(), /*add_padding=*/false); - trace_context.setByReferenceKey(Constants::get().GRPC_TRACE_BIN, val); + Constants::get().GRPC_TRACE_BIN.setRefKey(trace_context, val); break; } case OpenCensusConfig::CLOUD_TRACE_CONTEXT: - trace_context.setByReferenceKey( - Constants::get().X_CLOUD_TRACE_CONTEXT, - ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); + Constants::get().X_CLOUD_TRACE_CONTEXT.setRefKey( + trace_context, ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); break; case OpenCensusConfig::B3: - trace_context.setByReferenceKey(Constants::get().X_B3_TRACEID, - ::opencensus::trace::propagation::ToB3TraceIdHeader(ctx)); - trace_context.setByReferenceKey(Constants::get().X_B3_SPANID, - ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); - trace_context.setByReferenceKey(Constants::get().X_B3_SAMPLED, - ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); + Constants::get().X_B3_TRACEID.setRefKey( + trace_context, ::opencensus::trace::propagation::ToB3TraceIdHeader(ctx)); + Constants::get().X_B3_SPANID.setRefKey( + trace_context, ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); + Constants::get().X_B3_SAMPLED.setRefKey( + trace_context, ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); // OpenCensus's trace context propagation doesn't produce the // "X-B3-Flags:" header. break; diff --git a/source/extensions/tracers/opentelemetry/BUILD b/source/extensions/tracers/opentelemetry/BUILD index ea305b4ad950..e84423ccf272 100644 --- a/source/extensions/tracers/opentelemetry/BUILD +++ b/source/extensions/tracers/opentelemetry/BUILD @@ -68,6 +68,7 @@ envoy_cc_library( "//source/common/http:message_lib", "//source/common/http:utility_lib", "//source/common/protobuf", + "//source/common/tracing:trace_context_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@opentelemetry_proto//:trace_cc_proto", ], diff --git a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h index d197ba2d5f97..d1d8b6c10a18 100644 --- a/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h +++ b/source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h @@ -17,14 +17,6 @@ namespace Extensions { namespace Tracers { namespace OpenTelemetry { -class OpenTelemetryConstantValues { -public: - const Http::LowerCaseString TRACE_PARENT{"traceparent"}; - const Http::LowerCaseString TRACE_STATE{"tracestate"}; -}; - -using OpenTelemetryConstants = ConstSingleton; - /** * OpenTelemetry tracing driver. */ diff --git a/source/extensions/tracers/opentelemetry/span_context_extractor.cc b/source/extensions/tracers/opentelemetry/span_context_extractor.cc index fb9cb9e977f3..6f0165267f3c 100644 --- a/source/extensions/tracers/opentelemetry/span_context_extractor.cc +++ b/source/extensions/tracers/opentelemetry/span_context_extractor.cc @@ -3,6 +3,7 @@ #include "envoy/tracing/tracer.h" #include "source/common/http/header_map_impl.h" +#include "source/common/tracing/trace_context_impl.h" #include "absl/strings/escaping.h" #include "span_context.h" @@ -13,14 +14,6 @@ namespace Tracers { namespace OpenTelemetry { namespace { -const Http::LowerCaseString& openTelemetryPropagationHeader() { - CONSTRUCT_ON_FIRST_USE(Http::LowerCaseString, "traceparent"); -} - -const Http::LowerCaseString& openTelemetryTraceStateHeader() { - CONSTRUCT_ON_FIRST_USE(Http::LowerCaseString, "tracestate"); -} - // See https://www.w3.org/TR/trace-context/#traceparent-header constexpr int kTraceparentHeaderSize = 55; // 2 + 1 + 32 + 1 + 16 + 1 + 2 constexpr int kVersionHexSize = 2; @@ -45,12 +38,12 @@ SpanContextExtractor::SpanContextExtractor(Tracing::TraceContext& trace_context) SpanContextExtractor::~SpanContextExtractor() = default; bool SpanContextExtractor::propagationHeaderPresent() { - auto propagation_header = trace_context_.getByKey(openTelemetryPropagationHeader()); + auto propagation_header = OpenTelemetryConstants::get().TRACE_PARENT.get(trace_context_); return propagation_header.has_value(); } absl::StatusOr SpanContextExtractor::extractSpanContext() { - auto propagation_header = trace_context_.getByKey(openTelemetryPropagationHeader()); + auto propagation_header = OpenTelemetryConstants::get().TRACE_PARENT.get(trace_context_); if (!propagation_header.has_value()) { // We should have already caught this, but just in case. return absl::InvalidArgumentError("No propagation header found"); @@ -96,7 +89,7 @@ absl::StatusOr SpanContextExtractor::extractSpanContext() { // it is invalid and MUST be discarded. Because we're already checking for the // traceparent header above, we don't need to check here. // See https://www.w3.org/TR/trace-context/#processing-model-for-working-with-trace-context - absl::string_view tracestate_key = openTelemetryTraceStateHeader(); + absl::string_view tracestate_key = OpenTelemetryConstants::get().TRACE_STATE.key(); std::vector tracestate_values; // Multiple tracestate header fields MUST be handled as specified by RFC7230 Section 3.2.2 Field // Order. diff --git a/source/extensions/tracers/opentelemetry/span_context_extractor.h b/source/extensions/tracers/opentelemetry/span_context_extractor.h index ddac0f55024e..dffeb6218c92 100644 --- a/source/extensions/tracers/opentelemetry/span_context_extractor.h +++ b/source/extensions/tracers/opentelemetry/span_context_extractor.h @@ -5,6 +5,7 @@ #include "source/common/common/statusor.h" #include "source/common/http/header_map_impl.h" +#include "source/common/tracing/trace_context_impl.h" #include "source/extensions/tracers/opentelemetry/span_context.h" namespace Envoy { @@ -12,6 +13,14 @@ namespace Extensions { namespace Tracers { namespace OpenTelemetry { +class OpenTelemetryConstantValues { +public: + const Tracing::TraceContextHandler TRACE_PARENT{"traceparent"}; + const Tracing::TraceContextHandler TRACE_STATE{"tracestate"}; +}; + +using OpenTelemetryConstants = ConstSingleton; + /** * This class is used to SpanContext extracted from the HTTP traceparent header * See https://www.w3.org/TR/trace-context/#traceparent-header. diff --git a/source/extensions/tracers/opentelemetry/tracer.cc b/source/extensions/tracers/opentelemetry/tracer.cc index 7f03a8ddcaef..8c8553015510 100644 --- a/source/extensions/tracers/opentelemetry/tracer.cc +++ b/source/extensions/tracers/opentelemetry/tracer.cc @@ -7,6 +7,7 @@ #include "source/common/common/empty_string.h" #include "source/common/common/hex.h" +#include "source/common/tracing/trace_context_impl.h" #include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h" #include "opentelemetry/proto/trace/v1/trace.pb.h" @@ -16,14 +17,20 @@ namespace Extensions { namespace Tracers { namespace OpenTelemetry { -constexpr absl::string_view kTraceParent = "traceparent"; -constexpr absl::string_view kTraceState = "tracestate"; constexpr absl::string_view kDefaultVersion = "00"; using opentelemetry::proto::collector::trace::v1::ExportTraceServiceRequest; namespace { +const Tracing::TraceContextHandler& traceParentHeader() { + CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "traceparent"); +} + +const Tracing::TraceContextHandler& traceStateHeader() { + CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "tracestate"); +} + void callSampler(SamplerSharedPtr sampler, const absl::optional span_context, Span& new_span, const std::string& operation_name, OptRef trace_context) { @@ -84,9 +91,9 @@ void Span::injectContext(Tracing::TraceContext& trace_context, std::string traceparent_header_value = absl::StrCat(kDefaultVersion, "-", trace_id_hex, "-", span_id_hex, "-", trace_flags_hex); // Set the traceparent in the trace_context. - trace_context.setByReferenceKey(kTraceParent, traceparent_header_value); + traceParentHeader().setRefKey(trace_context, traceparent_header_value); // Also set the tracestate. - trace_context.setByReferenceKey(kTraceState, span_.trace_state()); + traceStateHeader().setRefKey(trace_context, span_.trace_state()); } void Span::setTag(absl::string_view name, absl::string_view value) { diff --git a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc index 932799a5c90a..33c9f67051e3 100644 --- a/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc +++ b/source/extensions/tracers/skywalking/skywalking_tracer_impl.cc @@ -50,7 +50,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config&, Tracing::TraceContext auto& tracer = tls_slot_ptr_->getTyped().tracer(); TracingContextPtr tracing_context; // TODO(shikugawa): support extension span header. - auto propagation_header = trace_context.getByKey(skywalkingPropagationHeaderKey()); + auto propagation_header = skywalkingPropagationHeaderKey().get(trace_context); if (!propagation_header.has_value()) { // Although a sampling flag can be added to the propagation header, it will be ignored by most // of SkyWalking agent. The agent will enable tracing anyway if it see the propagation header. diff --git a/source/extensions/tracers/skywalking/tracer.cc b/source/extensions/tracers/skywalking/tracer.cc index 605074bab719..903beb9cd5fd 100644 --- a/source/extensions/tracers/skywalking/tracer.cc +++ b/source/extensions/tracers/skywalking/tracer.cc @@ -12,8 +12,8 @@ static constexpr absl::string_view StatusCodeTag = "status_code"; static constexpr absl::string_view UrlTag = "url"; } // namespace -const Http::LowerCaseString& skywalkingPropagationHeaderKey() { - CONSTRUCT_ON_FIRST_USE(Http::LowerCaseString, "sw8"); +const Tracing::TraceContextHandler& skywalkingPropagationHeaderKey() { + CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "sw8"); } void Span::setTag(absl::string_view name, absl::string_view value) { @@ -54,7 +54,7 @@ void Span::injectContext(Tracing::TraceContext& trace_context, auto sw8_header = tracing_context_->createSW8HeaderValue({remote_address.data(), remote_address.size()}); if (sw8_header.has_value()) { - trace_context.setByReferenceKey(skywalkingPropagationHeaderKey(), sw8_header.value()); + skywalkingPropagationHeaderKey().setRefKey(trace_context, sw8_header.value()); // Rewrite operation name with latest upstream request path for the EXIT span. absl::string_view upstream_request_path = trace_context.path(); diff --git a/source/extensions/tracers/skywalking/tracer.h b/source/extensions/tracers/skywalking/tracer.h index e3894d8ae564..64f623319c18 100644 --- a/source/extensions/tracers/skywalking/tracer.h +++ b/source/extensions/tracers/skywalking/tracer.h @@ -6,6 +6,7 @@ #include "source/common/tracing/common_values.h" #include "source/common/tracing/null_span_impl.h" +#include "source/common/tracing/trace_context_impl.h" #include "source/extensions/tracers/skywalking/trace_segment_reporter.h" #include "cpp2sky/tracing_context.h" @@ -19,7 +20,7 @@ namespace SkyWalking { using cpp2sky::TracingContextPtr; using cpp2sky::TracingSpanPtr; -const Http::LowerCaseString& skywalkingPropagationHeaderKey(); +const Tracing::TraceContextHandler& skywalkingPropagationHeaderKey(); class Tracer { public: diff --git a/source/extensions/tracers/xray/tracer.cc b/source/extensions/tracers/xray/tracer.cc index 2c0eb6ad3b61..01bff55a3f23 100644 --- a/source/extensions/tracers/xray/tracer.cc +++ b/source/extensions/tracers/xray/tracer.cc @@ -101,11 +101,19 @@ void Span::finishSpan() { broker_.send(json); } // namespace XRay +const Tracing::TraceContextHandler& xRayTraceHeader() { + CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "x-amzn-trace-id"); +} + +const Tracing::TraceContextHandler& xForwardedForHeader() { + CONSTRUCT_ON_FIRST_USE(Tracing::TraceContextHandler, "x-forwarded-for"); +} + void Span::injectContext(Tracing::TraceContext& trace_context, const Upstream::HostDescriptionConstSharedPtr&) { const std::string xray_header_value = fmt::format("Root={};Parent={};Sampled={}", traceId(), id(), sampled() ? "1" : "0"); - trace_context.setByReferenceKey(XRayTraceHeader, xray_header_value); + xRayTraceHeader().setRefKey(trace_context, xray_header_value); } Tracing::SpanPtr Span::spawnChild(const Tracing::Config& config, const std::string& operation_name, diff --git a/source/extensions/tracers/xray/tracer.h b/source/extensions/tracers/xray/tracer.h index d09fb34c5111..9ecb2b75b39c 100644 --- a/source/extensions/tracers/xray/tracer.h +++ b/source/extensions/tracers/xray/tracer.h @@ -13,6 +13,7 @@ #include "source/common/http/codes.h" #include "source/common/protobuf/utility.h" #include "source/common/tracing/common_values.h" +#include "source/common/tracing/trace_context_impl.h" #include "source/extensions/tracers/xray/daemon_broker.h" #include "source/extensions/tracers/xray/sampling_strategy.h" #include "source/extensions/tracers/xray/xray_configuration.h" @@ -27,10 +28,11 @@ namespace XRay { constexpr absl::string_view SpanClientIp = "client_ip"; constexpr absl::string_view SpanXForwardedFor = "x_forwarded_for"; -constexpr absl::string_view XForwardedForHeader = "x-forwarded-for"; -constexpr absl::string_view XRayTraceHeader = "x-amzn-trace-id"; constexpr absl::string_view Subsegment = "subsegment"; +const Tracing::TraceContextHandler& xRayTraceHeader(); +const Tracing::TraceContextHandler& xForwardedForHeader(); + class Span : public Tracing::Span, Logger::Loggable { public: /** diff --git a/source/extensions/tracers/xray/xray_tracer_impl.cc b/source/extensions/tracers/xray/xray_tracer_impl.cc index ad1b2a6d8b00..b3003c705d0e 100644 --- a/source/extensions/tracers/xray/xray_tracer_impl.cc +++ b/source/extensions/tracers/xray/xray_tracer_impl.cc @@ -77,7 +77,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, // TODO(suniltheta) - how do we factor this into the logic above UNREFERENCED_PARAMETER(tracing_decision); - const auto header = trace_context.getByKey(XRayTraceHeader); + const auto header = xRayTraceHeader().get(trace_context); absl::optional should_trace; XRayHeader xray_header; if (header.has_value()) { @@ -109,7 +109,7 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, return tracer->startSpan(config, operation_name, stream_info.startTime(), header.has_value() ? absl::optional(xray_header) : absl::nullopt, - trace_context.getByKey(XForwardedForHeader)); + xForwardedForHeader().get(trace_context)); } // Instead of returning nullptr, we return a Span that is marked as not-sampled. diff --git a/source/extensions/tracers/zipkin/span_context_extractor.cc b/source/extensions/tracers/zipkin/span_context_extractor.cc index 7ab3eb92af5f..1e6c1f154258 100644 --- a/source/extensions/tracers/zipkin/span_context_extractor.cc +++ b/source/extensions/tracers/zipkin/span_context_extractor.cc @@ -35,7 +35,7 @@ SpanContextExtractor::~SpanContextExtractor() = default; bool SpanContextExtractor::extractSampled(const Tracing::Decision tracing_decision) { bool sampled(false); - auto b3_header_entry = trace_context_.getByKey(ZipkinCoreConstants::get().B3); + auto b3_header_entry = ZipkinCoreConstants::get().B3.get(trace_context_); if (b3_header_entry.has_value()) { // This is an implicitly untrusted header, so only the first value is used. absl::string_view b3 = b3_header_entry.value(); @@ -61,7 +61,7 @@ bool SpanContextExtractor::extractSampled(const Tracing::Decision tracing_decisi return getSamplingFlags(b3[sampled_pos], tracing_decision); } - auto x_b3_sampled_entry = trace_context_.getByKey(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto x_b3_sampled_entry = ZipkinCoreConstants::get().X_B3_SAMPLED.get(trace_context_); if (!x_b3_sampled_entry.has_value()) { return tracing_decision.traced; } @@ -74,7 +74,7 @@ bool SpanContextExtractor::extractSampled(const Tracing::Decision tracing_decisi } std::pair SpanContextExtractor::extractSpanContext(bool is_sampled) { - if (trace_context_.getByKey(ZipkinCoreConstants::get().B3).has_value()) { + if (ZipkinCoreConstants::get().B3.get(trace_context_).has_value()) { return extractSpanContextFromB3SingleFormat(is_sampled); } uint64_t trace_id(0); @@ -82,8 +82,8 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa uint64_t span_id(0); uint64_t parent_id(0); - auto b3_trace_id_entry = trace_context_.getByKey(ZipkinCoreConstants::get().X_B3_TRACE_ID); - auto b3_span_id_entry = trace_context_.getByKey(ZipkinCoreConstants::get().X_B3_SPAN_ID); + auto b3_trace_id_entry = ZipkinCoreConstants::get().X_B3_TRACE_ID.get(trace_context_); + auto b3_span_id_entry = ZipkinCoreConstants::get().X_B3_SPAN_ID.get(trace_context_); if (b3_span_id_entry.has_value() && b3_trace_id_entry.has_value()) { // Extract trace id - which can either be 128 or 64 bit. For 128 bit, // it needs to be divided into two 64 bit numbers (high and low). @@ -107,8 +107,7 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa throw ExtractorException(absl::StrCat("Invalid span id ", spid.c_str())); } - auto b3_parent_id_entry = - trace_context_.getByKey(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID); + auto b3_parent_id_entry = ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.get(trace_context_); if (b3_parent_id_entry.has_value() && !b3_parent_id_entry.value().empty()) { // This is an implicitly untrusted header, so only the first value is used. const std::string pspid(b3_parent_id_entry.value()); @@ -125,7 +124,7 @@ std::pair SpanContextExtractor::extractSpanContext(bool is_sa std::pair SpanContextExtractor::extractSpanContextFromB3SingleFormat(bool is_sampled) { - auto b3_head_entry = trace_context_.getByKey(ZipkinCoreConstants::get().B3); + auto b3_head_entry = ZipkinCoreConstants::get().B3.get(trace_context_); ASSERT(b3_head_entry.has_value()); // This is an implicitly untrusted header, so only the first value is used. const std::string b3(b3_head_entry.value()); diff --git a/source/extensions/tracers/zipkin/zipkin_core_constants.h b/source/extensions/tracers/zipkin/zipkin_core_constants.h index ee82dc36055a..3685849259f4 100644 --- a/source/extensions/tracers/zipkin/zipkin_core_constants.h +++ b/source/extensions/tracers/zipkin/zipkin_core_constants.h @@ -5,6 +5,7 @@ #include "envoy/http/header_map.h" #include "source/common/singleton/const_singleton.h" +#include "source/common/tracing/trace_context_impl.h" namespace Envoy { namespace Extensions { @@ -44,14 +45,14 @@ constexpr bool DEFAULT_SHARED_SPAN_CONTEXT = true; class ZipkinCoreConstantValues { public: // Zipkin B3 headers - const Http::LowerCaseString X_B3_TRACE_ID{"x-b3-traceid"}; - const Http::LowerCaseString X_B3_SPAN_ID{"x-b3-spanid"}; - const Http::LowerCaseString X_B3_PARENT_SPAN_ID{"x-b3-parentspanid"}; - const Http::LowerCaseString X_B3_SAMPLED{"x-b3-sampled"}; - const Http::LowerCaseString X_B3_FLAGS{"x-b3-flags"}; + const Tracing::TraceContextHandler X_B3_TRACE_ID{"x-b3-traceid"}; + const Tracing::TraceContextHandler X_B3_SPAN_ID{"x-b3-spanid"}; + const Tracing::TraceContextHandler X_B3_PARENT_SPAN_ID{"x-b3-parentspanid"}; + const Tracing::TraceContextHandler X_B3_SAMPLED{"x-b3-sampled"}; + const Tracing::TraceContextHandler X_B3_FLAGS{"x-b3-flags"}; // Zipkin b3 single header - const Http::LowerCaseString B3{"b3"}; + const Tracing::TraceContextHandler B3{"b3"}; }; using ZipkinCoreConstants = ConstSingleton; diff --git a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc index 4e81476e1b75..7642681d8321 100644 --- a/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc +++ b/source/extensions/tracers/zipkin/zipkin_tracer_impl.cc @@ -42,19 +42,18 @@ std::string ZipkinSpan::getBaggage(absl::string_view) { return EMPTY_STRING; } void ZipkinSpan::injectContext(Tracing::TraceContext& trace_context, const Upstream::HostDescriptionConstSharedPtr&) { // Set the trace-id and span-id headers properly, based on the newly-created span structure. - trace_context.setByReferenceKey(ZipkinCoreConstants::get().X_B3_TRACE_ID, - span_.traceIdAsHexString()); - trace_context.setByReferenceKey(ZipkinCoreConstants::get().X_B3_SPAN_ID, span_.idAsHexString()); + ZipkinCoreConstants::get().X_B3_TRACE_ID.setRefKey(trace_context, span_.traceIdAsHexString()); + ZipkinCoreConstants::get().X_B3_SPAN_ID.setRefKey(trace_context, span_.idAsHexString()); // Set the parent-span header properly, based on the newly-created span structure. if (span_.isSetParentId()) { - trace_context.setByReferenceKey(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, - span_.parentIdAsHexString()); + ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.setRefKey(trace_context, + span_.parentIdAsHexString()); } // Set the sampled header. - trace_context.setByReferenceKey(ZipkinCoreConstants::get().X_B3_SAMPLED, - span_.sampled() ? SAMPLED : NOT_SAMPLED); + ZipkinCoreConstants::get().X_B3_SAMPLED.setRefKey(trace_context, + span_.sampled() ? SAMPLED : NOT_SAMPLED); } void ZipkinSpan::setSampled(bool sampled) { span_.setSampled(sampled); } diff --git a/test/common/http/header_map_impl_test.cc b/test/common/http/header_map_impl_test.cc index 9ac4c5c93f5b..e4d949680161 100644 --- a/test/common/http/header_map_impl_test.cc +++ b/test/common/http/header_map_impl_test.cc @@ -1051,89 +1051,6 @@ TEST(HeaderMapImplTest, ValidHeaderString) { EXPECT_FALSE(validHeaderString("abc\n")); } -TEST(HeaderMapImplTest, HttpTraceContextTest) { - { - TestRequestHeaderMapImpl request_headers; - - // Protocol. - EXPECT_EQ(request_headers.protocol(), ""); - request_headers.addCopy(Http::Headers::get().Protocol, "HTTP/x"); - EXPECT_EQ(request_headers.protocol(), "HTTP/x"); - - // Host. - EXPECT_EQ(request_headers.host(), ""); - request_headers.addCopy(Http::Headers::get().Host, "test.com:233"); - EXPECT_EQ(request_headers.host(), "test.com:233"); - - // Path. - EXPECT_EQ(request_headers.path(), ""); - request_headers.addCopy(Http::Headers::get().Path, "/anything"); - EXPECT_EQ(request_headers.path(), "/anything"); - - // Method. - EXPECT_EQ(request_headers.method(), ""); - request_headers.addCopy(Http::Headers::get().Method, Http::Headers::get().MethodValues.Options); - EXPECT_EQ(request_headers.method(), Http::Headers::get().MethodValues.Options); - } - - { - size_t size = 0; - TestRequestHeaderMapImpl request_headers{{"host", "foo"}, {"bar", "var"}, {"ok", "no"}}; - request_headers.forEach([&size](absl::string_view key, absl::string_view val) { - size += key.size(); - size += val.size(); - return true; - }); - // 'host' will be converted to ':authority'. - EXPECT_EQ(23, size); - EXPECT_EQ(23, request_headers.byteSize()); - - request_headers.removeByKey("non-existent-header"); - EXPECT_EQ(23, request_headers.byteSize()); - - request_headers.removeByKey("ok"); - EXPECT_EQ(19, request_headers.byteSize()); - EXPECT_TRUE(request_headers.get(Http::LowerCaseString("ok")).empty()); - - // Appending will append to the existing value if it exists using "," as the - // delimiter. - request_headers.appendCopy(Http::LowerCaseString("bar"), "baz"); - EXPECT_EQ(23, request_headers.byteSize()); - EXPECT_EQ(1, request_headers.get(Http::LowerCaseString("bar")).size()); - - // Adding will store both key and value. - request_headers.addCopy(Http::LowerCaseString("bar"), "qux"); - EXPECT_EQ(29, request_headers.byteSize()); - EXPECT_EQ(2, request_headers.get(Http::LowerCaseString("bar")).size()); - - request_headers.removeByKey("bar"); - EXPECT_EQ(13, request_headers.byteSize()); - EXPECT_TRUE(request_headers.get(Http::LowerCaseString("bar")).empty()); - } - - { - TestRequestHeaderMapImpl request_headers{{"host", "foo"}}; - EXPECT_EQ(request_headers.getByKey("host").value(), "foo"); - - request_headers.setByKey("trace_key", "trace_value"); - EXPECT_EQ(request_headers.getByKey("trace_key").value(), "trace_value"); - - std::string trace_ref_key = "trace_ref_key"; - request_headers.setByReferenceKey(trace_ref_key, "trace_value"); - auto* header_entry = request_headers.get(Http::LowerCaseString(trace_ref_key))[0]; - EXPECT_EQ(reinterpret_cast(trace_ref_key.data()), - reinterpret_cast(header_entry->key().getStringView().data())); - - std::string trace_ref_value = "trace_ref_key"; - request_headers.setByReference(trace_ref_key, trace_ref_value); - header_entry = request_headers.get(Http::LowerCaseString(trace_ref_key))[0]; - EXPECT_EQ(reinterpret_cast(trace_ref_key.data()), - reinterpret_cast(header_entry->key().getStringView().data())); - EXPECT_EQ(reinterpret_cast(trace_ref_value.data()), - reinterpret_cast(header_entry->value().getStringView().data())); - } -} - // Test the header map max limits are setup correctly. TEST(HeaderMapImplTest, HeaderMapMaxLimits) { auto request_header_default = RequestHeaderMapImpl::create(); diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 8e84ecb970a5..7cb9fed96e0c 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -138,8 +138,8 @@ genHeaders(const std::string& host, const std::string& path, const std::string& } if (random_value_pair.has_value()) { - hdrs.setByKey(Envoy::Http::LowerCaseString(random_value_pair.value().first), - random_value_pair.value().second); + hdrs.setCopy(Envoy::Http::LowerCaseString(random_value_pair.value().first), + random_value_pair.value().second); } return hdrs; } diff --git a/test/common/tracing/BUILD b/test/common/tracing/BUILD index 84dacc8b5136..84911ca50618 100644 --- a/test/common/tracing/BUILD +++ b/test/common/tracing/BUILD @@ -84,3 +84,14 @@ envoy_cc_test( "//source/common/tracing:tracer_config_lib", ], ) + +envoy_cc_test( + name = "trace_context_impl_test", + srcs = [ + "trace_context_impl_test.cc", + ], + deps = [ + "//source/common/tracing:http_tracer_lib", + "//source/common/tracing:trace_context_lib", + ], +) diff --git a/test/common/tracing/http_tracer_impl_test.cc b/test/common/tracing/http_tracer_impl_test.cc index 93f992d7f8f8..b0d325833943 100644 --- a/test/common/tracing/http_tracer_impl_test.cc +++ b/test/common/tracing/http_tracer_impl_test.cc @@ -709,6 +709,58 @@ TEST_F(HttpConnManFinalizerImplTest, CustomTagOverwritesCommonTag) { config); } +TEST(HttpTraceContextTest, HttpTraceContextTest) { + { + Http::TestRequestHeaderMapImpl request_headers; + HttpTraceContext trace_context(request_headers); + + // Protocol. + EXPECT_EQ(trace_context.protocol(), ""); + request_headers.addCopy(Http::Headers::get().Protocol, "HTTP/x"); + EXPECT_EQ(trace_context.protocol(), "HTTP/x"); + + // Host. + EXPECT_EQ(trace_context.host(), ""); + request_headers.addCopy(Http::Headers::get().Host, "test.com:233"); + EXPECT_EQ(trace_context.host(), "test.com:233"); + + // Path. + EXPECT_EQ(trace_context.path(), ""); + request_headers.addCopy(Http::Headers::get().Path, "/anything"); + EXPECT_EQ(trace_context.path(), "/anything"); + + // Method. + EXPECT_EQ(trace_context.method(), ""); + request_headers.addCopy(Http::Headers::get().Method, Http::Headers::get().MethodValues.Options); + EXPECT_EQ(trace_context.method(), Http::Headers::get().MethodValues.Options); + + // Set. + trace_context.set("foo", "bar"); + EXPECT_EQ(request_headers.get_("foo"), "bar"); + + // Get. + EXPECT_EQ(trace_context.get("foo").value(), "bar"); + + // Remove. + trace_context.remove("foo"); + EXPECT_EQ(request_headers.get_("foo"), ""); + EXPECT_EQ(trace_context.get("foo"), absl::nullopt); + } + + { + size_t size = 0; + Http::TestRequestHeaderMapImpl request_headers{{"host", "foo"}, {"bar", "var"}, {"ok", "no"}}; + HttpTraceContext trace_context(request_headers); + trace_context.forEach([&size](absl::string_view key, absl::string_view val) { + size += key.size(); + size += val.size(); + return true; + }); + // 'host' will be converted to ':authority'. + EXPECT_EQ(23, size); + } +} + } // namespace } // namespace Tracing } // namespace Envoy diff --git a/test/common/tracing/trace_context_impl_test.cc b/test/common/tracing/trace_context_impl_test.cc new file mode 100644 index 000000000000..531112c53a4b --- /dev/null +++ b/test/common/tracing/trace_context_impl_test.cc @@ -0,0 +1,166 @@ +#include "source/common/http/header_map_impl.h" +#include "source/common/tracing/http_tracer_impl.h" +#include "source/common/tracing/trace_context_impl.h" + +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Tracing { +namespace { + +TEST(TraceContextHandlerTest, TraceContextHandlerGetTest) { + // The key will be lowercase. + { + TraceContextHandler handler("KEY"); + EXPECT_EQ("key", handler.key().get()); + } + + TraceContextHandler normal_key("key"); + TraceContextHandler inline_key("content-type"); // This key is inline key for HTTP. + + // Test get. + { + auto headers = Http::RequestHeaderMapImpl::create(); + headers->setContentType("text/plain"); + headers->addCopy(Http::LowerCaseString("key"), "value"); + + HttpTraceContext http_tracer_context(*headers); + TestTraceContextImpl trace_context{{"key", "value"}, {"content-type", "text/plain"}}; + + EXPECT_EQ("value", normal_key.get(trace_context).value()); + EXPECT_EQ("text/plain", inline_key.get(trace_context).value()); + + EXPECT_EQ("value", normal_key.get(http_tracer_context).value()); + EXPECT_EQ("text/plain", inline_key.get(http_tracer_context).value()); + } +} + +TEST(TraceContextHandlerTest, TraceContextHandlerSetTest) { + + TraceContextHandler normal_key("key"); + TraceContextHandler inline_key("content-type"); // This key is inline key for HTTP. + + // Test set. + { + auto headers = Http::RequestHeaderMapImpl::create(); + HttpTraceContext http_tracer_context(*headers); + + TestTraceContextImpl trace_context{}; + + normal_key.set(trace_context, "value"); + EXPECT_EQ("value", normal_key.get(trace_context).value()); + + inline_key.set(trace_context, "text/html"); + EXPECT_EQ("text/html", inline_key.get(trace_context).value()); + + normal_key.set(http_tracer_context, "value"); + EXPECT_EQ("value", normal_key.get(http_tracer_context).value()); + + inline_key.set(http_tracer_context, "text/html"); + EXPECT_EQ("text/html", inline_key.get(http_tracer_context).value()); + } +} + +TEST(TraceContextHandlerTest, TraceContextHandlerRemoveTest) { + + TraceContextHandler normal_key("key"); + TraceContextHandler inline_key("content-type"); // This key is inline key for HTTP. + + // Test remove. + { + auto headers = Http::RequestHeaderMapImpl::create(); + headers->setContentType("text/plain"); + headers->addCopy(Http::LowerCaseString("key"), "value"); + + HttpTraceContext http_tracer_context(*headers); + TestTraceContextImpl trace_context{{"key", "value"}, {"content-type", "text/plain"}}; + + normal_key.remove(trace_context); + EXPECT_FALSE(normal_key.get(trace_context).has_value()); + + inline_key.remove(trace_context); + EXPECT_FALSE(inline_key.get(trace_context).has_value()); + + normal_key.remove(http_tracer_context); + EXPECT_FALSE(normal_key.get(http_tracer_context).has_value()); + + inline_key.remove(http_tracer_context); + EXPECT_FALSE(inline_key.get(http_tracer_context).has_value()); + } +} + +TEST(TraceContextHandlerTest, TraceContextHandlerSetRefKeyTest) { + + TraceContextHandler normal_key("key"); + TraceContextHandler inline_key("content-type"); // This key is inline key for HTTP. + // Test setRefKey. + { + auto headers = Http::RequestHeaderMapImpl::create(); + HttpTraceContext http_tracer_context(*headers); + TestTraceContextImpl trace_context{}; + + normal_key.setRefKey(trace_context, "value"); + auto iter = trace_context.context_map_.find("key"); + // setRefKey make no sense for non-HTTP context. + EXPECT_NE(iter->first.data(), normal_key.key().get().data()); + + inline_key.setRefKey(trace_context, "text/html"); + auto iter2 = trace_context.context_map_.find("content-type"); + // setRefKey make no sense for non-HTTP context. + EXPECT_NE(iter2->first.data(), inline_key.key().get().data()); + + normal_key.setRefKey(http_tracer_context, "value"); + auto iter3 = headers->get(Http::LowerCaseString("key")); + // setRefKey make sense for HTTP context. + EXPECT_EQ(iter3[0]->key().getStringView().data(), normal_key.key().get().data()); + + inline_key.setRefKey(http_tracer_context, "text/html"); + auto iter4 = headers->get(Http::LowerCaseString("content-type")); + // Note, setRefKey make no sense for inline key of HTTP context because + // inline key is stored in central registry and won't be referenced. + EXPECT_NE(iter4[0]->key().getStringView().data(), inline_key.key().get().data()); + } +} + +TEST(TraceContextHandlerTest, TraceContextHandlerSetRefTest) { + + TraceContextHandler normal_key("key"); + TraceContextHandler inline_key("content-type"); // This key is inline key for HTTP. + // Test setRef + { + auto headers = Http::RequestHeaderMapImpl::create(); + + HttpTraceContext http_tracer_context(*headers); + TestTraceContextImpl trace_context{}; + + const std::string value = "value"; + const std::string text_html = "text/html"; + + normal_key.setRef(trace_context, value); + auto iter = trace_context.context_map_.find("key"); + // setRef make no sense for non-HTTP context. + EXPECT_NE(iter->first.data(), value.data()); + + inline_key.setRef(trace_context, text_html); + auto iter2 = trace_context.context_map_.find("content-type"); + // setRef make no sense for non-HTTP context. + EXPECT_NE(iter2->first.data(), text_html.data()); + + normal_key.setRef(http_tracer_context, value); + auto iter3 = headers->get(Http::LowerCaseString("key")); + // setRef make sense for HTTP context. + EXPECT_EQ(iter3[0]->key().getStringView().data(), normal_key.key().get().data()); + EXPECT_EQ(iter3[0]->value().getStringView().data(), value.data()); + + inline_key.setRef(http_tracer_context, text_html); + auto iter4 = headers->get(Http::LowerCaseString("content-type")); + // setRef make sense for inline key of HTTP context, the value will be referenced. + EXPECT_EQ(iter4[0]->value().getStringView().data(), text_html.data()); + } +} + +} // namespace +} // namespace Tracing +} // namespace Envoy diff --git a/test/common/tracing/tracer_impl_test.cc b/test/common/tracing/tracer_impl_test.cc index 6535d3756b99..e2cd10049b07 100644 --- a/test/common/tracing/tracer_impl_test.cc +++ b/test/common/tracing/tracer_impl_test.cc @@ -289,6 +289,7 @@ class TracerImplTest : public testing::Test { {"grpc-status", "14"}, {"grpc-message", "unavailable"}}; Http::TestResponseTrailerMapImpl response_trailers_; + Tracing::HttpTraceContext trace_context_{request_headers_}; NiceMock stream_info_; NiceMock local_info_; NiceMock config_; @@ -303,7 +304,7 @@ TEST_F(TracerImplTest, BasicFunctionalityNullSpan) { EXPECT_CALL(config_, operationName()).Times(2); const std::string operation_name = "ingress"; EXPECT_CALL(*driver_, startSpan_(_, _, _, operation_name, _)).WillOnce(Return(nullptr)); - tracer_->startSpan(config_, request_headers_, stream_info_, {Reason::Sampling, true}); + tracer_->startSpan(config_, trace_context_, stream_info_, {Reason::Sampling, true}); } TEST_F(TracerImplTest, BasicFunctionalityNodeSet) { @@ -316,7 +317,7 @@ TEST_F(TracerImplTest, BasicFunctionalityNodeSet) { EXPECT_CALL(*span, setTag(_, _)).Times(testing::AnyNumber()); EXPECT_CALL(*span, setTag(Eq(Tracing::Tags::get().NodeId), Eq("node_name"))); - tracer_->startSpan(config_, request_headers_, stream_info_, {Reason::Sampling, true}); + tracer_->startSpan(config_, trace_context_, stream_info_, {Reason::Sampling, true}); } TEST_F(TracerImplTest, ChildGrpcUpstreamSpanTest) { @@ -330,7 +331,7 @@ TEST_F(TracerImplTest, ChildGrpcUpstreamSpanTest) { EXPECT_CALL(*span, setTag(Eq(Tracing::Tags::get().NodeId), Eq("node_name"))); auto parent_span = - tracer_->startSpan(config_, request_headers_, stream_info_, {Reason::Sampling, true}); + tracer_->startSpan(config_, trace_context_, stream_info_, {Reason::Sampling, true}); NiceMock* second_span = new NiceMock(); @@ -376,8 +377,7 @@ TEST_F(TracerImplTest, MetadataCustomTagReturnsDefaultValue) { *testing_metadata.mutable_default_value() = "default_value"; MetadataCustomTag tag("testing", testing_metadata); StreamInfo::MockStreamInfo testing_info_; - Http::TestRequestHeaderMapImpl header_map_; - CustomTagContext context{&header_map_, testing_info_}; + CustomTagContext context{trace_context_, testing_info_}; EXPECT_EQ(tag.value(context), "default_value"); } diff --git a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc index 15fba28c1308..571b4816d4bb 100644 --- a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc +++ b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc @@ -2081,7 +2081,7 @@ TEST(TunnelingConfigImplTest, HeadersToAdd) { auto headers = Http::TestRequestHeaderMapImpl{{":scheme", "http"}, {":authority", "host.com"}}; config.headerEvaluator().evaluateHeaders(headers, {}, stream_info); - EXPECT_EQ("test_val", headers.getByKey("test_key")); + EXPECT_EQ("test_val", headers.get_("test_key")); } TEST(TunnelingConfigImplTest, ProxyHostFromFilterState) { diff --git a/test/extensions/http/header_validators/envoy_default/http1_header_validator_test.cc b/test/extensions/http/header_validators/envoy_default/http1_header_validator_test.cc index 33a881681479..8556ec7d1173 100644 --- a/test/extensions/http/header_validators/envoy_default/http1_header_validator_test.cc +++ b/test/extensions/http/header_validators/envoy_default/http1_header_validator_test.cc @@ -610,7 +610,7 @@ TEST_F(Http1HeaderValidatorTest, ValidateRequestHeaderMapNormalizePath) { EXPECT_TRUE(uhv->validateRequestHeaders(headers).ok()); // The transform method should normalize path EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir2"); } TEST_F(Http1HeaderValidatorTest, ValidateRequestHeaderMapRejectPath) { @@ -781,7 +781,7 @@ TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInPathAllowed) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Note that \ is translated to / and [] remain unencoded - EXPECT_EQ(headers.path(), "/path/with%22%3C%3E[]%5E%60%7B%7D/%7C"); + EXPECT_EQ(headers.getPathValue(), "/path/with%22%3C%3E[]%5E%60%7B%7D/%7C"); } // Validate that without path normalization additional characters remain untouched @@ -796,7 +796,7 @@ TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInPathAllowedWithoutPathNor {":path", absl::StrCat("/path/with", AdditionallyAllowedCharacters)}}; EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), R"str(/path/with"<>[]^`{}\|)str"); + EXPECT_EQ(headers.getPathValue(), R"str(/path/with"<>[]^`{}\|)str"); } TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInQueryAllowed) { @@ -814,7 +814,7 @@ TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInQueryAllowed) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Additional characters in query always remain untouched - EXPECT_EQ(headers.path(), R"str(/path/with?value="<>[]^`{}\|)str"); + EXPECT_EQ(headers.getPathValue(), R"str(/path/with?value="<>[]^`{}\|)str"); } TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInFragmentAllowed) { @@ -832,7 +832,7 @@ TEST_F(Http1HeaderValidatorTest, AdditionalCharactersInFragmentAllowed) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // UHV strips fragment from URL path - EXPECT_EQ(headers.path(), "/path/with?value=aaa"); + EXPECT_EQ(headers.getPathValue(), "/path/with?value=aaa"); } } // namespace diff --git a/test/extensions/http/header_validators/envoy_default/http2_header_validator_test.cc b/test/extensions/http/header_validators/envoy_default/http2_header_validator_test.cc index 83ada3244c69..831f7c9ca529 100644 --- a/test/extensions/http/header_validators/envoy_default/http2_header_validator_test.cc +++ b/test/extensions/http/header_validators/envoy_default/http2_header_validator_test.cc @@ -280,10 +280,10 @@ TEST_F(Http2HeaderValidatorTest, RequestExtendedConnect) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Extended CONNECT is transformed to H/1 upgrade - EXPECT_EQ(headers.method(), "GET"); + EXPECT_EQ(headers.getMethodValue(), "GET"); EXPECT_EQ(headers.getUpgradeValue(), "websocket"); EXPECT_EQ(headers.getConnectionValue(), "upgrade"); - EXPECT_EQ(headers.protocol(), ""); + EXPECT_EQ(headers.getProtocolValue(), ""); } TEST_F(Http2HeaderValidatorTest, RequestExtendedConnectNoScheme) { @@ -295,7 +295,7 @@ TEST_F(Http2HeaderValidatorTest, RequestExtendedConnectNoScheme) { EXPECT_REJECT_WITH_DETAILS(uhv->validateRequestHeaders(headers), UhvResponseCodeDetail::get().InvalidScheme); // If validation failed, the extended CONNECT request should not be transformed to H/1 upgrade - EXPECT_EQ(headers.method(), "CONNECT"); + EXPECT_EQ(headers.getMethodValue(), "CONNECT"); } TEST_F(Http2HeaderValidatorTest, RequestExtendedConnectNoPath) { @@ -330,12 +330,12 @@ TEST_F(Http2HeaderValidatorTest, RequestExtendedConnectPathNormalization) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir2"); // Expect transformation to H/1 upgrade as well - EXPECT_EQ(headers.method(), "GET"); + EXPECT_EQ(headers.getMethodValue(), "GET"); EXPECT_EQ(headers.getUpgradeValue(), "websocket"); EXPECT_EQ(headers.getConnectionValue(), "upgrade"); - EXPECT_EQ(headers.protocol(), ""); + EXPECT_EQ(headers.getProtocolValue(), ""); } TEST_F(Http2HeaderValidatorTest, RequestExtendedConnectNoAuthorityIsOk) { @@ -369,13 +369,13 @@ TEST_F(Http2HeaderValidatorTest, UpstreamUpgradeRequestTransformedToExtendedConn auto result = uhv->transformRequestHeaders(headers); EXPECT_TRUE(result.status.ok()); // Expect the extended CONNECT request - EXPECT_EQ(result.new_headers->method(), "CONNECT"); - EXPECT_EQ(result.new_headers->protocol(), "websocket"); + EXPECT_EQ(result.new_headers->getMethodValue(), "CONNECT"); + EXPECT_EQ(result.new_headers->getProtocolValue(), "websocket"); EXPECT_EQ(result.new_headers->Upgrade(), nullptr); EXPECT_EQ(result.new_headers->Connection(), nullptr); // No path normalization is expected at the client codec - EXPECT_EQ(result.new_headers->path(), "/./dir1/../dir2"); - EXPECT_EQ(result.new_headers->host(), "envoy.com"); + EXPECT_EQ(result.new_headers->getPathValue(), "/./dir1/../dir2"); + EXPECT_EQ(result.new_headers->getHostValue(), "envoy.com"); EXPECT_EQ(result.new_headers->getSchemeValue(), "https"); // New headers must be valid H/2 extended CONNECT headers @@ -672,7 +672,7 @@ TEST_F(Http2HeaderValidatorTest, ValidateRequestHeaderMapNormalizePath) { EXPECT_TRUE(uhv->validateRequestHeaders(headers).ok()); EXPECT_TRUE(uhv->transformRequestHeaders(headers).ok()); - EXPECT_EQ(headers.path(), "/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir2"); } TEST_F(Http2HeaderValidatorTest, ValidateRequestHeaderMapRejectPath) { @@ -832,8 +832,8 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInPathAllowedHttp2) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Note that \ is translated to / and [] remain unencoded - EXPECT_EQ(headers.path(), absl::StrCat("/path/with%09%20%22%3C%3E[]%5E%60%7B%7D/%7C", - generatePercentEncodedExtendedAscii())); + EXPECT_EQ(headers.getPathValue(), absl::StrCat("/path/with%09%20%22%3C%3E[]%5E%60%7B%7D/%7C", + generatePercentEncodedExtendedAscii())); } // Validate that H/3 UHV allows additional characters "<>[]^`{}\| space TAB @@ -853,7 +853,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInPathAllowedHttp3) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Note that \ is translated to / and [] remain unencoded - EXPECT_EQ(headers.path(), "/path/with%09%20%22%3C%3E[]%5E%60%7B%7D/%7C"); + EXPECT_EQ(headers.getPathValue(), "/path/with%09%20%22%3C%3E[]%5E%60%7B%7D/%7C"); } // Validate that without path normalization additional characters remain untouched @@ -868,7 +868,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInPathAllowedWithoutPathNor {":path", absl::StrCat("/path/with", AdditionallyAllowedCharactersHttp2)}}; EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), + EXPECT_EQ(headers.getPathValue(), absl::StrCat("/path/with\t \"<>[]^`{}\\|", generateExtendedAsciiString())); } @@ -884,7 +884,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInPathAllowedWithoutPathNor {":path", absl::StrCat("/path/with", AdditionallyAllowedCharactersHttp3)}}; EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/path/with\t \"<>[]^`{}\\|"); + EXPECT_EQ(headers.getPathValue(), "/path/with\t \"<>[]^`{}\\|"); } TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInQueryAllowedHttp2) { @@ -902,7 +902,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInQueryAllowedHttp2) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Additional characters in query always remain untouched - EXPECT_EQ(headers.path(), + EXPECT_EQ(headers.getPathValue(), absl::StrCat("/path/with?value=\t \"<>[]^`{}\\|", generateExtendedAsciiString())); } @@ -922,7 +922,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInQueryAllowedHttp3) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // Additional characters in query always remain untouched - EXPECT_EQ(headers.path(), "/path/with?value=\t \"<>[]^`{}\\|"); + EXPECT_EQ(headers.getPathValue(), "/path/with?value=\t \"<>[]^`{}\\|"); } TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInFragmentAllowedHttp2) { @@ -940,7 +940,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInFragmentAllowedHttp2) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // UHV strips fragment from URL path - EXPECT_EQ(headers.path(), "/path/with?value=aaa"); + EXPECT_EQ(headers.getPathValue(), "/path/with?value=aaa"); } TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInFragmentAllowedHttp3) { @@ -959,7 +959,7 @@ TEST_F(Http2HeaderValidatorTest, AdditionalCharactersInFragmentAllowedHttp3) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); // UHV strips fragment from URL path - EXPECT_EQ(headers.path(), "/path/with?value=aaa"); + EXPECT_EQ(headers.getPathValue(), "/path/with?value=aaa"); } } // namespace diff --git a/test/extensions/http/header_validators/envoy_default/http_common_validation_test.cc b/test/extensions/http/header_validators/envoy_default/http_common_validation_test.cc index 47a57b652d9f..08de2d95443e 100644 --- a/test/extensions/http/header_validators/envoy_default/http_common_validation_test.cc +++ b/test/extensions/http/header_validators/envoy_default/http_common_validation_test.cc @@ -63,7 +63,7 @@ TEST_P(HttpCommonValidationTest, MalformedUrlEncodingAllowed) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/path%Z0with%xYbad%7Jencoding%"); + EXPECT_EQ(headers.getPathValue(), "/path%Z0with%xYbad%7Jencoding%"); } TEST_P(HttpCommonValidationTest, MalformedUrlEncodingRejectedWithOverride) { @@ -89,7 +89,7 @@ TEST_P(HttpCommonValidationTest, BackslashInPathIsTranslatedToSlash) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/path/with/back/slash%5C"); + EXPECT_EQ(headers.getPathValue(), "/path/with/back/slash%5C"); } TEST_P(HttpCommonValidationTest, BackslashInPathIsRejectedWithOverride) { @@ -147,7 +147,7 @@ TEST_P(HttpCommonValidationTest, FragmentStrippedFromPathWhenConfigured) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/path/with?query=and"); + EXPECT_EQ(headers.getPathValue(), "/path/with?query=and"); } TEST_P(HttpCommonValidationTest, ValidateRequestHeaderMapRedirectPath) { @@ -164,7 +164,7 @@ TEST_P(HttpCommonValidationTest, ValidateRequestHeaderMapRedirectPath) { ::Envoy::Http::ServerHeaderValidator::RequestHeadersTransformationResult::Action::Redirect); EXPECT_EQ(result.details(), "uhv.path_normalization_redirect"); // By default decoded backslash (%5C) is converted to forward slash. - EXPECT_EQ(headers.path(), "/dir1/dir2/dir4"); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2/dir4"); } TEST_P(HttpCommonValidationTest, ValidateRequestHeadersNoPathNormalization) { @@ -180,7 +180,7 @@ TEST_P(HttpCommonValidationTest, ValidateRequestHeadersNoPathNormalization) { EXPECT_EQ( result.action(), ::Envoy::Http::ServerHeaderValidator::RequestHeadersTransformationResult::Action::Redirect); - EXPECT_EQ(headers.path(), "/dir1/dir2\\.."); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2\\.."); } TEST_P(HttpCommonValidationTest, NoPathNormalizationNoSlashDecoding) { @@ -192,7 +192,7 @@ TEST_P(HttpCommonValidationTest, NoPathNormalizationNoSlashDecoding) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); auto result = uhv->transformRequestHeaders(headers); EXPECT_ACCEPT(result); - EXPECT_EQ(headers.path(), "/dir1%2Fdir2%5cdir3"); + EXPECT_EQ(headers.getPathValue(), "/dir1%2Fdir2%5cdir3"); } TEST_P(HttpCommonValidationTest, NoPathNormalizationDecodeSlashesAndForward) { @@ -204,7 +204,7 @@ TEST_P(HttpCommonValidationTest, NoPathNormalizationDecodeSlashesAndForward) { EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); auto result = uhv->transformRequestHeaders(headers); EXPECT_ACCEPT(result); - EXPECT_EQ(headers.path(), "/dir1/dir2\\../dir3"); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2\\../dir3"); } TEST_P(HttpCommonValidationTest, RejectEncodedSlashes) { @@ -237,7 +237,7 @@ TEST_P(HttpCommonValidationTest, AllowPercent00WithOverride) { auto uhv = createUhv(empty_config); EXPECT_ACCEPT(uhv->validateRequestHeaders(headers)); EXPECT_ACCEPT(uhv->transformRequestHeaders(headers)); - EXPECT_EQ(headers.path(), "/dir1%00dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir1%00dir2"); } } // namespace diff --git a/test/extensions/http/header_validators/envoy_default/path_normalizer_fuzz_test.cc b/test/extensions/http/header_validators/envoy_default/path_normalizer_fuzz_test.cc index 501646fb1be0..b86ac9d3a217 100644 --- a/test/extensions/http/header_validators/envoy_default/path_normalizer_fuzz_test.cc +++ b/test/extensions/http/header_validators/envoy_default/path_normalizer_fuzz_test.cc @@ -49,11 +49,11 @@ DEFINE_PROTO_FUZZER( Extensions::Http::HeaderValidators::EnvoyDefault::PathNormalizer:: PathNormalizationResult::Action::Redirect) { // Additional sanity checks on the normalized path - RELEASE_ASSERT(header_map->path().size() <= input.path().size(), + RELEASE_ASSERT(header_map->getPathValue().size() <= input.path().size(), "Normalized path is always shorter or the same length."); - RELEASE_ASSERT(header_map->method() == input.method(), ":method should not change."); + RELEASE_ASSERT(header_map->getMethodValue() == input.method(), ":method should not change."); auto original_query_or_fragment = input.path().find_first_of("?#"); - auto normalized_query_or_fragment = header_map->path().find_first_of("?#"); + auto normalized_query_or_fragment = header_map->getPathValue().find_first_of("?#"); RELEASE_ASSERT( (original_query_or_fragment != std::string::npos && normalized_query_or_fragment != absl::string_view::npos) || @@ -62,23 +62,26 @@ DEFINE_PROTO_FUZZER( "Query/fragment must be present or absent in both original and normalized paths"); if (original_query_or_fragment != std::string::npos) { RELEASE_ASSERT(input.path().substr(original_query_or_fragment) == - header_map->path().substr(normalized_query_or_fragment), + header_map->getPathValue().substr(normalized_query_or_fragment), "Original and normalized query/path should be the same"); } if (!input.options().skip_merging_slashes()) { - RELEASE_ASSERT(header_map->path().substr(0, normalized_query_or_fragment).find("//") == - absl::string_view::npos, - ":path must not contain adjacent slashes."); + RELEASE_ASSERT( + header_map->getPathValue().substr(0, normalized_query_or_fragment).find("//") == + absl::string_view::npos, + ":path must not contain adjacent slashes."); } if (!input.options().skip_path_normalization()) { - RELEASE_ASSERT(header_map->path().substr(0, normalized_query_or_fragment).find("/./") == - absl::string_view::npos, - ":path must not contain /./"); - RELEASE_ASSERT(header_map->path().substr(0, normalized_query_or_fragment).find("/../") == - absl::string_view::npos, - ":path must not contain /../"); + RELEASE_ASSERT( + header_map->getPathValue().substr(0, normalized_query_or_fragment).find("/./") == + absl::string_view::npos, + ":path must not contain /./"); + RELEASE_ASSERT( + header_map->getPathValue().substr(0, normalized_query_or_fragment).find("/../") == + absl::string_view::npos, + ":path must not contain /../"); } } } diff --git a/test/extensions/http/header_validators/envoy_default/path_normalizer_test.cc b/test/extensions/http/header_validators/envoy_default/path_normalizer_test.cc index e2cafabed358..30a956b4e039 100644 --- a/test/extensions/http/header_validators/envoy_default/path_normalizer_test.cc +++ b/test/extensions/http/header_validators/envoy_default/path_normalizer_test.cc @@ -172,7 +172,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriRoot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/"); + EXPECT_EQ(headers.getPathValue(), "/"); EXPECT_TRUE(result.ok()); } @@ -182,7 +182,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriRootPreserveQueryFragment) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/root/child?x=1#anchor"); + EXPECT_EQ(headers.getPathValue(), "/root/child?x=1#anchor"); EXPECT_TRUE(result.ok()); } @@ -192,7 +192,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriRootPreserveFragment) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/root/child#anchor"); + EXPECT_EQ(headers.getPathValue(), "/root/child#anchor"); EXPECT_TRUE(result.ok()); } @@ -202,7 +202,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriDotDot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir2"); EXPECT_TRUE(result.ok()); } @@ -212,7 +212,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriDot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir1/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2"); EXPECT_TRUE(result.ok()); } @@ -222,7 +222,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriTrailingDotDot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/"); + EXPECT_EQ(headers.getPathValue(), "/"); EXPECT_TRUE(result.ok()); } @@ -232,7 +232,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriEncodedDotDot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir2"); + EXPECT_EQ(headers.getPathValue(), "/dir2"); EXPECT_TRUE(result.ok()); } @@ -242,7 +242,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriTrailingDot) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir1/"); + EXPECT_EQ(headers.getPathValue(), "/dir1/"); EXPECT_TRUE(result.ok()); } @@ -252,7 +252,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriDotInSegments) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir1/.dir2/..dir3/dir.4/dir..5"); + EXPECT_EQ(headers.getPathValue(), "/dir1/.dir2/..dir3/dir.4/dir..5"); EXPECT_TRUE(result.ok()); } @@ -262,7 +262,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriMergeSlashes) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/root/child/"); + EXPECT_EQ(headers.getPathValue(), "/root/child/"); EXPECT_TRUE(result.ok()); } @@ -273,7 +273,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriPercentDecodeNormalized) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/%FF"); + EXPECT_EQ(headers.getPathValue(), "/%FF"); EXPECT_TRUE(result.ok()); } @@ -283,7 +283,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriPercentDecoded) { auto normalizer = create(empty_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/~/dir1"); + EXPECT_EQ(headers.getPathValue(), "/~/dir1"); EXPECT_TRUE(result.ok()); } @@ -293,7 +293,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriSkipMergingSlashes) { auto normalizer = create(skip_merging_slashes_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "//root//child//"); + EXPECT_EQ(headers.getPathValue(), "//root//child//"); EXPECT_TRUE(result.ok()); } @@ -303,7 +303,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriSkipMergingSlashesWithDecodeSlashes) auto normalizer = create(skip_merging_slashes_with_decode_slashes_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/root//child//"); + EXPECT_EQ(headers.getPathValue(), "/root//child//"); EXPECT_TRUE(result.ok()); } @@ -314,7 +314,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriDecodeSlashes) { auto normalizer = create(decode_encoded_slash_config); auto result = normalizer->normalizePathUri(headers); - EXPECT_EQ(headers.path(), "/dir1/dir2/dir3/dir4"); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2/dir3/dir4"); EXPECT_TRUE(result.ok()); } @@ -346,7 +346,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriRedirectEncodedSlashes) { EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Redirect); EXPECT_EQ(result.details(), "uhv.path_normalization_redirect"); - EXPECT_EQ(headers.path(), "/dir1/dir2/dir3"); + EXPECT_EQ(headers.getPathValue(), "/dir1/dir2/dir3"); } TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesDefault) { @@ -358,7 +358,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesDefault) { EXPECT_TRUE(result.ok()); // By default slashes are not decoded - EXPECT_EQ(headers.path(), "/dir1%2Fdir2%5Cdir3"); + EXPECT_EQ(headers.getPathValue(), "/dir1%2Fdir2%5Cdir3"); } TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesKept) { @@ -369,7 +369,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesKept) { auto result = normalizer->normalizePathUri(headers); EXPECT_TRUE(result.ok()); - EXPECT_EQ(headers.path(), "/dir1%2Fdir2%5Cdir3"); + EXPECT_EQ(headers.getPathValue(), "/dir1%2Fdir2%5Cdir3"); } TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesImplDefault) { @@ -380,7 +380,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriNormalizeEncodedSlashesImplDefault) { auto result = normalizer->normalizePathUri(headers); EXPECT_TRUE(result.ok()); - EXPECT_EQ(headers.path(), "/dir1%2Fdir2"); + EXPECT_EQ(headers.getPathValue(), "/dir1%2Fdir2"); } TEST_F(PathNormalizerTest, NormalizePathUriInvalidBeyondRoot) { @@ -424,7 +424,7 @@ TEST_F(PathNormalizerTest, MalformedUrlEncodingAllowed) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), "/path%Z0with%xYbad%7Jencoding%A"); + EXPECT_EQ(headers.getPathValue(), "/path%Z0with%xYbad%7Jencoding%A"); } TEST_F(PathNormalizerTest, NormalizePathUriAuthorityFormConnect) { @@ -435,7 +435,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriAuthorityFormConnect) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), ""); + EXPECT_EQ(headers.getPathValue(), ""); } TEST_F(PathNormalizerTest, NormalizePathUriAuthorityFormWithPathConnect) { @@ -468,7 +468,7 @@ TEST_F(PathNormalizerTest, NormalizePathUriAsteriskFormOptions) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), "*"); + EXPECT_EQ(headers.getPathValue(), "*"); } TEST_F(PathNormalizerTest, NormalizePathUriAsteriskFormNotOptions) { @@ -491,7 +491,7 @@ TEST_F(PathNormalizerTest, BackslashTranslatedToSlashByDefault) { EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); // In query backslash is untouched - EXPECT_EQ(headers.path(), "/path/with/back/slash%5c?key=val\\ue"); + EXPECT_EQ(headers.getPathValue(), "/path/with/back/slash%5c?key=val\\ue"); } TEST_F(PathNormalizerTest, BackslashPreservedWithOverride) { @@ -502,7 +502,7 @@ TEST_F(PathNormalizerTest, BackslashPreservedWithOverride) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), "/path\\with/back\\/slash%5C"); + EXPECT_EQ(headers.getPathValue(), "/path\\with/back\\/slash%5C"); } TEST_F(PathNormalizerTest, PreservePercentEncodedCaseByDefault) { @@ -512,7 +512,7 @@ TEST_F(PathNormalizerTest, PreservePercentEncodedCaseByDefault) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), "/dir1%Abdir2%3a%fFZ"); + EXPECT_EQ(headers.getPathValue(), "/dir1%Abdir2%3a%fFZ"); } TEST_F(PathNormalizerTest, NormalizePercentEncodedCase) { @@ -523,7 +523,7 @@ TEST_F(PathNormalizerTest, NormalizePercentEncodedCase) { auto result = normalizer->normalizePathUri(headers); EXPECT_EQ(result.action(), PathNormalizer::PathNormalizationResult::Action::Accept); - EXPECT_EQ(headers.path(), "/dir1%ABdir2%3A%FFZ"); + EXPECT_EQ(headers.getPathValue(), "/dir1%ABdir2%3A%FFZ"); } } // namespace EnvoyDefault diff --git a/test/extensions/tracers/common/ot/opentracing_driver_impl_test.cc b/test/extensions/tracers/common/ot/opentracing_driver_impl_test.cc index 7f52995e5600..09c337108c1b 100644 --- a/test/extensions/tracers/common/ot/opentracing_driver_impl_test.cc +++ b/test/extensions/tracers/common/ot/opentracing_driver_impl_test.cc @@ -365,7 +365,7 @@ TEST_F(OpenTracingDriverTest, ExtractUsingForeach) { {Tracing::Reason::Sampling, true}); for (const auto& [key, value] : extracted_headers) { - EXPECT_EQ(value, request_headers_.getByKey(key)); + EXPECT_EQ(value, request_headers_.get(key)); } } diff --git a/test/extensions/tracers/datadog/agent_http_client_test.cc b/test/extensions/tracers/datadog/agent_http_client_test.cc index 98e60c971578..08a461b90894 100644 --- a/test/extensions/tracers/datadog/agent_http_client_test.cc +++ b/test/extensions/tracers/datadog/agent_http_client_test.cc @@ -78,7 +78,7 @@ TEST_F(DatadogAgentHttpClientTest, PathFromURL) { .WillOnce( Invoke([this](Http::RequestMessagePtr& message, Http::AsyncClient::Callbacks&, const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { - EXPECT_EQ(url_.path, message->headers().path()); + EXPECT_EQ(url_.path, message->headers().getPathValue()); return &request_; })); @@ -121,17 +121,23 @@ TEST_F(DatadogAgentHttpClientTest, RequestHeaders) { }; EXPECT_CALL(cluster_manager_.instance_.thread_local_cluster_.async_client_, send_(_, _, _)) - .WillOnce( - Invoke([this](Http::RequestMessagePtr& message, Http::AsyncClient::Callbacks&, - const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { - EXPECT_EQ("test_host", message->headers().getHostValue()); - - EXPECT_EQ("bar", message->headers().getByKey("foo")); - EXPECT_EQ("boing boing", message->headers().getByKey("baz-boing")); - EXPECT_EQ("boing boing boing", message->headers().getByKey("boing-boing")); - - return &request_; - })); + .WillOnce(Invoke([this](Http::RequestMessagePtr& message, Http::AsyncClient::Callbacks&, + const Http::AsyncClient::RequestOptions&) + -> Http::AsyncClient::Request* { + EXPECT_EQ("test_host", message->headers().getHostValue()); + + EXPECT_EQ("bar", + message->headers().get(Http::LowerCaseString("foo"))[0]->value().getStringView()); + EXPECT_EQ( + "boing boing", + message->headers().get(Http::LowerCaseString("baz-boing"))[0]->value().getStringView()); + EXPECT_EQ("boing boing boing", message->headers() + .get(Http::LowerCaseString("boing-boing"))[0] + ->value() + .getStringView()); + + return &request_; + })); // `~AgentHTTPClient()` will cancel the request since we don't finish it here. EXPECT_CALL(request_, cancel()); diff --git a/test/extensions/tracers/opencensus/tracer_test.cc b/test/extensions/tracers/opencensus/tracer_test.cc index 22bf937d752e..0548b99bc569 100644 --- a/test/extensions/tracers/opencensus/tracer_test.cc +++ b/test/extensions/tracers/opencensus/tracer_test.cc @@ -209,7 +209,7 @@ void testIncomingHeaders( {"x-request-id", "foo"}, }; for (const auto& kv : headers) { - request_headers.setByKey(Http::LowerCaseString(kv.first), kv.second); + request_headers.set(Http::LowerCaseString(kv.first), kv.second); } const std::string operation_name{"my_operation_2"}; @@ -316,6 +316,13 @@ TEST(OpenCensusTracerTest, ConstantSamplerAlwaysOn) { EXPECT_EQ(1, samplerTestHelper(oc_config)); } +// Test no sampler set. +TEST(OpenCensusTracerTest, NoSamplerSet) { + OpenCensusConfig oc_config; + oc_config.mutable_trace_config(); + samplerTestHelper(oc_config); +} + // Test constant_sampler that's always off. TEST(OpenCensusTracerTest, ConstantSamplerAlwaysOff) { OpenCensusConfig oc_config; diff --git a/test/extensions/tracers/opentelemetry/opentelemetry_tracer_impl_test.cc b/test/extensions/tracers/opentelemetry/opentelemetry_tracer_impl_test.cc index befc5a433c48..223c74352756 100644 --- a/test/extensions/tracers/opentelemetry/opentelemetry_tracer_impl_test.cc +++ b/test/extensions/tracers/opentelemetry/opentelemetry_tracer_impl_test.cc @@ -4,6 +4,7 @@ #include "source/common/tracing/http_tracer_impl.h" #include "source/extensions/tracers/opentelemetry/opentelemetry_tracer_impl.h" +#include "source/extensions/tracers/opentelemetry/span_context_extractor.h" #include "test/mocks/common.h" #include "test/mocks/server/tracer_factory_context.h" @@ -161,9 +162,9 @@ TEST_F(OpenTelemetryDriverTest, ParseSpanContextFromHeadersTest) { const std::vector v = {version, trace_id_hex, Hex::uint64ToHex(parent_span_id), trace_flags}; const std::string parent_trace_header = absl::StrJoin(v, "-"); - request_headers.set(OpenTelemetryConstants::get().TRACE_PARENT, parent_trace_header); + request_headers.set(OpenTelemetryConstants::get().TRACE_PARENT.key(), parent_trace_header); // Also add tracestate. - request_headers.set(OpenTelemetryConstants::get().TRACE_STATE, "test=foo"); + request_headers.set(OpenTelemetryConstants::get().TRACE_STATE.key(), "test=foo"); // Mock the random call for generating span ID so we can check it later. const uint64_t new_span_id = 3; @@ -177,17 +178,18 @@ TEST_F(OpenTelemetryDriverTest, ParseSpanContextFromHeadersTest) { EXPECT_EQ(span->getTraceIdAsHex(), trace_id_hex); // Remove headers, then inject context into header from the span. - request_headers.remove(OpenTelemetryConstants::get().TRACE_PARENT); - request_headers.remove(OpenTelemetryConstants::get().TRACE_STATE); + request_headers.remove(OpenTelemetryConstants::get().TRACE_PARENT.key()); + request_headers.remove(OpenTelemetryConstants::get().TRACE_STATE.key()); span->injectContext(request_headers, nullptr); - auto sampled_entry = request_headers.getByKey(OpenTelemetryConstants::get().TRACE_PARENT); + auto sampled_entry = request_headers.get(OpenTelemetryConstants::get().TRACE_PARENT.key()); EXPECT_EQ(sampled_entry.has_value(), true); EXPECT_EQ( sampled_entry.value(), absl::StrJoin({version, trace_id_hex, Hex::uint64ToHex(new_span_id), trace_flags}, "-")); - auto sampled_tracestate_entry = request_headers.get(OpenTelemetryConstants::get().TRACE_STATE); + auto sampled_tracestate_entry = + request_headers.get(OpenTelemetryConstants::get().TRACE_STATE.key()); EXPECT_EQ(sampled_tracestate_entry.has_value(), true); EXPECT_EQ(sampled_tracestate_entry.value(), "test=foo"); constexpr absl::string_view request_yaml = R"( @@ -260,10 +262,10 @@ TEST_F(OpenTelemetryDriverTest, GenerateSpanContextWithoutHeadersTest) { operation_name_, {Tracing::Reason::Sampling, true}); // Remove headers, then inject context into header from the span. - request_headers.remove(OpenTelemetryConstants::get().TRACE_PARENT); + request_headers.remove(OpenTelemetryConstants::get().TRACE_PARENT.key()); span->injectContext(request_headers, nullptr); - auto sampled_entry = request_headers.get(OpenTelemetryConstants::get().TRACE_PARENT); + auto sampled_entry = request_headers.get(OpenTelemetryConstants::get().TRACE_PARENT.key()); // Ends in 01 because span should be sampled. See // https://w3c.github.io/trace-context/#trace-flags. @@ -277,7 +279,8 @@ TEST_F(OpenTelemetryDriverTest, NullSpanWithPropagationHeaderError) { // Add an invalid OTLP header to the request headers. Tracing::TestTraceContextImpl request_headers{ {":authority", "test.com"}, {":path", "/"}, {":method", "GET"}}; - request_headers.set(OpenTelemetryConstants::get().TRACE_PARENT, "invalid00-0000000000000003-01"); + request_headers.set(OpenTelemetryConstants::get().TRACE_PARENT.key(), + "invalid00-0000000000000003-01"); Tracing::SpanPtr span = driver_->startSpan(mock_tracing_config_, request_headers, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); diff --git a/test/extensions/tracers/opentelemetry/span_context_extractor_test.cc b/test/extensions/tracers/opentelemetry/span_context_extractor_test.cc index a09fba2e3564..b87f984768eb 100644 --- a/test/extensions/tracers/opentelemetry/span_context_extractor_test.cc +++ b/test/extensions/tracers/opentelemetry/span_context_extractor_test.cc @@ -1,3 +1,4 @@ +#include "source/common/tracing/http_tracer_impl.h" #include "source/extensions/tracers/opentelemetry/span_context_extractor.h" #include "test/test_common/status_utility.h" @@ -21,8 +22,9 @@ constexpr absl::string_view parent_id = "0000000000000003"; constexpr absl::string_view trace_flags = "01"; TEST(SpanContextExtractorTest, ExtractSpanContext) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, parent_id, trace_flags)}}; + SpanContextExtractor span_context_extractor(request_headers); absl::StatusOr span_context = span_context_extractor.extractSpanContext(); @@ -35,7 +37,7 @@ TEST(SpanContextExtractorTest, ExtractSpanContext) { TEST(SpanContextExtractorTest, ExtractSpanContextNotSampled) { const std::string trace_flags_unsampled{"00"}; - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, parent_id, trace_flags_unsampled)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -49,7 +51,7 @@ TEST(SpanContextExtractorTest, ExtractSpanContextNotSampled) { } TEST(SpanContextExtractorTest, ThrowsExceptionWithoutHeader) { - Http::TestRequestHeaderMapImpl request_headers{{}}; + Tracing::TestTraceContextImpl request_headers{{}}; SpanContextExtractor span_context_extractor(request_headers); absl::StatusOr span_context = span_context_extractor.extractSpanContext(); @@ -59,7 +61,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithoutHeader) { } TEST(SpanContextExtractorTest, ThrowsExceptionWithTooLongHeader) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("000{}-{}-{}-{}", version, trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -70,7 +72,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithTooLongHeader) { } TEST(SpanContextExtractorTest, ThrowsExceptionWithTooShortHeader) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}", trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -81,7 +83,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithTooShortHeader) { } TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidHyphenation) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}{}-{}-{}", version, trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -94,7 +96,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidHyphenation) { TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidSizes) { const std::string invalid_version{"0"}; const std::string invalid_trace_flags{"001"}; - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", invalid_version, trace_id, parent_id, invalid_trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -107,7 +109,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidSizes) { TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidHex) { const std::string invalid_version{"ZZ"}; - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", invalid_version, trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -120,7 +122,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithInvalidHex) { TEST(SpanContextExtractorTest, ThrowsExceptionWithAllZeroTraceId) { const std::string invalid_trace_id{"00000000000000000000000000000000"}; - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, invalid_trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -133,7 +135,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithAllZeroTraceId) { TEST(SpanContextExtractorTest, ThrowsExceptionWithAllZeroParentId) { const std::string invalid_parent_id{"0000000000000000"}; - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, invalid_parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); @@ -145,7 +147,7 @@ TEST(SpanContextExtractorTest, ThrowsExceptionWithAllZeroParentId) { } TEST(SpanContextExtractorTest, ExtractSpanContextWithEmptyTracestate) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, parent_id, trace_flags)}}; SpanContextExtractor span_context_extractor(request_headers); absl::StatusOr span_context = span_context_extractor.extractSpanContext(); @@ -155,7 +157,7 @@ TEST(SpanContextExtractorTest, ExtractSpanContextWithEmptyTracestate) { } TEST(SpanContextExtractorTest, ExtractSpanContextWithTracestate) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, parent_id, trace_flags)}, {"tracestate", "sample-tracestate"}}; SpanContextExtractor span_context_extractor(request_headers); @@ -166,7 +168,7 @@ TEST(SpanContextExtractorTest, ExtractSpanContextWithTracestate) { } TEST(SpanContextExtractorTest, IgnoreTracestateWithoutTraceparent) { - Http::TestRequestHeaderMapImpl request_headers{{"tracestate", "sample-tracestate"}}; + Tracing::TestTraceContextImpl request_headers{{"tracestate", "sample-tracestate"}}; SpanContextExtractor span_context_extractor(request_headers); absl::StatusOr span_context = span_context_extractor.extractSpanContext(); @@ -179,7 +181,8 @@ TEST(SpanContextExtractorTest, ExtractSpanContextWithMultipleTracestateEntries) {"traceparent", fmt::format("{}-{}-{}-{}", version, trace_id, parent_id, trace_flags)}, {"tracestate", "sample-tracestate"}, {"tracestate", "sample-tracestate-2"}}; - SpanContextExtractor span_context_extractor(request_headers); + Tracing::HttpTraceContext trace_context(request_headers); + SpanContextExtractor span_context_extractor(trace_context); absl::StatusOr span_context = span_context_extractor.extractSpanContext(); EXPECT_OK(span_context); diff --git a/test/extensions/tracers/xray/tracer_test.cc b/test/extensions/tracers/xray/tracer_test.cc index 26fb29c5d540..a9bed48890cb 100644 --- a/test/extensions/tracers/xray/tracer_test.cc +++ b/test/extensions/tracers/xray/tracer_test.cc @@ -509,7 +509,7 @@ TEST_F(XRayTracerTest, SpanInjectContextHasXRayHeader) { absl::nullopt /*client_ip from x-forwarded-for header*/); Tracing::TestTraceContextImpl request_headers{}; span->injectContext(request_headers, nullptr); - auto header = request_headers.get(Http::LowerCaseString{XRayTraceHeader}); + auto header = request_headers.get(xRayTraceHeader().key()); ASSERT_FALSE(!header.has_value()); EXPECT_NE(header.value().find("Root="), absl::string_view::npos); EXPECT_NE(header.value().find("Parent="), absl::string_view::npos); @@ -527,7 +527,7 @@ TEST_F(XRayTracerTest, SpanInjectContextHasXRayHeaderNonSampled) { auto span = tracer.createNonSampledSpan(absl::nullopt /*headers*/); Tracing::TestTraceContextImpl request_headers{}; span->injectContext(request_headers, nullptr); - auto header = request_headers.get(Http::LowerCaseString{XRayTraceHeader}); + auto header = request_headers.get(xRayTraceHeader().key()); ASSERT_FALSE(!header.has_value()); EXPECT_NE(header.value().find("Root="), absl::string_view::npos); EXPECT_NE(header.value().find("Parent="), absl::string_view::npos); diff --git a/test/extensions/tracers/xray/xray_tracer_impl_test.cc b/test/extensions/tracers/xray/xray_tracer_impl_test.cc index 11d7a2ed9c5e..4a7a2c995c32 100644 --- a/test/extensions/tracers/xray/xray_tracer_impl_test.cc +++ b/test/extensions/tracers/xray/xray_tracer_impl_test.cc @@ -43,7 +43,7 @@ class XRayDriverTest : public ::testing::Test { }; TEST_F(XRayDriverTest, XRayTraceHeaderNotSampled) { - request_headers_.set(std::string(XRayTraceHeader), "Root=1-272793;Parent=5398ad8;Sampled=0"); + request_headers_.set(xRayTraceHeader().key(), "Root=1-272793;Parent=5398ad8;Sampled=0"); XRayConfiguration config{"" /*daemon_endpoint*/, "test_segment_name", "" /*sampling_rules*/, "" /*origin*/, aws_metadata_}; @@ -59,7 +59,7 @@ TEST_F(XRayDriverTest, XRayTraceHeaderNotSampled) { } TEST_F(XRayDriverTest, XRayTraceHeaderSampled) { - request_headers_.set(std::string(XRayTraceHeader), "Root=1-272793;Parent=5398ad8;Sampled=1"); + request_headers_.set(xRayTraceHeader().key(), "Root=1-272793;Parent=5398ad8;Sampled=1"); XRayConfiguration config{"" /*daemon_endpoint*/, "test_segment_name", "" /*sampling_rules*/, "" /*origin*/, aws_metadata_}; @@ -73,7 +73,7 @@ TEST_F(XRayDriverTest, XRayTraceHeaderSampled) { } TEST_F(XRayDriverTest, XRayTraceHeaderSamplingUnknown) { - request_headers_.set(std::string(XRayTraceHeader), "Root=1-272793;Parent=5398ad8;Sampled="); + request_headers_.set(xRayTraceHeader().key(), "Root=1-272793;Parent=5398ad8;Sampled="); XRayConfiguration config{"" /*daemon_endpoint*/, "test_segment_name", "" /*sampling_rules*/, "" /*origin*/, aws_metadata_}; @@ -91,7 +91,7 @@ TEST_F(XRayDriverTest, XRayTraceHeaderSamplingUnknown) { } TEST_F(XRayDriverTest, XRayTraceHeaderWithoutSamplingDecision) { - request_headers_.set(std::string(XRayTraceHeader), "Root=1-272793;Parent=5398ad8;"); + request_headers_.set(xRayTraceHeader().key(), "Root=1-272793;Parent=5398ad8;"); // sampling rules with default fixed_target = 0 & rate = 0 XRayConfiguration config{"" /*daemon_endpoint*/, "test_segment_name", R"EOF( { @@ -134,7 +134,7 @@ TEST_F(XRayDriverTest, NoXRayTracerHeader) { } TEST_F(XRayDriverTest, XForwardedForHeaderSet) { - request_headers_.set(std::string(XForwardedForHeader), "191.251.191.251"); + request_headers_.set(xForwardedForHeader().key(), "191.251.191.251"); XRayConfiguration config{"" /*daemon_endpoint*/, "test_segment_name", "" /*sampling_rules*/, "" /*origin*/, aws_metadata_}; Driver driver(config, context_); diff --git a/test/extensions/tracers/zipkin/span_context_extractor_test.cc b/test/extensions/tracers/zipkin/span_context_extractor_test.cc index 1b6f41bf6ea0..393b995f7167 100644 --- a/test/extensions/tracers/zipkin/span_context_extractor_test.cc +++ b/test/extensions/tracers/zipkin/span_context_extractor_test.cc @@ -20,7 +20,7 @@ const std::string parent_id{"0000000000000002"}; } // namespace TEST(ZipkinSpanContextExtractorTest, Largest) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}-{}-1-{}", trace_id_high, trace_id, span_id, parent_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); @@ -35,7 +35,7 @@ TEST(ZipkinSpanContextExtractorTest, Largest) { } TEST(ZipkinSpanContextExtractorTest, WithoutParentDebug) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}-{}-d", trace_id_high, trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); @@ -50,7 +50,7 @@ TEST(ZipkinSpanContextExtractorTest, WithoutParentDebug) { } TEST(ZipkinSpanContextExtractorTest, MalformedUuid) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "b970dafd-0d95-40aa-95d8-1d8725aebe40"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "b970dafd-0d95-40aa-95d8-1d8725aebe40"}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: invalid trace id b970dafd-0d95-40"); @@ -58,7 +58,7 @@ TEST(ZipkinSpanContextExtractorTest, MalformedUuid) { } TEST(ZipkinSpanContextExtractorTest, MiddleOfString) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}-{},", trace_id, trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -67,7 +67,7 @@ TEST(ZipkinSpanContextExtractorTest, MiddleOfString) { } TEST(ZipkinSpanContextExtractorTest, DebugOnly) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "d"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "d"}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); EXPECT_FALSE(context.second); @@ -81,7 +81,7 @@ TEST(ZipkinSpanContextExtractorTest, DebugOnly) { } TEST(ZipkinSpanContextExtractorTest, Sampled) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "1"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "1"}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); EXPECT_FALSE(context.second); @@ -95,7 +95,7 @@ TEST(ZipkinSpanContextExtractorTest, Sampled) { } TEST(ZipkinSpanContextExtractorTest, SampledFalse) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "0"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "0"}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); EXPECT_FALSE(context.second); @@ -109,7 +109,7 @@ TEST(ZipkinSpanContextExtractorTest, SampledFalse) { } TEST(ZipkinSpanContextExtractorTest, IdNotYetSampled128) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}-{}", trace_id_high, trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); @@ -124,7 +124,7 @@ TEST(ZipkinSpanContextExtractorTest, IdNotYetSampled128) { } TEST(ZipkinSpanContextExtractorTest, IdsUnsampled) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", fmt::format("{}-{}-0", trace_id, span_id)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", fmt::format("{}-{}-0", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); EXPECT_TRUE(context.second); @@ -138,7 +138,7 @@ TEST(ZipkinSpanContextExtractorTest, IdsUnsampled) { } TEST(ZipkinSpanContextExtractorTest, ParentUnsampled) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-0-{}", trace_id, span_id, parent_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); @@ -153,7 +153,7 @@ TEST(ZipkinSpanContextExtractorTest, ParentUnsampled) { } TEST(ZipkinSpanContextExtractorTest, ParentDebug) { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-d-{}", trace_id, span_id, parent_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); @@ -168,7 +168,7 @@ TEST(ZipkinSpanContextExtractorTest, ParentDebug) { } TEST(ZipkinSpanContextExtractorTest, IdsWithDebug) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", fmt::format("{}-{}-d", trace_id, span_id)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", fmt::format("{}-{}-d", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(true); EXPECT_TRUE(context.second); @@ -182,7 +182,7 @@ TEST(ZipkinSpanContextExtractorTest, IdsWithDebug) { } TEST(ZipkinSpanContextExtractorTest, WithoutSampled) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", fmt::format("{}-{}", trace_id, span_id)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", fmt::format("{}-{}", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); auto context = extractor.extractSpanContext(false); EXPECT_TRUE(context.second); @@ -197,7 +197,7 @@ TEST(ZipkinSpanContextExtractorTest, WithoutSampled) { TEST(ZipkinSpanContextExtractorTest, TooBig) { { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}{}-{}-{}", trace_id, trace_id, trace_id, span_id, trace_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -206,7 +206,7 @@ TEST(ZipkinSpanContextExtractorTest, TooBig) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}-{}-1-{}a", trace_id_high, trace_id, span_id, parent_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -215,7 +215,7 @@ TEST(ZipkinSpanContextExtractorTest, TooBig) { } TEST(ZipkinSpanContextExtractorTest, Empty) { - Http::TestRequestHeaderMapImpl request_headers{{"b3", ""}}; + Tracing::TestTraceContextImpl request_headers{{"b3", ""}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: empty"); @@ -223,8 +223,8 @@ TEST(ZipkinSpanContextExtractorTest, Empty) { TEST(ZipkinSpanContextExtractorTest, InvalidInput) { { - Http::TestRequestHeaderMapImpl request_headers{ - {"X-B3-TraceId", trace_id_high + trace_id.substr(0, 15) + "!"}, {"X-B3-SpanId", span_id}}; + Tracing::TestTraceContextImpl request_headers{ + {"x-b3-traceid", trace_id_high + trace_id.substr(0, 15) + "!"}, {"x-b3-spanid", span_id}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, fmt::format("Invalid traceid_high {} or tracid {}", trace_id_high, @@ -232,7 +232,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}!{}-{}", trace_id.substr(0, 15), trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE( @@ -241,7 +241,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}{}!-{}", trace_id, trace_id.substr(0, 15), span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE( @@ -250,7 +250,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}!-{}", trace_id.substr(0, 15), span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE( @@ -259,14 +259,14 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", fmt::format("{}!{}", trace_id, span_id)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", fmt::format("{}!{}", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: not exists span id"); } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}!", trace_id, span_id.substr(0, 15))}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE( @@ -275,7 +275,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}!0", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -283,7 +283,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-c", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -291,7 +291,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-d!{}", trace_id, span_id, parent_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -299,7 +299,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-d-{}!", trace_id, span_id, parent_id.substr(0, 15))}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE( @@ -308,7 +308,7 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "-"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "-"}}; SpanContextExtractor extractor(request_headers); EXPECT_TRUE(extractor.extractSampled({Tracing::Reason::Sampling, true})); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -318,49 +318,49 @@ TEST(ZipkinSpanContextExtractorTest, InvalidInput) { TEST(ZipkinSpanContextExtractorTest, Truncated) { { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "-1"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "-1"}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "1-"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "1-"}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", "1-"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", "1-"}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", trace_id.substr(0, 15)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", trace_id.substr(0, 15)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", trace_id}}; + Tracing::TestTraceContextImpl request_headers{{"b3", trace_id}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{{"b3", trace_id + "-"}}; + Tracing::TestTraceContextImpl request_headers{{"b3", trace_id + "-"}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}", trace_id.substr(0, 15), span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -368,7 +368,7 @@ TEST(ZipkinSpanContextExtractorTest, Truncated) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}", trace_id, span_id.substr(0, 15))}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -376,15 +376,14 @@ TEST(ZipkinSpanContextExtractorTest, Truncated) { } { - Http::TestRequestHeaderMapImpl request_headers{ - {"b3", fmt::format("{}-{}-", trace_id, span_id)}}; + Tracing::TestTraceContextImpl request_headers{{"b3", fmt::format("{}-{}-", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, "Invalid input: truncated"); } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-1-", trace_id, span_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -392,7 +391,7 @@ TEST(ZipkinSpanContextExtractorTest, Truncated) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-1-{}", trace_id, span_id, parent_id.substr(0, 15))}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, @@ -400,7 +399,7 @@ TEST(ZipkinSpanContextExtractorTest, Truncated) { } { - Http::TestRequestHeaderMapImpl request_headers{ + Tracing::TestTraceContextImpl request_headers{ {"b3", fmt::format("{}-{}-{}{}", trace_id, span_id, trace_id, trace_id)}}; SpanContextExtractor extractor(request_headers); EXPECT_THROW_WITH_MESSAGE(extractor.extractSpanContext(true), ExtractorException, diff --git a/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc b/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc index 270f2453663a..37dd69a83ea1 100644 --- a/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc +++ b/test/extensions/tracers/zipkin/zipkin_tracer_impl_test.cc @@ -496,9 +496,9 @@ TEST_F(ZipkinDriverTest, FlushSpansTimer) { TEST_F(ZipkinDriverTest, NoB3ContextSampledTrue) { setupValidDriver("HTTP_JSON"); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()).has_value()); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); @@ -510,9 +510,9 @@ TEST_F(ZipkinDriverTest, NoB3ContextSampledTrue) { TEST_F(ZipkinDriverTest, NoB3ContextSampledFalse) { setupValidDriver("HTTP_JSON"); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()).has_value()); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, false}); @@ -524,11 +524,11 @@ TEST_F(ZipkinDriverTest, NoB3ContextSampledFalse) { TEST_F(ZipkinDriverTest, PropagateB3NoSampleDecisionSampleTrue) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()).has_value()); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); @@ -540,11 +540,11 @@ TEST_F(ZipkinDriverTest, PropagateB3NoSampleDecisionSampleTrue) { TEST_F(ZipkinDriverTest, PropagateB3NoSampleDecisionSampleFalse) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()).has_value()); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, false}); @@ -556,19 +556,19 @@ TEST_F(ZipkinDriverTest, PropagateB3NoSampleDecisionSampleFalse) { TEST_F(ZipkinDriverTest, PropagateB3NotSampled) { setupValidDriver("HTTP_JSON"); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID.key()).has_value()); // Only context header set is B3 sampled to indicate trace should not be sampled - request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED, NOT_SAMPLED); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED.key(), NOT_SAMPLED); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); - request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED); + request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); span->injectContext(request_headers_, nullptr); - auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); // Check B3 sampled flag is set to not sample EXPECT_EQ(NOT_SAMPLED, sampled_entry.value()); @@ -577,21 +577,21 @@ TEST_F(ZipkinDriverTest, PropagateB3NotSampled) { TEST_F(ZipkinDriverTest, PropagateB3NotSampledWithFalse) { setupValidDriver("HTTP_JSON"); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID.key()).has_value()); // Only context header set is B3 sampled to indicate trace should not be sampled (using legacy // 'false' value) const std::string sampled = "false"; - request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED, sampled); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED.key(), sampled); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); - request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED); + request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); span->injectContext(request_headers_, nullptr); - auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); // Check B3 sampled flag is set to not sample EXPECT_EQ(NOT_SAMPLED, sampled_entry.value()); } @@ -599,21 +599,21 @@ TEST_F(ZipkinDriverTest, PropagateB3NotSampledWithFalse) { TEST_F(ZipkinDriverTest, PropagateB3SampledWithTrue) { setupValidDriver("HTTP_JSON"); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID).has_value()); - EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_SPAN_ID.key()).has_value()); + EXPECT_TRUE(!request_headers_.get(ZipkinCoreConstants::get().X_B3_TRACE_ID.key()).has_value()); // Only context header set is B3 sampled to indicate trace should be sampled (using legacy // 'true' value) const std::string sampled = "true"; - request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED, sampled); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED.key(), sampled); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, false}); - request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED); + request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); span->injectContext(request_headers_, nullptr); - auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); // Check B3 sampled flag is set to sample EXPECT_EQ(SAMPLED, sampled_entry.value()); } @@ -621,11 +621,11 @@ TEST_F(ZipkinDriverTest, PropagateB3SampledWithTrue) { TEST_F(ZipkinDriverTest, PropagateB3SampleFalse) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED, NOT_SAMPLED); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED.key(), NOT_SAMPLED); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); @@ -735,9 +735,9 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromB3HeadersTest) { const std::string span_id = Hex::uint64ToHex(generateRandom64()); const std::string parent_id = Hex::uint64ToHex(generateRandom64()); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, trace_id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, span_id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, parent_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), trace_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), span_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), parent_id); // New span will have an SR annotation - so its span and parent ids will be // the same as the supplied span context (i.e. shared context) @@ -757,13 +757,13 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromB3HeadersEmptyParentSpanTest) { // Root span so have same trace and span id const std::string id = Hex::uint64ToHex(generateRandom64()); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED, SAMPLED); + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SAMPLED.key(), SAMPLED); // Set parent span id to empty string, to ensure it is ignored const std::string parent_span_id = ""; - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, parent_span_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), parent_span_id); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); @@ -781,9 +781,9 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromB3Headers128TraceIdTest) { const std::string span_id = Hex::uint64ToHex(generateRandom64()); const std::string parent_id = Hex::uint64ToHex(generateRandom64()); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, trace_id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, span_id); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, parent_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), trace_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), span_id); + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), parent_id); // New span will have an SR annotation - so its span and parent ids will be // the same as the supplied span context (i.e. shared context) @@ -803,10 +803,10 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromB3Headers128TraceIdTest) { TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidTraceIdB3HeadersTest) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, std::string("xyz")); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), std::string("xyz")); + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, @@ -817,10 +817,10 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidTraceIdB3HeadersTest) { TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidSpanIdB3HeadersTest) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, std::string("xyz")); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), std::string("xyz")); + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, @@ -831,11 +831,11 @@ TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidSpanIdB3HeadersTest) { TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidParentIdB3HeadersTest) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, std::string("xyz")); + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), std::string("xyz")); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, true}); @@ -850,11 +850,11 @@ TEST_F(ZipkinDriverTest, ExplicitlySetSampledFalse) { span->setSampled(false); - request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED); + request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); span->injectContext(request_headers_, nullptr); - auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); // Check B3 sampled flag is set to not sample EXPECT_EQ(NOT_SAMPLED, sampled_entry.value()); } @@ -867,22 +867,22 @@ TEST_F(ZipkinDriverTest, ExplicitlySetSampledTrue) { span->setSampled(true); - request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED); + request_headers_.remove(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); span->injectContext(request_headers_, nullptr); - auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED); + auto sampled_entry = request_headers_.get(ZipkinCoreConstants::get().X_B3_SAMPLED.key()); // Check B3 sampled flag is set to sample EXPECT_EQ(SAMPLED, sampled_entry.value()); } TEST_F(ZipkinDriverTest, DuplicatedHeader) { setupValidDriver("HTTP_JSON"); - request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_TRACE_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); - request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID, + request_headers_.set(ZipkinCoreConstants::get().X_B3_PARENT_SPAN_ID.key(), Hex::uint64ToHex(generateRandom64())); Tracing::SpanPtr span = driver_->startSpan(config_, request_headers_, stream_info_, operation_name_, {Tracing::Reason::Sampling, false}); diff --git a/test/integration/filters/invalid_header_filter.cc b/test/integration/filters/invalid_header_filter.cc index db7e14104daf..cff2a0ea346d 100644 --- a/test/integration/filters/invalid_header_filter.cc +++ b/test/integration/filters/invalid_header_filter.cc @@ -30,7 +30,8 @@ class InvalidHeaderFilter : public Http::PassThroughFilter { // Insert invalid characters by bypassing assert(valid()) checks, which would not run // in release mode headers.addCopy(Http::LowerCaseString("x-foo"), "hello x-oops: yes"); - absl::string_view value = headers.getByKey("x-foo").value(); + absl::string_view value = + headers.get(Http::LowerCaseString("x-foo"))[0]->value().getStringView(); char* data = const_cast(value.data()); data[5] = '\r'; data[6] = '\n'; @@ -40,7 +41,8 @@ class InvalidHeaderFilter : public Http::PassThroughFilter { // Insert invalid characters by bypassing assert(valid()) checks, which would not run // in release mode headers.addCopy(Http::LowerCaseString("x-foo"), "hello GET /evil HTTP/1.1"); - absl::string_view value = headers.getByKey("x-foo").value(); + absl::string_view value = + headers.get(Http::LowerCaseString("x-foo"))[0]->value().getStringView(); char* data = const_cast(value.data()); data[5] = '\r'; data[6] = '\n'; diff --git a/test/test_common/BUILD b/test/test_common/BUILD index 0f73483cb045..260abad9c73f 100644 --- a/test/test_common/BUILD +++ b/test/test_common/BUILD @@ -138,6 +138,7 @@ envoy_cc_test_library( "//envoy/http:codec_interface", "//envoy/network:address_interface", "//envoy/server/overload:thread_local_overload_state", + "//envoy/tracing:trace_context_interface", "//source/common/api:api_lib", "//source/common/common:empty_string", "//source/common/common:thread_lib", diff --git a/test/test_common/utility.h b/test/test_common/utility.h index ef7535e02c3d..ac0545a5a7cd 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -12,6 +12,7 @@ #include "envoy/stats/stats.h" #include "envoy/stats/store.h" #include "envoy/thread/thread.h" +#include "envoy/tracing/trace_context.h" #include "envoy/type/matcher/v3/string.pb.h" #include "envoy/type/v3/percent.pb.h" @@ -904,10 +905,7 @@ class TestTraceContextImpl : public Tracing::TraceContext { } } } - absl::optional get(absl::string_view key) const { return getByKey(key); } - void set(absl::string_view key, absl::string_view value) { setByKey(key, value); } - void remove(absl::string_view key) { removeByKey(key); } - absl::optional getByKey(absl::string_view key) const override { + absl::optional get(absl::string_view key) const override { auto iter = context_map_.find(key); if (iter == context_map_.end()) { return absl::nullopt; @@ -915,14 +913,10 @@ class TestTraceContextImpl : public Tracing::TraceContext { return iter->second; } - void setByKey(absl::string_view key, absl::string_view val) override { + void set(absl::string_view key, absl::string_view val) override { context_map_.insert({std::string(key), std::string(val)}); } - void setByReferenceKey(absl::string_view key, absl::string_view val) override { - setByKey(key, val); - } - void setByReference(absl::string_view key, absl::string_view val) override { setByKey(key, val); } - void removeByKey(absl::string_view key) override { context_map_.erase(std::string(key)); } + void remove(absl::string_view key) override { context_map_.erase(std::string(key)); } std::string context_protocol_; std::string context_host_; @@ -1164,38 +1158,6 @@ class TestRequestHeaderMapImpl INLINE_REQ_NUMERIC_HEADERS(DEFINE_TEST_INLINE_NUMERIC_HEADER_FUNCS) INLINE_REQ_RESP_STRING_HEADERS(DEFINE_TEST_INLINE_STRING_HEADER_FUNCS) INLINE_REQ_RESP_NUMERIC_HEADERS(DEFINE_TEST_INLINE_NUMERIC_HEADER_FUNCS) - - // Tracing::TraceContext - absl::string_view protocol() const override { return header_map_->getProtocolValue(); } - absl::string_view host() const override { return header_map_->getHostValue(); } - absl::string_view path() const override { return header_map_->getPathValue(); } - absl::string_view method() const override { return header_map_->getMethodValue(); } - void forEach(IterateCallback callback) const override { - ASSERT(header_map_); - header_map_->iterate([cb = std::move(callback)](const HeaderEntry& entry) { - if (cb(entry.key().getStringView(), entry.value().getStringView())) { - return HeaderMap::Iterate::Continue; - } - return HeaderMap::Iterate::Break; - }); - } - absl::optional getByKey(absl::string_view key) const override { - ASSERT(header_map_); - return header_map_->getByKey(key); - } - void setByKey(absl::string_view key, absl::string_view value) override { - ASSERT(header_map_); - header_map_->setByKey(key, value); - } - void setByReference(absl::string_view key, absl::string_view val) override { - ASSERT(header_map_); - header_map_->setByReference(key, val); - } - void setByReferenceKey(absl::string_view key, absl::string_view val) override { - ASSERT(header_map_); - header_map_->setByReferenceKey(key, val); - } - void removeByKey(absl::string_view key) override { header_map_->removeByKey(key); } }; using TestRequestTrailerMapImpl = TestHeaderMapImplBase; From 6b152468de33832161951348aac5e2219935f258 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 20 Dec 2023 07:54:52 +0800 Subject: [PATCH 030/126] singleton manager: enhance singleton manager to support pin (#31391) * singleton manager: enhance singleton manager to support pin Signed-off-by: wbpcode * fix spelling Signed-off-by: wbpcode * fix building Signed-off-by: wbpcode * fix building 2 Signed-off-by: wbpcode * fix building 3 Signed-off-by: wbpcode * fix test and building Signed-off-by: wbpcode --------- Signed-off-by: wbpcode --- .../private_key_providers/test/config_test.cc | 3 +- .../private_key_providers/test/ops_test.cc | 3 +- envoy/singleton/manager.h | 45 +++++++++---- source/common/singleton/manager_impl.cc | 11 +++- source/common/singleton/manager_impl.h | 4 +- test/common/singleton/manager_impl_test.cc | 64 +++++++++++++++++-- .../file_system_http_cache_test.cc | 13 ++-- .../alts/alts_integration_test.cc | 11 +++- 8 files changed, 124 insertions(+), 30 deletions(-) diff --git a/contrib/qat/private_key_providers/test/config_test.cc b/contrib/qat/private_key_providers/test/config_test.cc index 9cbbafada6fe..55542d230809 100644 --- a/contrib/qat/private_key_providers/test/config_test.cc +++ b/contrib/qat/private_key_providers/test/config_test.cc @@ -35,7 +35,8 @@ parsePrivateKeyProviderFromV3Yaml(const std::string& yaml_string) { class FakeSingletonManager : public Singleton::Manager { public: FakeSingletonManager(LibQatCryptoSharedPtr libqat) : libqat_(libqat) {} - Singleton::InstanceSharedPtr get(const std::string&, Singleton::SingletonFactoryCb) override { + Singleton::InstanceSharedPtr get(const std::string&, Singleton::SingletonFactoryCb, + bool) override { return std::make_shared(libqat_); } diff --git a/contrib/qat/private_key_providers/test/ops_test.cc b/contrib/qat/private_key_providers/test/ops_test.cc index 3f61f68c6367..9ea47b1d172e 100644 --- a/contrib/qat/private_key_providers/test/ops_test.cc +++ b/contrib/qat/private_key_providers/test/ops_test.cc @@ -44,7 +44,8 @@ class TestCallbacks : public Envoy::Ssl::PrivateKeyConnectionCallbacks { class FakeSingletonManager : public Singleton::Manager { public: FakeSingletonManager(LibQatCryptoSharedPtr libqat) : libqat_(libqat) {} - Singleton::InstanceSharedPtr get(const std::string&, Singleton::SingletonFactoryCb) override { + Singleton::InstanceSharedPtr get(const std::string&, Singleton::SingletonFactoryCb, + bool) override { return std::make_shared(libqat_); } diff --git a/envoy/singleton/manager.h b/envoy/singleton/manager.h index 88800eda6273..e8d65b13ae42 100644 --- a/envoy/singleton/manager.h +++ b/envoy/singleton/manager.h @@ -67,30 +67,53 @@ class Manager { * This is a helper on top of get() that casts the object stored to the specified type. Since the * manager only stores pointers to the base interface, dynamic_cast provides some level of * protection via RTTI. + * @param name the unique name of the singleton instance. This should be provided by the macro + * SINGLETON_MANAGER_REGISTERED_NAME. + * @param cb supplies the singleton creation callback. This will only be called if the singleton + * does not already exist. + * @param pin supplies whether the singleton should be pinned. By default, the manager only stores + * a weak pointer. This allows a singleton to be cleaned up if it is not needed any more. All code + * that uses singletons must store the shared_ptr for as long as the singleton is needed. But if + * the pin is set to true, the singleton will be stored as a shared_ptr. This is useful if the + * users want to keep the singleton around for the lifetime of the server even if it is not used + * for a while. + * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not + * exist. */ - template std::shared_ptr getTyped(const std::string& name, SingletonFactoryCb cb) { - return std::dynamic_pointer_cast(get(name, cb)); + template + std::shared_ptr getTyped(const std::string& name, SingletonFactoryCb cb, bool pin = false) { + return std::dynamic_pointer_cast(get(name, cb, pin)); } /** * This is a non-constructing getter. Use when the caller can deal with instances where * the singleton being accessed may not have been constructed previously. - * @return InstancePtr the singleton. nullptr if the singleton does not exist. + * @param name the unique name of singleton instance. This should be provided by the macro + * SINGLETON_MANAGER_REGISTERED_NAME. + * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not + * exist. */ template std::shared_ptr getTyped(const std::string& name) { - return std::dynamic_pointer_cast(get(name, [] { return nullptr; })); + return std::dynamic_pointer_cast(get( + name, [] { return nullptr; }, false)); } /** * Get a singleton and create it if it does not exist. - * @param name supplies the singleton name. Must be registered via RegistrationImpl. - * @param singleton supplies the singleton creation callback. This will only be called if the - * singleton does not already exist. NOTE: The manager only stores a weak pointer. This - * allows a singleton to be cleaned up if it is not needed any more. All code that uses - * singletons must store the shared_ptr for as long as the singleton is needed. - * @return InstancePtr the singleton. + * @param name the unique name of the singleton instance. This should be provided by the macro + * SINGLETON_MANAGER_REGISTERED_NAME. + * @param cb supplies the singleton creation callback. This will only be called if the singleton + * does not already exist. + * @param pin supplies whether the singleton should be pinned. By default, the manager only stores + * a weak pointer. This allows a singleton to be cleaned up if it is not needed any more. All code + * that uses singletons must store the shared_ptr for as long as the singleton is needed. But if + * the pin is set to true, the singleton will be stored as a shared_ptr. This is useful if the + * users want to keep the singleton around for the lifetime of the server even if it is not used + * for a while. + * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not + * exist. */ - virtual InstanceSharedPtr get(const std::string& name, SingletonFactoryCb) PURE; + virtual InstanceSharedPtr get(const std::string& name, SingletonFactoryCb cb, bool pin) PURE; }; using ManagerPtr = std::unique_ptr; diff --git a/source/common/singleton/manager_impl.cc b/source/common/singleton/manager_impl.cc index 0e3fca61b870..a71fd7f3a9f6 100644 --- a/source/common/singleton/manager_impl.cc +++ b/source/common/singleton/manager_impl.cc @@ -8,18 +8,23 @@ namespace Envoy { namespace Singleton { -InstanceSharedPtr ManagerImpl::get(const std::string& name, SingletonFactoryCb cb) { +InstanceSharedPtr ManagerImpl::get(const std::string& name, SingletonFactoryCb cb, bool pin) { ASSERT(run_tid_ == thread_factory_.currentThreadId()); ENVOY_BUG(Registry::FactoryRegistry::getFactory(name) != nullptr, "invalid singleton name '" + name + "'. Make sure it is registered."); - if (nullptr == singletons_[name].lock()) { + auto existing_singleton = singletons_[name].lock(); + + if (existing_singleton == nullptr) { InstanceSharedPtr singleton = cb(); singletons_[name] = singleton; + if (pin && singleton != nullptr) { + pinned_singletons_.push_back(singleton); + } return singleton; } else { - return singletons_[name].lock(); + return existing_singleton; } } diff --git a/source/common/singleton/manager_impl.h b/source/common/singleton/manager_impl.h index 32de2d112750..cc715f55c1b8 100644 --- a/source/common/singleton/manager_impl.h +++ b/source/common/singleton/manager_impl.h @@ -21,10 +21,12 @@ class ManagerImpl : public Manager, NonCopyable { : thread_factory_(thread_factory), run_tid_(thread_factory.currentThreadId()) {} // Singleton::Manager - InstanceSharedPtr get(const std::string& name, SingletonFactoryCb cb) override; + InstanceSharedPtr get(const std::string& name, SingletonFactoryCb cb, bool pin) override; private: absl::node_hash_map> singletons_; + std::vector pinned_singletons_; + Thread::ThreadFactory& thread_factory_; const Thread::ThreadId run_tid_; }; diff --git a/test/common/singleton/manager_impl_test.cc b/test/common/singleton/manager_impl_test.cc index 9b7b75e0866c..d1a8513fbd48 100644 --- a/test/common/singleton/manager_impl_test.cc +++ b/test/common/singleton/manager_impl_test.cc @@ -14,7 +14,8 @@ namespace { static void deathTestWorker() { ManagerImpl manager(Thread::threadFactoryForTest()); - manager.get("foo", [] { return nullptr; }); + manager.get( + "foo", [] { return nullptr; }, false); } TEST(SingletonManagerImplDeathTest, NotRegistered) { @@ -41,9 +42,11 @@ TEST(SingletonManagerImplTest, Basic) { ManagerImpl manager(Thread::threadFactoryForTest()); std::shared_ptr singleton = std::make_shared(); - EXPECT_EQ(singleton, manager.get("test_singleton", [singleton] { return singleton; })); + EXPECT_EQ(singleton, manager.get( + "test_singleton", [singleton] { return singleton; }, false)); EXPECT_EQ(1UL, singleton.use_count()); - EXPECT_EQ(singleton, manager.get("test_singleton", [] { return nullptr; })); + EXPECT_EQ(singleton, manager.get( + "test_singleton", [] { return nullptr; }, false)); EXPECT_CALL(*singleton, onDestroy()); singleton.reset(); @@ -57,7 +60,8 @@ TEST(SingletonManagerImplTest, NonConstructingGetTyped) { std::shared_ptr singleton = std::make_shared(); // Use a construct on first use getter. - EXPECT_EQ(singleton, manager.get("test_singleton", [singleton] { return singleton; })); + EXPECT_EQ(singleton, manager.get( + "test_singleton", [singleton] { return singleton; }, false)); // Now access should return the constructed singleton. EXPECT_EQ(singleton, manager.getTyped("test_singleton")); EXPECT_EQ(1UL, singleton.use_count()); @@ -66,6 +70,58 @@ TEST(SingletonManagerImplTest, NonConstructingGetTyped) { singleton.reset(); } +TEST(SingletonManagerImplTest, PinnedSingleton) { + + { + ManagerImpl manager(Thread::threadFactoryForTest()); + TestSingleton* singleton_ptr{}; + + // Register a singleton and get it. + auto singleton = manager.getTyped(SINGLETON_MANAGER_REGISTERED_NAME(test), + [&]() -> InstanceSharedPtr { + auto s = std::make_shared(); + singleton_ptr = s.get(); + return s; + }); + EXPECT_EQ(singleton, manager.getTyped(SINGLETON_MANAGER_REGISTERED_NAME(test))); + + EXPECT_CALL(*singleton_ptr, onDestroy()); + // Destroy all copies of the singleton shared pointer. + singleton.reset(); + + // The singleton should be destroyed now. + EXPECT_EQ(nullptr, manager.getTyped(SINGLETON_MANAGER_REGISTERED_NAME(test))); + } + + { + ManagerImpl manager(Thread::threadFactoryForTest()); + TestSingleton* singleton_ptr{}; + + // Register a pinned singleton and get it. + auto singleton = manager.getTyped( + SINGLETON_MANAGER_REGISTERED_NAME(test), + [&]() -> InstanceSharedPtr { + auto s = std::make_shared(); + singleton_ptr = s.get(); + return s; + }, + true); + EXPECT_EQ(singleton, manager.getTyped(SINGLETON_MANAGER_REGISTERED_NAME(test))); + + auto* expected_value = singleton.get(); + + // Destroy all copies of the singleton shared pointer. + singleton.reset(); + + // The singleton should still be available. + EXPECT_EQ(expected_value, + manager.getTyped(SINGLETON_MANAGER_REGISTERED_NAME(test)).get()); + + // Destroy the singleton after the manager is destroyed. + EXPECT_CALL(*singleton_ptr, onDestroy()); + } +} + } // namespace } // namespace Singleton } // namespace Envoy diff --git a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc index 892f2ca24d62..7da8d9f93be0 100644 --- a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc +++ b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc @@ -265,15 +265,16 @@ class MockSingletonManager : public Singleton::ManagerImpl { public: MockSingletonManager() : Singleton::ManagerImpl(Thread::threadFactoryForTest()) { // By default just act like a real SingletonManager, but allow overrides. - ON_CALL(*this, get(_, _)) + ON_CALL(*this, get(_, _, _)) .WillByDefault(std::bind(&MockSingletonManager::realGet, this, std::placeholders::_1, - std::placeholders::_2)); + std::placeholders::_2, std::placeholders::_3)); } MOCK_METHOD(Singleton::InstanceSharedPtr, get, - (const std::string& name, Singleton::SingletonFactoryCb cb)); - Singleton::InstanceSharedPtr realGet(const std::string& name, Singleton::SingletonFactoryCb cb) { - return Singleton::ManagerImpl::get(name, cb); + (const std::string& name, Singleton::SingletonFactoryCb cb, bool pin)); + Singleton::InstanceSharedPtr realGet(const std::string& name, Singleton::SingletonFactoryCb cb, + bool pin) { + return Singleton::ManagerImpl::get(name, cb, pin); } }; @@ -282,7 +283,7 @@ class FileSystemHttpCacheTestWithMockFiles : public FileSystemHttpCacheTest { FileSystemHttpCacheTestWithMockFiles() { ON_CALL(context_.server_factory_context_, singletonManager()) .WillByDefault(ReturnRef(mock_singleton_manager_)); - ON_CALL(mock_singleton_manager_, get(HasSubstr("async_file_manager_factory_singleton"), _)) + ON_CALL(mock_singleton_manager_, get(HasSubstr("async_file_manager_factory_singleton"), _, _)) .WillByDefault(Return(mock_async_file_manager_factory_)); ON_CALL(*mock_async_file_manager_factory_, getAsyncFileManager(_, _)) .WillByDefault(Return(mock_async_file_manager_)); diff --git a/test/extensions/transport_sockets/alts/alts_integration_test.cc b/test/extensions/transport_sockets/alts/alts_integration_test.cc index db28ca0568b0..0b86fe77e5b0 100644 --- a/test/extensions/transport_sockets/alts/alts_integration_test.cc +++ b/test/extensions/transport_sockets/alts/alts_integration_test.cc @@ -368,10 +368,15 @@ class AltsIntegrationTestBase : public Event::TestUsingSimulatedTime, // state, this is done by the test server instead. class FakeSingletonManager : public Singleton::Manager { public: - Singleton::InstanceSharedPtr get(const std::string&, - Singleton::SingletonFactoryCb cb) override { - return cb(); + Singleton::InstanceSharedPtr get(const std::string&, Singleton::SingletonFactoryCb cb, + bool pin) override { + auto singleton = cb(); + if (pin) { + pinned_singletons_.push_back(singleton); + } + return singleton; } + std::vector pinned_singletons_; }; FakeSingletonManager fsm; ON_CALL(mock_factory_ctx.server_context_, singletonManager()).WillByDefault(ReturnRef(fsm)); From b039d8a316a081d1eae3e3222e045b749d26765e Mon Sep 17 00:00:00 2001 From: code Date: Wed, 20 Dec 2023 14:16:19 +0800 Subject: [PATCH 031/126] generic proxy: new kafka codec support (#31407) * initial commit Signed-off-by: wbpcode * add more test Signed-off-by: wbpcode * complete test Signed-off-by: wbpcode * Kick CI Signed-off-by: wbpcode --------- Signed-off-by: wbpcode --- api/BUILD | 1 + .../generic_proxy/codecs/kafka/v3/BUILD | 12 + .../generic_proxy/codecs/kafka/v3/kafka.proto | 35 +++ api/versioning/BUILD | 1 + contrib/contrib_build_config.bzl | 1 + contrib/extensions_metadata.yaml | 7 + .../filters/network/source/codecs/kafka/BUILD | 25 ++ .../network/source/codecs/kafka/config.cc | 92 ++++++ .../network/source/codecs/kafka/config.h | 166 +++++++++++ .../filters/network/test/codecs/kafka/BUILD | 21 ++ .../network/test/codecs/kafka/config_test.cc | 282 ++++++++++++++++++ tools/proto_format/format_api.py | 1 + 12 files changed, 644 insertions(+) create mode 100644 api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/BUILD create mode 100644 api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/kafka.proto create mode 100644 contrib/generic_proxy/filters/network/source/codecs/kafka/BUILD create mode 100644 contrib/generic_proxy/filters/network/source/codecs/kafka/config.cc create mode 100644 contrib/generic_proxy/filters/network/source/codecs/kafka/config.h create mode 100644 contrib/generic_proxy/filters/network/test/codecs/kafka/BUILD create mode 100644 contrib/generic_proxy/filters/network/test/codecs/kafka/config_test.cc diff --git a/api/BUILD b/api/BUILD index 20324443712f..e9eb8cd0c252 100644 --- a/api/BUILD +++ b/api/BUILD @@ -82,6 +82,7 @@ proto_library( "//contrib/envoy/extensions/filters/network/client_ssl_auth/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/action/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3:pkg", + "//contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/router/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/v3:pkg", diff --git a/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/BUILD b/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/BUILD new file mode 100644 index 000000000000..d49202b74ab4 --- /dev/null +++ b/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/BUILD @@ -0,0 +1,12 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "@com_github_cncf_xds//udpa/annotations:pkg", + "@com_github_cncf_xds//xds/annotations/v3:pkg", + ], +) diff --git a/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/kafka.proto b/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/kafka.proto new file mode 100644 index 000000000000..0e6998f8ec3d --- /dev/null +++ b/api/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/kafka.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +package envoy.extensions.filters.network.generic_proxy.codecs.kafka.v3; + +import "xds/annotations/v3/status.proto"; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.network.generic_proxy.codecs.kafka.v3"; +option java_outer_classname = "KafkaProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3;kafkav3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; +option (xds.annotations.v3.file_status).work_in_progress = true; + +// [#protodoc-title: Kafka codec configuration for Generic Proxy] +// [#extension: envoy.generic_proxy.codecs.kafka] + +// Configuration for Kafka codec. This codec gives the generic proxy the ability to proxy +// Kafka traffic. But note any route configuration for Kafka traffic is not supported yet. +// The generic proxy can only used to generate logs or metrics for Kafka traffic but cannot +// do matching or routing. +// +// .. note:: +// The codec can currently only be used in the sidecar mode. And to ensure the codec works +// properly, please make sure the following conditions are met: +// +// 1. The generic proxy must be configured with a wildcard route that matches all traffic. +// 2. The target cluster must be configured as a original destination cluster. +// 3. The :ref:`bind_upstream_connection +// ` +// of generic proxy router must be set to true to ensure same upstream connection is used +// for all traffic from same downstream connection. +message KafkaCodecConfig { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 9f50e26ddf5c..828efeaa0dd2 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -20,6 +20,7 @@ proto_library( "//contrib/envoy/extensions/filters/network/client_ssl_auth/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/action/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3:pkg", + "//contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/router/v3:pkg", "//contrib/envoy/extensions/filters/network/generic_proxy/v3:pkg", diff --git a/contrib/contrib_build_config.bzl b/contrib/contrib_build_config.bzl index 9bcf18bbb1a6..b8e7811a168c 100644 --- a/contrib/contrib_build_config.bzl +++ b/contrib/contrib_build_config.bzl @@ -72,6 +72,7 @@ CONTRIB_EXTENSIONS = { # "envoy.filters.generic.router": "//contrib/generic_proxy/filters/network/source/router:config", "envoy.generic_proxy.codecs.dubbo": "//contrib/generic_proxy/filters/network/source/codecs/dubbo:config", + "envoy.generic_proxy.codecs.kafka": "//contrib/generic_proxy/filters/network/source/codecs/kafka:config", # # xDS delegates diff --git a/contrib/extensions_metadata.yaml b/contrib/extensions_metadata.yaml index d570c39271ed..8168b063da58 100644 --- a/contrib/extensions_metadata.yaml +++ b/contrib/extensions_metadata.yaml @@ -132,6 +132,13 @@ envoy.generic_proxy.codecs.dubbo: status: wip type_urls: - envoy.extensions.filters.network.generic_proxy.codecs.dubbo.v3.DubboCodecConfig +envoy.generic_proxy.codecs.kafka: + categories: + - envoy.generic_proxy.codecs + security_posture: requires_trusted_downstream_and_upstream + status: wip + type_urls: + - envoy.extensions.filters.network.generic_proxy.codecs.kafka.v3.KafkaCodecConfig envoy.router.cluster_specifier_plugin.golang: categories: - envoy.router.cluster_specifier_plugin diff --git a/contrib/generic_proxy/filters/network/source/codecs/kafka/BUILD b/contrib/generic_proxy/filters/network/source/codecs/kafka/BUILD new file mode 100644 index 000000000000..807d8a1c160b --- /dev/null +++ b/contrib/generic_proxy/filters/network/source/codecs/kafka/BUILD @@ -0,0 +1,25 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_contrib_extension", + "envoy_contrib_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_contrib_package() + +envoy_cc_contrib_extension( + name = "config", + srcs = [ + "config.cc", + ], + hdrs = [ + "config.h", + ], + deps = [ + "//contrib/generic_proxy/filters/network/source/interface:codec_interface", + "//contrib/kafka/filters/network/source:kafka_request_codec_lib", + "//contrib/kafka/filters/network/source:kafka_response_codec_lib", + "@envoy_api//contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3:pkg_cc_proto", + ], +) diff --git a/contrib/generic_proxy/filters/network/source/codecs/kafka/config.cc b/contrib/generic_proxy/filters/network/source/codecs/kafka/config.cc new file mode 100644 index 000000000000..d5d600e2cf5d --- /dev/null +++ b/contrib/generic_proxy/filters/network/source/codecs/kafka/config.cc @@ -0,0 +1,92 @@ +#include "contrib/generic_proxy/filters/network/source/codecs/kafka/config.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace GenericProxy { +namespace Codec { +namespace Kafka { + +KafkaServerCodec::KafkaServerCodec() : response_encoder_(response_buffer_) {} + +void KafkaServerCodec::setCodecCallbacks(GenericProxy::ServerCodecCallbacks& callbacks) { + request_callbacks_ = std::make_shared(callbacks); + request_decoder_ = std::make_shared( + std::vector{request_callbacks_}); +} + +void KafkaServerCodec::decode(Envoy::Buffer::Instance& buffer, bool) { + request_buffer_.move(buffer); + request_decoder_->onData(request_buffer_); + // All data has been consumed, so we can drain the buffer. + request_buffer_.drain(request_buffer_.length()); +} + +void KafkaServerCodec::encode(const GenericProxy::StreamFrame& frame, + GenericProxy::EncodingCallbacks& callbacks) { + auto* typed_response = dynamic_cast(&frame); + if (typed_response == nullptr) { + ENVOY_LOG(error, "Kafka codec: invalid response frame type and cannot encode"); + return; + } + if (typed_response->response_ != nullptr) { + response_encoder_.encode(*typed_response->response_); + } else { + ENVOY_LOG(error, "Kafka codec: invalid empty response frame type and close connection"); + request_callbacks_->callbacks_.connection()->close(Network::ConnectionCloseType::FlushWrite); + return; + } + callbacks.onEncodingSuccess(response_buffer_, true); + // All data should be consumed by the generic proxy and send to the network. + ASSERT(response_buffer_.length() == 0); +} +GenericProxy::ResponsePtr KafkaServerCodec::respond(absl::Status, absl::string_view, + const GenericProxy::Request&) { + return std::make_unique(nullptr); +}; + +KafkaClientCodec::KafkaClientCodec() : request_encoder_(request_buffer_) {} + +void KafkaClientCodec::setCodecCallbacks(GenericProxy::ClientCodecCallbacks& callbacks) { + response_callbacks_ = std::make_shared(callbacks); + response_decoder_ = std::make_shared( + std::vector{response_callbacks_}); +} + +void KafkaClientCodec::decode(Envoy::Buffer::Instance& buffer, bool) { + response_buffer_.move(buffer); + response_decoder_->onData(response_buffer_); + // All data has been consumed, so we can drain the buffer. + response_buffer_.drain(response_buffer_.length()); +} + +void KafkaClientCodec::encode(const GenericProxy::StreamFrame& frame, + GenericProxy::EncodingCallbacks& callbacks) { + auto* typed_request = dynamic_cast(&frame); + if (typed_request == nullptr) { + ENVOY_LOG(error, "Kafka codec: invalid request frame type and cannot encode"); + return; + } + response_decoder_->expectResponse(typed_request->request_->request_header_.correlation_id_, + typed_request->request_->request_header_.api_key_, + typed_request->request_->request_header_.api_version_); + request_encoder_.encode(*typed_request->request_); + callbacks.onEncodingSuccess(request_buffer_, true); + // All data should be consumed by the generic proxy and send to the network. + ASSERT(request_buffer_.length() == 0); +} + +CodecFactoryPtr +KafkaCodecFactoryConfig::createCodecFactory(const Protobuf::Message&, + Envoy::Server::Configuration::FactoryContext&) { + return std::make_unique(); +} + +REGISTER_FACTORY(KafkaCodecFactoryConfig, CodecFactoryConfig); + +} // namespace Kafka +} // namespace Codec +} // namespace GenericProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/contrib/generic_proxy/filters/network/source/codecs/kafka/config.h b/contrib/generic_proxy/filters/network/source/codecs/kafka/config.h new file mode 100644 index 000000000000..c9b7064459ac --- /dev/null +++ b/contrib/generic_proxy/filters/network/source/codecs/kafka/config.h @@ -0,0 +1,166 @@ +#pragma once + +#include "source/common/buffer/buffer_impl.h" + +#include "contrib/envoy/extensions/filters/network/generic_proxy/codecs/kafka/v3/kafka.pb.h" +#include "contrib/generic_proxy/filters/network/source/interface/codec.h" +#include "contrib/kafka/filters/network/source/request_codec.h" +#include "contrib/kafka/filters/network/source/response_codec.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace GenericProxy { +namespace Codec { +namespace Kafka { + +using ProtoConfig = + envoy::extensions::filters::network::generic_proxy::codecs::kafka::v3::KafkaCodecConfig; + +class KafkaRequestFrame : public GenericProxy::StreamRequest { +public: + KafkaRequestFrame(NetworkFilters::Kafka::AbstractRequestSharedPtr request) + : request_(std::move(request)) { + ASSERT(request_ != nullptr); + } + + FrameFlags frameFlags() const override { + if (request_ == nullptr) { + return FrameFlags{}; + } + return FrameFlags{ + StreamFlags{static_cast(request_->request_header_.correlation_id_)}}; + } + + absl::string_view protocol() const override { return "kafka"; } + + NetworkFilters::Kafka::AbstractRequestSharedPtr request_; +}; + +class KafkaResponseFrame : public GenericProxy::StreamResponse { +public: + KafkaResponseFrame(NetworkFilters::Kafka::AbstractResponseSharedPtr response) + : response_(std::move(response)) {} + + FrameFlags frameFlags() const override { + if (response_ == nullptr) { + return FrameFlags{}; + } + return FrameFlags{StreamFlags{static_cast(response_->metadata_.correlation_id_)}}; + } + + absl::string_view protocol() const override { return "kafka"; } + + NetworkFilters::Kafka::AbstractResponseSharedPtr response_; +}; + +class KafkaRequestCallbacks : public NetworkFilters::Kafka::RequestCallback, + public Envoy::Logger::Loggable { +public: + KafkaRequestCallbacks(GenericProxy::ServerCodecCallbacks& callbacks) : callbacks_(callbacks) {} + + void onMessage(NetworkFilters::Kafka::AbstractRequestSharedPtr request) override { + ENVOY_CONN_LOG(debug, "Kafka codec: new request from downstream client", + callbacks_.connection().ref()); + callbacks_.onDecodingSuccess(std::make_unique(std::move(request))); + } + + void onFailedParse(NetworkFilters::Kafka::RequestParseFailureSharedPtr) override { + ENVOY_CONN_LOG(debug, "Kafka codec: failed to parse request from downstream client", + callbacks_.connection().ref()); + callbacks_.onDecodingFailure(); + } + + GenericProxy::ServerCodecCallbacks& callbacks_; +}; + +class KafkaResponseCallbacks : public NetworkFilters::Kafka::ResponseCallback, + public Envoy::Logger::Loggable { +public: + KafkaResponseCallbacks(GenericProxy::ClientCodecCallbacks& callbacks) : callbacks_(callbacks) {} + + void onMessage(NetworkFilters::Kafka::AbstractResponseSharedPtr response) override { + ENVOY_CONN_LOG(debug, "Kafka codec: new response from upstream server", + callbacks_.connection().ref()); + callbacks_.onDecodingSuccess(std::make_unique(std::move(response))); + } + + void onFailedParse(NetworkFilters::Kafka::ResponseMetadataSharedPtr) override { + ENVOY_CONN_LOG(debug, "Kafka codec: failed to parse response from upstream server", + callbacks_.connection().ref()); + callbacks_.onDecodingFailure(); + } + +private: + GenericProxy::ClientCodecCallbacks& callbacks_; +}; + +class KafkaServerCodec : public GenericProxy::ServerCodec, + public Envoy::Logger::Loggable { +public: + KafkaServerCodec(); + + void setCodecCallbacks(GenericProxy::ServerCodecCallbacks& callbacks) override; + void decode(Envoy::Buffer::Instance& buffer, bool end_stream) override; + void encode(const GenericProxy::StreamFrame& frame, + GenericProxy::EncodingCallbacks& callbacks) override; + GenericProxy::ResponsePtr respond(absl::Status, absl::string_view, + const GenericProxy::Request&) override; + + Envoy::Buffer::OwnedImpl request_buffer_; + Envoy::Buffer::OwnedImpl response_buffer_; + + NetworkFilters::Kafka::RequestDecoderSharedPtr request_decoder_; + NetworkFilters::Kafka::ResponseEncoder response_encoder_; + + std::shared_ptr request_callbacks_; +}; + +class KafkaClientCodec : public GenericProxy::ClientCodec, + public Envoy::Logger::Loggable { +public: + KafkaClientCodec(); + + void setCodecCallbacks(GenericProxy::ClientCodecCallbacks& callbacks) override; + void decode(Envoy::Buffer::Instance& buffer, bool end_stream) override; + void encode(const GenericProxy::StreamFrame& frame, + GenericProxy::EncodingCallbacks& callbacks) override; + + Envoy::Buffer::OwnedImpl request_buffer_; + Envoy::Buffer::OwnedImpl response_buffer_; + + NetworkFilters::Kafka::ResponseDecoderSharedPtr response_decoder_; + NetworkFilters::Kafka::RequestEncoder request_encoder_; + + std::shared_ptr response_callbacks_; +}; + +class KafkaCodecFactory : public GenericProxy::CodecFactory { +public: + GenericProxy::ClientCodecPtr createClientCodec() const override { + return std::make_unique(); + } + + GenericProxy::ServerCodecPtr createServerCodec() const override { + return std::make_unique(); + } +}; + +class KafkaCodecFactoryConfig : public GenericProxy::CodecFactoryConfig { +public: + // CodecFactoryConfig + GenericProxy::CodecFactoryPtr + createCodecFactory(const Envoy::Protobuf::Message& config, + Envoy::Server::Configuration::FactoryContext& context) override; + std::string name() const override { return "envoy.generic_proxy.codecs.kafka"; } + Envoy::ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } +}; + +} // namespace Kafka +} // namespace Codec +} // namespace GenericProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/contrib/generic_proxy/filters/network/test/codecs/kafka/BUILD b/contrib/generic_proxy/filters/network/test/codecs/kafka/BUILD new file mode 100644 index 000000000000..d3c54211c8ea --- /dev/null +++ b/contrib/generic_proxy/filters/network/test/codecs/kafka/BUILD @@ -0,0 +1,21 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_test", + "envoy_contrib_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_contrib_package() + +envoy_cc_test( + name = "config_test", + srcs = [ + "config_test.cc", + ], + deps = [ + "//contrib/generic_proxy/filters/network/source/codecs/kafka:config", + "//contrib/generic_proxy/filters/network/test/mocks:codec_mocks", + "//test/mocks/server:factory_context_mocks", + ], +) diff --git a/contrib/generic_proxy/filters/network/test/codecs/kafka/config_test.cc b/contrib/generic_proxy/filters/network/test/codecs/kafka/config_test.cc new file mode 100644 index 000000000000..7bee7cecd916 --- /dev/null +++ b/contrib/generic_proxy/filters/network/test/codecs/kafka/config_test.cc @@ -0,0 +1,282 @@ +#include +#include + +#include "test/mocks/server/factory_context.h" + +#include "contrib/generic_proxy/filters/network/source/codecs/kafka/config.h" +#include "contrib/generic_proxy/filters/network/test/mocks/codec.h" +#include "contrib/kafka/filters/network/source/external/requests.h" +#include "contrib/kafka/filters/network/source/external/responses.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace NetworkFilters { +namespace GenericProxy { +namespace Codec { +namespace Kafka { +namespace { + +using testing::NiceMock; + +TEST(KafkaCodecTest, SimpleFrameTest) { + + { + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + + KafkaRequestFrame frame(request); + EXPECT_EQ(frame.frameFlags().streamFlags().streamId(), 3); + } + + { + KafkaResponseFrame frame(nullptr); + EXPECT_EQ(frame.protocol(), "kafka"); + EXPECT_EQ(frame.frameFlags().streamFlags().streamId(), 0); + } + + { + auto response = + std::make_shared>( + NetworkFilters::Kafka::ResponseMetadata(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, + 3), + NetworkFilters::Kafka::FetchResponse({}, {})); + + KafkaResponseFrame frame(response); + EXPECT_EQ(frame.frameFlags().streamFlags().streamId(), 3); + } +} + +TEST(KafkaCodecTest, KafkaRequestCallbacksTest) { + NiceMock callbacks; + + KafkaRequestCallbacks request_callbacks(callbacks); + + { + EXPECT_CALL(callbacks, onDecodingSuccess(_)); + + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + + request_callbacks.onMessage(request); + } + + { + EXPECT_CALL(callbacks, onDecodingFailure()); + request_callbacks.onFailedParse(nullptr); + } +} + +TEST(KafkaCodecTest, KafkaResponseCallbacksTest) { + NiceMock callbacks; + + KafkaResponseCallbacks response_callbacks(callbacks); + + { + EXPECT_CALL(callbacks, onDecodingSuccess(_)); + + auto response = + std::make_shared>( + NetworkFilters::Kafka::ResponseMetadata(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, + 3), + NetworkFilters::Kafka::FetchResponse({}, {})); + + response_callbacks.onMessage(response); + } + + { + EXPECT_CALL(callbacks, onDecodingFailure()); + response_callbacks.onFailedParse(nullptr); + } +} + +TEST(KafkaCodecTest, KafkaServerCodecTest) { + NiceMock callbacks; + + KafkaServerCodec server_codec; + server_codec.setCodecCallbacks(callbacks); + + { + // Test respond() method. + + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + + KafkaRequestFrame frame(request); + auto local_response = server_codec.respond(absl::OkStatus(), "", frame); + + EXPECT_NE(local_response, nullptr); + EXPECT_EQ(dynamic_cast(local_response.get())->response_, nullptr); + } + + { + // Test decode() method. + EXPECT_CALL(callbacks, onDecodingSuccess(_)) + .WillOnce(testing::Invoke([](StreamFramePtr request) { + EXPECT_EQ(dynamic_cast(request.get()) + ->request_->request_header_.correlation_id_, + 3); + })); + + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + + Buffer::OwnedImpl buffer; + const uint32_t size = htobe32(request->computeSize()); + buffer.add(&size, sizeof(size)); // Encode data length. + + request->encode(buffer); + server_codec.decode(buffer, false); + } + + { + // Test encode() method with non-response frame. + + NiceMock encoding_callbacks; + + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + KafkaRequestFrame request_frame(request); + + // Do nothiing. + server_codec.encode(request_frame, encoding_callbacks); + } + + { + // Test encode() method without actual response. + + NiceMock encoding_callbacks; + NiceMock mock_connection; + + KafkaResponseFrame response_frame(nullptr); + + // Expect close connection. + EXPECT_CALL(callbacks, connection()) + .WillOnce(testing::Return(makeOptRef(mock_connection))); + EXPECT_CALL(mock_connection, close(Network::ConnectionCloseType::FlushWrite)); + + server_codec.encode(response_frame, encoding_callbacks); + } + + { + // Test encode() method with response. + + NiceMock encoding_callbacks; + + auto response = + std::make_shared>( + NetworkFilters::Kafka::ResponseMetadata(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, + 3), + NetworkFilters::Kafka::FetchResponse({}, {})); + + KafkaResponseFrame response_frame(response); + + Envoy::Buffer::OwnedImpl dst_buffer; + const uint32_t size = htobe32(response->computeSize()); + dst_buffer.add(&size, sizeof(size)); // Encode data length. + response->encode(dst_buffer); + + EXPECT_CALL(encoding_callbacks, onEncodingSuccess(_, true)) + .WillOnce(testing::Invoke([&](Buffer::Instance& buffer, bool) { + EXPECT_EQ(buffer.toString(), dst_buffer.toString()); + })); + server_codec.encode(response_frame, encoding_callbacks); + } +} + +TEST(KafkaCodecTest, KafkaClientCodecTest) { + NiceMock callbacks; + + KafkaClientCodec client_codec; + client_codec.setCodecCallbacks(callbacks); + + { + // Test decode() method. + EXPECT_CALL(callbacks, onDecodingSuccess(_)) + .WillOnce(testing::Invoke([](StreamFramePtr response) { + EXPECT_EQ(dynamic_cast(response.get()) + ->response_->metadata_.correlation_id_, + 3); + })); + + auto response = + std::make_shared>( + NetworkFilters::Kafka::ResponseMetadata(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, + 3), + NetworkFilters::Kafka::FetchResponse({}, {})); + + Buffer::OwnedImpl buffer; + const uint32_t size = htobe32(response->computeSize()); + buffer.add(&size, sizeof(size)); // Encode data length. + + response->encode(buffer); + + client_codec.response_decoder_->expectResponse(3, 0, 0); + client_codec.decode(buffer, false); + } + + { + // Test encode() method with non-request frame. + + NiceMock encoding_callbacks; + + auto response = + std::make_shared>( + NetworkFilters::Kafka::ResponseMetadata(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, + 3), + NetworkFilters::Kafka::FetchResponse({}, {})); + KafkaResponseFrame response_frame(response); + + // Do nothiing. + client_codec.encode(response_frame, encoding_callbacks); + } + + { + // Test encode() method with request. + + NiceMock encoding_callbacks; + + auto request = + std::make_shared>( + NetworkFilters::Kafka::RequestHeader(NetworkFilters::Kafka::FETCH_REQUEST_API_KEY, 0, 3, + absl::nullopt), + NetworkFilters::Kafka::FetchRequest({}, {}, {}, {})); + + KafkaRequestFrame request_frame(request); + + Envoy::Buffer::OwnedImpl dst_buffer; + const uint32_t size = htobe32(request->computeSize()); + dst_buffer.add(&size, sizeof(size)); // Encode data length. + request->encode(dst_buffer); + + EXPECT_CALL(encoding_callbacks, onEncodingSuccess(_, true)) + .WillOnce(testing::Invoke([&](Buffer::Instance& buffer, bool) { + EXPECT_EQ(buffer.toString(), dst_buffer.toString()); + })); + + client_codec.encode(request_frame, encoding_callbacks); + } +} + +} // namespace +} // namespace Kafka +} // namespace Codec +} // namespace GenericProxy +} // namespace NetworkFilters +} // namespace Extensions +} // namespace Envoy diff --git a/tools/proto_format/format_api.py b/tools/proto_format/format_api.py index 759ef9bac653..8306a1f51515 100644 --- a/tools/proto_format/format_api.py +++ b/tools/proto_format/format_api.py @@ -32,6 +32,7 @@ 'envoy.extensions.filters.network.client_ssl_auth.v3', 'envoy.extensions.filters.network.generic_proxy.action.v3', 'envoy.extensions.filters.network.generic_proxy.codecs.dubbo.v3', + 'envoy.extensions.filters.network.generic_proxy.codecs.kafka.v3', 'envoy.extensions.filters.network.generic_proxy.matcher.v3', 'envoy.extensions.filters.network.generic_proxy.router.v3', 'envoy.extensions.filters.network.generic_proxy.v3', From 812a9acbd5cb8a81b3113216c0512939ed635fe7 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 20 Dec 2023 23:32:48 +0800 Subject: [PATCH 032/126] clean server factory context and partly revert #29289 (#31458) * clean server factory context and partly revert #29289 Signed-off-by: wbpcode * minor update Signed-off-by: wbpcode --------- Signed-off-by: wbpcode --- envoy/http/filter_factory.h | 8 ------- envoy/server/BUILD | 1 - envoy/server/factory_context.h | 22 ------------------- source/common/filter/config_discovery_impl.h | 19 +++++++++++----- source/common/http/filter_chain_helper.cc | 15 ++++++++++++- source/common/http/filter_chain_helper.h | 13 ++++++++--- .../filters/http/composite/action.cc | 16 +++++++++----- .../network/http_connection_manager/config.cc | 6 ++--- .../network/http_connection_manager/config.h | 2 +- source/server/BUILD | 1 - source/server/server.h | 9 +------- .../filter/config_discovery_impl_test.cc | 4 ++-- test/common/http/filter_chain_helper_test.cc | 10 +++++---- test/mocks/server/server_factory_context.cc | 8 +------ test/mocks/server/server_factory_context.h | 13 +---------- 15 files changed, 63 insertions(+), 84 deletions(-) diff --git a/envoy/http/filter_factory.h b/envoy/http/filter_factory.h index 640add7f36ea..ec0247017157 100644 --- a/envoy/http/filter_factory.h +++ b/envoy/http/filter_factory.h @@ -23,14 +23,6 @@ class FilterChainFactoryCallbacks; */ using FilterFactoryCb = std::function; -// Struct of canonical filter name and HTTP stream filter factory callback. -struct NamedHttpFilterFactoryCb { - // Canonical filter name. - std::string name; - // Factory function used to create filter instances. - Http::FilterFactoryCb factory_cb; -}; - /** * Simple struct of additional contextual information of HTTP filter, e.g. filter config name * from configuration, canonical filter name, etc. diff --git a/envoy/server/BUILD b/envoy/server/BUILD index 9459ab72096f..a412c4e164dd 100644 --- a/envoy/server/BUILD +++ b/envoy/server/BUILD @@ -175,7 +175,6 @@ envoy_cc_library( ":process_context_interface", "//envoy/access_log:access_log_interface", "//envoy/api:api_interface", - "//envoy/config:dynamic_extension_config_provider_interface", "//envoy/config:typed_config_interface", "//envoy/config:typed_metadata_interface", "//envoy/grpc:context_interface", diff --git a/envoy/server/factory_context.h b/envoy/server/factory_context.h index 50588c96f8e4..8a139fbcb0c4 100644 --- a/envoy/server/factory_context.h +++ b/envoy/server/factory_context.h @@ -7,7 +7,6 @@ #include "envoy/access_log/access_log.h" #include "envoy/common/random_generator.h" #include "envoy/config/core/v3/base.pb.h" -#include "envoy/config/dynamic_extension_config_provider.h" #include "envoy/config/typed_config.h" #include "envoy/config/typed_metadata.h" #include "envoy/grpc/context.h" @@ -37,14 +36,9 @@ #include "source/common/protobuf/protobuf.h" namespace Envoy { -namespace Filter { -template class FilterConfigProviderManager; -} // namespace Filter namespace Server { namespace Configuration { -using HttpExtensionConfigProviderSharedPtr = - std::shared_ptr>; /** * Common interface for downstream and upstream network filters to access server * wide resources. This could be treated as limited form of server factory context. @@ -137,14 +131,6 @@ class CommonFactoryContext { virtual ServerLifecycleNotifier& lifecycleNotifier() PURE; }; -class FactoryContext; - -using DownstreamHTTPFilterConfigProviderManager = - Filter::FilterConfigProviderManager; -using DownstreamHTTPFilterConfigProviderManagerSharedPtr = - std::shared_ptr; - /** * ServerFactoryContext is an specialization of common interface for downstream and upstream network * filters. The implementation guarantees the lifetime is no shorter than server. It could be used @@ -209,14 +195,6 @@ class ServerFactoryContext : public virtual CommonFactoryContext { * @return whether external healthchecks are currently failed or not. */ virtual bool healthCheckFailed() const PURE; - - /** - * Returns the downstream HTTP filter config provider manager. - * - * @return DownstreamHTTPFilterConfigProviderManagerSharedPtr - */ - virtual DownstreamHTTPFilterConfigProviderManagerSharedPtr - downstreamHttpFilterConfigProviderManager() PURE; }; /** diff --git a/source/common/filter/config_discovery_impl.h b/source/common/filter/config_discovery_impl.h index fadcdbea6d72..16889d5a4e46 100644 --- a/source/common/filter/config_discovery_impl.h +++ b/source/common/filter/config_discovery_impl.h @@ -87,8 +87,7 @@ class DynamicFilterConfigProviderImpl : public DynamicFilterConfigProviderImplBa if (!tls->isShutdown()) { tls->runOnAllThreads([](OptRef tls) { tls->config_ = {}; }, // Extend the lifetime of TLS by capturing main_config_, because - // otherwise, the callback to clear TLS worker content is not - // executed. + // otherwise, the callback to clear TLS worker content is not executed. [main_config = main_config_]() { // Explicitly delete TLS on the main thread. main_config->tls_.reset(); @@ -179,12 +178,20 @@ class DynamicFilterConfigProviderImpl : public DynamicFilterConfigProviderImplBa const ProtobufTypes::MessagePtr default_configuration_; }; +// Struct of canonical filter name and HTTP stream filter factory callback. +struct NamedHttpFilterFactoryCb { + // Canonical filter name. + std::string name; + // Factory function used to create filter instances. + Http::FilterFactoryCb factory_cb; +}; + // Implementation of a HTTP dynamic filter config provider. // NeutralHttpFilterConfigFactory can either be a NamedHttpFilterConfigFactory // or an UpstreamHttpFilterConfigFactory. template class HttpDynamicFilterConfigProviderImpl - : public DynamicFilterConfigProviderImpl { + : public DynamicFilterConfigProviderImpl { public: HttpDynamicFilterConfigProviderImpl( FilterConfigSubscriptionSharedPtr& subscription, @@ -208,7 +215,7 @@ class HttpDynamicFilterConfigProviderImpl } private: - Http::NamedHttpFilterFactoryCb + NamedHttpFilterFactoryCb instantiateFilterFactory(const Protobuf::Message& message) const override { auto* factory = Registry::FactoryRegistry::getFactoryByType( message.GetTypeName()); @@ -641,7 +648,7 @@ class FilterConfigProviderManagerImpl : public FilterConfigProviderManagerImplBa // HTTP filter class HttpFilterConfigProviderManagerImpl : public FilterConfigProviderManagerImpl< - Server::Configuration::NamedHttpFilterConfigFactory, Http::NamedHttpFilterFactoryCb, + Server::Configuration::NamedHttpFilterConfigFactory, NamedHttpFilterFactoryCb, Server::Configuration::FactoryContext, HttpDynamicFilterConfigProviderImpl< Server::Configuration::FactoryContext, @@ -668,7 +675,7 @@ class HttpFilterConfigProviderManagerImpl // HTTP filter class UpstreamHttpFilterConfigProviderManagerImpl : public FilterConfigProviderManagerImpl< - Server::Configuration::UpstreamHttpFilterConfigFactory, Http::NamedHttpFilterFactoryCb, + Server::Configuration::UpstreamHttpFilterConfigFactory, NamedHttpFilterFactoryCb, Server::Configuration::UpstreamFactoryContext, HttpDynamicFilterConfigProviderImpl< Server::Configuration::UpstreamFactoryContext, diff --git a/source/common/http/filter_chain_helper.cc b/source/common/http/filter_chain_helper.cc index 5278da2a3d88..4963dd6e3ae0 100644 --- a/source/common/http/filter_chain_helper.cc +++ b/source/common/http/filter_chain_helper.cc @@ -5,6 +5,7 @@ #include "envoy/registry/registry.h" +#include "source/common/common/empty_string.h" #include "source/common/common/fmt.h" #include "source/common/config/utility.h" #include "source/common/http/utility.h" @@ -26,7 +27,7 @@ void FilterChainUtility::createFilterChainForFactories( auto config = filter_config_provider.provider->config(); if (config.has_value()) { - Http::NamedHttpFilterFactoryCb& factory_cb = config.value().get(); + Filter::NamedHttpFilterFactoryCb& factory_cb = config.value().get(); manager.applyFilterFactoryCb({filter_config_provider.provider->name(), factory_cb.name}, factory_cb.factory_cb); continue; @@ -45,6 +46,7 @@ void FilterChainUtility::createFilterChainForFactories( } } +SINGLETON_MANAGER_REGISTRATION(downstream_filter_config_provider_manager); SINGLETON_MANAGER_REGISTRATION(upstream_filter_config_provider_manager); std::shared_ptr @@ -57,5 +59,16 @@ FilterChainUtility::createSingletonUpstreamFilterConfigProviderManager( return upstream_filter_config_provider_manager; } +std::shared_ptr +FilterChainUtility::createSingletonDownstreamFilterConfigProviderManager( + Server::Configuration::ServerFactoryContext& context) { + std::shared_ptr + downstream_filter_config_provider_manager = + context.singletonManager().getTyped( + SINGLETON_MANAGER_REGISTERED_NAME(downstream_filter_config_provider_manager), + [] { return std::make_shared(); }, true); + return downstream_filter_config_provider_manager; +} + } // namespace Http } // namespace Envoy diff --git a/source/common/http/filter_chain_helper.h b/source/common/http/filter_chain_helper.h index fb90378e2efc..39d6ce6dd6af 100644 --- a/source/common/http/filter_chain_helper.h +++ b/source/common/http/filter_chain_helper.h @@ -15,8 +15,11 @@ namespace Envoy { namespace Http { +using DownstreamFilterConfigProviderManager = + Filter::FilterConfigProviderManager; using UpstreamFilterConfigProviderManager = - Filter::FilterConfigProviderManager; // Allows graceful handling of missing configuration for ECDS. @@ -38,7 +41,7 @@ static Http::FilterFactoryCb MissingConfigFilterFactory = class FilterChainUtility : Logger::Loggable { public: struct FilterFactoryProvider { - Filter::FilterConfigProviderPtr provider; + Filter::FilterConfigProviderPtr provider; // If true, this filter is disabled by default and must be explicitly enabled by // route configuration. bool disabled{}; @@ -52,6 +55,10 @@ class FilterChainUtility : Logger::Loggable { const FilterChainOptions& options, const FilterFactoriesList& filter_factories); + static std::shared_ptr + createSingletonDownstreamFilterConfigProviderManager( + Server::Configuration::ServerFactoryContext& context); + static std::shared_ptr createSingletonUpstreamFilterConfigProviderManager( Server::Configuration::ServerFactoryContext& context); @@ -62,7 +69,7 @@ class FilterChainHelper : Logger::Loggable { public: using FilterFactoriesList = FilterChainUtility::FilterFactoriesList; using FilterConfigProviderManager = - Filter::FilterConfigProviderManager; + Filter::FilterConfigProviderManager; FilterChainHelper(FilterConfigProviderManager& filter_config_provider_manager, Server::Configuration::ServerFactoryContext& server_context, diff --git a/source/extensions/filters/http/composite/action.cc b/source/extensions/filters/http/composite/action.cc index 2d7e6edd56b9..d7cb694e7452 100644 --- a/source/extensions/filters/http/composite/action.cc +++ b/source/extensions/filters/http/composite/action.cc @@ -4,6 +4,10 @@ namespace Envoy { namespace Extensions { namespace HttpFilters { namespace Composite { + +using HttpExtensionConfigProviderSharedPtr = std::shared_ptr< + Config::DynamicExtensionConfigProvider>; + void ExecuteFilterAction::createFilters(Http::FilterChainFactoryCallbacks& callbacks) const { cb_(callbacks); } @@ -29,11 +33,13 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createActionFactoryCb( Server::Configuration::FactoryContext& factory_context = context.factory_context_.value(); Server::Configuration::ServerFactoryContext& server_factory_context = context.server_factory_context_.value(); - Server::Configuration::HttpExtensionConfigProviderSharedPtr provider = - server_factory_context.downstreamHttpFilterConfigProviderManager() - ->createDynamicFilterConfigProvider( - config_discovery, composite_action.dynamic_config().name(), server_factory_context, - factory_context, server_factory_context.clusterManager(), false, "http", nullptr); + auto provider_manager = + Envoy::Http::FilterChainUtility::createSingletonDownstreamFilterConfigProviderManager( + server_factory_context); + HttpExtensionConfigProviderSharedPtr provider = + provider_manager->createDynamicFilterConfigProvider( + config_discovery, composite_action.dynamic_config().name(), server_factory_context, + factory_context, server_factory_context.clusterManager(), false, "http", nullptr); return [provider = std::move(provider)]() -> Matcher::ActionPtr { auto config_value = provider->config(); if (config_value.has_value()) { diff --git a/source/extensions/filters/network/http_connection_manager/config.cc b/source/extensions/filters/network/http_connection_manager/config.cc index 5817e8844338..2dca9a73952c 100644 --- a/source/extensions/filters/network/http_connection_manager/config.cc +++ b/source/extensions/filters/network/http_connection_manager/config.cc @@ -231,9 +231,9 @@ Utility::Singletons Utility::createSingletons(Server::Configuration::FactoryCont auto tracer_manager = Tracing::TracerManagerImpl::singleton(context); - Server::Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr - filter_config_provider_manager = - context.serverFactoryContext().downstreamHttpFilterConfigProviderManager(); + std::shared_ptr filter_config_provider_manager = + Http::FilterChainUtility::createSingletonDownstreamFilterConfigProviderManager( + server_context); return {date_provider, route_config_provider_manager, scoped_routes_config_provider_manager, tracer_manager, filter_config_provider_manager}; diff --git a/source/extensions/filters/network/http_connection_manager/config.h b/source/extensions/filters/network/http_connection_manager/config.h index c85ab06bc34c..b0a29a0f009b 100644 --- a/source/extensions/filters/network/http_connection_manager/config.h +++ b/source/extensions/filters/network/http_connection_manager/config.h @@ -46,7 +46,7 @@ namespace NetworkFilters { namespace HttpConnectionManager { using FilterConfigProviderManager = - Filter::FilterConfigProviderManager; /** diff --git a/source/server/BUILD b/source/server/BUILD index 82e7eeb9a56b..f0d63ba47174 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -361,7 +361,6 @@ envoy_cc_library( "//envoy/server:factory_context_interface", "//envoy/server:instance_interface", "//source/common/config:metadata_lib", - "//source/common/filter:config_discovery_lib", "//source/common/listener_manager:listener_info_lib", ], ) diff --git a/source/server/server.h b/source/server/server.h index ee7e083b3d50..dcfd5be7e5a9 100644 --- a/source/server/server.h +++ b/source/server/server.h @@ -172,9 +172,7 @@ class ServerFactoryContextImpl : public Configuration::ServerFactoryContext, public Configuration::TransportSocketFactoryContext { public: explicit ServerFactoryContextImpl(Instance& server) - : server_(server), server_scope_(server_.stats().createScope("")), - filter_config_provider_manager_( - std::make_shared()) {} + : server_(server), server_scope_(server_.stats().createScope("")) {} // Configuration::ServerFactoryContext Upstream::ClusterManager& clusterManager() override { return server_.clusterManager(); } @@ -203,10 +201,6 @@ class ServerFactoryContextImpl : public Configuration::ServerFactoryContext, envoy::config::bootstrap::v3::Bootstrap& bootstrap() override { return server_.bootstrap(); } OverloadManager& overloadManager() override { return server_.overloadManager(); } bool healthCheckFailed() const override { return server_.healthCheckFailed(); } - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr - downstreamHttpFilterConfigProviderManager() override { - return filter_config_provider_manager_; - } // Configuration::TransportSocketFactoryContext ServerFactoryContext& serverFactoryContext() override { return *this; } @@ -228,7 +222,6 @@ class ServerFactoryContextImpl : public Configuration::ServerFactoryContext, private: Instance& server_; Stats::ScopeSharedPtr server_scope_; - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr filter_config_provider_manager_; }; /** diff --git a/test/common/filter/config_discovery_impl_test.cc b/test/common/filter/config_discovery_impl_test.cc index 60bf7a88b217..7e1b1c2333fa 100644 --- a/test/common/filter/config_discovery_impl_test.cc +++ b/test/common/filter/config_discovery_impl_test.cc @@ -275,7 +275,7 @@ class FilterConfigDiscoveryImplTest : public FilterConfigDiscoveryTestBase { // HTTP filter test class HttpFilterConfigDiscoveryImplTest : public FilterConfigDiscoveryImplTest< - Http::NamedHttpFilterFactoryCb, Server::Configuration::FactoryContext, + NamedHttpFilterFactoryCb, Server::Configuration::FactoryContext, HttpFilterConfigProviderManagerImpl, TestHttpFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory, Server::Configuration::MockFactoryContext> { @@ -292,7 +292,7 @@ class HttpFilterConfigDiscoveryImplTest // Upstream HTTP filter test class HttpUpstreamFilterConfigDiscoveryImplTest : public FilterConfigDiscoveryImplTest< - Http::NamedHttpFilterFactoryCb, Server::Configuration::UpstreamFactoryContext, + NamedHttpFilterFactoryCb, Server::Configuration::UpstreamFactoryContext, UpstreamHttpFilterConfigProviderManagerImpl, TestHttpFilterFactory, Server::Configuration::UpstreamHttpFilterConfigFactory, Server::Configuration::MockUpstreamFactoryContext> { diff --git a/test/common/http/filter_chain_helper_test.cc b/test/common/http/filter_chain_helper_test.cc index 220bb8328d7b..75483f21cd68 100644 --- a/test/common/http/filter_chain_helper_test.cc +++ b/test/common/http/filter_chain_helper_test.cc @@ -28,8 +28,9 @@ TEST(FilterChainUtilityTest, CreateFilterChainForFactoriesWithRouteDisabled) { for (const auto& name : {"filter_0", "filter_1", "filter_2"}) { auto provider = - std::make_unique>( - Http::NamedHttpFilterFactoryCb{"filter_type_name", [](FilterChainFactoryCallbacks&) {}}, + std::make_unique>( + Filter::NamedHttpFilterFactoryCb{"filter_type_name", + [](FilterChainFactoryCallbacks&) {}}, name); filter_factories.push_back({std::move(provider), false}); } @@ -60,8 +61,9 @@ TEST(FilterChainUtilityTest, CreateFilterChainForFactoriesWithRouteDisabledAndDe for (const auto& name : {"filter_0", "filter_1", "filter_2"}) { auto provider = - std::make_unique>( - Http::NamedHttpFilterFactoryCb{"filter_type_name", [](FilterChainFactoryCallbacks&) {}}, + std::make_unique>( + Filter::NamedHttpFilterFactoryCb{"filter_type_name", + [](FilterChainFactoryCallbacks&) {}}, name); filter_factories.push_back({std::move(provider), true}); } diff --git a/test/mocks/server/server_factory_context.cc b/test/mocks/server/server_factory_context.cc index c9bfdc5d153f..6de698d5c0a2 100644 --- a/test/mocks/server/server_factory_context.cc +++ b/test/mocks/server/server_factory_context.cc @@ -10,9 +10,7 @@ using ::testing::ReturnRef; MockServerFactoryContext::MockServerFactoryContext() : singleton_manager_(new Singleton::ManagerImpl(Thread::threadFactoryForTest())), http_context_(store_.symbolTable()), grpc_context_(store_.symbolTable()), - router_context_(store_.symbolTable()), - filter_config_provider_manager_( - std::make_shared()) { + router_context_(store_.symbolTable()) { ON_CALL(*this, clusterManager()).WillByDefault(ReturnRef(cluster_manager_)); ON_CALL(*this, mainThreadDispatcher()).WillByDefault(ReturnRef(dispatcher_)); ON_CALL(*this, drainDecision()).WillByDefault(ReturnRef(drain_manager_)); @@ -42,10 +40,6 @@ MockServerFactoryContext::~MockServerFactoryContext() = default; MockStatsConfig::MockStatsConfig() = default; MockStatsConfig::~MockStatsConfig() = default; -StatelessMockServerFactoryContext::StatelessMockServerFactoryContext() - : filter_config_provider_manager_( - std::make_shared()) {} - MockGenericFactoryContext::~MockGenericFactoryContext() = default; MockGenericFactoryContext::MockGenericFactoryContext() { diff --git a/test/mocks/server/server_factory_context.h b/test/mocks/server/server_factory_context.h index 83225a4c6f06..9c8d754227aa 100644 --- a/test/mocks/server/server_factory_context.h +++ b/test/mocks/server/server_factory_context.h @@ -83,10 +83,6 @@ class MockServerFactoryContext : public virtual ServerFactoryContext { MOCK_METHOD(AccessLog::AccessLogManager&, accessLogManager, (), ()); MOCK_METHOD(OverloadManager&, overloadManager, ()); MOCK_METHOD(bool, healthCheckFailed, (), (const)); - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr - downstreamHttpFilterConfigProviderManager() override { - return filter_config_provider_manager_; - } testing::NiceMock cluster_manager_; testing::NiceMock dispatcher_; @@ -111,8 +107,6 @@ class MockServerFactoryContext : public virtual ServerFactoryContext { Router::ContextImpl router_context_; envoy::config::bootstrap::v3::Bootstrap bootstrap_; testing::NiceMock options_; - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr filter_config_provider_manager_{ - std::make_shared()}; }; class MockGenericFactoryContext : public GenericFactoryContext { @@ -134,7 +128,7 @@ class MockGenericFactoryContext : public GenericFactoryContext { // threads. Global state in the MockServerFactoryContext causes thread safety issues in this case. class StatelessMockServerFactoryContext : public virtual ServerFactoryContext { public: - StatelessMockServerFactoryContext(); + StatelessMockServerFactoryContext() = default; ~StatelessMockServerFactoryContext() override = default; MOCK_METHOD(Upstream::ClusterManager&, clusterManager, ()); @@ -165,11 +159,6 @@ class StatelessMockServerFactoryContext : public virtual ServerFactoryContext { MOCK_METHOD(AccessLog::AccessLogManager&, accessLogManager, (), ()); MOCK_METHOD(OverloadManager&, overloadManager, ()); MOCK_METHOD(bool, healthCheckFailed, (), (const)); - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr - downstreamHttpFilterConfigProviderManager() override { - return filter_config_provider_manager_; - } - Configuration::DownstreamHTTPFilterConfigProviderManagerSharedPtr filter_config_provider_manager_; }; } // namespace Configuration From becaf450c4a6a256d2cb1fa94c53091df6880323 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 20 Dec 2023 18:20:29 +0000 Subject: [PATCH 033/126] mobile/ci: Use new CI for scheduled/triggered (+cleanups) (#31469) Signed-off-by: Ryan Northey --- .github/workflows/_cache.yml | 8 +- .github/workflows/_finish.yml | 8 +- .github/workflows/_load.yml | 10 +- .github/workflows/_load_env.yml | 114 +++++++++ .github/workflows/_mobile_container_ci.yml | 6 + .github/workflows/_request.yml | 10 +- .github/workflows/_run.yml | 22 +- .github/workflows/_stage_publish.yml | 8 +- .github/workflows/_stage_verify.yml | 8 +- .github/workflows/_start.yml | 10 +- .github/workflows/codeql-push.yml | 2 +- .github/workflows/command.yml | 9 +- .github/workflows/envoy-dependency.yml | 18 +- .github/workflows/envoy-release.yml | 16 +- .github/workflows/envoy-sync.yml | 4 +- .github/workflows/mobile-android_build.yml | 12 +- .github/workflows/mobile-ios_build.yml | 4 +- .github/workflows/mobile-perf.yml | 4 +- .github/workflows/mobile-release.yml | 265 +++++++-------------- mobile/.bazelrc | 8 + 20 files changed, 288 insertions(+), 258 deletions(-) create mode 100644 .github/workflows/_load_env.yml diff --git a/.github/workflows/_cache.yml b/.github/workflows/_cache.yml index 4461da055193..f122ae64cb12 100644 --- a/.github/workflows/_cache.yml +++ b/.github/workflows/_cache.yml @@ -39,20 +39,20 @@ jobs: docker: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 id: appauth name: Appauth (mutex lock) with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.19 id: docker name: Prime Docker cache (${{ inputs.image-tag }}) with: image-tag: ${{ inputs.image-tag }} lock-token: ${{ steps.appauth.outputs.token }} lock-repository: ${{ inputs.lock-repository }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: data name: Cache data with: @@ -60,7 +60,7 @@ jobs: input: | cached: ${{ steps.docker.outputs.cached }} key: ${{ inputs.image-tag }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.19 name: Summary with: json: ${{ steps.data.outputs.value }} diff --git a/.github/workflows/_finish.yml b/.github/workflows/_finish.yml index c7a9ddf9bc1a..b905ecb59d87 100644 --- a/.github/workflows/_finish.yml +++ b/.github/workflows/_finish.yml @@ -36,7 +36,7 @@ jobs: actions: read contents: read steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 name: Incoming data id: needs with: @@ -87,7 +87,7 @@ jobs: summary: "Check has finished", text: $text}}}} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 name: Print summary with: input: ${{ toJSON(steps.needs.outputs.value).summary-title }} @@ -95,13 +95,13 @@ jobs: "## \(.)" options: -Rr output-path: GITHUB_STEP_SUMMARY - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 name: Update check with: action: update diff --git a/.github/workflows/_load.yml b/.github/workflows/_load.yml index 44c595bfb756..a28c07e685e7 100644 --- a/.github/workflows/_load.yml +++ b/.github/workflows/_load.yml @@ -91,7 +91,7 @@ jobs: # Handle any failure in triggering job # Remove any `checks` we dont care about # Prepare a check request - - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.19 name: Load env id: data with: @@ -102,13 +102,13 @@ jobs: GH_TOKEN: ${{ github.token }} # Update the check - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 name: Update check if: ${{ fromJSON(steps.data.outputs.data).data.check.action == 'RUN' }} with: @@ -116,7 +116,7 @@ jobs: checks: ${{ toJSON(fromJSON(steps.data.outputs.data).checks) }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 name: Print request summary with: input: | @@ -136,7 +136,7 @@ jobs: | $summary.summary as $summary | "${{ inputs.template-request-summary }}" - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: request-output name: Load request with: diff --git a/.github/workflows/_load_env.yml b/.github/workflows/_load_env.yml new file mode 100644 index 000000000000..bdd8fb966046 --- /dev/null +++ b/.github/workflows/_load_env.yml @@ -0,0 +1,114 @@ +name: Request/load + +permissions: + contents: read + +on: + workflow_call: + secrets: + lock-app-id: + required: true + lock-app-key: + required: true + + inputs: + branch-name: + type: string + default: main + cache-docker: + type: boolean + default: true + config-file: + type: string + default: ./.github/config.yml + event-name: + type: string + default: ${{ github.workflow }} + event-type: + type: string + default: ${{ github.event_name == 'workflow_dispatch' && 'dispatch' || 'scheduled' }} + trusted: + type: boolean + default: true + + outputs: + build-image: + value: ${{ jobs.request.outputs.build-image }} + build-image-mobile: + value: ${{ jobs.request.outputs.build-image-mobile }} + request: + value: ${{ jobs.request.outputs.request }} + trusted: + value: ${{ jobs.request.outputs.trusted }} + +concurrency: + group: | + ${{ github.actor != 'trigger-release-envoy[bot]' + && github.head_ref + || github.run_id + }}-${{ github.workflow }}-env + cancel-in-progress: true + +env: + CI_DEBUG: ${{ vars.CI_DEBUG && true || false }} + + +jobs: + request: + if: ${{ github.repository == 'envoyproxy/envoy' || vars.ENVOY_CI }} + runs-on: ubuntu-22.04 + outputs: + build-image: ${{ toJSON(fromJSON(steps.env.outputs.data).request.build-image) }} + build-image-mobile: ${{ fromJSON(steps.env.outputs.data).request.build-image-mobile }} + request: ${{ steps.env.outputs.data }} + trusted: true + steps: + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + id: started + name: Create timestamp + with: + options: -r + filter: | + now + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + id: checkout + name: Checkout Envoy repository + - name: Generate environment variables + uses: envoyproxy/toolshed/gh-actions/envoy/ci/env@actions-v0.2.19 + id: env + with: + branch-name: ${{ inputs.branch-name }} + config-file: ${{ inputs.config-file }} + started: ${{ steps.started.outputs.value }} + token: ${{ secrets.GITHUB_TOKEN }} + vars: ${{ toJSON(vars) }} + trusted: ${{ inputs.trusted }} + + - name: Request summary + id: summary + uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.19 + with: + actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} + base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} + event-name: ${{ inputs.event-name }} + event-type: ${{ inputs.event-type }} + link: ${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }} + output-path: GITHUB_STEP_SUMMARY + data: ${{ steps.env.outputs.data }} + tables: ${{ toJSON(fromJSON(steps.env.outputs.data).config.tables) }} + icon: ${{ fromJSON(steps.env.outputs.data).config.envoy.icon }} + message: ${{ fromJSON(steps.env.outputs.data).request.message }} + ref: ${{ fromJSON(steps.env.outputs.data).request.ref }} + sha: ${{ fromJSON(steps.env.outputs.data).request.sha }} + target-branch: ${{ fromJSON(steps.env.outputs.data).request.target-branch }} + + cache: + secrets: + app-id: ${{ secrets.lock-app-id }} + app-key: ${{ secrets.lock-app-key }} + uses: ./.github/workflows/_cache.yml + needs: request + if: ${{ inputs.cache-docker }} + with: + request: ${{ toJSON(needs.request.outputs) }} + image-tag: ${{ fromJSON(needs.request.outputs.build-image).default }} diff --git a/.github/workflows/_mobile_container_ci.yml b/.github/workflows/_mobile_container_ci.yml index c2d6f79d682a..da6b777c46e7 100644 --- a/.github/workflows/_mobile_container_ci.yml +++ b/.github/workflows/_mobile_container_ci.yml @@ -34,6 +34,7 @@ on: --volume=${PWD}:/source --volume=${TMP_ENTRYPOINT}:/tmp/mobile-entrypoint.sh --volume=/tmp/cache:/root/.cache + --volume=/tmp/container-output:/tmp/container-output --workdir=/source/mobile --entrypoint=/tmp/mobile-entrypoint.sh -e GITHUB_TOKEN @@ -68,6 +69,9 @@ on: default: | NOTICE Streaming build results + output-path: + type: string + default: /tmp/container-output rbe: type: boolean default: true @@ -137,8 +141,10 @@ jobs: downloads: ${{ inputs.downloads }} error-match: ${{ inputs.error-match }} notice-match: ${{ inputs.notice-match }} + output-path: ${{ inputs.output-path }} request: ${{ inputs.request }} source: ${{ inputs.source }} + steps-pre: ${{ inputs.steps-pre }} steps-post: ${{ inputs.steps-post }} target: ${{ inputs.target }} trusted: ${{ fromJSON(inputs.request).request.trusted }} diff --git a/.github/workflows/_request.yml b/.github/workflows/_request.yml index 454f917a7f1a..813e844d55f6 100644 --- a/.github/workflows/_request.yml +++ b/.github/workflows/_request.yml @@ -40,14 +40,14 @@ jobs: env: ${{ steps.data.outputs.value }} config: ${{ steps.config.outputs.config }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 id: checkout name: Checkout Envoy repository with: @@ -60,7 +60,7 @@ jobs: # *ALL* variables collected should be treated as untrusted and should be sanitized before # use - name: Generate environment variables from commit - uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.19 id: env with: branch-name: ${{ steps.checkout.outputs.branch-name }} @@ -71,7 +71,7 @@ jobs: vars: ${{ toJSON(vars) }} - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.19 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} @@ -87,7 +87,7 @@ jobs: target-branch: ${{ fromJSON(steps.env.outputs.data).request.target-branch }} - name: Environment data - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: data with: input: | diff --git a/.github/workflows/_run.yml b/.github/workflows/_run.yml index b4e23f7f56cf..a810ac2497ee 100644 --- a/.github/workflows/_run.yml +++ b/.github/workflows/_run.yml @@ -57,6 +57,9 @@ on: default: | NOTICE Streaming build results + output-path: + type: string + default: rbe: type: boolean default: true @@ -91,7 +94,7 @@ on: summary-post: type: string default: | - - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.19 with: context: %{{ inputs.context }} steps-pre: @@ -152,7 +155,7 @@ jobs: name: ${{ inputs.command }} ${{ inputs.target }} timeout-minutes: ${{ inputs.timeout-minutes }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: started name: Create timestamp with: @@ -160,7 +163,7 @@ jobs: filter: | now # This controls which input vars are exposed to the run action (and related steps) - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 name: Context id: context with: @@ -168,7 +171,7 @@ jobs: input: ${{ inputs.request }} filter: | . - | .check as $check + | (.check // {name: "${{ github.workflow }}"}) as $check | .config as $config | if "${{ inputs.runs-on }}" != "" then "${{ inputs.runs-on }}" @@ -181,11 +184,11 @@ jobs: | . * {$config, $check} - if: ${{ inputs.cache-build-image }} name: Restore Docker cache ${{ inputs.cache-build-image && format('({0})', inputs.cache-build-image) || '' }} - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.19 with: image_tag: ${{ inputs.cache-build-image }} - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 id: appauth name: Appauth if: ${{ inputs.trusted }} @@ -196,7 +199,7 @@ jobs: # - the workaround is to allow the token to be passed through. token: ${{ github.token }} token-ok: true - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 id: checkout name: Checkout Envoy repository with: @@ -213,7 +216,7 @@ jobs: token: ${{ inputs.trusted && steps.appauth.outputs.token || github.token }} # This is currently only use by mobile-docs and can be removed once they are updated to the newer website - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 id: checkout-extra name: Checkout extra repository (for publishing) if: ${{ inputs.checkout-extra }} @@ -221,7 +224,7 @@ jobs: config: ${{ inputs.checkout-extra }} ssh-key: ${{ inputs.trusted && inputs.ssh-key-extra || '' }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 name: Run CI ${{ inputs.command }} ${{ inputs.target }} with: args: ${{ inputs.args != '--' && inputs.args || inputs.target }} @@ -236,6 +239,7 @@ jobs: entrypoint: ${{ inputs.entrypoint }} error-match: ${{ inputs.error-match }} notice-match: ${{ inputs.notice-match }} + output-path: ${{ inputs.output-path }} report-pre: ${{ inputs.report-pre }} report-post: ${{ inputs.report-post }} source: ${{ inputs.source }} diff --git a/.github/workflows/_stage_publish.yml b/.github/workflows/_stage_publish.yml index e0fadbf2aa25..b3684a78ceda 100644 --- a/.github/workflows/_stage_publish.yml +++ b/.github/workflows/_stage_publish.yml @@ -63,7 +63,7 @@ jobs: export ENVOY_PUBLISH_DRY_RUN=${{ (fromJSON(inputs.request).request.version.dev || ! inputs.trusted) && 1 || '' }} steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 with: options: -Rr input: >- @@ -80,7 +80,7 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)/\($path)" - - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.19 with: url: %{{ steps.url.outputs.value }} path: %{{ runner.temp }}/release.signed @@ -98,12 +98,12 @@ jobs: needs: - publish steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.19 with: ref: main repository: ${{ fromJSON(inputs.request).request.version.dev && 'envoyproxy/envoy-website' || 'envoyproxy/archive' }} diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index f320faeb6a8f..3209bad28c66 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -50,7 +50,7 @@ jobs: rbe: false steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 with: options: -Rr input: >- @@ -66,15 +66,15 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)" - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 with: url: %{{ steps.url.outputs.value }}/docker/envoy.tar variant: dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 with: url: %{{ steps.url.outputs.value }}/docker/envoy-contrib.tar variant: contrib-dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 with: url: %{{ steps.url.outputs.value }}/docker/envoy-google-vrp.tar variant: google-vrp-dev diff --git a/.github/workflows/_start.yml b/.github/workflows/_start.yml index c7a1760679ad..ca9474ff03e7 100644 --- a/.github/workflows/_start.yml +++ b/.github/workflows/_start.yml @@ -54,7 +54,7 @@ jobs: start: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 id: check-config name: Prepare check data with: @@ -77,13 +77,13 @@ jobs: | .skipped.output.summary = "${{ inputs.skipped-summary }}" | .skipped.output.text = "" - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 name: Start checks id: checks with: @@ -94,7 +94,7 @@ jobs: ${{ fromJSON(inputs.env).summary.summary }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.19 name: Summary with: collapse-open: true @@ -118,7 +118,7 @@ jobs: output-path: GITHUB_STEP_SUMMARY title: Checks started/skipped - - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.19 name: Save env id: data with: diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 94ba6261013f..6afd6a6544f4 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Pre-cleanup - uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.19 with: to_remove: | /usr/local/lib/android diff --git a/.github/workflows/command.yml b/.github/workflows/command.yml index 4ea970e4fcda..aca3aeedc1cc 100644 --- a/.github/workflows/command.yml +++ b/.github/workflows/command.yml @@ -22,12 +22,13 @@ jobs: if: >- ${{ github.event.issue.pull_request - && github.repository == 'envoyproxy/envoy' + && (vars.ENVOY_CI + || github.repository == 'envoyproxy/envoy') && github.actor != 'repokitteh-read-only[bot]' && github.actor != 'dependabot[bot]' }} steps: - - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.19 name: Parse command from comment id: command with: @@ -36,14 +37,14 @@ jobs: ^/(retest) # /retest - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 if: ${{ steps.command.outputs.command == 'retest' }} id: appauth-retest name: Appauth (retest) with: key: ${{ secrets.ENVOY_CI_APP_KEY }} app_id: ${{ secrets.ENVOY_CI_APP_ID }} - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.19 if: ${{ steps.command.outputs.command == 'retest' }} name: Retest with: diff --git a/.github/workflows/envoy-dependency.yml b/.github/workflows/envoy-dependency.yml index 589f858d58ed..ca3152806f1b 100644 --- a/.github/workflows/envoy-dependency.yml +++ b/.github/workflows/envoy-dependency.yml @@ -50,16 +50,16 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 with: token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.19 id: update name: Update dependency (${{ inputs.dependency }}) with: @@ -92,13 +92,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.19 name: Upload diff with: name: ${{ inputs.dependency }}-${{ steps.update.outputs.output }} - name: Create a PR if: ${{ inputs.pr }} - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 with: base: main body: | @@ -129,11 +129,11 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 id: checkout name: Checkout Envoy repository with: @@ -175,7 +175,7 @@ jobs: - name: Check Docker SHAs id: build-images - uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.19 with: images: | sha: envoyproxy/envoy-build-ubuntu:${{ steps.build-tools.outputs.tag }} @@ -204,7 +204,7 @@ jobs: name: Update SHAs working-directory: envoy - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 with: base: main body: Created by Envoy dependency bot diff --git a/.github/workflows/envoy-release.yml b/.github/workflows/envoy-release.yml index 80c6e2c04b7f..1ac25a41ff12 100644 --- a/.github/workflows/envoy-release.yml +++ b/.github/workflows/envoy-release.yml @@ -55,7 +55,7 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} @@ -77,10 +77,10 @@ jobs: name: Check changelog summary - if: ${{ inputs.author }} name: Validate signoff email - uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.19 with: email: ${{ inputs.author }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 name: Create release with: source: | @@ -105,7 +105,7 @@ jobs: name: Release version id: release - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 with: base: ${{ github.ref_name }} commit: false @@ -130,13 +130,13 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} committer-name: ${{ env.COMMITTER_NAME }} committer-email: ${{ env.COMMITTER_EMAIL }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 name: Sync version histories with: command: >- @@ -146,7 +146,7 @@ jobs: -- --signoff="${{ env.COMMITTER_NAME }} <${{ env.COMMITTER_EMAIL }}>" - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 with: append-commit-message: true base: ${{ github.ref_name }} @@ -176,7 +176,7 @@ jobs: name: Create release branch steps: - name: Checkout repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.18 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml index d5af50330a1a..005a4713d8be 100644 --- a/.github/workflows/envoy-sync.yml +++ b/.github/workflows/envoy-sync.yml @@ -28,12 +28,12 @@ jobs: - data-plane-api - mobile-website steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.19 with: repository: "envoyproxy/${{ matrix.downstream }}" ref: main diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 8a6df4e37ddb..76f799e8eed0 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -75,9 +75,9 @@ jobs: target: kotlin-hello-world runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.19 steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 with: apk: bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity @@ -104,7 +104,7 @@ jobs: target: ${{ matrix.target }} runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.19 steps-post: ${{ matrix.steps-post }} timeout-minutes: 50 trusted: ${{ fromJSON(needs.load.outputs.trusted) }} @@ -115,7 +115,7 @@ jobs: include: - name: java-hello-world steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 with: apk: bazel-bin/examples/java/hello_world/hello_envoy.apk app: io.envoyproxy.envoymobile.helloenvoy/.MainActivity @@ -134,7 +134,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/baseline:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 with: apk: bazel-bin/test/kotlin/apps/baseline/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoybaselinetest/.MainActivity @@ -149,7 +149,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/experimental:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 with: apk: bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index aa1be794333b..474c1c29f658 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -86,7 +86,7 @@ jobs: ./ci/mac_ci_setup.sh ./bazelw shutdown steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.19 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} @@ -127,7 +127,7 @@ jobs: source: | ./ci/mac_ci_setup.sh steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.18 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.19 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} diff --git a/.github/workflows/mobile-perf.yml b/.github/workflows/mobile-perf.yml index 7a0e43573d52..807f1eda861b 100644 --- a/.github/workflows/mobile-perf.yml +++ b/.github/workflows/mobile-perf.yml @@ -47,10 +47,10 @@ jobs: request: ${{ needs.load.outputs.request }} source: ${{ matrix.source }} container-output: | - "bazel-bin/test/performance/test_binary_size": /tmp/mobile/bazel-bin/test/performance/test_binary_size/${{ matrix.target }} + "bazel-bin/test/performance/test_binary_size": test_binary_size/${{ matrix.target }} target: ${{ matrix.target }} upload-name: ${{ matrix.target }} - upload-path: /tmp/mobile/bazel-bin/test/performance/test_binary_size + upload-path: /tmp/container-output/test_binary_size timeout-minutes: 90 strategy: matrix: diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 05c093364cfa..e3eaf65704c0 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -1,4 +1,4 @@ -name: mobile_release +name: Mobile/Release permissions: contents: read @@ -11,191 +11,89 @@ on: jobs: env: - if: ${{ github.repository == 'envoyproxy/envoy' }} - uses: ./.github/workflows/_load.yml + secrets: + lock-app-key: ${{ secrets.ENVOY_CI_MUTEX_APP_KEY }} + lock-app-id: ${{ secrets.ENVOY_CI_MUTEX_APP_ID }} permissions: contents: read - pull-requests: read + uses: ./.github/workflows/_load_env.yml - android_release_artifacts: - if: >- - ${{ - github.repository == 'envoyproxy/envoy' - && (github.event.schedule - || !contains(github.actor, '[bot]')) - }} - needs: env - permissions: - contents: read - packages: read - name: android_release_artifacts - runs-on: ${{ fromJSON(needs.request.outputs.request).ci.agent-ubuntu }} - timeout-minutes: 120 - container: - image: ${{ needs.env.outputs.build-image-mobile }} - env: - CC: /opt/llvm/bin/clang - CXX: /opt/llvm/bin/clang++ - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Add safe directory - run: git config --global --add safe.directory /__w/envoy/envoy - - name: 'Build envoy.aar distributable' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - working-directory: mobile - run: | - version="0.5.0.$(date '+%Y%m%d')" - ./bazelw build \ - --config=mobile-remote-release-clang \ - --remote_header="Authorization=Bearer $GITHUB_TOKEN" \ - --fat_apk_cpu=x86,x86_64,armeabi-v7a,arm64-v8a \ - --define=pom_version="$version" \ - --config=mobile-release-android \ - --linkopt=-fuse-ld=lld \ - //:android_dist - - name: 'Tar artifacts' - run: | - tar -czvf envoy_android_aar_sources.tar.gz \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy.aar \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-pom.xml \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-sources.jar \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy-javadoc.jar - working-directory: mobile - - uses: actions/upload-artifact@v3 - with: - name: envoy_android_aar_sources - path: mobile/envoy_android_aar_sources.tar.gz - - android_release_deploy: - name: android_release_deploy - needs: android_release_artifacts + release: permissions: contents: read packages: read - runs-on: ubuntu-22.04 - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Add safe directory - run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v3 - with: - name: envoy_android_aar_sources - path: . - - name: Expand archive - run: | - tar -xvf envoy_android_aar_sources.tar.gz - mv bazel-bin/library/kotlin/io/envoyproxy/envoymobile/* . - - name: 'Configure gpg signing' - env: - GPG_KEY: ${{ secrets.EM_GPG_KEY }} - GPG_KEY_NAME: ${{ secrets.EM_GPG_KEY_NAME }} - GPG_PASSPHRASE: ${{ secrets.EM_GPG_PASSPHRASE }} - run: | - # https://github.com/keybase/keybase-issues/issues/2798 - export GPG_TTY=$(tty) - # Import gpg keys and warm the passphrase to avoid the gpg - # passphrase prompt when initating a deploy - # `--pinentry-mode=loopback` could be needed to ensure we - # suppress the gpg prompt - echo $GPG_KEY | base64 --decode > signing-key - gpg --passphrase $GPG_PASSPHRASE --batch --import signing-key - shred signing-key - - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy.aar - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy-pom.xml - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy-javadoc.jar - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy-sources.jar - - name: 'Release to sonatype repository' - env: - READWRITE_USER: ${{ secrets.EM_SONATYPE_USER }} - READWRITE_API_KEY: ${{ secrets.EM_SONATYPE_PASSWORD }} - SONATYPE_PROFILE_ID: ${{ secrets.EM_SONATYPE_PROFILE_ID }} - run: | - version="0.5.0.$(date '+%Y%m%d')" - python mobile/ci/sonatype_nexus_upload.py \ - --profile_id=$SONATYPE_PROFILE_ID \ - --artifact_id=envoy \ - --version=$version \ - --files \ - envoy.aar \ - envoy-pom.xml \ - envoy-sources.jar \ - envoy-javadoc.jar \ - --signed_files \ - envoy.aar.asc \ - envoy-pom.xml.asc \ - envoy-sources.jar.asc \ - envoy-javadoc.jar.asc - - android_xds_release_artifacts: if: >- ${{ - github.repository == 'envoyproxy/envoy' + (github.repository == 'envoyproxy/envoy' + || vars.ENVOY_CI) && (github.event.schedule || !contains(github.actor, '[bot]')) }} needs: env - permissions: - contents: read - packages: read - name: android_xds_release_artifacts - runs-on: ${{ fromJSON(needs.env.outputs.request).ci.agent-ubuntu }} - timeout-minutes: 120 - container: - image: ${{ needs.env.outputs.build-image-mobile }} - env: - CC: /opt/llvm/bin/clang - CXX: /opt/llvm/bin/clang++ - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Add safe directory - run: git config --global --add safe.directory /__w/envoy/envoy - - name: 'Build envoy_xds.aar distributable' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - working-directory: mobile - run: | - # --define=envoy_mobile_xds=enabled must be defined last because - # --config=mobile-release-android has --define=envoy_mobile_xds=disabled - version="0.5.0.$(date '+%Y%m%d')" - ./bazelw build \ - --config=mobile-remote-release-clang \ - --remote_header="Authorization=Bearer $GITHUB_TOKEN" \ - --fat_apk_cpu=x86,x86_64,armeabi-v7a,arm64-v8a \ - --define=pom_version="$version" \ - --config=mobile-release-android \ - --define=envoy_mobile_xds=enabled \ - --linkopt=-fuse-ld=lld \ - //:android_xds_dist - - name: 'Tar artifacts' - run: | - tar -czvf envoy_xds_android_aar_sources.tar.gz \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds.aar \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-pom.xml \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-sources.jar \ - bazel-bin/library/kotlin/io/envoyproxy/envoymobile/envoy_xds-javadoc.jar - working-directory: mobile - - uses: actions/upload-artifact@v3 - with: - name: envoy_xds_android_aar_sources - path: mobile/envoy_xds_android_aar_sources.tar.gz + uses: ./.github/workflows/_mobile_container_ci.yml + with: + args: ${{ matrix.args }} + container: ${{ fromJSON(needs.env.outputs.build-image).mobile }} + container-output: | + "bazel-bin/library/kotlin/io/envoyproxy/envoymobile/${{ matrix.output }}.aar": build/ + "bazel-bin/library/kotlin/io/envoyproxy/envoymobile/${{ matrix.output }}-pom.xml": build/ + "bazel-bin/library/kotlin/io/envoyproxy/envoymobile/${{ matrix.output }}-sources.jar": build/ + "bazel-bin/library/kotlin/io/envoyproxy/envoymobile/${{ matrix.output }}-javadoc.jar": build/ + request: ${{ needs.env.outputs.request }} + steps-pre: | + - run: | + mkdir /tmp/mobile + VERSION="0.5.0.$(date '+%Y%m%d')" + echo "VERSION=${VERSION}" >> $GITHUB_ENV + shell: bash + steps-post: | + - run: | + mkdir /tmp/output + shell: bash + - name: Tar artifacts + run: >- + tar + -czhf + /tmp/output/${{ matrix.output }}_android_aar_sources.tar.gz + -C + /tmp/container-output/build + . + shell: bash + target: ${{ matrix.target }} + upload-name: ${{ matrix.output }}_android_aar_sources + upload-path: /tmp/output/${{ matrix.output }}_android_aar_sources.tar.gz + strategy: + fail-fast: false + matrix: + include: + - target: android-release + args: >- + build + --config=mobile-remote-release-clang-android-publish + --define=pom_version=$VERSION + //:android_dist + output: envoy + - target: xds-release + args: >- + build + --config=mobile-remote-release-clang-android-publish-xds + --define=pom_version=$VERSION + //:android_xds_dist + output: envoy_xds - android_xds_release_deploy: - name: android_xds_release_deploy - needs: android_xds_release_artifacts + deploy: + needs: release permissions: contents: read packages: read runs-on: ubuntu-22.04 timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - output: envoy + - output: envoy_xds steps: - uses: actions/checkout@v4 with: @@ -204,12 +102,11 @@ jobs: run: git config --global --add safe.directory /__w/envoy/envoy - uses: actions/download-artifact@v3 with: - name: envoy_xds_android_aar_sources + name: ${{ matrix.output }}_android_aar_sources path: . - name: Expand archive run: | - tar -xvf envoy_xds_android_aar_sources.tar.gz - mv bazel-bin/library/kotlin/io/envoyproxy/envoymobile/* . + tar -xf ${{ matrix.output }}_android_aar_sources.tar.gz - name: 'Configure gpg signing' env: GPG_KEY: ${{ secrets.EM_GPG_KEY }} @@ -226,10 +123,10 @@ jobs: gpg --passphrase $GPG_PASSPHRASE --batch --import signing-key shred signing-key - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy_xds.aar - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy_xds-pom.xml - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy_xds-javadoc.jar - gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab envoy_xds-sources.jar + gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab ${{ matrix.output }}.aar + gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab ${{ matrix.output }}-pom.xml + gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab ${{ matrix.output }}-javadoc.jar + gpg --pinentry-mode=loopback --passphrase $GPG_PASSPHRASE -ab ${{ matrix.output }}-sources.jar - name: 'Release to sonatype repository' env: READWRITE_USER: ${{ secrets.EM_SONATYPE_USER }} @@ -239,15 +136,15 @@ jobs: version="0.5.0.$(date '+%Y%m%d')" python mobile/ci/sonatype_nexus_upload.py \ --profile_id=$SONATYPE_PROFILE_ID \ - --artifact_id=envoy-xds \ + --artifact_id=${{ matrix.output }} \ --version=$version \ --files \ - envoy_xds.aar \ - envoy_xds-pom.xml \ - envoy_xds-sources.jar \ - envoy_xds-javadoc.jar \ + ${{ matrix.output }}.aar \ + ${{ matrix.output }}-pom.xml \ + ${{ matrix.output }}-sources.jar \ + ${{ matrix.output }}-javadoc.jar \ --signed_files \ - envoy_xds.aar.asc \ - envoy_xds-pom.xml.asc \ - envoy_xds-sources.jar.asc \ - envoy_xds-javadoc.jar.asc + ${{ matrix.output }}.aar.asc \ + ${{ matrix.output }}-pom.xml.asc \ + ${{ matrix.output }}-sources.jar.asc \ + ${{ matrix.output }}-javadoc.jar.asc diff --git a/mobile/.bazelrc b/mobile/.bazelrc index bc6464190e0a..26769b110898 100644 --- a/mobile/.bazelrc +++ b/mobile/.bazelrc @@ -121,6 +121,14 @@ build:mobile-remote-release-clang-android --config=mobile-remote-release-clang build:mobile-remote-release-clang-android --fat_apk_cpu=x86_64 build:mobile-remote-release-clang-android --linkopt=-fuse-ld=lld +build:mobile-remote-release-clang-android-publish --config=mobile-remote-release-clang +build:mobile-remote-release-clang-android-publish --config=mobile-release-android +build:mobile-remote-release-clang-android-publish --fat_apk_cpu=x86,x86_64,armeabi-v7a,arm64-v8a +build:mobile-remote-release-clang-android-publish --linkopt=-fuse-ld=lld + +build:mobile-remote-release-clang-android-publish-xds --config=mobile-remote-release-clang-android-publish +build:mobile-remote-release-clang-android-publish-xds --define=envoy_mobile_xds=enabled + # Compile releases optimizing for size (eg -Os, etc). build:mobile-release-common --config=sizeopt From e48fff9628c78ab1e481b20d39ced8ac034184a8 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 20 Dec 2023 18:47:39 +0000 Subject: [PATCH 034/126] bazel/updater: Fix for version (#31467) Signed-off-by: Ryan Northey --- .github/workflows/envoy-dependency.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/envoy-dependency.yml b/.github/workflows/envoy-dependency.yml index ca3152806f1b..35368d95f137 100644 --- a/.github/workflows/envoy-dependency.yml +++ b/.github/workflows/envoy-dependency.yml @@ -66,12 +66,14 @@ jobs: input: | dependency: ${{ inputs.dependency }} task: ${{ inputs.task }} - version: ${{ inputs.version }} + version: "${{ inputs.version }}" input-format: yaml filter: | - .version[:7] as $version + .version as $version | .dependency as $dependency | .task as $task + | (try ($version | validate::sha(40) | .[:7]) + catch $version) as $version_short | {} | if $task == "bazel" then . @@ -85,9 +87,9 @@ jobs: | .task as $task | .target as $target | (" - echo \"Updating(\($task)): \($dependency) -> \($version)\" + echo \"Updating(\($task)): \($dependency) -> \($version_short)\" bazel run --config=ci //bazel:\($target) \($dependency) \($version) - OUTPUT=\($version) + OUTPUT=\($version_short) " | bash::output) env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From ce116958fb6b31e8ab0558cd86ec028105811f31 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 20 Dec 2023 20:24:28 +0000 Subject: [PATCH 035/126] Revert "deps: Bump build images -> `6eba113` (#31372)" (#31470) This reverts commit 37faed9e3fdaf37b39e8ca9c320e02aabe5c7358. Signed-off-by: Ryan Northey --- .bazelrc | 4 ++-- .devcontainer/Dockerfile | 2 +- .github/config.yml | 8 ++++---- examples/shared/build/Dockerfile | 2 +- mobile/third_party/rbe_configs/config/BUILD | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.bazelrc b/.bazelrc index df66d82946b7..a5b1ab886dba 100644 --- a/.bazelrc +++ b/.bazelrc @@ -357,7 +357,7 @@ build:compile-time-options --@envoy//source/extensions/filters/http/kill_request # Docker sandbox # NOTE: Update this from https://github.com/envoyproxy/envoy-build-tools/blob/main/toolchains/rbe_toolchains_config.bzl#L8 -build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:d117d6139f3af1eede6bb1606ad05ffccb766eef3262b336dd31bcf02a81a669 +build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 build:docker-sandbox --spawn_strategy=docker build:docker-sandbox --strategy=Javac=docker build:docker-sandbox --strategy=Closure=docker @@ -518,7 +518,7 @@ build:rbe-envoy-engflow --grpc_keepalive_time=30s build:rbe-envoy-engflow --remote_timeout=3600s build:rbe-envoy-engflow --bes_timeout=3600s build:rbe-envoy-engflow --bes_upload_mode=fully_async -build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:d117d6139f3af1eede6bb1606ad05ffccb766eef3262b336dd31bcf02a81a669 +build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 ############################################################################# # debug: Various Bazel debugging flags diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d1329f4f8aa8..62ba4e83d738 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM gcr.io/envoy-ci/envoy-build:6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:56466807485ba97d3ae79b4fa54cf9723bd9eb327783917d4bdc736483e5d72a +FROM gcr.io/envoy-ci/envoy-build:7467652575122d8d54e767a68f141598bd855383@sha256:af98298b715958527d3c3b42ae968a09223d237c843e129c586b7e76b8c69a0d ARG USERNAME=vscode ARG USER_UID=501 diff --git a/.github/config.yml b/.github/config.yml index d31ac8c2ce6e..c7d767ec5f2e 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -2,11 +2,11 @@ agent-ubuntu: ubuntu-22.04 build-image: # Authoritative configuration for build image/s repo: envoyproxy/envoy-build-ubuntu - sha: d117d6139f3af1eede6bb1606ad05ffccb766eef3262b336dd31bcf02a81a669 - mobile-sha: 82a79f368aa7da9a3ed904352deb24e6e52c5eae156fdc5ca2fb3fca6650ed6d + sha: 8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 + mobile-sha: 292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f # this is authoritative, but is not currently used in github ci - gcr-sha: 56466807485ba97d3ae79b4fa54cf9723bd9eb327783917d4bdc736483e5d72a - tag: 6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c + gcr-sha: af98298b715958527d3c3b42ae968a09223d237c843e129c586b7e76b8c69a0d + tag: 7467652575122d8d54e767a68f141598bd855383 config: envoy: diff --git a/examples/shared/build/Dockerfile b/examples/shared/build/Dockerfile index fc548e6d8c62..7c2b63fe5b1f 100644 --- a/examples/shared/build/Dockerfile +++ b/examples/shared/build/Dockerfile @@ -1,4 +1,4 @@ -FROM envoyproxy/envoy-build-ubuntu:6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:d117d6139f3af1eede6bb1606ad05ffccb766eef3262b336dd31bcf02a81a669 +FROM envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ diff --git a/mobile/third_party/rbe_configs/config/BUILD b/mobile/third_party/rbe_configs/config/BUILD index 34111494ce5c..df1b76d803e9 100644 --- a/mobile/third_party/rbe_configs/config/BUILD +++ b/mobile/third_party/rbe_configs/config/BUILD @@ -42,7 +42,7 @@ platform( "@bazel_tools//tools/cpp:clang", ], exec_properties = { - "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:82a79f368aa7da9a3ed904352deb24e6e52c5eae156fdc5ca2fb3fca6650ed6d", + "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-7467652575122d8d54e767a68f141598bd855383@sha256:292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f", "OSFamily": "Linux", "Pool": "linux", }, @@ -57,7 +57,7 @@ platform( "@bazel_tools//tools/cpp:clang", ], exec_properties = { - "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-6eba113ee1a0ef8e4f71830e90b6aedbbeb7360c@sha256:82a79f368aa7da9a3ed904352deb24e6e52c5eae156fdc5ca2fb3fca6650ed6d", + "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-7467652575122d8d54e767a68f141598bd855383@sha256:292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f", "OSFamily": "Linux", "Pool": "linux", # Necessary to workaround https://github.com/google/sanitizers/issues/916, otherwise, dangling threads in the From cd13b6045ea0fa9926173501d1cd27f93d19ade5 Mon Sep 17 00:00:00 2001 From: Joshua Marantz Date: Wed, 20 Dec 2023 16:38:52 -0500 Subject: [PATCH 036/126] drain: reproduce and fix a draining race condition that fails tsan (#31452) Commit Message: This reproduces and fixes a race condition on DrainManagerImpl::drain_deadline_ which is written from the main thread by DrainManagerImpl::startDrainSequence via admin, and read from worker threads via the DrainManagerImpl::drainClose() API. The race condition is resolved by updating the draining_ atomic bool after updating drain_deadline_, as C++ will not re-order statements around atomics. drainClose() does not look at drain_deadline_ unless draining_ is true, and startDrainSequence will not write drain_deadline_ a second time. Additionally, jitter was added based on the --drain-time-s command-line parameter. However, that defaults to 0 and was used as a modulus to calculate jitter, which causes an arithmetic exception. Instead we assume no jitter. Another similar bug was fixed where there could be a microsecond left, but we calculate the modulus for the jitter based on rounding that to milliseconds, which could be zero. Additional Description: Risk Level: low Testing: //test/... Docs Changes: n/a Release Notes: n/a Platform Specific Features: n/a Fixes: #31457 Signed-off-by: Joshua Marantz --- source/server/drain_manager_impl.cc | 60 +++++++++++++---- test/server/drain_manager_impl_test.cc | 82 ++++++++++++++---------- test/server/server_test.cc | 89 +++++++++++++++++++------- 3 files changed, 161 insertions(+), 70 deletions(-) diff --git a/source/server/drain_manager_impl.cc b/source/server/drain_manager_impl.cc index 27eed8d92d41..23ac96cdb88f 100644 --- a/source/server/drain_manager_impl.cc +++ b/source/server/drain_manager_impl.cc @@ -70,13 +70,23 @@ bool DrainManagerImpl::drainClose() const { const auto remaining_time = std::chrono::duration_cast(drain_deadline_ - current_time); + const auto drain_time = server_.options().drainTime(); ASSERT(server_.options().drainTime() >= remaining_time); - const auto elapsed_time = server_.options().drainTime() - remaining_time; + const auto drain_time_count = drain_time.count(); + + // If the user hasn't specified a drain timeout it will be zero, so we'll + // confirm the drainClose immediately. Otherwise we'll use the drain timeout + // as a modulus to a random number to salt the drain timing. + if (drain_time_count == 0) { + return true; + } + const auto elapsed_time = drain_time - remaining_time; return static_cast(elapsed_time.count()) > - (server_.api().randomGenerator().random() % server_.options().drainTime().count()); + (server_.api().randomGenerator().random() % drain_time_count); } Common::CallbackHandlePtr DrainManagerImpl::addOnDrainCloseCb(DrainCloseCb cb) const { + ASSERT_IS_MAIN_OR_TEST_THREAD(); ASSERT(dispatcher_.isThreadSafe()); if (draining_) { @@ -84,14 +94,21 @@ Common::CallbackHandlePtr DrainManagerImpl::addOnDrainCloseCb(DrainCloseCb cb) c // Calculate the delay. If using an immediate drain-strategy or past our deadline, use // a zero millisecond delay. Otherwise, pick a random value within the remaining time-span. - std::chrono::milliseconds drain_delay = - (server_.options().drainStrategy() != Server::DrainStrategy::Immediate && - current_time < drain_deadline_) - ? std::chrono::milliseconds(server_.api().randomGenerator().random() % - std::chrono::duration_cast( - drain_deadline_ - current_time) - .count()) - : std::chrono::milliseconds{0}; + std::chrono::milliseconds drain_delay{0}; + if (server_.options().drainStrategy() != Server::DrainStrategy::Immediate) { + if (current_time < drain_deadline_) { + const auto delta = drain_deadline_ - current_time; + const auto ms = std::chrono::duration_cast(delta).count(); + + // Note; current_time may be less than drain_deadline_ by only a + // microsecond (delta will be 1000 nanoseconds), in which case when we + // convert to milliseconds that will be 0, which will throw a SIGFPE + // if used as a modulus unguarded. + if (ms > 0) { + drain_delay = std::chrono::milliseconds(server_.api().randomGenerator().random() % ms); + } + } + } cb(drain_delay); return nullptr; } @@ -100,6 +117,7 @@ Common::CallbackHandlePtr DrainManagerImpl::addOnDrainCloseCb(DrainCloseCb cb) c } void DrainManagerImpl::addDrainCompleteCallback(std::function cb) { + ASSERT_IS_MAIN_OR_TEST_THREAD(); ASSERT(draining_); // If the drain-tick-timer is active, add the callback to the queue. If not defined @@ -112,6 +130,7 @@ void DrainManagerImpl::addDrainCompleteCallback(std::function cb) { } void DrainManagerImpl::startDrainSequence(std::function drain_complete_cb) { + ASSERT_IS_MAIN_OR_TEST_THREAD(); ASSERT(drain_complete_cb); // If we've already started draining (either through direct invocation or through @@ -122,7 +141,24 @@ void DrainManagerImpl::startDrainSequence(std::function drain_complete_c } ASSERT(!drain_tick_timer_); - draining_ = true; + const std::chrono::seconds drain_delay(server_.options().drainTime()); + + // Note https://github.com/envoyproxy/envoy/issues/31457, previous to which, + // drain_deadline_ was set *after* draining_ resulting in a read/write race between + // the main thread running this function from admin, and the worker thread calling + // drainClose. Note that drain_deadline_ is default-constructed which guarantees + // to set the time-since epoch to a count of 0 + // (https://en.cppreference.com/w/cpp/chrono/time_point/time_point). + ASSERT(drain_deadline_.time_since_epoch().count() == 0, "drain_deadline_ cannot be set twice."); + + // Since draining_ is atomic, it is safe to set drain_deadline_ without a mutex + // as drain_close() only reads from drain_deadline_ if draining_ is true, and + // C++ will not re-order an assign to an atomic. See + // https://stackoverflow.com/questions/40320254/reordering-atomic-operations-in-c . + drain_deadline_ = dispatcher_.timeSource().monotonicTime() + drain_delay; + + // Atomic assign must come after the assign to drain_deadline_. + draining_.store(true, std::memory_order_seq_cst); // Signal to child drain-managers to start their drain sequence children_->runCallbacks(); @@ -136,9 +172,7 @@ void DrainManagerImpl::startDrainSequence(std::function drain_complete_c drain_tick_timer_.reset(); }); addDrainCompleteCallback(drain_complete_cb); - const std::chrono::seconds drain_delay(server_.options().drainTime()); drain_tick_timer_->enableTimer(drain_delay); - drain_deadline_ = dispatcher_.timeSource().monotonicTime() + drain_delay; // Call registered on-drain callbacks - with gradual delays // Note: This will distribute drain events in the first 1/4th of the drain window diff --git a/test/server/drain_manager_impl_test.cc b/test/server/drain_manager_impl_test.cc index d0a2a63b6c1e..5ad7eb97f4c5 100644 --- a/test/server/drain_manager_impl_test.cc +++ b/test/server/drain_manager_impl_test.cc @@ -33,6 +33,44 @@ class DrainManagerImplTest : public Event::TestUsingSimulatedTime, .WillByDefault(Return(std::chrono::seconds(900))); } + template + void testRegisterCallbackAfterDrainBeginGradualStrategy(Duration delay) { + ON_CALL(server_.options_, drainStrategy()) + .WillByDefault(Return(Server::DrainStrategy::Gradual)); + ON_CALL(server_.options_, drainTime()).WillByDefault(Return(std::chrono::seconds(1))); + + DrainManagerImpl drain_manager(server_, envoy::config::listener::v3::Listener::DEFAULT, + server_.dispatcher()); + + testing::MockFunction cb_before_drain; + testing::MockFunction cb_after_drain1; + testing::MockFunction cb_after_drain2; + + EXPECT_CALL(cb_before_drain, Call(_)); + // Validate that callbacks after the drain sequence has started (or after the drain deadline + // has been reached) are called with a random value between 0 (immediate) and the max + // drain window (minus time that has passed). + EXPECT_CALL(cb_after_drain1, Call(_)).WillOnce(Invoke([](std::chrono::milliseconds delay) { + EXPECT_THAT(delay.count(), Ge(0)); + EXPECT_THAT(delay.count(), Le(990)); + })); + EXPECT_CALL(cb_after_drain2, Call(_)).WillOnce(Invoke([](std::chrono::milliseconds delay) { + EXPECT_EQ(delay.count(), 0); + })); + + auto before_handle = drain_manager.addOnDrainCloseCb(cb_before_drain.AsStdFunction()); + drain_manager.startDrainSequence([] {}); + + server_.api_.time_system_.advanceTimeWait(std::chrono::milliseconds(10)); + auto after_handle1 = drain_manager.addOnDrainCloseCb(cb_after_drain1.AsStdFunction()); + + server_.api_.time_system_.advanceTimeWait(delay); + auto after_handle2 = drain_manager.addOnDrainCloseCb(cb_after_drain2.AsStdFunction()); + + EXPECT_EQ(after_handle1, nullptr); + EXPECT_EQ(after_handle2, nullptr); + } + NiceMock server_; }; @@ -266,42 +304,18 @@ TEST_F(DrainManagerImplTest, OnDrainCallbacksNonEvenlyDividedSteps) { EXPECT_TRUE(drain_manager.draining()); } -// Validate the expected behavior when a drain-close callback is registered after draining has begun -// with a Gradual drain strategy (should be called with delay between 0 and maximum) +// Validate the expected behavior when a drain-close callback is registered +// after draining has begun with a Gradual drain strategy (should be called with +// delay between 0 and maximum) TEST_F(DrainManagerImplTest, RegisterCallbackAfterDrainBeginGradualStrategy) { - ON_CALL(server_.options_, drainStrategy()).WillByDefault(Return(Server::DrainStrategy::Gradual)); - ON_CALL(server_.options_, drainTime()).WillByDefault(Return(std::chrono::seconds(1))); - - DrainManagerImpl drain_manager(server_, envoy::config::listener::v3::Listener::DEFAULT, - server_.dispatcher()); - - testing::MockFunction cb_before_drain; - testing::MockFunction cb_after_drain1; - testing::MockFunction cb_after_drain2; - - EXPECT_CALL(cb_before_drain, Call(_)); - // Validate that callbacks after the drain sequence has started (or after the drain deadline - // has been reached) are called with a random value between 0 (immediate) and the max - // drain window (minus time that has passed). - EXPECT_CALL(cb_after_drain1, Call(_)).WillOnce(Invoke([](std::chrono::milliseconds delay) { - EXPECT_THAT(delay.count(), Ge(0)); - EXPECT_THAT(delay.count(), Le(990)); - })); - EXPECT_CALL(cb_after_drain2, Call(_)).WillOnce(Invoke([](std::chrono::milliseconds delay) { - EXPECT_EQ(delay.count(), 0); - })); - - auto before_handle = drain_manager.addOnDrainCloseCb(cb_before_drain.AsStdFunction()); - drain_manager.startDrainSequence([] {}); - - server_.api_.time_system_.advanceTimeWait(std::chrono::milliseconds(10)); - auto after_handle1 = drain_manager.addOnDrainCloseCb(cb_after_drain1.AsStdFunction()); - - server_.api_.time_system_.advanceTimeWait(std::chrono::milliseconds(1000)); - auto after_handle2 = drain_manager.addOnDrainCloseCb(cb_after_drain2.AsStdFunction()); + testRegisterCallbackAfterDrainBeginGradualStrategy(std::chrono::milliseconds(1000)); +} - EXPECT_EQ(after_handle1, nullptr); - EXPECT_EQ(after_handle2, nullptr); +// Repeat above test, but add simulated delay that falls 1 microsecond short of +// the deadline, thus triggering a corner case where the current time is less +// than the deadline by 1 microsecond, which rounds to 0 milliseconds. +TEST_F(DrainManagerImplTest, RegisterCallbackAfterDrainBeginGradualStrategyMicroDelay) { + testRegisterCallbackAfterDrainBeginGradualStrategy(std::chrono::microseconds(990 * 1000 - 1)); } // Validate the expected behavior when a drain-close callback is registered after draining has begun diff --git a/test/server/server_test.cc b/test/server/server_test.cc index 699798a34e52..5f088d5aba8f 100644 --- a/test/server/server_test.cc +++ b/test/server/server_test.cc @@ -642,35 +642,78 @@ TEST_P(ServerInstanceImplTest, LifecycleNotifications) { server_thread->join(); } -TEST_P(ServerInstanceImplTest, DrainParentListenerAfterWorkersStarted) { - bool workers_started = false; - absl::Notification workers_started_fired, workers_started_block; - // Expect drainParentListeners not to be called before workers start. - EXPECT_CALL(restart_, drainParentListeners).Times(0); - - // Run the server in a separate thread so we can test different lifecycle stages. - auto server_thread = Thread::threadFactoryForTest().createThread([&] { - auto hooks = CustomListenerHooks([&]() { - workers_started = true; - workers_started_fired.Notify(); - workers_started_block.WaitForNotification(); +class ServerInstanceImplWorkersTest : public ServerInstanceImplTest { +protected: + ServerInstanceImplWorkersTest() { + bool workers_started = false; + + // Expect drainParentListeners not to be called before workers start. + EXPECT_CALL(restart_, drainParentListeners).Times(0); + + // Run the server in a separate thread so we can test different lifecycle stages. + server_thread_ = Thread::threadFactoryForTest().createThread([&] { + auto hooks = CustomListenerHooks([&]() { + workers_started = true; + workers_started_fired_.Notify(); + workers_started_block_.WaitForNotification(); + }); + initialize("test/server/test_data/server/node_bootstrap.yaml", false, hooks); + server_->run(); + server_ = nullptr; + thread_local_ = nullptr; }); - initialize("test/server/test_data/server/node_bootstrap.yaml", false, hooks); - server_->run(); - server_ = nullptr; - thread_local_ = nullptr; - }); - workers_started_fired.WaitForNotification(); - EXPECT_TRUE(workers_started); + workers_started_fired_.WaitForNotification(); + EXPECT_TRUE(workers_started); + EXPECT_CALL(restart_, drainParentListeners); + } + + ~ServerInstanceImplWorkersTest() { + server_->dispatcher().post([&] { server_->shutdown(); }); + server_thread_->join(); + } + + absl::Notification workers_started_fired_; + absl::Notification workers_started_block_; + Thread::ThreadPtr server_thread_; +}; + +INSTANTIATE_TEST_SUITE_P(IpVersions, ServerInstanceImplWorkersTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + +TEST_P(ServerInstanceImplWorkersTest, DrainParentListenerAfterWorkersStarted) { EXPECT_TRUE(TestUtility::findGauge(stats_store_, "server.state")->used()); EXPECT_EQ(0L, TestUtility::findGauge(stats_store_, "server.state")->value()); + workers_started_block_.Notify(); +} - EXPECT_CALL(restart_, drainParentListeners); - workers_started_block.Notify(); +TEST_P(ServerInstanceImplWorkersTest, DrainCloseAfterWorkersStarted) { + absl::Notification drain_closes_started, drain_complete; + workers_started_block_.Notify(); - server_->dispatcher().post([&] { server_->shutdown(); }); - server_thread->join(); + DrainManager& drain_manager = server_->drainManager(); + + // To reproduce the race condition from + // https://github.com/envoyproxy/envoy/issues/31457 we make sure that the + // infinite drainClose spin-loop (mimicing high traffic) is running before we + // initiate the drain sequence. + auto drain_thread = Thread::threadFactoryForTest().createThread([&] { + bool closed = drain_manager.drainClose(); + drain_closes_started.Notify(); + while (!closed) { + closed = drain_manager.drainClose(); + } + }); + drain_closes_started.WaitForNotification(); + + // Now that we are starting to try to call drainClose, we'll start the drain sequence, then + // wait for that to complete. + server_->dispatcher().post( + [&] { drain_manager.startDrainSequence([&drain_complete]() { drain_complete.Notify(); }); }); + + drain_complete.WaitForNotification(); + drain_thread->join(); } // A test target which never signals that it is ready. From 9db3bd6a8a471ee282ed83909cf0236ba919de66 Mon Sep 17 00:00:00 2001 From: tmsnan Date: Thu, 21 Dec 2023 09:50:21 +0800 Subject: [PATCH 037/126] generic proxy : Optimize generic proxy stats classification (#31446) * generic proxy : Optimize generic proxy stats classification Signed-off-by: zhaonan * update changelog Signed-off-by: zhaonan * fix format Signed-off-by: zhaonan * update changelog Signed-off-by: zhaonan --------- Signed-off-by: zhaonan --- changelogs/current.yaml | 3 +++ contrib/generic_proxy/filters/network/source/proxy.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 50b21469c601..5494ba2ba005 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -73,6 +73,9 @@ minor_behavior_changes: - area: admin change: | Switch no admin ``warning`` -> ``info``. +- area: generic_proxy + change: | + Update the stats prefix of generic proxy from ```` to ``generic_proxy.``. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* diff --git a/contrib/generic_proxy/filters/network/source/proxy.h b/contrib/generic_proxy/filters/network/source/proxy.h index 6136065b7df0..3dc1eeb77db4 100644 --- a/contrib/generic_proxy/filters/network/source/proxy.h +++ b/contrib/generic_proxy/filters/network/source/proxy.h @@ -57,7 +57,7 @@ class FilterConfigImpl : public FilterConfig { Tracing::ConnectionManagerTracingConfigPtr tracing_config, std::vector&& access_logs, Envoy::Server::Configuration::FactoryContext& context) - : stat_prefix_(stat_prefix), + : stat_prefix_(fmt::format("generic_proxy.{}.", stat_prefix)), stats_(GenericFilterStats::generateStats(stat_prefix_, context.scope())), codec_factory_(std::move(codec)), route_config_provider_(std::move(route_config_provider)), factories_(std::move(factories)), drain_decision_(context.drainDecision()), From 6273573560def8329a32584016b6884c7924dc5c Mon Sep 17 00:00:00 2001 From: Ryan Hamilton Date: Thu, 21 Dec 2023 00:55:47 -0800 Subject: [PATCH 038/126] deps: Bump build images/toolchains -> fd9ec00/157af2c (#31474) * deps: Bump `envoy_build_tools` -> 157af2c * deps: Bump build images -> `fd9ec00` * Fix code that offended gcc-11 Signed-off-by: Ryan Hamilton Signed-off-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> Signed-off-by: Ryan Northey Co-authored-by: dependency-envoy[bot] <148525496+dependency-envoy[bot]@users.noreply.github.com> --- .bazelrc | 4 ++-- .devcontainer/Dockerfile | 2 +- .github/config.yml | 8 ++++---- bazel/repository_locations.bzl | 6 +++--- examples/shared/build/Dockerfile | 2 +- mobile/third_party/rbe_configs/config/BUILD | 4 ++-- test/common/quic/envoy_quic_client_stream_test.cc | 2 +- test/common/quic/envoy_quic_utils_test.cc | 2 +- test/common/router/config_impl_test.cc | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.bazelrc b/.bazelrc index a5b1ab886dba..dedce6437731 100644 --- a/.bazelrc +++ b/.bazelrc @@ -357,7 +357,7 @@ build:compile-time-options --@envoy//source/extensions/filters/http/kill_request # Docker sandbox # NOTE: Update this from https://github.com/envoyproxy/envoy-build-tools/blob/main/toolchains/rbe_toolchains_config.bzl#L8 -build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 +build:docker-sandbox --experimental_docker_image=envoyproxy/envoy-build-ubuntu:fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:1386a26f687826850ba488d66a6cd5337c5941b3b8793d08cfa6f9df12aa2fcf build:docker-sandbox --spawn_strategy=docker build:docker-sandbox --strategy=Javac=docker build:docker-sandbox --strategy=Closure=docker @@ -518,7 +518,7 @@ build:rbe-envoy-engflow --grpc_keepalive_time=30s build:rbe-envoy-engflow --remote_timeout=3600s build:rbe-envoy-engflow --bes_timeout=3600s build:rbe-envoy-engflow --bes_upload_mode=fully_async -build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 +build:rbe-envoy-engflow --remote_default_exec_properties=container-image=docker://docker.io/envoyproxy/envoy-build-ubuntu:fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:1386a26f687826850ba488d66a6cd5337c5941b3b8793d08cfa6f9df12aa2fcf ############################################################################# # debug: Various Bazel debugging flags diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 62ba4e83d738..cdf3e9815ce9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM gcr.io/envoy-ci/envoy-build:7467652575122d8d54e767a68f141598bd855383@sha256:af98298b715958527d3c3b42ae968a09223d237c843e129c586b7e76b8c69a0d +FROM gcr.io/envoy-ci/envoy-build:fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:b0c0e07c97337fdd56423ddd6749a4250adaea9f66f85763a8d9cec36162c972 ARG USERNAME=vscode ARG USER_UID=501 diff --git a/.github/config.yml b/.github/config.yml index c7d767ec5f2e..b7b51adaad95 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -2,11 +2,11 @@ agent-ubuntu: ubuntu-22.04 build-image: # Authoritative configuration for build image/s repo: envoyproxy/envoy-build-ubuntu - sha: 8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 - mobile-sha: 292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f + sha: 1386a26f687826850ba488d66a6cd5337c5941b3b8793d08cfa6f9df12aa2fcf + mobile-sha: 1db9bac6578115179fe686cd0e58ee340e2cb3737d19d9136a264d5d94351961 # this is authoritative, but is not currently used in github ci - gcr-sha: af98298b715958527d3c3b42ae968a09223d237c843e129c586b7e76b8c69a0d - tag: 7467652575122d8d54e767a68f141598bd855383 + gcr-sha: b0c0e07c97337fdd56423ddd6749a4250adaea9f66f85763a8d9cec36162c972 + tag: fd9ec000fdd72d5c5e4e4ef16db4f9103058779e config: envoy: diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 7c4d5ca49dfb..7f6213b0820b 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -102,11 +102,11 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "envoy-build-tools", project_desc = "Common build tools shared by the Envoy/UDPA ecosystem", project_url = "https://github.com/envoyproxy/envoy-build-tools", - version = "f727ec142156c8076384a35c0e2d51da3c1d7813", - sha256 = "72510592f34f3fd6269c5fdd2286465a05ce6ca438ac1faebfdb88ed309fe9da", + version = "157af2cabe71d054d4b9837a66f8458cb7bee2f0", + sha256 = "ab284f8b15f2b590d6fa3140d1f93d3fb96fbbea5ea0dfa01f48eb6d61d1c96b", strip_prefix = "envoy-build-tools-{version}", urls = ["https://github.com/envoyproxy/envoy-build-tools/archive/{version}.tar.gz"], - release_date = "2023-10-16", + release_date = "2023-12-20", use_category = ["build"], license = "Apache-2.0", license_url = "https://github.com/envoyproxy/envoy-build-tools/blob/{version}/LICENSE", diff --git a/examples/shared/build/Dockerfile b/examples/shared/build/Dockerfile index 7c2b63fe5b1f..cd8a748a4384 100644 --- a/examples/shared/build/Dockerfile +++ b/examples/shared/build/Dockerfile @@ -1,4 +1,4 @@ -FROM envoyproxy/envoy-build-ubuntu:7467652575122d8d54e767a68f141598bd855383@sha256:8781bc7e431b754c142edbfc937905fdf343db91f3fe19bbf54c362828db9849 +FROM envoyproxy/envoy-build-ubuntu:fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:1386a26f687826850ba488d66a6cd5337c5941b3b8793d08cfa6f9df12aa2fcf ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ diff --git a/mobile/third_party/rbe_configs/config/BUILD b/mobile/third_party/rbe_configs/config/BUILD index df1b76d803e9..be86c7f0724e 100644 --- a/mobile/third_party/rbe_configs/config/BUILD +++ b/mobile/third_party/rbe_configs/config/BUILD @@ -42,7 +42,7 @@ platform( "@bazel_tools//tools/cpp:clang", ], exec_properties = { - "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-7467652575122d8d54e767a68f141598bd855383@sha256:292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f", + "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:1db9bac6578115179fe686cd0e58ee340e2cb3737d19d9136a264d5d94351961", "OSFamily": "Linux", "Pool": "linux", }, @@ -57,7 +57,7 @@ platform( "@bazel_tools//tools/cpp:clang", ], exec_properties = { - "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-7467652575122d8d54e767a68f141598bd855383@sha256:292273a428ebb093cc69c2f225c7c4218ff2ea84e0cb6ee80e7a6771a09e026f", + "container-image": "docker://envoyproxy/envoy-build-ubuntu:mobile-fd9ec000fdd72d5c5e4e4ef16db4f9103058779e@sha256:1db9bac6578115179fe686cd0e58ee340e2cb3737d19d9136a264d5d94351961", "OSFamily": "Linux", "Pool": "linux", # Necessary to workaround https://github.com/google/sanitizers/issues/916, otherwise, dangling threads in the diff --git a/test/common/quic/envoy_quic_client_stream_test.cc b/test/common/quic/envoy_quic_client_stream_test.cc index 996e621ec42c..076216ae100e 100644 --- a/test/common/quic/envoy_quic_client_stream_test.cc +++ b/test/common/quic/envoy_quic_client_stream_test.cc @@ -349,7 +349,7 @@ TEST_F(EnvoyQuicClientStreamTest, PostRequestAnd1xx) { size_t i = 0; // Receive several 10x headers, only the first 100 Continue header should be // delivered. - for (const std::string& status : {"100", "199", "100"}) { + for (const std::string status : {"100", "199", "100"}) { spdy::Http2HeaderBlock continue_header; continue_header[":status"] = status; continue_header["i"] = absl::StrCat("", i++); diff --git a/test/common/quic/envoy_quic_utils_test.cc b/test/common/quic/envoy_quic_utils_test.cc index de24bbec1de6..6950b09777a6 100644 --- a/test/common/quic/envoy_quic_utils_test.cc +++ b/test/common/quic/envoy_quic_utils_test.cc @@ -24,7 +24,7 @@ TEST(EnvoyQuicUtilsTest, ConversionBetweenQuicAddressAndEnvoyAddress) { quic::QuicSocketAddress quic_uninitialized_addr; EXPECT_EQ(nullptr, quicAddressToEnvoyAddressInstance(quic_uninitialized_addr)); - for (const std::string& ip_str : {"fd00:0:0:1::1", "1.2.3.4"}) { + for (const std::string ip_str : {"fd00:0:0:1::1", "1.2.3.4"}) { quic::QuicIpAddress quic_ip; quic_ip.FromString(ip_str); quic::QuicSocketAddress quic_addr(quic_ip, 12345); diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index 7cb9fed96e0c..810481e02f17 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -2204,7 +2204,7 @@ most_specific_header_mutations_wins: true // Validate that we can't add :-prefixed or Host request headers. TEST_F(RouteMatcherTest, TestRequestHeadersToAddNoHostOrPseudoHeader) { - for (const std::string& header : + for (const std::string header : {":path", ":authority", ":method", ":scheme", ":status", ":protocol", "host"}) { const std::string yaml = fmt::format(R"EOF( virtual_hosts: @@ -2230,7 +2230,7 @@ TEST_F(RouteMatcherTest, TestRequestHeadersToAddNoHostOrPseudoHeader) { // Validate that we can't remove :-prefixed request headers. TEST_F(RouteMatcherTest, TestRequestHeadersToRemoveNoPseudoHeader) { - for (const std::string& header : + for (const std::string header : {":path", ":authority", ":method", ":scheme", ":status", ":protocol", "host"}) { const std::string yaml = fmt::format(R"EOF( virtual_hosts: From 072c4f0ff342bb697a80ca7676eae78d9c92bf88 Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Thu, 21 Dec 2023 22:50:14 +0800 Subject: [PATCH 039/126] Golang filter: SendLocalReply support multiple header values for a header name (#31392) * Golang filter: SendLocalReply support multiple header values for a header name Signed-off-by: Michael Sauter Signed-off-by: doujiang24 --- contrib/golang/common/go/api/capi.go | 2 +- contrib/golang/common/go/api/filter.go | 2 +- contrib/golang/filters/http/source/cgo.cc | 2 +- .../filters/http/source/go/pkg/http/capi_impl.go | 12 +++++++----- .../golang/filters/http/source/go/pkg/http/filter.go | 2 +- .../filters/http/test/golang_integration_test.cc | 9 +++++++++ .../filters/http/test/test_data/basic/filter.go | 7 ++++--- 7 files changed, 24 insertions(+), 12 deletions(-) diff --git a/contrib/golang/common/go/api/capi.go b/contrib/golang/common/go/api/capi.go index c8c83fcb8bec..2ff034c7f510 100644 --- a/contrib/golang/common/go/api/capi.go +++ b/contrib/golang/common/go/api/capi.go @@ -21,7 +21,7 @@ import "unsafe" type HttpCAPI interface { HttpContinue(r unsafe.Pointer, status uint64) - HttpSendLocalReply(r unsafe.Pointer, responseCode int, bodyText string, headers map[string]string, grpcStatus int64, details string) + HttpSendLocalReply(r unsafe.Pointer, responseCode int, bodyText string, headers map[string][]string, grpcStatus int64, details string) // Send a specialized reply that indicates that the filter has failed on the go side. Internally this is used for // when unhandled panics are detected. diff --git a/contrib/golang/common/go/api/filter.go b/contrib/golang/common/go/api/filter.go index a6e4fc7f9dcc..20e913cbb8ac 100644 --- a/contrib/golang/common/go/api/filter.go +++ b/contrib/golang/common/go/api/filter.go @@ -152,7 +152,7 @@ type FilterCallbacks interface { StreamFilterCallbacks // Continue or SendLocalReply should be last API invoked, no more code after them. Continue(StatusType) - SendLocalReply(responseCode int, bodyText string, headers map[string]string, grpcStatus int64, details string) + SendLocalReply(responseCode int, bodyText string, headers map[string][]string, grpcStatus int64, details string) // RecoverPanic recover panic in defer and terminate the request by SendLocalReply with 500 status code. RecoverPanic() Log(level LogType, msg string) diff --git a/contrib/golang/filters/http/source/cgo.cc b/contrib/golang/filters/http/source/cgo.cc index f48803526093..5cd8e047ba43 100644 --- a/contrib/golang/filters/http/source/cgo.cc +++ b/contrib/golang/filters/http/source/cgo.cc @@ -92,7 +92,7 @@ CAPIStatus envoyGoFilterHttpSendLocalReply(void* r, int response_code, void* bod const auto& key = header_values[i]; const auto& value = header_values[i + 1]; if (value.length() > 0) { - headers.setCopy(Http::LowerCaseString(key), value); + headers.addCopy(Http::LowerCaseString(key), value); } } }; diff --git a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go index a02c2e5d796d..a195c3b26162 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go +++ b/contrib/golang/filters/http/source/go/pkg/http/capi_impl.go @@ -118,7 +118,7 @@ func (c *httpCApiImpl) HttpContinue(r unsafe.Pointer, status uint64) { // Only may panic with errRequestFinished, errFilterDestroyed or errNotInGo, // won't panic with errInvalidPhase and others, otherwise will cause deadloop, see RecoverPanic for the details. -func (c *httpCApiImpl) HttpSendLocalReply(r unsafe.Pointer, responseCode int, bodyText string, headers map[string]string, grpcStatus int64, details string) { +func (c *httpCApiImpl) HttpSendLocalReply(r unsafe.Pointer, responseCode int, bodyText string, headers map[string][]string, grpcStatus int64, details string) { hLen := len(headers) strs := make([]*C.char, 0, hLen*2) defer func() { @@ -127,10 +127,12 @@ func (c *httpCApiImpl) HttpSendLocalReply(r unsafe.Pointer, responseCode int, bo } }() // TODO: use runtime.Pinner after go1.22 release for better performance. - for k, v := range headers { - keyStr := C.CString(k) - valueStr := C.CString(v) - strs = append(strs, keyStr, valueStr) + for k, h := range headers { + for _, v := range h { + keyStr := C.CString(k) + valueStr := C.CString(v) + strs = append(strs, keyStr, valueStr) + } } res := C.envoyGoFilterHttpSendLocalReply(r, C.int(responseCode), unsafe.Pointer(unsafe.StringData(bodyText)), C.int(len(bodyText)), diff --git a/contrib/golang/filters/http/source/go/pkg/http/filter.go b/contrib/golang/filters/http/source/go/pkg/http/filter.go index e33f099f2469..c9b1d3424c75 100644 --- a/contrib/golang/filters/http/source/go/pkg/http/filter.go +++ b/contrib/golang/filters/http/source/go/pkg/http/filter.go @@ -114,7 +114,7 @@ func (r *httpRequest) Continue(status api.StatusType) { cAPI.HttpContinue(unsafe.Pointer(r.req), uint64(status)) } -func (r *httpRequest) SendLocalReply(responseCode int, bodyText string, headers map[string]string, grpcStatus int64, details string) { +func (r *httpRequest) SendLocalReply(responseCode int, bodyText string, headers map[string][]string, grpcStatus int64, details string) { cAPI.HttpSendLocalReply(unsafe.Pointer(r.req), responseCode, bodyText, headers, grpcStatus, details) } diff --git a/contrib/golang/filters/http/test/golang_integration_test.cc b/contrib/golang/filters/http/test/golang_integration_test.cc index 872f330f418c..56e568caa596 100644 --- a/contrib/golang/filters/http/test/golang_integration_test.cc +++ b/contrib/golang/filters/http/test/golang_integration_test.cc @@ -551,6 +551,15 @@ name: golang // verify content-type EXPECT_EQ("text/html", getHeader(response->headers(), "content-type")); + // verify two values + auto values = response->headers().get(Http::LowerCaseString("x-two-values")); + if (values.size() == 2) { + EXPECT_EQ("foo", values[0]->value().getStringView()); + EXPECT_EQ("bar", values[1]->value().getStringView()); + } else { + EXPECT_EQ(values.size(), 2); + } + cleanup(); } diff --git a/contrib/golang/filters/http/test/test_data/basic/filter.go b/contrib/golang/filters/http/test/test_data/basic/filter.go index 6a9dd725be1e..9990be5b4b77 100644 --- a/contrib/golang/filters/http/test/test_data/basic/filter.go +++ b/contrib/golang/filters/http/test/test_data/basic/filter.go @@ -86,9 +86,10 @@ func (f *filter) fail(msg string, a ...any) api.StatusType { } func (f *filter) sendLocalReply(phase string) api.StatusType { - headers := map[string]string{ - "Content-type": "text/html", - "test-phase": phase, + headers := map[string][]string{ + "Content-type": {"text/html"}, + "test-phase": {phase}, + "x-two-values": {"foo", "bar"}, } body := fmt.Sprintf("forbidden from go in %s\r\n", phase) f.callbacks.SendLocalReply(403, body, headers, 0, "") From 487ad2c1301461fc25c65820f2a17aab793e5ca2 Mon Sep 17 00:00:00 2001 From: Zhewei Hu Date: Thu, 21 Dec 2023 07:11:41 -0800 Subject: [PATCH 040/126] Revert "[ZK filter] Remove EnvoyException on data plane (#30438)" (#31314) This reverts commit 8d15ca7ae14d866e5365b37be824f07ff783f041. Signed-off-by: Zhewei Hu --- .../network/zookeeper_proxy/decoder.cc | 833 ++++++------------ .../filters/network/zookeeper_proxy/decoder.h | 84 +- .../filters/network/zookeeper_proxy/filter.cc | 33 +- .../filters/network/zookeeper_proxy/filter.h | 10 +- .../filters/network/zookeeper_proxy/utils.cc | 44 +- .../filters/network/zookeeper_proxy/utils.h | 37 +- 6 files changed, 331 insertions(+), 710 deletions(-) diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.cc b/source/extensions/filters/network/zookeeper_proxy/decoder.cc index 92367e55063a..968dc798b321 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.cc +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.cc @@ -42,26 +42,15 @@ const char* createFlagsToString(CreateFlags flags) { return "unknown"; } -absl::StatusOr> DecoderImpl::decodeOnData(Buffer::Instance& data, - uint64_t& offset) { +absl::optional DecoderImpl::decodeOnData(Buffer::Instance& data, uint64_t& offset) { ENVOY_LOG(trace, "zookeeper_proxy: decoding request with {} bytes at offset {}", data.length(), offset); // Check message length. - const absl::StatusOr len = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - len, fmt::format("peekInt32 for len: {}", len.status().message())); - - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with len {} at offset {}", len.value(), - offset); - - absl::Status status = ensureMinLength(len.value(), XID_LENGTH + INT_LENGTH); // xid + opcode - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("ensureMinLength: {}", status.message())); - - status = ensureMaxLength(len.value()); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("ensureMaxLength: {}", status.message())); + const int32_t len = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with len {} at offset {}", len, offset); + ensureMinLength(len, XID_LENGTH + INT_LENGTH); // xid + opcode + ensureMaxLength(len); auto start_time = time_source_.monotonicTime(); @@ -75,40 +64,26 @@ absl::StatusOr> DecoderImpl::decodeOnData(Buffer::Instan // ZooKeeper server to the next. Thus, the special xid. // However, some client implementations might expose setWatches // as a regular data request, so we support that as well. - const absl::StatusOr xid = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - xid, fmt::format("peerInt32 for xid: {}", xid.status().message())); - - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with xid {} at offset {}", xid.value(), - offset); - - switch (static_cast(xid.value())) { + const int32_t xid = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with xid {} at offset {}", xid, offset); + switch (static_cast(xid)) { case XidCodes::ConnectXid: - status = parseConnect(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseConnect: {}", status.message())); - - control_requests_by_xid_[xid.value()].push({OpCodes::Connect, std::move(start_time)}); + parseConnect(data, offset, len); + control_requests_by_xid_[xid].push({OpCodes::Connect, std::move(start_time)}); return OpCodes::Connect; case XidCodes::PingXid: offset += OPCODE_LENGTH; callbacks_.onPing(); - control_requests_by_xid_[xid.value()].push({OpCodes::Ping, std::move(start_time)}); + control_requests_by_xid_[xid].push({OpCodes::Ping, std::move(start_time)}); return OpCodes::Ping; case XidCodes::AuthXid: - status = parseAuthRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseAuthRequest: {}", status.message())); - - control_requests_by_xid_[xid.value()].push({OpCodes::SetAuth, std::move(start_time)}); + parseAuthRequest(data, offset, len); + control_requests_by_xid_[xid].push({OpCodes::SetAuth, std::move(start_time)}); return OpCodes::SetAuth; case XidCodes::SetWatchesXid: offset += OPCODE_LENGTH; - status = parseSetWatchesRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseSetWatchesRequest: {}", status.message())); - - control_requests_by_xid_[xid.value()].push({OpCodes::SetWatches, std::move(start_time)}); + parseSetWatchesRequest(data, offset, len); + control_requests_by_xid_[xid].push({OpCodes::SetWatches, std::move(start_time)}); return OpCodes::SetWatches; default: // WATCH_XID is generated by the server, so that and everything @@ -122,164 +97,100 @@ absl::StatusOr> DecoderImpl::decodeOnData(Buffer::Instan // for two cases: auth requests can happen at any time and ping requests // must happen every 1/3 of the negotiated session timeout, to keep // the session alive. - const absl::StatusOr oc = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - oc, fmt::format("peekInt32 for opcode: {}", oc.status().message())); - - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with opcode {} at offset {}", oc.value(), - offset); - - const auto opcode = static_cast(oc.value()); + const int32_t oc = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with opcode {} at offset {}", oc, offset); + const auto opcode = static_cast(oc); switch (opcode) { case OpCodes::GetData: - status = parseGetDataRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseGetDataRequest: {}", status.message())); + parseGetDataRequest(data, offset, len); break; case OpCodes::Create: case OpCodes::Create2: case OpCodes::CreateContainer: case OpCodes::CreateTtl: - status = parseCreateRequest(data, offset, len.value(), static_cast(opcode)); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseCreateRequest: {}", status.message())); + parseCreateRequest(data, offset, len, static_cast(opcode)); break; case OpCodes::SetData: - status = parseSetRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseSetRequest: {}", status.message())); + parseSetRequest(data, offset, len); break; case OpCodes::GetChildren: - status = parseGetChildrenRequest(data, offset, len.value(), false); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseGetChildrenRequest: {}", status.message())); + parseGetChildrenRequest(data, offset, len, false); break; case OpCodes::GetChildren2: - status = parseGetChildrenRequest(data, offset, len.value(), true); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseGetChildrenRequest: {}", status.message())); + parseGetChildrenRequest(data, offset, len, true); break; case OpCodes::Delete: - status = parseDeleteRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseDeleteRequest: {}", status.message())); + parseDeleteRequest(data, offset, len); break; case OpCodes::Exists: - status = parseExistsRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseExistsRequest: {}", status.message())); + parseExistsRequest(data, offset, len); break; case OpCodes::GetAcl: - status = parseGetAclRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseGetAclRequest: {}", status.message())); + parseGetAclRequest(data, offset, len); break; case OpCodes::SetAcl: - status = parseSetAclRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseSetAclRequest: {}", status.message())); + parseSetAclRequest(data, offset, len); break; case OpCodes::Sync: - status = callbacks_.onSyncRequest(pathOnlyRequest(data, offset, len.value())); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("onSyncRequest: {}", status.message())); + callbacks_.onSyncRequest(pathOnlyRequest(data, offset, len)); break; case OpCodes::Check: - status = parseCheckRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseCheckRequest: {}", status.message())); + parseCheckRequest(data, offset, len); break; case OpCodes::Multi: - status = parseMultiRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseMultiRequest: {}", status.message())); + parseMultiRequest(data, offset, len); break; case OpCodes::Reconfig: - status = parseReconfigRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseReconfigRequest: {}", status.message())); + parseReconfigRequest(data, offset, len); break; case OpCodes::SetWatches: - status = parseSetWatchesRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseSetWatchesRequest: {}", status.message())); + parseSetWatchesRequest(data, offset, len); break; case OpCodes::SetWatches2: - status = parseSetWatches2Request(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseSetWatches2Request: {}", status.message())); + parseSetWatches2Request(data, offset, len); break; case OpCodes::AddWatch: - status = parseAddWatchRequest(data, offset, len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseAddWatchRequest: {}", status.message())); + parseAddWatchRequest(data, offset, len); break; case OpCodes::CheckWatches: - status = parseXWatchesRequest(data, offset, len.value(), OpCodes::CheckWatches); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseXWatchesRequest (check watches): {}", status.message())); + parseXWatchesRequest(data, offset, len, OpCodes::CheckWatches); break; case OpCodes::RemoveWatches: - status = parseXWatchesRequest(data, offset, len.value(), OpCodes::RemoveWatches); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseXWatchesRequest (remove watches): {}", status.message())); + parseXWatchesRequest(data, offset, len, OpCodes::RemoveWatches); break; case OpCodes::GetEphemerals: - status = callbacks_.onGetEphemeralsRequest(pathOnlyRequest(data, offset, len.value())); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("onGetEphemeralsRequest: {}", status.message())); + callbacks_.onGetEphemeralsRequest(pathOnlyRequest(data, offset, len)); break; case OpCodes::GetAllChildrenNumber: - status = callbacks_.onGetAllChildrenNumberRequest(pathOnlyRequest(data, offset, len.value())); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("onGetAllChildrenNumberRequest: {}", status.message())); + callbacks_.onGetAllChildrenNumberRequest(pathOnlyRequest(data, offset, len)); break; case OpCodes::Close: callbacks_.onCloseRequest(); break; default: - ENVOY_LOG(debug, "zookeeper_proxy: decodeOnData exception: unknown opcode {}", - enumToSignedInt(opcode)); - callbacks_.onDecodeError(); - return absl::nullopt; + throw EnvoyException(fmt::format("Unknown opcode: {}", enumToSignedInt(opcode))); } - requests_by_xid_[xid.value()] = {opcode, std::move(start_time)}; + requests_by_xid_[xid] = {opcode, std::move(start_time)}; return opcode; } -absl::StatusOr> DecoderImpl::decodeOnWrite(Buffer::Instance& data, - uint64_t& offset) { +absl::optional DecoderImpl::decodeOnWrite(Buffer::Instance& data, uint64_t& offset) { ENVOY_LOG(trace, "zookeeper_proxy: decoding response with {} bytes at offset {}", data.length(), offset); // Check message length. - const absl::StatusOr len = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - len, fmt::format("peekInt32 for len: {}", len.status().message())); - - ENVOY_LOG(trace, "zookeeper_proxy: decoding response with len.value() {} at offset {}", - len.value(), offset); - - absl::Status status = - ensureMinLength(len.value(), XID_LENGTH + ZXID_LENGTH + INT_LENGTH); // xid + zxid + err - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("ensureMinLength: {}", status.message())); - - status = ensureMaxLength(len.value()); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("ensureMaxLength: {}", status.message())); - - const absl::StatusOr xid = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - xid, fmt::format("peekInt32 for xid: {}", xid.status().message())); + const int32_t len = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding response with len {} at offset {}", len, offset); + ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + INT_LENGTH); // xid + zxid + err + ensureMaxLength(len); - ENVOY_LOG(trace, "zookeeper_proxy: decoding response with xid {} at offset {}", xid.value(), - offset); - const auto xid_code = static_cast(xid.value()); + const auto xid = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding response with xid {} at offset {}", xid, offset); + const auto xid_code = static_cast(xid); - absl::StatusOr latency; + std::chrono::milliseconds latency; OpCodes opcode; switch (xid_code) { @@ -290,517 +201,321 @@ absl::StatusOr> DecoderImpl::decodeOnWrite(Buffer::Insta case XidCodes::AuthXid: ABSL_FALLTHROUGH_INTENDED; case XidCodes::SetWatchesXid: - latency = fetchControlRequestData(xid.value(), opcode); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - latency, fmt::format("fetchControlRequestData: {}", latency.status().message())); + latency = fetchControlRequestData(xid, opcode); break; case XidCodes::WatchXid: // WATCH_XID is generated by the server, no need to fetch opcode and latency here. break; default: - latency = fetchDataRequestData(xid.value(), opcode); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - latency, fmt::format("fetchDataRequestData: {}", latency.status().message())); + latency = fetchDataRequestData(xid, opcode); } // Connect responses are special, they have no full reply header // but just an XID with no zxid nor error fields like the ones // available for all other server generated messages. if (xid_code == XidCodes::ConnectXid) { - status = parseConnectResponse(data, offset, len.value(), latency.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, fmt::format("parseConnectResponse: {}", status.message())) + parseConnectResponse(data, offset, len, latency); return opcode; } // Control responses that aren't connect, with XIDs <= 0. - const absl::StatusOr zxid = helper_.peekInt64(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - zxid, fmt::format("peekInt64 for zxid: {}", zxid.status().message())); - - const absl::StatusOr error = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - error, fmt::format("peekInt32 for error: {}", error.status().message())); - - ENVOY_LOG(trace, - "zookeeper_proxy: decoding response with zxid.value() {} and error {} at offset {}", - zxid.value(), error.value(), offset); - + const auto zxid = helper_.peekInt64(data, offset); + const auto error = helper_.peekInt32(data, offset); + ENVOY_LOG(trace, "zookeeper_proxy: decoding response with zxid {} and error {} at offset {}", + zxid, error, offset); switch (xid_code) { case XidCodes::PingXid: - callbacks_.onResponse(OpCodes::Ping, xid.value(), zxid.value(), error.value(), latency.value()); + callbacks_.onResponse(OpCodes::Ping, xid, zxid, error, latency); return opcode; case XidCodes::AuthXid: - callbacks_.onResponse(OpCodes::SetAuth, xid.value(), zxid.value(), error.value(), - latency.value()); + callbacks_.onResponse(OpCodes::SetAuth, xid, zxid, error, latency); return opcode; case XidCodes::SetWatchesXid: - callbacks_.onResponse(OpCodes::SetWatches, xid.value(), zxid.value(), error.value(), - latency.value()); + callbacks_.onResponse(OpCodes::SetWatches, xid, zxid, error, latency); return opcode; case XidCodes::WatchXid: - status = parseWatchEvent(data, offset, len.value(), zxid.value(), error.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, - fmt::format("parseWatchEvent: {}", status.message())); - + parseWatchEvent(data, offset, len, zxid, error); return absl::nullopt; // WATCH_XID is generated by the server, it has no corresponding opcode. default: break; } - callbacks_.onResponse(opcode, xid.value(), zxid.value(), error.value(), latency.value()); - offset += (len.value() - (XID_LENGTH + ZXID_LENGTH + INT_LENGTH)); + callbacks_.onResponse(opcode, xid, zxid, error, latency); + offset += (len - (XID_LENGTH + ZXID_LENGTH + INT_LENGTH)); return opcode; } -absl::Status DecoderImpl::ensureMinLength(const int32_t len, const int32_t minlen) const { +void DecoderImpl::ensureMinLength(const int32_t len, const int32_t minlen) const { if (len < minlen) { - return absl::InvalidArgumentError("packet is too small"); + throw EnvoyException("Packet is too small"); } - return absl::OkStatus(); } -absl::Status DecoderImpl::ensureMaxLength(const int32_t len) const { +void DecoderImpl::ensureMaxLength(const int32_t len) const { if (static_cast(len) > max_packet_bytes_) { - return absl::InvalidArgumentError("packet is too big"); + throw EnvoyException("Packet is too big"); } - return absl::OkStatus(); } -absl::Status DecoderImpl::parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - absl::Status status = - ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); // Skip zxid, timeout, and session id. offset += ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH; // Skip password. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr readonly = maybeReadBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(readonly, - readonly.status().message()); + skipString(data, offset); - callbacks_.onConnect(readonly.value()); + const bool readonly = maybeReadBool(data, offset); - return absl::OkStatus(); + callbacks_.onConnect(readonly); } -absl::Status DecoderImpl::parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - absl::Status status = - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + INT_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + INT_LENGTH + INT_LENGTH); + // Skip opcode + type. offset += OPCODE_LENGTH + INT_LENGTH; - - const absl::StatusOr scheme = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(scheme, scheme.status().message()); - + const std::string scheme = helper_.peekString(data, offset); // Skip credential. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + skipString(data, offset); - callbacks_.onAuthRequest(scheme.value()); - - return absl::OkStatus(); + callbacks_.onAuthRequest(scheme); } -absl::Status DecoderImpl::parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - - const absl::StatusOr watch = helper_.peekBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); +void DecoderImpl::parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - callbacks_.onGetDataRequest(path.value(), watch.value()); + const std::string path = helper_.peekString(data, offset); + const bool watch = helper_.peekBool(data, offset); - return absl::OkStatus(); + callbacks_.onGetDataRequest(path, watch); } -absl::Status DecoderImpl::skipAcls(Buffer::Instance& data, uint64_t& offset) { - const absl::StatusOr count = helper_.peekInt32(data, offset); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(count, - fmt::format("skipAcls: {}", count.status().message())); +void DecoderImpl::skipAcls(Buffer::Instance& data, uint64_t& offset) { + const int32_t count = helper_.peekInt32(data, offset); - for (int i = 0; i < count.value(); ++i) { + for (int i = 0; i < count; ++i) { // Perms. - absl::StatusOr perms = helper_.peekInt32(data, offset); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(perms, - fmt::format("skipAcls: {}", perms.status().message())); + helper_.peekInt32(data, offset); // Skip scheme. - absl::Status status = skipString(data, offset); - ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); + skipString(data, offset); // Skip cred. - status = skipString(data, offset); - ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); + skipString(data, offset); } - - return absl::OkStatus(); } -absl::Status DecoderImpl::parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - OpCodes opcode) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (4 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + OpCodes opcode) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (4 * INT_LENGTH)); - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + const std::string path = helper_.peekString(data, offset); // Skip data. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - status = skipAcls(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - absl::StatusOr flag_data = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(flag_data, - flag_data.status().message()); + skipString(data, offset); + skipAcls(data, offset); - const CreateFlags flags = static_cast(flag_data.value()); - status = callbacks_.onCreateRequest(path.value(), flags, opcode); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - return absl::OkStatus(); + const CreateFlags flags = static_cast(helper_.peekInt32(data, offset)); + callbacks_.onCreateRequest(path, flags, opcode); } -absl::Status DecoderImpl::parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); + const std::string path = helper_.peekString(data, offset); // Skip data. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipString(data, offset); // Ignore version. - absl::StatusOr version = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); + helper_.peekInt32(data, offset); - callbacks_.onSetRequest(path.value()); - - return absl::OkStatus(); + callbacks_.onSetRequest(path); } -absl::Status DecoderImpl::parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len, const bool two) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - - const absl::StatusOr watch = helper_.peekBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); +void DecoderImpl::parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + const bool two) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - callbacks_.onGetChildrenRequest(path.value(), watch.value(), two); + const std::string path = helper_.peekString(data, offset); + const bool watch = helper_.peekBool(data, offset); - return absl::OkStatus(); + callbacks_.onGetChildrenRequest(path, watch, two); } -absl::Status DecoderImpl::parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + const std::string path = helper_.peekString(data, offset); + const int32_t version = helper_.peekInt32(data, offset); - const absl::StatusOr version = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); - - callbacks_.onDeleteRequest(path.value(), version.value()); - - return absl::OkStatus(); + callbacks_.onDeleteRequest(path, version); } -absl::Status DecoderImpl::parseExistsRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); - const absl::StatusOr watch = helper_.peekBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); + const std::string path = helper_.peekString(data, offset); + const bool watch = helper_.peekBool(data, offset); - callbacks_.onExistsRequest(path.value(), watch.value()); - - return absl::OkStatus(); + callbacks_.onExistsRequest(path, watch); } -absl::Status DecoderImpl::parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); - callbacks_.onGetAclRequest(path.value()); + const std::string path = helper_.peekString(data, offset); - return absl::OkStatus(); + callbacks_.onGetAclRequest(path); } -absl::Status DecoderImpl::parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - - status = skipAcls(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr version = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); +void DecoderImpl::parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - callbacks_.onSetAclRequest(path.value(), version.value()); + const std::string path = helper_.peekString(data, offset); + skipAcls(data, offset); + const int32_t version = helper_.peekInt32(data, offset); - return absl::OkStatus(); + callbacks_.onSetAclRequest(path, version); } -absl::StatusOr DecoderImpl::pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - status, - fmt::format("zookeeper_proxy: path only request decoding exception {}", status.message())); - +std::string DecoderImpl::pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); return helper_.peekString(data, offset); } -absl::Status DecoderImpl::parseCheckRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - - const absl::StatusOr version = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); +void DecoderImpl::parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - callbacks_.onCheckRequest(path.value(), version.value()); + const std::string path = helper_.peekString(data, offset); + const int32_t version = helper_.peekInt32(data, offset); - return absl::OkStatus(); + callbacks_.onCheckRequest(path, version); } -absl::Status DecoderImpl::parseMultiRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { +void DecoderImpl::parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { // Treat empty transactions as a decoding error, there should be at least 1 header. - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + MULTI_HEADER_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + MULTI_HEADER_LENGTH); while (true) { - const absl::StatusOr opcode = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(opcode, opcode.status().message()); - - const absl::StatusOr done = helper_.peekBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(done, done.status().message()); - + const int32_t opcode = helper_.peekInt32(data, offset); + const bool done = helper_.peekBool(data, offset); // Ignore error field. - const absl::StatusOr error = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(error, error.status().message()); + helper_.peekInt32(data, offset); - if (done.value()) { + if (done) { break; } - switch (static_cast(opcode.value())) { + switch (static_cast(opcode)) { case OpCodes::Create: - status = parseCreateRequest(data, offset, len, OpCodes::Create); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + parseCreateRequest(data, offset, len, OpCodes::Create); break; case OpCodes::SetData: - status = parseSetRequest(data, offset, len); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + parseSetRequest(data, offset, len); break; case OpCodes::Check: - status = parseCheckRequest(data, offset, len); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + parseCheckRequest(data, offset, len); break; case OpCodes::Delete: - status = parseDeleteRequest(data, offset, len); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + parseDeleteRequest(data, offset, len); break; default: - callbacks_.onDecodeError(); - return absl::InvalidArgumentError( - fmt::format("unknown opcode within a transaction: {}", opcode.value())); + throw EnvoyException(fmt::format("Unknown opcode within a transaction: {}", opcode)); } } callbacks_.onMultiRequest(); - - return absl::OkStatus(); } -absl::Status DecoderImpl::parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH) + LONG_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH) + LONG_LENGTH); // Skip joining. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipString(data, offset); // Skip leaving. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + skipString(data, offset); // Skip new members. - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipString(data, offset); // Read config id. - absl::StatusOr config_id = helper_.peekInt64(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(config_id, - config_id.status().message()); + helper_.peekInt64(data, offset); callbacks_.onReconfigRequest(); - - return absl::OkStatus(); } -absl::Status DecoderImpl::parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (3 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (3 * INT_LENGTH)); // Ignore relative Zxid. - absl::StatusOr zxid = helper_.peekInt64(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(zxid, zxid.status().message()); - + helper_.peekInt64(data, offset); // Data watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Exist watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Child watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + skipStrings(data, offset); callbacks_.onSetWatchesRequest(); - - return absl::OkStatus(); } -absl::Status DecoderImpl::parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (5 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (5 * INT_LENGTH)); // Ignore relative Zxid. - absl::StatusOr zxid = helper_.peekInt64(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(zxid, zxid.status().message()); - + helper_.peekInt64(data, offset); // Data watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Exist watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Child watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Persistent watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - + skipStrings(data, offset); // Persistent recursive watches. - status = skipStrings(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + skipStrings(data, offset); callbacks_.onSetWatches2Request(); - - return absl::OkStatus(); } -absl::Status DecoderImpl::parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - const absl::StatusOr mode = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(mode, mode.status().message()); + const std::string path = helper_.peekString(data, offset); + const int32_t mode = helper_.peekInt32(data, offset); - callbacks_.onAddWatchRequest(path.value(), mode.value()); - - return absl::OkStatus(); + callbacks_.onAddWatchRequest(path, mode); } -absl::Status DecoderImpl::parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len, OpCodes opcode) { - absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + OpCodes opcode) { + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); - const absl::StatusOr watch_type = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch_type, - watch_type.status().message()); + const std::string path = helper_.peekString(data, offset); + const int32_t type = helper_.peekInt32(data, offset); if (opcode == OpCodes::CheckWatches) { - callbacks_.onCheckWatchesRequest(path.value(), watch_type.value()); + callbacks_.onCheckWatchesRequest(path, type); } else { - callbacks_.onRemoveWatchesRequest(path.value(), watch_type.value()); + callbacks_.onRemoveWatchesRequest(path, type); } - - return absl::OkStatus(); } -absl::Status DecoderImpl::skipString(Buffer::Instance& data, uint64_t& offset) { - const absl::StatusOr slen = helper_.peekInt32(data, offset); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(slen, - fmt::format("skipString: {}", slen.status().message())); - - if (slen.value() < 0) { +void DecoderImpl::skipString(Buffer::Instance& data, uint64_t& offset) { + const int32_t slen = helper_.peekInt32(data, offset); + if (slen < 0) { ENVOY_LOG(trace, "zookeeper_proxy: decoding response with negative string length {} at offset {}", - slen.value(), offset); - return absl::OkStatus(); + slen, offset); + return; } - - helper_.skip(slen.value(), offset); - - return absl::OkStatus(); + helper_.skip(slen, offset); } -absl::Status DecoderImpl::skipStrings(Buffer::Instance& data, uint64_t& offset) { - const absl::StatusOr count = helper_.peekInt32(data, offset); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(count, - fmt::format("skipStrings: {}", count.status().message())); +void DecoderImpl::skipStrings(Buffer::Instance& data, uint64_t& offset) { + const int32_t count = helper_.peekInt32(data, offset); - for (int i = 0; i < count.value(); ++i) { - absl::Status status = skipString(data, offset); - ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); + for (int i = 0; i < count; ++i) { + skipString(data, offset); } - - return absl::OkStatus(); } Network::FilterStatus DecoderImpl::onData(Buffer::Instance& data) { @@ -814,14 +529,9 @@ Network::FilterStatus DecoderImpl::onWrite(Buffer::Instance& data) { Network::FilterStatus DecoderImpl::decodeAndBuffer(Buffer::Instance& data, DecodeType dtype, Buffer::OwnedImpl& zk_filter_buffer) { const uint32_t zk_filter_buffer_len = zk_filter_buffer.length(); - absl::Status status; if (zk_filter_buffer_len == 0) { - status = decodeAndBufferHelper(data, dtype, zk_filter_buffer); - if (!status.ok()) { - ENVOY_LOG(debug, "zookeeper_proxy: decodeAndBufferHelper exception: {}", status.message()); - } - + decodeAndBufferHelper(data, dtype, zk_filter_buffer); return Network::FilterStatus::Continue; } @@ -829,59 +539,52 @@ Network::FilterStatus DecoderImpl::decodeAndBuffer(Buffer::Instance& data, Decod // Prepending ZooKeeper filter buffer to the current network filter buffer can help to generate // full packets. data.prepend(zk_filter_buffer); - - status = decodeAndBufferHelper(data, dtype, zk_filter_buffer); - if (!status.ok()) { - ENVOY_LOG(debug, "zookeeper_proxy: decodeAndBufferHelper exception: {}", status.message()); - } - + decodeAndBufferHelper(data, dtype, zk_filter_buffer); // Drain the prepended ZooKeeper filter buffer. data.drain(zk_filter_buffer_len); return Network::FilterStatus::Continue; } -absl::Status DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, - Buffer::OwnedImpl& zk_filter_buffer) { +void DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, + Buffer::OwnedImpl& zk_filter_buffer) { ASSERT(dtype == DecodeType::READ || dtype == DecodeType::WRITE); const uint32_t data_len = data.length(); uint64_t offset = 0; - absl::StatusOr len = 0; - absl::Status status; + uint32_t len = 0; // Boolean to check whether there is at least one full packet in the network filter buffer (to // which the ZooKeeper filter buffer is prepended). bool has_full_packets = false; while (offset < data_len) { - // Peek packet length. - len = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( - len, fmt::format("peekInt32 for len: {}", len.status().message())); - - status = ensureMinLength(len.value(), dtype == DecodeType::READ - ? XID_LENGTH + INT_LENGTH - : XID_LENGTH + ZXID_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - status = ensureMaxLength(len.value()); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - offset += len.value(); - if (offset <= data_len) { - has_full_packets = true; + TRY_NEEDS_AUDIT { + // Peek packet length. + len = helper_.peekInt32(data, offset); + ensureMinLength(len, dtype == DecodeType::READ ? XID_LENGTH + INT_LENGTH + : XID_LENGTH + ZXID_LENGTH + INT_LENGTH); + ensureMaxLength(len); + offset += len; + if (offset <= data_len) { + has_full_packets = true; + } + } + END_TRY catch (const EnvoyException& e) { + ENVOY_LOG(debug, "zookeeper_proxy: decoding exception {}", e.what()); + callbacks_.onDecodeError(); + return; } } if (offset == data_len) { decode(data, dtype, offset); - return absl::OkStatus(); + return; } ASSERT(offset > data_len); std::string temp_data; if (has_full_packets) { - offset -= INT_LENGTH + len.value(); + offset -= INT_LENGTH + len; ASSERT(offset < data_len); // Decode full packets. // offset here represents the length of all full packets. @@ -898,112 +601,87 @@ absl::Status DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeTy data.copyOut(0, data_len, temp_data.data()); zk_filter_buffer.add(temp_data.data(), temp_data.length()); } - - return absl::OkStatus(); } void DecoderImpl::decode(Buffer::Instance& data, DecodeType dtype, uint64_t full_packets_len) { uint64_t offset = 0; - while (offset < full_packets_len) { - // Reset the helper's cursor, to ensure the current message stays within the - // allowed max length, even when it's different than the declared length - // by the message. - // - // Note: we need to keep two cursors — offset and helper_'s internal one — because - // a buffer may contain multiple messages, so offset is global while helper_'s - // internal cursor gets reset for each individual message. - helper_.reset(); - - const uint64_t current = offset; - absl::StatusOr> opcode; - switch (dtype) { - case DecodeType::READ: - opcode = decodeOnData(data, offset); - if (opcode.ok()) { - callbacks_.onRequestBytes(opcode.value(), offset - current); + TRY_NEEDS_AUDIT { + while (offset < full_packets_len) { + // Reset the helper's cursor, to ensure the current message stays within the + // allowed max length, even when it's different than the declared length + // by the message. + // + // Note: we need to keep two cursors — offset and helper_'s internal one — because + // a buffer may contain multiple messages, so offset is global while helper_'s + // internal cursor gets reset for each individual message. + helper_.reset(); + + const uint64_t current = offset; + absl::optional opcode; + switch (dtype) { + case DecodeType::READ: + opcode = decodeOnData(data, offset); + callbacks_.onRequestBytes(opcode, offset - current); break; - } - ENVOY_LOG(debug, "zookeeper_proxy: decodeOnData exception: {}", opcode.status().message()); - return; - case DecodeType::WRITE: - opcode = decodeOnWrite(data, offset); - if (opcode.ok()) { - callbacks_.onResponseBytes(opcode.value(), offset - current); + case DecodeType::WRITE: + opcode = decodeOnWrite(data, offset); + callbacks_.onResponseBytes(opcode, offset - current); break; } - ENVOY_LOG(debug, "zookeeper_proxy: decodeOnWrite exception: {}", opcode.status().message()); - return; } } + END_TRY catch (const EnvoyException& e) { + ENVOY_LOG(debug, "zookeeper_proxy: decoding exception {}", e.what()); + callbacks_.onDecodeError(); + } } -absl::Status DecoderImpl::parseConnectResponse(Buffer::Instance& data, uint64_t& offset, - uint32_t len, - const std::chrono::milliseconds latency) { - absl::Status status = - ensureMinLength(len, PROTOCOL_VERSION_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); +void DecoderImpl::parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, + const std::chrono::milliseconds latency) { + ensureMinLength(len, PROTOCOL_VERSION_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); - const absl::StatusOr timeout = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(timeout, timeout.status().message()); + const auto timeout = helper_.peekInt32(data, offset); // Skip session id + password. offset += SESSION_LENGTH; - status = skipString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr readonly = maybeReadBool(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(readonly, - readonly.status().message()); + skipString(data, offset); - callbacks_.onConnectResponse(0, timeout.value(), readonly.value(), latency); + const bool readonly = maybeReadBool(data, offset); - return absl::OkStatus(); + callbacks_.onConnectResponse(0, timeout, readonly, latency); } -absl::Status DecoderImpl::parseWatchEvent(Buffer::Instance& data, uint64_t& offset, - const uint32_t len, const int64_t zxid, - const int32_t error) { - absl::Status status = ensureMinLength(len, SERVER_HEADER_LENGTH + (3 * INT_LENGTH)); - EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - - const absl::StatusOr event_type = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(event_type, - event_type.status().message()); - - const absl::StatusOr client_state = helper_.peekInt32(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(client_state, - client_state.status().message()); - - const absl::StatusOr path = helper_.peekString(data, offset); - EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); +void DecoderImpl::parseWatchEvent(Buffer::Instance& data, uint64_t& offset, const uint32_t len, + const int64_t zxid, const int32_t error) { + ensureMinLength(len, SERVER_HEADER_LENGTH + (3 * INT_LENGTH)); - callbacks_.onWatchEvent(event_type.value(), client_state.value(), path.value(), zxid, error); + const auto event_type = helper_.peekInt32(data, offset); + const auto client_state = helper_.peekInt32(data, offset); + const auto path = helper_.peekString(data, offset); - return absl::OkStatus(); + callbacks_.onWatchEvent(event_type, client_state, path, zxid, error); } -absl::StatusOr DecoderImpl::maybeReadBool(Buffer::Instance& data, uint64_t& offset) { +bool DecoderImpl::maybeReadBool(Buffer::Instance& data, uint64_t& offset) { if (data.length() >= offset + 1) { return helper_.peekBool(data, offset); } return false; } -absl::StatusOr DecoderImpl::fetchControlRequestData(const int32_t xid, - OpCodes& opcode) { +std::chrono::milliseconds DecoderImpl::fetchControlRequestData(const int32_t xid, OpCodes& opcode) { // Find the corresponding request queue for this XID. const auto it = control_requests_by_xid_.find(xid); // If this fails, it's either a server-side bug or a malformed packet. if (it == control_requests_by_xid_.end()) { - return absl::InvalidArgumentError(fmt::format("control request xid {} not found", xid)); + throw EnvoyException(fmt::format("control request xid {} not found", xid)); } std::queue& rq_queue = it->second; if (rq_queue.empty()) { - return absl::InvalidArgumentError(fmt::format("control request queue for {} is empty", xid)); + throw EnvoyException(fmt::format("control request queue for {} is empty", xid)); } std::chrono::milliseconds latency = std::chrono::duration_cast( @@ -1014,14 +692,13 @@ absl::StatusOr DecoderImpl::fetchControlRequestData(c return latency; } -absl::StatusOr DecoderImpl::fetchDataRequestData(const int32_t xid, - OpCodes& opcode) { +std::chrono::milliseconds DecoderImpl::fetchDataRequestData(const int32_t xid, OpCodes& opcode) { // Find the corresponding request for this XID. const auto it = requests_by_xid_.find(xid); // If this fails, it's either a server-side bug or a malformed packet. if (it == requests_by_xid_.end()) { - return absl::InvalidArgumentError(fmt::format("data request xid {} not found", xid)); + throw EnvoyException(fmt::format("xid {} not found", xid)); } std::chrono::milliseconds latency = std::chrono::duration_cast( diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.h b/source/extensions/filters/network/zookeeper_proxy/decoder.h index 8718a8d9d6b1..34ad9b4d32ff 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.h +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.h @@ -12,7 +12,6 @@ #include "source/extensions/filters/network/zookeeper_proxy/utils.h" #include "absl/container/node_hash_map.h" -#include "absl/status/statusor.h" namespace Envoy { namespace Extensions { @@ -86,17 +85,16 @@ class DecoderCallbacks { virtual void onPing() PURE; virtual void onAuthRequest(const std::string& scheme) PURE; virtual void onGetDataRequest(const std::string& path, bool watch) PURE; - virtual absl::Status onCreateRequest(const std::string& path, CreateFlags flags, - OpCodes opcode) PURE; + virtual void onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) PURE; virtual void onSetRequest(const std::string& path) PURE; virtual void onGetChildrenRequest(const std::string& path, bool watch, bool v2) PURE; - virtual absl::Status onGetEphemeralsRequest(const absl::StatusOr& path) PURE; - virtual absl::Status onGetAllChildrenNumberRequest(const absl::StatusOr& path) PURE; + virtual void onGetEphemeralsRequest(const std::string& path) PURE; + virtual void onGetAllChildrenNumberRequest(const std::string& path) PURE; virtual void onDeleteRequest(const std::string& path, int32_t version) PURE; virtual void onExistsRequest(const std::string& path, bool watch) PURE; virtual void onGetAclRequest(const std::string& path) PURE; virtual void onSetAclRequest(const std::string& path, int32_t version) PURE; - virtual absl::Status onSyncRequest(const absl::StatusOr& path) PURE; + virtual void onSyncRequest(const std::string& path) PURE; virtual void onCheckRequest(const std::string& path, int32_t version) PURE; virtual void onMultiRequest() PURE; virtual void onReconfigRequest() PURE; @@ -153,50 +151,44 @@ class DecoderImpl : public Decoder, Logger::Loggable { // (4) removes the prepended data. Network::FilterStatus decodeAndBuffer(Buffer::Instance& data, DecodeType dtype, Buffer::OwnedImpl& zk_filter_buffer); - absl::Status decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, - Buffer::OwnedImpl& zk_filter_buffer); + void decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, + Buffer::OwnedImpl& zk_filter_buffer); void decode(Buffer::Instance& data, DecodeType dtype, uint64_t full_packets_len); // decodeOnData and decodeOnWrite return ZooKeeper opcode or absl::nullopt. // absl::nullopt indicates WATCH_XID, which is generated by the server and has no corresponding // opcode. - absl::StatusOr> decodeOnData(Buffer::Instance& data, uint64_t& offset); - absl::StatusOr> decodeOnWrite(Buffer::Instance& data, uint64_t& offset); - absl::Status parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - OpCodes opcode); - absl::Status skipAcls(Buffer::Instance& data, uint64_t& offset); - absl::Status parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - bool two); - absl::Status parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - absl::Status parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - OpCodes opcode); - absl::Status skipString(Buffer::Instance& data, uint64_t& offset); - absl::Status skipStrings(Buffer::Instance& data, uint64_t& offset); - absl::Status ensureMinLength(int32_t len, int32_t minlen) const; - absl::Status ensureMaxLength(int32_t len) const; - absl::StatusOr pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, - uint32_t len); - absl::Status parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const std::chrono::milliseconds latency); - absl::Status parseWatchEvent(Buffer::Instance& data, uint64_t& offset, uint32_t len, int64_t zxid, - int32_t error); - absl::StatusOr maybeReadBool(Buffer::Instance& data, uint64_t& offset); - absl::StatusOr fetchControlRequestData(const int32_t xid, - OpCodes& opcode); - absl::StatusOr fetchDataRequestData(const int32_t xid, - OpCodes& opcode); + absl::optional decodeOnData(Buffer::Instance& data, uint64_t& offset); + absl::optional decodeOnWrite(Buffer::Instance& data, uint64_t& offset); + void parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, OpCodes opcode); + void skipAcls(Buffer::Instance& data, uint64_t& offset); + void parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, bool two); + void parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, OpCodes opcode); + void skipString(Buffer::Instance& data, uint64_t& offset); + void skipStrings(Buffer::Instance& data, uint64_t& offset); + void ensureMinLength(int32_t len, int32_t minlen) const; + void ensureMaxLength(int32_t len) const; + std::string pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + void parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, + const std::chrono::milliseconds latency); + void parseWatchEvent(Buffer::Instance& data, uint64_t& offset, uint32_t len, int64_t zxid, + int32_t error); + bool maybeReadBool(Buffer::Instance& data, uint64_t& offset); + std::chrono::milliseconds fetchControlRequestData(const int32_t xid, OpCodes& opcode); + std::chrono::milliseconds fetchDataRequestData(const int32_t xid, OpCodes& opcode); DecoderCallbacks& callbacks_; const uint32_t max_packet_bytes_; diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.cc b/source/extensions/filters/network/zookeeper_proxy/filter.cc index 817fa14077d4..013bea03b1e0 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.cc +++ b/source/extensions/filters/network/zookeeper_proxy/filter.cc @@ -293,8 +293,8 @@ void ZooKeeperFilter::onGetDataRequest(const std::string& path, const bool watch setDynamicMetadata({{"opname", "getdata"}, {"path", path}, {"watch", watch ? "true" : "false"}}); } -absl::Status ZooKeeperFilter::onCreateRequest(const std::string& path, const CreateFlags flags, - const OpCodes opcode) { +void ZooKeeperFilter::onCreateRequest(const std::string& path, const CreateFlags flags, + const OpCodes opcode) { std::string opname; switch (opcode) { @@ -315,14 +315,12 @@ absl::Status ZooKeeperFilter::onCreateRequest(const std::string& path, const Cre config_->stats_.createttl_rq_.inc(); break; default: - return absl::InvalidArgumentError(fmt::format("unknown opcode: {}", enumToSignedInt(opcode))); + throw EnvoyException(fmt::format("Unknown opcode: {}", enumToSignedInt(opcode))); break; } setDynamicMetadata( {{"opname", opname}, {"path", path}, {"create_type", createFlagsToString(flags)}}); - - return absl::OkStatus(); } void ZooKeeperFilter::onSetRequest(const std::string& path) { @@ -364,13 +362,9 @@ void ZooKeeperFilter::onSetAclRequest(const std::string& path, const int32_t ver setDynamicMetadata({{"opname", "setacl"}, {"path", path}, {"version", std::to_string(version)}}); } -absl::Status ZooKeeperFilter::onSyncRequest(const absl::StatusOr& path) { - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - +void ZooKeeperFilter::onSyncRequest(const std::string& path) { config_->stats_.sync_rq_.inc(); - setDynamicMetadata({{"opname", "sync"}, {"path", path.value()}}); - - return absl::OkStatus(); + setDynamicMetadata({{"opname", "sync"}, {"path", path}}); } void ZooKeeperFilter::onCheckRequest(const std::string&, const int32_t) { @@ -412,23 +406,14 @@ void ZooKeeperFilter::onAddWatchRequest(const std::string& path, const int32_t m setDynamicMetadata({{"opname", "addwatch"}, {"path", path}, {"mode", std::to_string(mode)}}); } -absl::Status ZooKeeperFilter::onGetEphemeralsRequest(const absl::StatusOr& path) { - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - +void ZooKeeperFilter::onGetEphemeralsRequest(const std::string& path) { config_->stats_.getephemerals_rq_.inc(); - setDynamicMetadata({{"opname", "getephemerals"}, {"path", path.value()}}); - - return absl::OkStatus(); + setDynamicMetadata({{"opname", "getephemerals"}, {"path", path}}); } -absl::Status -ZooKeeperFilter::onGetAllChildrenNumberRequest(const absl::StatusOr& path) { - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - +void ZooKeeperFilter::onGetAllChildrenNumberRequest(const std::string& path) { config_->stats_.getallchildrennumber_rq_.inc(); - setDynamicMetadata({{"opname", "getallchildrennumber"}, {"path", path.value()}}); - - return absl::OkStatus(); + setDynamicMetadata({{"opname", "getallchildrennumber"}, {"path", path}}); } void ZooKeeperFilter::onCloseRequest() { diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.h b/source/extensions/filters/network/zookeeper_proxy/filter.h index 94f47506b211..294d8a3119da 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.h +++ b/source/extensions/filters/network/zookeeper_proxy/filter.h @@ -17,8 +17,6 @@ #include "source/common/stats/symbol_table.h" #include "source/extensions/filters/network/zookeeper_proxy/decoder.h" -#include "absl/status/statusor.h" - namespace Envoy { namespace Extensions { namespace NetworkFilters { @@ -342,14 +340,14 @@ class ZooKeeperFilter : public Network::Filter, void onPing() override; void onAuthRequest(const std::string& scheme) override; void onGetDataRequest(const std::string& path, bool watch) override; - absl::Status onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) override; + void onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) override; void onSetRequest(const std::string& path) override; void onGetChildrenRequest(const std::string& path, bool watch, bool v2) override; void onDeleteRequest(const std::string& path, int32_t version) override; void onExistsRequest(const std::string& path, bool watch) override; void onGetAclRequest(const std::string& path) override; void onSetAclRequest(const std::string& path, int32_t version) override; - absl::Status onSyncRequest(const absl::StatusOr& path) override; + void onSyncRequest(const std::string& path) override; void onCheckRequest(const std::string& path, int32_t version) override; void onMultiRequest() override; void onReconfigRequest() override; @@ -358,8 +356,8 @@ class ZooKeeperFilter : public Network::Filter, void onAddWatchRequest(const std::string& path, const int32_t mode) override; void onCheckWatchesRequest(const std::string& path, int32_t type) override; void onRemoveWatchesRequest(const std::string& path, int32_t type) override; - absl::Status onGetEphemeralsRequest(const absl::StatusOr& path) override; - absl::Status onGetAllChildrenNumberRequest(const absl::StatusOr& path) override; + void onGetEphemeralsRequest(const std::string& path) override; + void onGetAllChildrenNumberRequest(const std::string& path) override; void onCloseRequest() override; void onResponseBytes(const absl::optional opcode, const uint64_t bytes) override; void onConnectResponse(int32_t proto_version, int32_t timeout, bool readonly, diff --git a/source/extensions/filters/network/zookeeper_proxy/utils.cc b/source/extensions/filters/network/zookeeper_proxy/utils.cc index b16a6cdc163c..cf1c77a8bf19 100644 --- a/source/extensions/filters/network/zookeeper_proxy/utils.cc +++ b/source/extensions/filters/network/zookeeper_proxy/utils.cc @@ -7,27 +7,24 @@ namespace Extensions { namespace NetworkFilters { namespace ZooKeeperProxy { -absl::StatusOr BufferHelper::peekInt32(Buffer::Instance& buffer, uint64_t& offset) { - absl::Status status = ensureMaxLen(sizeof(int32_t)); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt32: {}", status.message())); +int32_t BufferHelper::peekInt32(Buffer::Instance& buffer, uint64_t& offset) { + ensureMaxLen(sizeof(int32_t)); const int32_t val = buffer.peekBEInt(offset); offset += sizeof(int32_t); return val; } -absl::StatusOr BufferHelper::peekInt64(Buffer::Instance& buffer, uint64_t& offset) { - absl::Status status = ensureMaxLen(sizeof(int64_t)); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt64: {}", status.message())); +int64_t BufferHelper::peekInt64(Buffer::Instance& buffer, uint64_t& offset) { + ensureMaxLen(sizeof(int64_t)); const int64_t val = buffer.peekBEInt(offset); offset += sizeof(int64_t); return val; } -absl::StatusOr BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& offset) { - absl::Status status = ensureMaxLen(1); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekBool: {}", status.message())); +bool BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& offset) { + ensureMaxLen(1); const char byte = buffer.peekInt(offset); const bool val = static_cast(byte); @@ -35,27 +32,24 @@ absl::StatusOr BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& return val; } -absl::StatusOr BufferHelper::peekString(Buffer::Instance& buffer, uint64_t& offset) { +std::string BufferHelper::peekString(Buffer::Instance& buffer, uint64_t& offset) { std::string val; - const absl::StatusOr len = peekInt32(buffer, offset); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(len, - fmt::format("peekString: {}", len.status().message())); + const uint32_t len = peekInt32(buffer, offset); - if (len.value() == 0) { + if (len == 0) { return val; } - if (buffer.length() < (offset + len.value())) { - return absl::InvalidArgumentError("peekString: buffer is smaller than string length"); + if (buffer.length() < (offset + len)) { + throw EnvoyException("peekString: buffer is smaller than string length"); } - absl::Status status = ensureMaxLen(len.value()); - RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekString: {}", status.message())); + ensureMaxLen(len); - std::unique_ptr data(new char[len.value()]); - buffer.copyOut(offset, len.value(), data.get()); - val.assign(data.get(), len.value()); - offset += len.value(); + std::unique_ptr data(new char[len]); + buffer.copyOut(offset, len, data.get()); + val.assign(data.get(), len); + offset += len; return val; } @@ -65,14 +59,12 @@ void BufferHelper::skip(const uint32_t len, uint64_t& offset) { current_ += len; } -absl::Status BufferHelper::ensureMaxLen(const uint32_t size) { +void BufferHelper::ensureMaxLen(const uint32_t size) { current_ += size; if (current_ > max_len_) { - return absl::InvalidArgumentError("read beyond max length"); + throw EnvoyException("read beyond max length"); } - - return absl::OkStatus(); } } // namespace ZooKeeperProxy diff --git a/source/extensions/filters/network/zookeeper_proxy/utils.h b/source/extensions/filters/network/zookeeper_proxy/utils.h index 76b43661dcfb..dc699afaf548 100644 --- a/source/extensions/filters/network/zookeeper_proxy/utils.h +++ b/source/extensions/filters/network/zookeeper_proxy/utils.h @@ -9,8 +9,6 @@ #include "source/common/common/byte_order.h" #include "source/common/common/logger.h" -#include "absl/status/statusor.h" - namespace Envoy { namespace Extensions { namespace NetworkFilters { @@ -19,8 +17,8 @@ namespace ZooKeeperProxy { /** * Helper for extracting ZooKeeper data from a buffer. * - * If at any point a peek is tried beyond max_len, an invalid argument error - * will be returned. This is important to protect Envoy against malformed + * If at any point a peek is tried beyond max_len, an EnvoyException + * will be thrown. This is important to protect Envoy against malformed * requests (e.g.: when the declared and actual length don't match). * * Note: ZooKeeper's protocol uses network byte ordering (big-endian). @@ -29,41 +27,20 @@ class BufferHelper : public Logger::Loggable { public: BufferHelper(uint32_t max_len) : max_len_(max_len) {} - absl::StatusOr peekInt32(Buffer::Instance& buffer, uint64_t& offset); - absl::StatusOr peekInt64(Buffer::Instance& buffer, uint64_t& offset); - absl::StatusOr peekString(Buffer::Instance& buffer, uint64_t& offset); - absl::StatusOr peekBool(Buffer::Instance& buffer, uint64_t& offset); + int32_t peekInt32(Buffer::Instance& buffer, uint64_t& offset); + int64_t peekInt64(Buffer::Instance& buffer, uint64_t& offset); + std::string peekString(Buffer::Instance& buffer, uint64_t& offset); + bool peekBool(Buffer::Instance& buffer, uint64_t& offset); void skip(uint32_t len, uint64_t& offset); void reset() { current_ = 0; } private: - absl::Status ensureMaxLen(uint32_t size); + void ensureMaxLen(uint32_t size); const uint32_t max_len_; uint32_t current_{}; }; -#define ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status) \ - if (!status.ok()) { \ - return status; \ - } - -#define EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status) \ - if (!status.ok()) { \ - callbacks_.onDecodeError(); \ - return status; \ - } - -#define RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, message) \ - if (!status.ok()) { \ - return absl::InvalidArgumentError(message); \ - } - -#define EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, message) \ - if (!status.ok()) { \ - callbacks_.onDecodeError(); \ - return absl::InvalidArgumentError(message); \ - } } // namespace ZooKeeperProxy } // namespace NetworkFilters } // namespace Extensions From 82da33138f03b09537c4d4e6b95e0ab964b5a6ee Mon Sep 17 00:00:00 2001 From: Raven Black Date: Thu, 21 Dec 2023 11:08:04 -0500 Subject: [PATCH 041/126] [cache-filter] don't set empty content-length (#31454) Signed-off-by: Raven Black --- source/extensions/filters/http/cache/cache_filter.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/extensions/filters/http/cache/cache_filter.cc b/source/extensions/filters/http/cache/cache_filter.cc index 1f7167e9d10d..8fe7fa56dbf7 100644 --- a/source/extensions/filters/http/cache/cache_filter.cc +++ b/source/extensions/filters/http/cache/cache_filter.cc @@ -540,9 +540,12 @@ void CacheFilter::processSuccessfulValidation(Http::ResponseHeaderMap& response_ filter_state_ = FilterState::EncodeServingFromCache; - // Update the 304 response status code and content-length + // Replace the 304 response status code with the cached status code. response_headers.setStatus(lookup_result_->headers_->getStatusValue()); - response_headers.setContentLength(lookup_result_->headers_->getContentLengthValue()); + + // Remove content length header if the 304 had one; if the cache entry had a + // content length header it will be added by the header adding block below. + response_headers.removeContentLength(); // A response that has been validated should not contain an Age header as it is equivalent to a // freshly served response from the origin, unless the 304 response has an Age header, which @@ -553,7 +556,7 @@ void CacheFilter::processSuccessfulValidation(Http::ResponseHeaderMap& response_ // Add any missing headers from the cached response to the 304 response. lookup_result_->headers_->iterate([&response_headers](const Http::HeaderEntry& cached_header) { // TODO(yosrym93): Try to avoid copying the header key twice. - Http::LowerCaseString key(std::string(cached_header.key().getStringView())); + Http::LowerCaseString key(cached_header.key().getStringView()); absl::string_view value = cached_header.value().getStringView(); if (response_headers.get(key).empty()) { response_headers.setCopy(key, value); From 55b942ae48e46e91625efb4abf43713e2c19dc73 Mon Sep 17 00:00:00 2001 From: zirain Date: Fri, 22 Dec 2023 14:44:51 +0800 Subject: [PATCH 042/126] improvement CEL doc (#31487) * improvement CEL formatter doc Signed-off-by: zirain * more page Signed-off-by: zirain * lint Signed-off-by: zirain --------- Signed-off-by: zirain --- .../extensions/access_loggers/filters/cel/v3/cel.proto | 5 +++-- api/envoy/extensions/formatter/cel/v3/cel.proto | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/envoy/extensions/access_loggers/filters/cel/v3/cel.proto b/api/envoy/extensions/access_loggers/filters/cel/v3/cel.proto index d8ef21a1cdf1..750ffd30d251 100644 --- a/api/envoy/extensions/access_loggers/filters/cel/v3/cel.proto +++ b/api/envoy/extensions/access_loggers/filters/cel/v3/cel.proto @@ -21,7 +21,8 @@ message ExpressionFilter { // Expressions are based on the set of Envoy :ref:`attributes `. // The provided expression must evaluate to true for logging (expression errors are considered false). // Examples: - // - ``response.code >= 400`` - // - ``(connection.mtls && request.headers['x-log-mtls'] == 'true') || request.url_path.contains('v1beta3')`` + // + // * ``response.code >= 400`` + // * ``(connection.mtls && request.headers['x-log-mtls'] == 'true') || request.url_path.contains('v1beta3')`` string expression = 1; } diff --git a/api/envoy/extensions/formatter/cel/v3/cel.proto b/api/envoy/extensions/formatter/cel/v3/cel.proto index ca9d01dedb4d..4e19fa5db954 100644 --- a/api/envoy/extensions/formatter/cel/v3/cel.proto +++ b/api/envoy/extensions/formatter/cel/v3/cel.proto @@ -24,10 +24,11 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // truncation up to Z characters long. // // Examples: -// - ``%CEL(response.code)%`` -// - ``%CEL(connection.mtls)%`` -// - ``%CEL(request.headers['x-envoy-original-path']):10%`` -// - ``%CEL(request.headers['x-log-mtls'] || request.url_path.contains('v1beta3'))%`` +// +// * ``%CEL(response.code)%`` +// * ``%CEL(connection.mtls)%`` +// * ``%CEL(request.headers['x-envoy-original-path']):10%`` +// * ``%CEL(request.headers['x-log-mtls'] || request.url_path.contains('v1beta3'))%`` // Configuration for the CEL formatter. message Cel { From e829b9ab789dbacc8e3a4b7a5bd3f899de20093e Mon Sep 17 00:00:00 2001 From: toddmgreer Date: Fri, 22 Dec 2023 06:26:57 -0800 Subject: [PATCH 043/126] Move operator<< overloads to the headers of the classes they stream. (#31375) * Move operator<< overloads to the headers of the classes they stream. Having them in separate headers invites ODR violations, and violates the style guide's requirement to "Define operators only on your own types. More precisely, define them in the same headers, .cc files, and namespaces as the types they operate on." https://google.github.io/styleguide/cppguide.html#Operator_Overloading Signed-off-by: Todd Greer --- .../filters/http/cache/cache_headers_utils.cc | 58 +++++++++++++++ .../filters/http/cache/cache_headers_utils.h | 4 ++ .../filters/http/cache/range_utils.cc | 5 ++ .../filters/http/cache/range_utils.h | 2 + test/extensions/filters/http/cache/BUILD | 15 ---- .../filters/http/cache/cache_filter_test.cc | 1 - .../http/cache/cache_headers_utils_test.cc | 22 +++++- test/extensions/filters/http/cache/common.cc | 72 ------------------- test/extensions/filters/http/cache/common.h | 20 ------ .../http_cache_implementation_test_common.h | 1 - .../filters/http/cache/http_cache_test.cc | 1 - .../filters/http/cache/range_utils_test.cc | 9 ++- .../http/cache/file_system_http_cache/BUILD | 1 - .../file_system_http_cache_test.cc | 1 - .../http/cache/simple_http_cache/BUILD | 1 - .../simple_http_cache_test.cc | 1 - 16 files changed, 98 insertions(+), 116 deletions(-) delete mode 100644 test/extensions/filters/http/cache/common.cc delete mode 100644 test/extensions/filters/http/cache/common.h diff --git a/source/extensions/filters/http/cache/cache_headers_utils.cc b/source/extensions/filters/http/cache/cache_headers_utils.cc index a02632d7c5ac..582746215dc2 100644 --- a/source/extensions/filters/http/cache/cache_headers_utils.cc +++ b/source/extensions/filters/http/cache/cache_headers_utils.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include "envoy/http/header_map.h" @@ -125,6 +126,63 @@ bool operator==(const ResponseCacheControl& lhs, const ResponseCacheControl& rhs (lhs.is_public_ == rhs.is_public_) && (lhs.max_age_ == rhs.max_age_); } +std::ostream& operator<<(std::ostream& os, const RequestCacheControl& request_cache_control) { + std::vector fields; + + if (request_cache_control.must_validate_) { + fields.push_back("must_validate"); + } + if (request_cache_control.no_store_) { + fields.push_back("no_store"); + } + if (request_cache_control.no_transform_) { + fields.push_back("no_transform"); + } + if (request_cache_control.only_if_cached_) { + fields.push_back("only_if_cached"); + } + if (request_cache_control.max_age_.has_value()) { + fields.push_back( + absl::StrCat("max-age=", std::to_string(request_cache_control.max_age_->count()))); + } + if (request_cache_control.min_fresh_.has_value()) { + fields.push_back( + absl::StrCat("min-fresh=", std::to_string(request_cache_control.min_fresh_->count()))); + } + if (request_cache_control.max_stale_.has_value()) { + fields.push_back( + absl::StrCat("max-stale=", std::to_string(request_cache_control.max_stale_->count()))); + } + + return os << "{" << absl::StrJoin(fields, ", ") << "}"; +} + +std::ostream& operator<<(std::ostream& os, const ResponseCacheControl& response_cache_control) { + std::vector fields; + + if (response_cache_control.must_validate_) { + fields.push_back("must_validate"); + } + if (response_cache_control.no_store_) { + fields.push_back("no_store"); + } + if (response_cache_control.no_transform_) { + fields.push_back("no_transform"); + } + if (response_cache_control.no_stale_) { + fields.push_back("no_stale"); + } + if (response_cache_control.is_public_) { + fields.push_back("public"); + } + if (response_cache_control.max_age_.has_value()) { + fields.push_back( + absl::StrCat("max-age=", std::to_string(response_cache_control.max_age_->count()))); + } + + return os << "{" << absl::StrJoin(fields, ", ") << "}"; +} + SystemTime CacheHeadersUtils::httpTime(const Http::HeaderEntry* header_entry) { if (!header_entry) { return {}; diff --git a/source/extensions/filters/http/cache/cache_headers_utils.h b/source/extensions/filters/http/cache/cache_headers_utils.h index c5a219f0fedd..440b58843d1a 100644 --- a/source/extensions/filters/http/cache/cache_headers_utils.h +++ b/source/extensions/filters/http/cache/cache_headers_utils.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "envoy/common/time.h" #include "envoy/extensions/filters/http/cache/v3/cache.pb.h" #include "envoy/http/header_map.h" @@ -93,6 +95,8 @@ struct ResponseCacheControl { bool operator==(const RequestCacheControl& lhs, const RequestCacheControl& rhs); bool operator==(const ResponseCacheControl& lhs, const ResponseCacheControl& rhs); +std::ostream& operator<<(std::ostream& os, const RequestCacheControl& request_cache_control); +std::ostream& operator<<(std::ostream& os, const ResponseCacheControl& response_cache_control); namespace CacheHeadersUtils { // Parses header_entry as an HTTP time. Returns SystemTime() if diff --git a/source/extensions/filters/http/cache/range_utils.cc b/source/extensions/filters/http/cache/range_utils.cc index 44a7eff02ed3..6fab49640460 100644 --- a/source/extensions/filters/http/cache/range_utils.cc +++ b/source/extensions/filters/http/cache/range_utils.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,10 @@ namespace Extensions { namespace HttpFilters { namespace Cache { +std::ostream& operator<<(std::ostream& os, const AdjustedByteRange& range) { + return os << "[" << range.begin() << "," << range.end() << ")"; +} + absl::optional RangeUtils::createRangeDetails(const Envoy::Http::RequestHeaderMap& request_headers, uint64_t content_length) { diff --git a/source/extensions/filters/http/cache/range_utils.h b/source/extensions/filters/http/cache/range_utils.h index 0f9d1ae90a83..4d7aa4728d2a 100644 --- a/source/extensions/filters/http/cache/range_utils.h +++ b/source/extensions/filters/http/cache/range_utils.h @@ -88,6 +88,8 @@ inline bool operator==(const AdjustedByteRange& lhs, const AdjustedByteRange& rh return lhs.begin() == rhs.begin() && lhs.end() == rhs.end(); } +std::ostream& operator<<(std::ostream& os, const AdjustedByteRange& range); + // Contains details about whether the ranges requested can be satisfied and, if // so, what those ranges are after being adjusted to fit the content. struct RangeDetails { diff --git a/test/extensions/filters/http/cache/BUILD b/test/extensions/filters/http/cache/BUILD index 81ab2735dae1..f45131e56f5d 100644 --- a/test/extensions/filters/http/cache/BUILD +++ b/test/extensions/filters/http/cache/BUILD @@ -9,16 +9,6 @@ licenses(["notice"]) # Apache 2 envoy_package() -envoy_cc_test_library( - name = "common", - srcs = ["common.cc"], - hdrs = ["common.h"], - deps = [ - "//source/extensions/filters/http/cache:cache_headers_utils_lib", - "//source/extensions/filters/http/cache:http_cache_lib", - ], -) - envoy_cc_test_library( name = "mocks", hdrs = ["mocks.h"], @@ -32,7 +22,6 @@ envoy_extension_cc_test( srcs = ["cache_headers_utils_test.cc"], extension_names = ["envoy.filters.http.cache"], deps = [ - ":common", "//envoy/http:header_map_interface", "//source/common/http:header_map_lib", "//source/extensions/filters/http/cache:cache_headers_utils_lib", @@ -64,7 +53,6 @@ envoy_extension_cc_test( srcs = ["http_cache_test.cc"], extension_names = ["envoy.filters.http.cache"], deps = [ - ":common", "//source/extensions/filters/http/cache:http_cache_lib", "//source/extensions/http/cache/simple_http_cache:config", "//test/mocks/http:http_mocks", @@ -79,7 +67,6 @@ envoy_extension_cc_test( srcs = ["range_utils_test.cc"], extension_names = ["envoy.filters.http.cache"], deps = [ - ":common", "//source/extensions/filters/http/cache:range_utils_lib", "//test/test_common:utility_lib", ], @@ -90,7 +77,6 @@ envoy_extension_cc_test( srcs = ["cache_filter_test.cc"], extension_names = ["envoy.filters.http.cache"], deps = [ - ":common", ":mocks", "//source/extensions/filters/http/cache:cache_filter_lib", "//source/extensions/filters/http/cache:cache_filter_logging_info_lib", @@ -163,7 +149,6 @@ envoy_extension_cc_test_library( deps = [ "//source/extensions/filters/http/cache:cache_headers_utils_lib", "//source/extensions/filters/http/cache:http_cache_lib", - "//test/extensions/filters/http/cache:common", "//test/mocks/server:factory_context_mocks", "//test/test_common:simulated_time_system_lib", "//test/test_common:utility_lib", diff --git a/test/extensions/filters/http/cache/cache_filter_test.cc b/test/extensions/filters/http/cache/cache_filter_test.cc index ee4f281190cc..d5a91f1a719b 100644 --- a/test/extensions/filters/http/cache/cache_filter_test.cc +++ b/test/extensions/filters/http/cache/cache_filter_test.cc @@ -5,7 +5,6 @@ #include "source/extensions/filters/http/cache/cache_filter_logging_info.h" #include "source/extensions/http/cache/simple_http_cache/simple_http_cache.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/extensions/filters/http/cache/mocks.h" #include "test/mocks/server/factory_context.h" #include "test/test_common/simulated_time_system.h" diff --git a/test/extensions/filters/http/cache/cache_headers_utils_test.cc b/test/extensions/filters/http/cache/cache_headers_utils_test.cc index 35a9a7dd60d2..2b5a0de3304e 100644 --- a/test/extensions/filters/http/cache/cache_headers_utils_test.cc +++ b/test/extensions/filters/http/cache/cache_headers_utils_test.cc @@ -10,7 +10,6 @@ #include "source/common/http/header_utility.h" #include "source/extensions/filters/http/cache/cache_headers_utils.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/test_common/simulated_time_system.h" #include "test/test_common/utility.h" @@ -155,6 +154,27 @@ TEST_P(RequestCacheControlTest, RequestCacheControlTest) { EXPECT_EQ(expected_request_cache_control, RequestCacheControl(cache_control_header)); } +// operator<<(ostream&, const RequestCacheControl&) is only used in tests, but lives in //source, +// and so needs test coverage. This test provides that coverage, to keep the coverage test happy. +TEST(RequestCacheControl, StreamingTest) { + std::ostringstream os; + RequestCacheControl request_cache_control( + "no-cache, no-store, no-transform, only-if-cached, max-age=0, min-fresh=0, max-stale=0"); + os << request_cache_control; + EXPECT_EQ(os.str(), "{must_validate, no_store, no_transform, only_if_cached, max-age=0, " + "min-fresh=0, max-stale=0}"); +} + +// operator<<(ostream&, const ResponseCacheControl&) is only used in tests, but lives in //source, +// and so needs test coverage. This test provides that coverage, to keep the coverage test happy. +TEST(ResponseCacheControl, StreamingTest) { + std::ostringstream os; + ResponseCacheControl response_cache_control( + "no-cache, must-revalidate, no-store, no-transform, max-age=0"); + os << response_cache_control; + EXPECT_EQ(os.str(), "{must_validate, no_store, no_transform, no_stale, max-age=0}"); +} + struct TestResponseCacheControl : public ResponseCacheControl { TestResponseCacheControl(bool must_validate, bool no_store, bool no_transform, bool no_stale, bool is_public, OptionalDuration max_age) { diff --git a/test/extensions/filters/http/cache/common.cc b/test/extensions/filters/http/cache/common.cc deleted file mode 100644 index 93c4c995c95e..000000000000 --- a/test/extensions/filters/http/cache/common.cc +++ /dev/null @@ -1,72 +0,0 @@ -#include "test/extensions/filters/http/cache/common.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace Cache { - -std::ostream& operator<<(std::ostream& os, const RequestCacheControl& request_cache_control) { - std::vector fields; - - if (request_cache_control.must_validate_) { - fields.push_back("must_validate"); - } - if (request_cache_control.no_store_) { - fields.push_back("no_store"); - } - if (request_cache_control.no_transform_) { - fields.push_back("no_transform"); - } - if (request_cache_control.only_if_cached_) { - fields.push_back("only_if_cached"); - } - if (request_cache_control.max_age_.has_value()) { - fields.push_back( - absl::StrCat("max-age=", std::to_string(request_cache_control.max_age_->count()))); - } - if (request_cache_control.min_fresh_.has_value()) { - fields.push_back( - absl::StrCat("min-fresh=", std::to_string(request_cache_control.min_fresh_->count()))); - } - if (request_cache_control.max_stale_.has_value()) { - fields.push_back( - absl::StrCat("max-stale=", std::to_string(request_cache_control.max_stale_->count()))); - } - - return os << "{" << absl::StrJoin(fields, ", ") << "}"; -} - -std::ostream& operator<<(std::ostream& os, const ResponseCacheControl& response_cache_control) { - std::vector fields; - - if (response_cache_control.must_validate_) { - fields.push_back("must_validate"); - } - if (response_cache_control.no_store_) { - fields.push_back("no_store"); - } - if (response_cache_control.no_transform_) { - fields.push_back("no_transform"); - } - if (response_cache_control.no_stale_) { - fields.push_back("no_stale"); - } - if (response_cache_control.is_public_) { - fields.push_back("public"); - } - if (response_cache_control.max_age_.has_value()) { - fields.push_back( - absl::StrCat("max-age=", std::to_string(response_cache_control.max_age_->count()))); - } - - return os << "{" << absl::StrJoin(fields, ", ") << "}"; -} - -std::ostream& operator<<(std::ostream& os, const AdjustedByteRange& range) { - return os << "[" << range.begin() << "," << range.end() << ")"; -} - -} // namespace Cache -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/test/extensions/filters/http/cache/common.h b/test/extensions/filters/http/cache/common.h deleted file mode 100644 index 6b6145c18eba..000000000000 --- a/test/extensions/filters/http/cache/common.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "source/extensions/filters/http/cache/cache_headers_utils.h" -#include "source/extensions/filters/http/cache/http_cache.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace Cache { - -std::ostream& operator<<(std::ostream& os, const RequestCacheControl& request_cache_control); - -std::ostream& operator<<(std::ostream& os, const ResponseCacheControl& response_cache_control); - -std::ostream& operator<<(std::ostream& os, const AdjustedByteRange& range); - -} // namespace Cache -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h index 362c7c22ea66..85c4ba8981fd 100644 --- a/test/extensions/filters/http/cache/http_cache_implementation_test_common.h +++ b/test/extensions/filters/http/cache/http_cache_implementation_test_common.h @@ -7,7 +7,6 @@ #include "source/extensions/filters/http/cache/cache_headers_utils.h" #include "source/extensions/filters/http/cache/http_cache.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/mocks/event/mocks.h" #include "test/mocks/http/mocks.h" #include "test/test_common/simulated_time_system.h" diff --git a/test/extensions/filters/http/cache/http_cache_test.cc b/test/extensions/filters/http/cache/http_cache_test.cc index f8cd99266b12..54c53fb5f2cf 100644 --- a/test/extensions/filters/http/cache/http_cache_test.cc +++ b/test/extensions/filters/http/cache/http_cache_test.cc @@ -4,7 +4,6 @@ #include "source/extensions/filters/http/cache/cache_headers_utils.h" #include "source/extensions/filters/http/cache/http_cache.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/mocks/http/mocks.h" #include "test/test_common/simulated_time_system.h" #include "test/test_common/test_runtime.h" diff --git a/test/extensions/filters/http/cache/range_utils_test.cc b/test/extensions/filters/http/cache/range_utils_test.cc index 84bc3c0028b1..980a4dc52fec 100644 --- a/test/extensions/filters/http/cache/range_utils_test.cc +++ b/test/extensions/filters/http/cache/range_utils_test.cc @@ -5,7 +5,6 @@ #include "source/extensions/filters/http/cache/range_utils.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/test_common/utility.h" #include "gtest/gtest.h" @@ -327,6 +326,14 @@ TEST(GetRangeDetailsTest, NotSatisfiableRange) { ASSERT_TRUE(result->ranges_.empty()); } +// operator<<(ostream&, const AdjustedByteRange&) is only used in tests, but lives in //source, +// and so needs test coverage. This test provides that coverage, to keep the coverage test happy. +TEST(AdjustedByteRange, StreamingTest) { + std::ostringstream os; + os << AdjustedByteRange(0, 1); + EXPECT_EQ(os.str(), "[0,1)"); +} + } // namespace } // namespace Cache } // namespace HttpFilters diff --git a/test/extensions/http/cache/file_system_http_cache/BUILD b/test/extensions/http/cache/file_system_http_cache/BUILD index ce137ae24c27..a5bf24f6ef25 100644 --- a/test/extensions/http/cache/file_system_http_cache/BUILD +++ b/test/extensions/http/cache/file_system_http_cache/BUILD @@ -18,7 +18,6 @@ envoy_extension_cc_test( "//source/extensions/filters/http/cache:cache_entry_utils_lib", "//source/extensions/http/cache/file_system_http_cache:config", "//test/extensions/common/async_files:mocks", - "//test/extensions/filters/http/cache:common", "//test/extensions/filters/http/cache:http_cache_implementation_test_common_lib", "//test/mocks/server:factory_context_mocks", "//test/test_common:simulated_time_system_lib", diff --git a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc index 7da8d9f93be0..004eb996d33e 100644 --- a/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc +++ b/test/extensions/http/cache/file_system_http_cache/file_system_http_cache_test.cc @@ -12,7 +12,6 @@ #include "source/extensions/http/cache/file_system_http_cache/file_system_http_cache.h" #include "test/extensions/common/async_files/mocks.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/extensions/filters/http/cache/http_cache_implementation_test_common.h" #include "test/mocks/server/factory_context.h" #include "test/test_common/environment.h" diff --git a/test/extensions/http/cache/simple_http_cache/BUILD b/test/extensions/http/cache/simple_http_cache/BUILD index 744f4bd8e289..a349aa162993 100644 --- a/test/extensions/http/cache/simple_http_cache/BUILD +++ b/test/extensions/http/cache/simple_http_cache/BUILD @@ -15,7 +15,6 @@ envoy_extension_cc_test( deps = [ "//source/extensions/filters/http/cache:cache_entry_utils_lib", "//source/extensions/http/cache/simple_http_cache:config", - "//test/extensions/filters/http/cache:common", "//test/extensions/filters/http/cache:http_cache_implementation_test_common_lib", "//test/mocks/server:factory_context_mocks", "//test/test_common:simulated_time_system_lib", diff --git a/test/extensions/http/cache/simple_http_cache/simple_http_cache_test.cc b/test/extensions/http/cache/simple_http_cache/simple_http_cache_test.cc index 718681770e73..3bb376ac41ea 100644 --- a/test/extensions/http/cache/simple_http_cache/simple_http_cache_test.cc +++ b/test/extensions/http/cache/simple_http_cache/simple_http_cache_test.cc @@ -6,7 +6,6 @@ #include "source/extensions/filters/http/cache/cache_headers_utils.h" #include "source/extensions/http/cache/simple_http_cache/simple_http_cache.h" -#include "test/extensions/filters/http/cache/common.h" #include "test/extensions/filters/http/cache/http_cache_implementation_test_common.h" #include "test/mocks/server/factory_context.h" #include "test/test_common/simulated_time_system.h" From 65ec5958e88a5c86f4efc5ec3402add75c4c6dc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:28:10 +0000 Subject: [PATCH 044/126] build(deps): bump envoyproxy/toolshed from actions-v0.2.19 to 0.2.20 (#31501) * build(deps): bump envoyproxy/toolshed from actions-v0.2.19 to 0.2.20 Bumps [envoyproxy/toolshed](https://github.com/envoyproxy/toolshed) from actions-v0.2.19 to 0.2.20. This release includes the previously tagged commit. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/compare/actions-v0.2.19...actions-v0.2.20) --- updated-dependencies: - dependency-name: envoyproxy/toolshed dependency-type: direct:production ... Signed-off-by: dependabot[bot] * fix-missing Signed-off-by: Ryan Northey --------- Signed-off-by: dependabot[bot] Signed-off-by: Ryan Northey Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ryan Northey --- .github/workflows/_cache.yml | 8 ++++---- .github/workflows/_finish.yml | 8 ++++---- .github/workflows/_load.yml | 10 +++++----- .github/workflows/_load_env.yml | 8 ++++---- .github/workflows/_request.yml | 10 +++++----- .github/workflows/_run.yml | 16 ++++++++-------- .github/workflows/_stage_publish.yml | 8 ++++---- .github/workflows/_stage_verify.yml | 8 ++++---- .github/workflows/_start.yml | 10 +++++----- .github/workflows/codeql-push.yml | 2 +- .github/workflows/command.yml | 6 +++--- .github/workflows/envoy-dependency.yml | 18 +++++++++--------- .github/workflows/envoy-release.yml | 16 ++++++++-------- .github/workflows/envoy-sync.yml | 4 ++-- .github/workflows/mobile-android_build.yml | 12 ++++++------ .github/workflows/mobile-ios_build.yml | 4 ++-- 16 files changed, 74 insertions(+), 74 deletions(-) diff --git a/.github/workflows/_cache.yml b/.github/workflows/_cache.yml index f122ae64cb12..81b5b3333531 100644 --- a/.github/workflows/_cache.yml +++ b/.github/workflows/_cache.yml @@ -39,20 +39,20 @@ jobs: docker: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 id: appauth name: Appauth (mutex lock) with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.20 id: docker name: Prime Docker cache (${{ inputs.image-tag }}) with: image-tag: ${{ inputs.image-tag }} lock-token: ${{ steps.appauth.outputs.token }} lock-repository: ${{ inputs.lock-repository }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: data name: Cache data with: @@ -60,7 +60,7 @@ jobs: input: | cached: ${{ steps.docker.outputs.cached }} key: ${{ inputs.image-tag }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.20 name: Summary with: json: ${{ steps.data.outputs.value }} diff --git a/.github/workflows/_finish.yml b/.github/workflows/_finish.yml index b905ecb59d87..37d0b445b7df 100644 --- a/.github/workflows/_finish.yml +++ b/.github/workflows/_finish.yml @@ -36,7 +36,7 @@ jobs: actions: read contents: read steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 name: Incoming data id: needs with: @@ -87,7 +87,7 @@ jobs: summary: "Check has finished", text: $text}}}} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 name: Print summary with: input: ${{ toJSON(steps.needs.outputs.value).summary-title }} @@ -95,13 +95,13 @@ jobs: "## \(.)" options: -Rr output-path: GITHUB_STEP_SUMMARY - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 name: Update check with: action: update diff --git a/.github/workflows/_load.yml b/.github/workflows/_load.yml index a28c07e685e7..de34daa521df 100644 --- a/.github/workflows/_load.yml +++ b/.github/workflows/_load.yml @@ -91,7 +91,7 @@ jobs: # Handle any failure in triggering job # Remove any `checks` we dont care about # Prepare a check request - - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.20 name: Load env id: data with: @@ -102,13 +102,13 @@ jobs: GH_TOKEN: ${{ github.token }} # Update the check - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 name: Update check if: ${{ fromJSON(steps.data.outputs.data).data.check.action == 'RUN' }} with: @@ -116,7 +116,7 @@ jobs: checks: ${{ toJSON(fromJSON(steps.data.outputs.data).checks) }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 name: Print request summary with: input: | @@ -136,7 +136,7 @@ jobs: | $summary.summary as $summary | "${{ inputs.template-request-summary }}" - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: request-output name: Load request with: diff --git a/.github/workflows/_load_env.yml b/.github/workflows/_load_env.yml index bdd8fb966046..ed9dd669babc 100644 --- a/.github/workflows/_load_env.yml +++ b/.github/workflows/_load_env.yml @@ -63,18 +63,18 @@ jobs: request: ${{ steps.env.outputs.data }} trusted: true steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 id: checkout name: Checkout Envoy repository - name: Generate environment variables - uses: envoyproxy/toolshed/gh-actions/envoy/ci/env@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/env@actions-v0.2.20 id: env with: branch-name: ${{ inputs.branch-name }} @@ -86,7 +86,7 @@ jobs: - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.20 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} diff --git a/.github/workflows/_request.yml b/.github/workflows/_request.yml index 813e844d55f6..5b9f183d0551 100644 --- a/.github/workflows/_request.yml +++ b/.github/workflows/_request.yml @@ -40,14 +40,14 @@ jobs: env: ${{ steps.data.outputs.value }} config: ${{ steps.config.outputs.config }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -60,7 +60,7 @@ jobs: # *ALL* variables collected should be treated as untrusted and should be sanitized before # use - name: Generate environment variables from commit - uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.20 id: env with: branch-name: ${{ steps.checkout.outputs.branch-name }} @@ -71,7 +71,7 @@ jobs: vars: ${{ toJSON(vars) }} - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.20 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} @@ -87,7 +87,7 @@ jobs: target-branch: ${{ fromJSON(steps.env.outputs.data).request.target-branch }} - name: Environment data - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: data with: input: | diff --git a/.github/workflows/_run.yml b/.github/workflows/_run.yml index a810ac2497ee..579efafa33d8 100644 --- a/.github/workflows/_run.yml +++ b/.github/workflows/_run.yml @@ -94,7 +94,7 @@ on: summary-post: type: string default: | - - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.20 with: context: %{{ inputs.context }} steps-pre: @@ -155,7 +155,7 @@ jobs: name: ${{ inputs.command }} ${{ inputs.target }} timeout-minutes: ${{ inputs.timeout-minutes }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: started name: Create timestamp with: @@ -163,7 +163,7 @@ jobs: filter: | now # This controls which input vars are exposed to the run action (and related steps) - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 name: Context id: context with: @@ -184,11 +184,11 @@ jobs: | . * {$config, $check} - if: ${{ inputs.cache-build-image }} name: Restore Docker cache ${{ inputs.cache-build-image && format('({0})', inputs.cache-build-image) || '' }} - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.20 with: image_tag: ${{ inputs.cache-build-image }} - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 id: appauth name: Appauth if: ${{ inputs.trusted }} @@ -199,7 +199,7 @@ jobs: # - the workaround is to allow the token to be passed through. token: ${{ github.token }} token-ok: true - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -216,7 +216,7 @@ jobs: token: ${{ inputs.trusted && steps.appauth.outputs.token || github.token }} # This is currently only use by mobile-docs and can be removed once they are updated to the newer website - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 id: checkout-extra name: Checkout extra repository (for publishing) if: ${{ inputs.checkout-extra }} @@ -224,7 +224,7 @@ jobs: config: ${{ inputs.checkout-extra }} ssh-key: ${{ inputs.trusted && inputs.ssh-key-extra || '' }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 name: Run CI ${{ inputs.command }} ${{ inputs.target }} with: args: ${{ inputs.args != '--' && inputs.args || inputs.target }} diff --git a/.github/workflows/_stage_publish.yml b/.github/workflows/_stage_publish.yml index b3684a78ceda..27996ebdffa2 100644 --- a/.github/workflows/_stage_publish.yml +++ b/.github/workflows/_stage_publish.yml @@ -63,7 +63,7 @@ jobs: export ENVOY_PUBLISH_DRY_RUN=${{ (fromJSON(inputs.request).request.version.dev || ! inputs.trusted) && 1 || '' }} steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 with: options: -Rr input: >- @@ -80,7 +80,7 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)/\($path)" - - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.20 with: url: %{{ steps.url.outputs.value }} path: %{{ runner.temp }}/release.signed @@ -98,12 +98,12 @@ jobs: needs: - publish steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.20 with: ref: main repository: ${{ fromJSON(inputs.request).request.version.dev && 'envoyproxy/envoy-website' || 'envoyproxy/archive' }} diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index 3209bad28c66..5f68de975347 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -50,7 +50,7 @@ jobs: rbe: false steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 with: options: -Rr input: >- @@ -66,15 +66,15 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)" - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy.tar variant: dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy-contrib.tar variant: contrib-dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy-google-vrp.tar variant: google-vrp-dev diff --git a/.github/workflows/_start.yml b/.github/workflows/_start.yml index ca9474ff03e7..318660ba4ddc 100644 --- a/.github/workflows/_start.yml +++ b/.github/workflows/_start.yml @@ -54,7 +54,7 @@ jobs: start: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 id: check-config name: Prepare check data with: @@ -77,13 +77,13 @@ jobs: | .skipped.output.summary = "${{ inputs.skipped-summary }}" | .skipped.output.text = "" - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 name: Start checks id: checks with: @@ -94,7 +94,7 @@ jobs: ${{ fromJSON(inputs.env).summary.summary }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.20 name: Summary with: collapse-open: true @@ -118,7 +118,7 @@ jobs: output-path: GITHUB_STEP_SUMMARY title: Checks started/skipped - - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.20 name: Save env id: data with: diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 6afd6a6544f4..a2390f264f3f 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Pre-cleanup - uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.20 with: to_remove: | /usr/local/lib/android diff --git a/.github/workflows/command.yml b/.github/workflows/command.yml index aca3aeedc1cc..1d26266237f1 100644 --- a/.github/workflows/command.yml +++ b/.github/workflows/command.yml @@ -28,7 +28,7 @@ jobs: && github.actor != 'dependabot[bot]' }} steps: - - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.20 name: Parse command from comment id: command with: @@ -37,14 +37,14 @@ jobs: ^/(retest) # /retest - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 if: ${{ steps.command.outputs.command == 'retest' }} id: appauth-retest name: Appauth (retest) with: key: ${{ secrets.ENVOY_CI_APP_KEY }} app_id: ${{ secrets.ENVOY_CI_APP_ID }} - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.20 if: ${{ steps.command.outputs.command == 'retest' }} name: Retest with: diff --git a/.github/workflows/envoy-dependency.yml b/.github/workflows/envoy-dependency.yml index 35368d95f137..8113ddaa810d 100644 --- a/.github/workflows/envoy-dependency.yml +++ b/.github/workflows/envoy-dependency.yml @@ -50,16 +50,16 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 with: token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.20 id: update name: Update dependency (${{ inputs.dependency }}) with: @@ -94,13 +94,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.20 name: Upload diff with: name: ${{ inputs.dependency }}-${{ steps.update.outputs.output }} - name: Create a PR if: ${{ inputs.pr }} - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 with: base: main body: | @@ -131,11 +131,11 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -177,7 +177,7 @@ jobs: - name: Check Docker SHAs id: build-images - uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.20 with: images: | sha: envoyproxy/envoy-build-ubuntu:${{ steps.build-tools.outputs.tag }} @@ -206,7 +206,7 @@ jobs: name: Update SHAs working-directory: envoy - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 with: base: main body: Created by Envoy dependency bot diff --git a/.github/workflows/envoy-release.yml b/.github/workflows/envoy-release.yml index 1ac25a41ff12..af108a20d9d5 100644 --- a/.github/workflows/envoy-release.yml +++ b/.github/workflows/envoy-release.yml @@ -55,7 +55,7 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} @@ -77,10 +77,10 @@ jobs: name: Check changelog summary - if: ${{ inputs.author }} name: Validate signoff email - uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.20 with: email: ${{ inputs.author }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 name: Create release with: source: | @@ -105,7 +105,7 @@ jobs: name: Release version id: release - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 with: base: ${{ github.ref_name }} commit: false @@ -130,13 +130,13 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} committer-name: ${{ env.COMMITTER_NAME }} committer-email: ${{ env.COMMITTER_EMAIL }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 name: Sync version histories with: command: >- @@ -146,7 +146,7 @@ jobs: -- --signoff="${{ env.COMMITTER_NAME }} <${{ env.COMMITTER_EMAIL }}>" - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 with: append-commit-message: true base: ${{ github.ref_name }} @@ -176,7 +176,7 @@ jobs: name: Create release branch steps: - name: Checkout repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.19 + uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml index 005a4713d8be..2f726ecade76 100644 --- a/.github/workflows/envoy-sync.yml +++ b/.github/workflows/envoy-sync.yml @@ -28,12 +28,12 @@ jobs: - data-plane-api - mobile-website steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.20 with: repository: "envoyproxy/${{ matrix.downstream }}" ref: main diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 76f799e8eed0..452d63d11fb5 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -75,9 +75,9 @@ jobs: target: kotlin-hello-world runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.20 steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 with: apk: bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity @@ -104,7 +104,7 @@ jobs: target: ${{ matrix.target }} runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.20 steps-post: ${{ matrix.steps-post }} timeout-minutes: 50 trusted: ${{ fromJSON(needs.load.outputs.trusted) }} @@ -115,7 +115,7 @@ jobs: include: - name: java-hello-world steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 with: apk: bazel-bin/examples/java/hello_world/hello_envoy.apk app: io.envoyproxy.envoymobile.helloenvoy/.MainActivity @@ -134,7 +134,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/baseline:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 with: apk: bazel-bin/test/kotlin/apps/baseline/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoybaselinetest/.MainActivity @@ -149,7 +149,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/experimental:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 with: apk: bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index 474c1c29f658..2aafe766d43c 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -86,7 +86,7 @@ jobs: ./ci/mac_ci_setup.sh ./bazelw shutdown steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.20 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} @@ -127,7 +127,7 @@ jobs: source: | ./ci/mac_ci_setup.sh steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.19 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.20 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} From e485fa5a995fb1de1efb34d0e5bbb05b27325fbd Mon Sep 17 00:00:00 2001 From: Jeongseok Son Date: Sun, 24 Dec 2023 10:52:28 -0800 Subject: [PATCH 045/126] Update QUICHE from b4deacb23 to 28317b632 (#31484) * Update QUICHE from b4deacb23 to 28317b632 https://github.com/google/quiche/compare/b4deacb23..28317b632 ``` $ git log b4deacb23..28317b632 --date=short --no-merges --format="%ad %al %s" 2023-12-20 wub Downgrade quic_send_alarm_postponed from QUIC_BUG to a DVLOG. Remove the information used to debug the send alarm issue. 2023-12-20 danzh No public description 2023-12-20 birenroy Adds a stream ID watermark to CallbackVisitor. 2023-12-19 birenroy Adds a unit test demonstrating that CallbackVisitor revives stream state even for closed streams. 2023-12-19 wub Fix a byte counting bug in QUIC BBR2. 2023-12-15 wub In QuicPacketCreator, saves next_transmission_type_ before calling the delegate_->MaybeBundleOpportunistically() and restore it after. 2023-12-14 danzh Each Quic server session only accepts up to certain number of new requests in each event loop. The rest will be postponed to the following event loop. 2023-12-13 wangsteve Remove optional::value(), map::at() from quic. 2023-12-13 diannahu Remove BalsaVisitorInterface::ProcessTrailers(). 2023-12-13 diannahu Remove BalsaFrame::set_balsa_trailer() and BalsaFrame::trailer(). 2023-12-13 ericorth Add IP/UDP packet generation to QUIC test tools 2023-12-12 wub Add connection option `RNIB` to remove non-initial burst in both client and server. 2023-12-11 ericorth Move InternetChecksum from quic/qbone/ to quic/core/ 2023-12-11 elburrito BlindSignAuth: Switch to Base64URL encoding for PrivacyPassTokenData outputs 2023-12-08 danzh Record pending duration histogram for a Quic stream if it was pending for whatever reason. And count how many streams has been pended for a QuicSession. 2023-12-08 danzh Refactor QuicSession::MaybeProcessPendingStream() to return a bool to indicate whether to continue processing the next pending stream or not. 2023-12-07 vasilvv Remove QuicheMemSlice::impl() accessor. ``` Signed-off-by: Jeongseok Son --- bazel/repository_locations.bzl | 6 +++--- source/common/http/http1/balsa_parser.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 7f6213b0820b..50d24de7cad6 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1172,12 +1172,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "QUICHE", project_desc = "QUICHE (QUIC, HTTP/2, Etc) is Google‘s implementation of QUIC and related protocols", project_url = "https://github.com/google/quiche", - version = "b4deacb2393a58af4214fa96b397f5bb80c0f687", - sha256 = "690fea0fd4b1e6225c8c3446336bb1b8def8f073f856cc00b9840f84f842b4d2", + version = "28317b63250a6d8e0fa5a621fd6898479692dd2b", + sha256 = "4e64ed3b61353912923cc2389adc63bc0977e29418c0ef88dd9c394be33f01dd", urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2023-12-07", + release_date = "2023-12-21", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", diff --git a/source/common/http/http1/balsa_parser.h b/source/common/http/http1/balsa_parser.h index 61d485ef1ced..b5c4491f7c7e 100644 --- a/source/common/http/http1/balsa_parser.h +++ b/source/common/http/http1/balsa_parser.h @@ -44,7 +44,6 @@ class BalsaParser : public Parser, public quiche::BalsaVisitorInterface { void OnTrailerInput(absl::string_view input) override; void OnTrailers(std::unique_ptr trailers) override; void ProcessHeaders(const quiche::BalsaHeaders& headers) override; - void ProcessTrailers(const quiche::BalsaHeaders& /*trailer*/) override{}; void OnRequestFirstLineInput(absl::string_view line_input, absl::string_view method_input, absl::string_view request_uri, absl::string_view version_input) override; From a5b712511d2b470b02f54d4be43e8b9e5647d5d6 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Mon, 25 Dec 2023 10:25:19 -0500 Subject: [PATCH 046/126] mobile: Add an engine termination test with open streams (#31488) Signed-off-by: Ali Beyad --- mobile/test/common/integration/BUILD | 1 + .../integration/client_integration_test.cc | 45 +++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/mobile/test/common/integration/BUILD b/mobile/test/common/integration/BUILD index 35dd44d664d4..b155b236ce7c 100644 --- a/mobile/test/common/integration/BUILD +++ b/mobile/test/common/integration/BUILD @@ -29,6 +29,7 @@ envoy_cc_test( "@envoy//source/common/quic:quic_transport_socket_factory_lib", "@envoy//source/common/quic:udp_gso_batch_writer_lib", "@envoy//source/extensions/udp_packet_writer/gso:config", + "@envoy//test/test_common:test_random_generator_lib", ], ) diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index a524b6d8cfc7..98429dbd3147 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -10,6 +10,7 @@ #include "test/common/integration/base_client_integration_test.h" #include "test/common/mocks/common/mocks.h" #include "test/integration/autonomous_upstream.h" +#include "test/test_common/test_random_generator.h" #include "extension_registry.h" #include "library/common/data/utility.h" @@ -142,7 +143,7 @@ class ClientIntegrationTest void basicTest(); void trickleTest(); - void explicitFlowControlWithCancels(uint32_t body_size = 1000); + void explicitFlowControlWithCancels(uint32_t body_size = 1000, bool terminate_engine = false); static std::string protocolToString(Http::CodecType type) { if (type == Http::CodecType::HTTP3) { @@ -344,7 +345,8 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowControl) { ASSERT_EQ(num_requests, cc_.on_complete_calls); } -void ClientIntegrationTest::explicitFlowControlWithCancels(uint32_t body_size) { +void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_size, + const bool terminate_engine) { default_request_headers_.addCopy(AutonomousStream::RESPONSE_SIZE_BYTES, std::to_string(body_size)); @@ -352,6 +354,13 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(uint32_t body_size) { std::vector prototype_streams; std::vector streams; + // Randomly select which request number to terminate the engine on. + uint32_t request_for_engine_termination = 0; + if (terminate_engine) { + TestRandomGenerator rand; + request_for_engine_termination = rand.random() % (num_requests / 2); + } + for (uint32_t i = 0; i < num_requests; ++i) { Platform::StreamPrototypeSharedPtr stream_prototype; { @@ -391,13 +400,27 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(uint32_t body_size) { } else { stream->readData(100); } + + if (terminate_engine && request_for_engine_termination == i) { + { + absl::MutexLock l(&engine_lock_); + ASSERT_EQ(engine_->terminate(), ENVOY_SUCCESS); + engine_.reset(); + } + break; + } } - ASSERT(streams.size() == num_requests); - ASSERT(prototype_streams.size() == num_requests); - terminal_callback_.waitReady(); - ASSERT_EQ(num_requests / 2, cc_.on_complete_calls); - ASSERT_EQ(num_requests / 2, cc_.on_cancel_calls); + if (terminate_engine) { + // Only the cancel calls are guaranteed to have completed when engine->terminate() is called. + EXPECT_GE(cc_.on_cancel_calls, request_for_engine_termination / 2); + } else { + ASSERT(streams.size() == num_requests); + ASSERT(prototype_streams.size() == num_requests); + terminal_callback_.waitReady(); + EXPECT_EQ(num_requests / 2, cc_.on_complete_calls); + EXPECT_EQ(num_requests / 2, cc_.on_cancel_calls); + } } TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancels) { @@ -409,7 +432,13 @@ TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancels) { TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancelsAfterComplete) { explicit_flow_control_ = true; initialize(); - explicitFlowControlWithCancels(100); + explicitFlowControlWithCancels(/*body_size=*/100); +} + +TEST_P(ClientIntegrationTest, ManyStreamExplicitFlowWithCancelsAfterCompleteEngineTermination) { + explicit_flow_control_ = true; + initialize(); + explicitFlowControlWithCancels(/*body_size=*/100, /*terminate_engine=*/true); } TEST_P(ClientIntegrationTest, ClearTextNotPermitted) { From 2f8e1a36ed808d760d6f791cdfc8f8cd568a1ad7 Mon Sep 17 00:00:00 2001 From: zirain Date: Tue, 26 Dec 2023 11:24:53 +0800 Subject: [PATCH 047/126] tcp_proxy: simply flushAccessLog (#31503) minor refactor Signed-off-by: zirain --- source/common/tcp_proxy/tcp_proxy.cc | 29 +++++++++++----------------- source/common/tcp_proxy/tcp_proxy.h | 1 + 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/source/common/tcp_proxy/tcp_proxy.cc b/source/common/tcp_proxy/tcp_proxy.cc index 60f1b6aabf03..15f24fe8d743 100644 --- a/source/common/tcp_proxy/tcp_proxy.cc +++ b/source/common/tcp_proxy/tcp_proxy.cc @@ -223,13 +223,8 @@ Filter::~Filter() { // Disable access log flush timer if it is enabled. disableAccessLogFlushTimer(); - const Formatter::HttpFormatterContext log_context{ - nullptr, nullptr, nullptr, {}, AccessLog::AccessLogType::TcpConnectionEnd}; - // Flush the final end stream access log entry. - for (const auto& access_log : config_->accessLogs()) { - access_log->log(log_context, getStreamInfo()); - } + flushAccessLog(AccessLog::AccessLogType::TcpConnectionEnd); ASSERT(generic_conn_pool_ == nullptr); ASSERT(upstream_ == nullptr); @@ -854,12 +849,7 @@ void Filter::onUpstreamConnection() { } if (config_->flushAccessLogOnConnected()) { - const Formatter::HttpFormatterContext log_context{ - nullptr, nullptr, nullptr, {}, AccessLog::AccessLogType::TcpUpstreamConnected}; - - for (const auto& access_log : config_->accessLogs()) { - access_log->log(log_context, getStreamInfo()); - } + flushAccessLog(AccessLog::AccessLogType::TcpUpstreamConnected); } } @@ -882,12 +872,7 @@ void Filter::onMaxDownstreamConnectionDuration() { } void Filter::onAccessLogFlushInterval() { - const Formatter::HttpFormatterContext log_context{ - nullptr, nullptr, nullptr, {}, AccessLog::AccessLogType::TcpPeriodic}; - - for (const auto& access_log : config_->accessLogs()) { - access_log->log(log_context, getStreamInfo()); - } + flushAccessLog(AccessLog::AccessLogType::TcpPeriodic); const SystemTime now = read_callbacks_->connection().dispatcher().timeSource().systemTime(); getStreamInfo().getDownstreamBytesMeter()->takeDownstreamPeriodicLoggingSnapshot(now); if (getStreamInfo().getUpstreamBytesMeter()) { @@ -896,6 +881,14 @@ void Filter::onAccessLogFlushInterval() { resetAccessLogFlushTimer(); } +void Filter::flushAccessLog(AccessLog::AccessLogType access_log_type) { + const Formatter::HttpFormatterContext log_context{nullptr, nullptr, nullptr, {}, access_log_type}; + + for (const auto& access_log : config_->accessLogs()) { + access_log->log(log_context, getStreamInfo()); + } +} + void Filter::resetAccessLogFlushTimer() { if (access_log_flush_timer_ != nullptr) { ASSERT(config_->accessLogFlushInterval().has_value()); diff --git a/source/common/tcp_proxy/tcp_proxy.h b/source/common/tcp_proxy/tcp_proxy.h index 6dc6f149833d..82ebcb8fb9d9 100644 --- a/source/common/tcp_proxy/tcp_proxy.h +++ b/source/common/tcp_proxy/tcp_proxy.h @@ -515,6 +515,7 @@ class Filter : public Network::ReadFilter, void onMaxDownstreamConnectionDuration(); void onAccessLogFlushInterval(); void resetAccessLogFlushTimer(); + void flushAccessLog(AccessLog::AccessLogType access_log_type); void disableAccessLogFlushTimer(); const ConfigSharedPtr config_; From b590b28275faf21d3ea108b52f56ec3fa135d6d1 Mon Sep 17 00:00:00 2001 From: ohadvano <49730675+ohadvano@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:01:04 +0200 Subject: [PATCH 048/126] stream_info: add missing response flag strings (#31521) * add missing response flag strings Signed-off-by: ohadvano * fix test Signed-off-by: ohadvano * fix format Signed-off-by: ohadvano --------- Signed-off-by: ohadvano --- api/envoy/config/accesslog/v3/accesslog.proto | 2 ++ source/common/stream_info/utility.h | 7 +++++++ test/common/access_log/access_log_impl_test.cc | 2 ++ 3 files changed, 11 insertions(+) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 0904b5d055a7..fe3ba2bc97ca 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -254,6 +254,8 @@ message ResponseFlagFilter { in: "UPE" in: "NC" in: "OM" + in: "DF" + in: "DO" } } }]; diff --git a/source/common/stream_info/utility.h b/source/common/stream_info/utility.h index 51f3e69f792b..e7794165b500 100644 --- a/source/common/stream_info/utility.h +++ b/source/common/stream_info/utility.h @@ -26,6 +26,8 @@ class ResponseFlagUtils { using FlagStringsAndEnum = std::pair; + // When adding a new flag, it's required to update the access log docs and the string + // mapping below - ``ALL_RESPONSE_STRINGS_FLAGS``. constexpr static absl::string_view NONE = "-"; constexpr static absl::string_view DOWNSTREAM_CONNECTION_TERMINATION = "DC"; constexpr static absl::string_view FAILED_LOCAL_HEALTH_CHECK = "LH"; @@ -54,6 +56,7 @@ class ResponseFlagUtils { constexpr static absl::string_view NO_CLUSTER_FOUND = "NC"; constexpr static absl::string_view OVERLOAD_MANAGER = "OM"; constexpr static absl::string_view DNS_FAIL = "DF"; + constexpr static absl::string_view DROP_OVERLOAD = "DO"; constexpr static absl::string_view DOWNSTREAM_CONNECTION_TERMINATION_LONG = "DownstreamConnectionTermination"; @@ -87,6 +90,8 @@ class ResponseFlagUtils { constexpr static absl::string_view UPSTREAM_PROTOCOL_ERROR_LONG = "UpstreamProtocolError"; constexpr static absl::string_view NO_CLUSTER_FOUND_LONG = "NoClusterFound"; constexpr static absl::string_view OVERLOAD_MANAGER_LONG = "OverloadManagerTerminated"; + constexpr static absl::string_view DNS_FAIL_LONG = "DnsResolutionFailed"; + constexpr static absl::string_view DROP_OVERLOAD_LONG = "DropOverload"; static constexpr std::array ALL_RESPONSE_STRINGS_FLAGS{ FlagStringsAndEnum{{FAILED_LOCAL_HEALTH_CHECK, FAILED_LOCAL_HEALTH_CHECK_LONG}, @@ -135,6 +140,8 @@ class ResponseFlagUtils { ResponseFlag::UpstreamProtocolError}, FlagStringsAndEnum{{NO_CLUSTER_FOUND, NO_CLUSTER_FOUND_LONG}, ResponseFlag::NoClusterFound}, FlagStringsAndEnum{{OVERLOAD_MANAGER, OVERLOAD_MANAGER_LONG}, ResponseFlag::OverloadManager}, + FlagStringsAndEnum{{DNS_FAIL, DNS_FAIL_LONG}, ResponseFlag::DnsResolutionFailed}, + FlagStringsAndEnum{{DROP_OVERLOAD, DROP_OVERLOAD_LONG}, ResponseFlag::DropOverLoad}, }; private: diff --git a/test/common/access_log/access_log_impl_test.cc b/test/common/access_log/access_log_impl_test.cc index 46c1860b0ce5..d003228f1a29 100644 --- a/test/common/access_log/access_log_impl_test.cc +++ b/test/common/access_log/access_log_impl_test.cc @@ -1067,6 +1067,8 @@ name: accesslog - UPE - NC - OM + - DF + - DO typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog path: /dev/null From 9108a1457513cdad1881fc6177a008aa511ef242 Mon Sep 17 00:00:00 2001 From: River <6375745+RiverPhillips@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:11:47 +0000 Subject: [PATCH 049/126] deps: bump `aspect_bazel_lib` => 2.1.0 (#31533) Signed-off-by: River Phillips --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 50d24de7cad6..720d74da85b5 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -148,12 +148,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Aspect Bazel helpers", project_desc = "Base Starlark libraries and basic Bazel rules which are useful for constructing rulesets and BUILD files", project_url = "https://github.com/aspect-build/bazel-lib", - version = "2.0.3", - sha256 = "c858cc637db5370f6fd752478d1153955b4b4cbec7ffe95eb4a47a48499a79c3", + version = "2.1.0", + sha256 = "fc8bd670380eaba5314769abbe9fee21d641e3da06d9d26b8073a301f6d62332", strip_prefix = "bazel-lib-{version}", urls = ["https://github.com/aspect-build/bazel-lib/archive/v{version}.tar.gz"], use_category = ["build"], - release_date = "2023-12-08", + release_date = "2023-12-23", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/aspect-build/bazel-lib/blob/v{version}/LICENSE", From 09ad5574dbc166957c3a3898ed5c2b6bcba0fa66 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Wed, 27 Dec 2023 21:52:53 -0500 Subject: [PATCH 050/126] ext_proc: Correct the filter type in the tests (#31527) It should be http filter (envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter), rather than listener filter Signed-off-by: tyxia --- .../filters/http/ext_proc/ext_proc_integration_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc index a7e111a13ffd..b75f2eb4e142 100644 --- a/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc +++ b/test/extensions/filters/http/ext_proc/ext_proc_integration_test.cc @@ -110,7 +110,7 @@ class ExtProcIntegrationTest : public HttpIntegrationTest, } // Construct a configuration proto for our filter and then re-write it // to JSON so that we can add it to the overall config - envoy::config::listener::v3::Filter ext_proc_filter; + envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter ext_proc_filter; std::string ext_proc_filter_name = "envoy.filters.http.ext_proc"; ext_proc_filter.set_name(ext_proc_filter_name); ext_proc_filter.mutable_typed_config()->PackFrom(proto_config_); @@ -123,7 +123,7 @@ class ExtProcIntegrationTest : public HttpIntegrationTest, test::integration::filters::LoggingTestFilterConfig logging_filter_config; logging_filter_config.set_logging_id(ext_proc_filter_name); logging_filter_config.set_upstream_cluster_name(valid_grpc_cluster_name); - envoy::config::listener::v3::Filter logging_filter; + envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter logging_filter; logging_filter.set_name("logging-test-filter"); logging_filter.mutable_typed_config()->PackFrom(logging_filter_config); @@ -2474,7 +2474,7 @@ TEST_P(ExtProcIntegrationTest, PerRouteGrpcService) { test::integration::filters::LoggingTestFilterConfig logging_filter_config; logging_filter_config.set_logging_id("envoy.filters.http.ext_proc"); logging_filter_config.set_upstream_cluster_name("ext_proc_server_1"); - envoy::config::listener::v3::Filter logging_filter; + envoy::extensions::filters::network::http_connection_manager::v3::HttpFilter logging_filter; logging_filter.set_name("logging-test-filter"); logging_filter.mutable_typed_config()->PackFrom(logging_filter_config); From 9d18a6c6fefe6bf2261e319d367168c66d779216 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 28 Dec 2023 11:40:48 +0000 Subject: [PATCH 051/126] dns: Switch resolution debug -> trace (#31505) Signed-off-by: Ryan Northey --- source/extensions/clusters/logical_dns/logical_dns_cluster.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc index de67ee077bb1..f1e84526b68f 100644 --- a/source/extensions/clusters/logical_dns/logical_dns_cluster.cc +++ b/source/extensions/clusters/logical_dns/logical_dns_cluster.cc @@ -90,7 +90,7 @@ LogicalDnsCluster::~LogicalDnsCluster() { } void LogicalDnsCluster::startResolve() { - ENVOY_LOG(debug, "starting async DNS resolution for {}", dns_address_); + ENVOY_LOG(trace, "starting async DNS resolution for {}", dns_address_); info_->configUpdateStats().update_attempt_.inc(); active_dns_query_ = dns_resolver_->resolve( @@ -98,7 +98,7 @@ void LogicalDnsCluster::startResolve() { [this](Network::DnsResolver::ResolutionStatus status, std::list&& response) -> void { active_dns_query_ = nullptr; - ENVOY_LOG(debug, "async DNS resolution complete for {}", dns_address_); + ENVOY_LOG(trace, "async DNS resolution complete for {}", dns_address_); std::chrono::milliseconds final_refresh_rate = dns_refresh_rate_ms_; From 037f968192efb169180821dc879d713be46da7f2 Mon Sep 17 00:00:00 2001 From: Henry Qin Date: Thu, 28 Dec 2023 03:45:03 -0800 Subject: [PATCH 052/126] Fix compiler warnings in unit tests. (#31435) This commit fixes three compiler warnings of the type [-Werror=range-loop-construct] Here is one example: ``` test/common/router/config_impl_test.cc:2207:27: error: loop variable 'header' of type 'const string&' {aka 'const std::__cxx11::basic_string&'} binds to a temporary constructed from type 'const char* const' ``` Signed-off-by: Henry Qin Co-authored-by: Ubuntu From 57f23d3092956972f2c23f869280310c7a65ca33 Mon Sep 17 00:00:00 2001 From: StarryNight Date: Thu, 28 Dec 2023 20:04:19 +0800 Subject: [PATCH 053/126] lua support cluster specifier extension (#31034) * lua cluster specifier api Signed-off-by: wangkai19 * fix api format Signed-off-by: wangkai19 * add validate for api filed Signed-off-by: wangkai19 * fix api format Signed-off-by: wangkai19 * implement lua cluster specifier plugin Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * add example Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * fix format Signed-off-by: wangkai19 * fix example Signed-off-by: wangkai19 * fix review Signed-off-by: wangkai19 * fix dep ci Signed-off-by: wangkai19 * add changelog Signed-off-by: wangkai19 * fix review Signed-off-by: wangkai19 * fix ut Signed-off-by: wangkai19 * add test Signed-off-by: wangkai19 --------- Signed-off-by: wangkai19 --- CODEOWNERS | 3 + api/BUILD | 1 + .../router/cluster_specifiers/lua/v3/BUILD | 12 ++ .../cluster_specifiers/lua/v3/lua.proto | 27 ++++ api/versioning/BUILD | 1 + bazel/repository_locations.bzl | 5 +- changelogs/current.yaml | 3 + .../cluster_specifier/cluster_specifier.rst | 8 + docs/root/api-v3/config/config.rst | 1 + .../cluster_specifier/cluster_specifier.rst | 1 + .../http/cluster_specifier/lua.rst | 92 +++++++++++ docs/root/start/sandboxes/index.rst | 1 + .../start/sandboxes/lua-cluster-specifier.rst | 71 +++++++++ examples/lua-cluster-specifier/README.md | 2 + .../lua-cluster-specifier/docker-compose.yaml | 14 ++ examples/lua-cluster-specifier/envoy.yaml | 58 +++++++ examples/lua-cluster-specifier/verify.sh | 19 +++ source/extensions/extensions_build_config.bzl | 6 + source/extensions/extensions_metadata.yaml | 7 + .../router/cluster_specifiers/lua/BUILD | 41 +++++ .../router/cluster_specifiers/lua/config.cc | 23 +++ .../router/cluster_specifiers/lua/config.h | 28 ++++ .../lua/lua_cluster_specifier.cc | 93 +++++++++++ .../lua/lua_cluster_specifier.h | 119 +++++++++++++++ .../router/cluster_specifiers/lua/BUILD | 35 +++++ .../cluster_specifiers/lua/config_test.cc | 69 +++++++++ .../lua/lua_cluster_specifier_test.cc | 144 ++++++++++++++++++ 27 files changed, 883 insertions(+), 1 deletion(-) create mode 100644 api/envoy/extensions/router/cluster_specifiers/lua/v3/BUILD create mode 100644 api/envoy/extensions/router/cluster_specifiers/lua/v3/lua.proto create mode 100644 docs/root/api-v3/config/cluster_specifier/cluster_specifier.rst create mode 100644 docs/root/configuration/http/cluster_specifier/lua.rst create mode 100644 docs/root/start/sandboxes/lua-cluster-specifier.rst create mode 100644 examples/lua-cluster-specifier/README.md create mode 100644 examples/lua-cluster-specifier/docker-compose.yaml create mode 100644 examples/lua-cluster-specifier/envoy.yaml create mode 100755 examples/lua-cluster-specifier/verify.sh create mode 100644 source/extensions/router/cluster_specifiers/lua/BUILD create mode 100644 source/extensions/router/cluster_specifiers/lua/config.cc create mode 100644 source/extensions/router/cluster_specifiers/lua/config.h create mode 100644 source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.cc create mode 100644 source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h create mode 100644 test/extensions/router/cluster_specifiers/lua/BUILD create mode 100644 test/extensions/router/cluster_specifiers/lua/config_test.cc create mode 100644 test/extensions/router/cluster_specifiers/lua/lua_cluster_specifier_test.cc diff --git a/CODEOWNERS b/CODEOWNERS index 02cf03558979..dd0f36e455fe 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -333,6 +333,9 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 /*/extensions/health_checkers/common @zuercher @botengyao +# Lua cluster specifier +/*/extensions/router/cluster_specifiers/lua @StarryVae @wbpcode + # Intentionally exempt (treated as core code) /*/extensions/filters/common @UNOWNED @UNOWNED /*/extensions/filters/http/common @UNOWNED @UNOWNED diff --git a/api/BUILD b/api/BUILD index e9eb8cd0c252..16a0037cf8e8 100644 --- a/api/BUILD +++ b/api/BUILD @@ -309,6 +309,7 @@ proto_library( "//envoy/extensions/retry/host/omit_host_metadata/v3:pkg", "//envoy/extensions/retry/host/previous_hosts/v3:pkg", "//envoy/extensions/retry/priority/previous_priorities/v3:pkg", + "//envoy/extensions/router/cluster_specifiers/lua/v3:pkg", "//envoy/extensions/stat_sinks/graphite_statsd/v3:pkg", "//envoy/extensions/stat_sinks/open_telemetry/v3:pkg", "//envoy/extensions/stat_sinks/wasm/v3:pkg", diff --git a/api/envoy/extensions/router/cluster_specifiers/lua/v3/BUILD b/api/envoy/extensions/router/cluster_specifiers/lua/v3/BUILD new file mode 100644 index 000000000000..09a37ad16b83 --- /dev/null +++ b/api/envoy/extensions/router/cluster_specifiers/lua/v3/BUILD @@ -0,0 +1,12 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/config/core/v3:pkg", + "@com_github_cncf_xds//udpa/annotations:pkg", + ], +) diff --git a/api/envoy/extensions/router/cluster_specifiers/lua/v3/lua.proto b/api/envoy/extensions/router/cluster_specifiers/lua/v3/lua.proto new file mode 100644 index 000000000000..b8ea10a02df7 --- /dev/null +++ b/api/envoy/extensions/router/cluster_specifiers/lua/v3/lua.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package envoy.extensions.router.cluster_specifiers.lua.v3; + +import "envoy/config/core/v3/base.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.router.cluster_specifiers.lua.v3"; +option java_outer_classname = "LuaProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/router/cluster_specifiers/lua/v3;luav3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Lua] +// +// Lua cluster specifier :ref:`configuration reference documentation `. +// [#extension: envoy.router.cluster_specifier_plugin.lua] + +message LuaConfig { + // The lua code that Envoy will execute to select cluster. + config.core.v3.DataSource source_code = 1 [(validate.rules).message = {required: true}]; + + // Default cluster. It will be used when the lua code execute failure. + string default_cluster = 2; +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 828efeaa0dd2..65ba4dc5c75f 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -248,6 +248,7 @@ proto_library( "//envoy/extensions/retry/host/omit_host_metadata/v3:pkg", "//envoy/extensions/retry/host/previous_hosts/v3:pkg", "//envoy/extensions/retry/priority/previous_priorities/v3:pkg", + "//envoy/extensions/router/cluster_specifiers/lua/v3:pkg", "//envoy/extensions/stat_sinks/graphite_statsd/v3:pkg", "//envoy/extensions/stat_sinks/open_telemetry/v3:pkg", "//envoy/extensions/stat_sinks/wasm/v3:pkg", diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 720d74da85b5..b2317039cee5 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -477,7 +477,10 @@ REPOSITORY_LOCATIONS_SPEC = dict( urls = ["https://github.com/LuaJIT/LuaJIT/archive/{version}.tar.gz"], release_date = "2023-04-16", use_category = ["dataplane_ext"], - extensions = ["envoy.filters.http.lua"], + extensions = [ + "envoy.filters.http.lua", + "envoy.router.cluster_specifier_plugin.lua", + ], cpe = "cpe:2.3:a:luajit:luajit:*", license = "MIT", license_url = "https://github.com/LuaJIT/LuaJIT/blob/{version}/COPYRIGHT", diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 5494ba2ba005..86c12032c43b 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -320,6 +320,9 @@ new_features: to add multiple namespaces with one filter and config to overwrite existing metadata is opt-in. :ref:`untyped_metadata ` may now be used to configure the ``set_metadata`` filter. +- area: lua + change: | + Added lua extension of router cluster specifier plugin to support selecting cluster dynamically by lua code. deprecated: - area: wasm diff --git a/docs/root/api-v3/config/cluster_specifier/cluster_specifier.rst b/docs/root/api-v3/config/cluster_specifier/cluster_specifier.rst new file mode 100644 index 000000000000..6202887d3121 --- /dev/null +++ b/docs/root/api-v3/config/cluster_specifier/cluster_specifier.rst @@ -0,0 +1,8 @@ +Cluster specifier +================= + +.. toctree:: + :glob: + :maxdepth: 2 + + ../../extensions/router/cluster_specifiers/*/v3/* diff --git a/docs/root/api-v3/config/config.rst b/docs/root/api-v3/config/config.rst index 015f5e20cb50..12d216da67c8 100644 --- a/docs/root/api-v3/config/config.rst +++ b/docs/root/api-v3/config/config.rst @@ -45,3 +45,4 @@ Extensions wasm/wasm watchdog/watchdog load_balancing_policies/load_balancing_policies + cluster_specifier/cluster_specifier diff --git a/docs/root/configuration/http/cluster_specifier/cluster_specifier.rst b/docs/root/configuration/http/cluster_specifier/cluster_specifier.rst index 54e3d14fc1ef..c3c799abf131 100644 --- a/docs/root/configuration/http/cluster_specifier/cluster_specifier.rst +++ b/docs/root/configuration/http/cluster_specifier/cluster_specifier.rst @@ -7,3 +7,4 @@ HTTP cluster specifier :maxdepth: 2 golang + lua diff --git a/docs/root/configuration/http/cluster_specifier/lua.rst b/docs/root/configuration/http/cluster_specifier/lua.rst new file mode 100644 index 000000000000..0cab42c25cd0 --- /dev/null +++ b/docs/root/configuration/http/cluster_specifier/lua.rst @@ -0,0 +1,92 @@ +.. _config_http_cluster_specifier_lua: + +Lua cluster specifier +===================== + +Overview +-------- + +The HTTP Lua cluster specifier allows `Lua `_ scripts to select router cluster +during the request flows. `LuaJIT `_ is used as the runtime. Because of this, the +supported Lua version is mostly 5.1 with some 5.2 features. See the `LuaJIT documentation +`_ for more details. + +Configuration +------------- + +* This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.router.cluster_specifiers.lua.v3.LuaConfig``. +* :ref:`v3 API reference ` + +A simple example of configuring Lua cluster specifier is as follow: + +.. code-block:: yaml + + routes: + - match: + prefix: "/" + route: + inline_cluster_specifier_plugin: + extension: + name: envoy.router.cluster_specifier_plugin.lua + typed_config: + "@type": type.googleapis.com/envoy.extensions.router.cluster_specifiers.lua.v3.LuaConfig + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: web_service + +Lua script defined in ``source_code`` will be executed to select router cluster, and just as cluster specifier +plugin in C++, Lua script can also select router cluster based on request headers. If Lua script execute failure, +``default_cluster`` will be used. + +Complete example +---------------- + +A complete example using Docker is available in :repo:`/examples/lua-cluster-specifier`. + +Route handle API +---------------- + +When Envoy loads the script in the configuration, it looks for a global function that the script defines: + +.. code-block:: lua + + function envoy_on_route(route_handle) + end + +During the route path, Envoy will run *envoy_on_route* as a coroutine, passing a handle to the route API. + +The following methods on the stream handle are supported: + +headers() +^^^^^^^^^ + +.. code-block:: lua + + local headers = handle:headers() + +Returns the stream's headers. The headers can be used to match to select a specific cluster. + +Returns a :ref:`header object `. + +.. _config_lua_cluster_specifier_header_wrapper: + +Header object API +----------------- + +get() +^^^^^ + +.. code-block:: lua + + headers:get(key) + +Gets a header. *key* is a string that supplies the header key. Returns a string that is the header +value or nil if there is no such header. If there are multiple headers in the same case-insensitive +key, their values will be combined with a *,* separator and returned as a string. diff --git a/docs/root/start/sandboxes/index.rst b/docs/root/start/sandboxes/index.rst index d04bf9eb78e7..aa8ce6e7ca85 100644 --- a/docs/root/start/sandboxes/index.rst +++ b/docs/root/start/sandboxes/index.rst @@ -65,6 +65,7 @@ The following sandboxes are available: load_reporting_service locality_load_balancing local_ratelimit + lua-cluster-specifier lua mysql opentelemetry diff --git a/docs/root/start/sandboxes/lua-cluster-specifier.rst b/docs/root/start/sandboxes/lua-cluster-specifier.rst new file mode 100644 index 000000000000..a7e4c852c849 --- /dev/null +++ b/docs/root/start/sandboxes/lua-cluster-specifier.rst @@ -0,0 +1,71 @@ +.. _install_sandboxes_lua_cluster_specifier: + +Lua Cluster Specifier +===================== + +.. sidebar:: Requirements + + .. include:: _include/docker-env-setup-link.rst + + :ref:`curl ` + Used to make ``HTTP`` requests. + +In this example, we show how the `Lua `_ cluster specifier can be used with the +Envoy proxy. + +The example Envoy proxy configuration includes a Lua cluster specifier plugin that contains a function: + +- ``envoy_on_route(route_handle)`` + +:ref:`See here ` for an overview of Envoy's Lua cluster specifier +and documentation regarding the function. + +Step 1: Build the sandbox +************************* + +Change to the ``examples/lua-cluster-specifier`` directory. + +.. code-block:: console + + $ pwd + envoy/examples/lua-cluster-specifier + $ docker compose pull + $ docker compose up --build -d + $ docker compose ps + + Name Command State Ports + -------------------------------------------------------------------------------------------- + lua-cluster-specifier-proxy-1 /docker-entrypoint.sh /usr ... Up 10000/tcp, 0.0.0.0:8000->8000/tcp + lua-cluster-specifier-web_service-1 /bin/echo-server Up 0.0.0.0:8080->8080/tcp + +Step 2: Send a request to the normal service +******************************************** + +The output from the ``curl`` command below should return 200, since the lua code select the normal service. + +Terminal 1 + +.. code-block:: console + + $ curl -i localhost:8000/anything 2>&1 |grep 200 + HTTP/1.1 200 OK + +Step 3: Send a request to the fake service +****************************************** + +The output from the ``curl`` command below should return 503, since the lua code select the fake service. + +Terminal 1 + +.. code-block:: console + + $ curl -i localhost:8000/anything -H "header_key:fake" 2>&1 |grep 503 + HTTP/1.1 503 Service Unavailable + +.. seealso:: + + :ref:`Envoy Lua cluster specifier ` + Learn more about the Envoy Lua cluster specifier. + + `Lua `_ + The Lua programming language. diff --git a/examples/lua-cluster-specifier/README.md b/examples/lua-cluster-specifier/README.md new file mode 100644 index 000000000000..0a1cd344b9b1 --- /dev/null +++ b/examples/lua-cluster-specifier/README.md @@ -0,0 +1,2 @@ +To learn about this sandbox and for instructions on how to run it please head over +to the [envoy docs](https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/lua-cluster-specifier.html) diff --git a/examples/lua-cluster-specifier/docker-compose.yaml b/examples/lua-cluster-specifier/docker-compose.yaml new file mode 100644 index 000000000000..904b030f8417 --- /dev/null +++ b/examples/lua-cluster-specifier/docker-compose.yaml @@ -0,0 +1,14 @@ +services: + + proxy: + build: + context: . + dockerfile: ../shared/envoy/Dockerfile + ports: + - "${PORT_PROXY:-8000}:8000" + + web_service: + build: + context: ../shared/echo + ports: + - "${PORT_WEB:-8080}:8080" diff --git a/examples/lua-cluster-specifier/envoy.yaml b/examples/lua-cluster-specifier/envoy.yaml new file mode 100644 index 000000000000..058e28179395 --- /dev/null +++ b/examples/lua-cluster-specifier/envoy.yaml @@ -0,0 +1,58 @@ +static_resources: + listeners: + - name: main + address: + socket_address: + address: 0.0.0.0 + port_value: 8000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress_http + codec_type: AUTO + route_config: + name: local_route + virtual_hosts: + - name: local_service + domains: + - "*" + routes: + - match: + prefix: "/" + route: + inline_cluster_specifier_plugin: + extension: + name: envoy.router.cluster_specifier_plugin.lua + typed_config: + "@type": type.googleapis.com/envoy.extensions.router.cluster_specifiers.lua.v3.LuaConfig + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: web_service + + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + clusters: + - name: web_service + type: STRICT_DNS # static + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: web_service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: httpbin.org + port_value: 80 diff --git a/examples/lua-cluster-specifier/verify.sh b/examples/lua-cluster-specifier/verify.sh new file mode 100755 index 000000000000..ec37d5b46d89 --- /dev/null +++ b/examples/lua-cluster-specifier/verify.sh @@ -0,0 +1,19 @@ +#!/bin/bash -e + +export NAME=lua-cluster-specifier +export PORT_PROXY="${LUA_CLUSTER_PORT_PROXY:-12620}" +export PORT_WEB="${LUA_CLUSTER_PORT_WEB:-12621}" + +# shellcheck source=examples/verify-common.sh +. "$(dirname "${BASH_SOURCE[0]}")/../verify-common.sh" + +run_log "Test Lua cluster specifier with normal cluster" +responds_with_header \ + "HTTP/1.1 200 OK" \ + "http://localhost:${PORT_PROXY}/" + +run_log "Test Lua cluster specifier with fake cluster" +responds_with_header \ + "HTTP/1.1 503 Service Unavailable" \ + "http://localhost:${PORT_PROXY}/" \ + -H 'header_key: fake' diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index efa1de486e61..a67bf3be4744 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -494,6 +494,12 @@ EXTENSIONS = { # Geolocation Provider # "envoy.geoip_providers.maxmind": "//source/extensions/geoip_providers/maxmind:config", + + # + # cluster specifier plugin + # + + "envoy.router.cluster_specifier_plugin.lua": "//source/extensions/router/cluster_specifiers/lua:config", } # These can be changed to ["//visibility:public"], for downstream builds which diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 739f8a5003d3..587fb00c0363 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -1073,6 +1073,13 @@ envoy.route.early_data_policy.default: status: stable type_urls: - envoy.extensions.early_data.v3.DefaultEarlyDataPolicy +envoy.router.cluster_specifier_plugin.lua: + categories: + - envoy.router.cluster_specifier_plugin + security_posture: robust_to_untrusted_downstream_and_upstream + status: alpha + type_urls: + - envoy.extensions.router.cluster_specifiers.lua.v3.LuaConfig envoy.stat_sinks.dog_statsd: categories: - envoy.stats_sinks diff --git a/source/extensions/router/cluster_specifiers/lua/BUILD b/source/extensions/router/cluster_specifiers/lua/BUILD new file mode 100644 index 000000000000..92927266d15e --- /dev/null +++ b/source/extensions/router/cluster_specifiers/lua/BUILD @@ -0,0 +1,41 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +# Lua cluster specifier plugin. + +envoy_extension_package() + +envoy_cc_library( + name = "lua_cluster_specifier_lib", + srcs = [ + "lua_cluster_specifier.cc", + ], + hdrs = [ + "lua_cluster_specifier.h", + ], + deps = [ + "//envoy/router:cluster_specifier_plugin_interface", + "//source/common/common:utility_lib", + "//source/common/http:utility_lib", + "//source/common/router:config_lib", + "//source/extensions/filters/common/lua:lua_lib", + "//source/extensions/filters/common/lua:wrappers_lib", + "@envoy_api//envoy/extensions/router/cluster_specifiers/lua/v3:pkg_cc_proto", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + ":lua_cluster_specifier_lib", + "//envoy/registry", + ], +) diff --git a/source/extensions/router/cluster_specifiers/lua/config.cc b/source/extensions/router/cluster_specifiers/lua/config.cc new file mode 100644 index 000000000000..fb7930caf859 --- /dev/null +++ b/source/extensions/router/cluster_specifiers/lua/config.cc @@ -0,0 +1,23 @@ +#include "source/extensions/router/cluster_specifiers/lua/config.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +Envoy::Router::ClusterSpecifierPluginSharedPtr +LuaClusterSpecifierPluginFactoryConfig::createClusterSpecifierPlugin( + const Protobuf::Message& config, Server::Configuration::CommonFactoryContext& context) { + + const auto& typed_config = dynamic_cast(config); + auto cluster_config = std::make_shared(typed_config, context); + return std::make_shared(cluster_config); +} + +REGISTER_FACTORY(LuaClusterSpecifierPluginFactoryConfig, + Envoy::Router::ClusterSpecifierPluginFactoryConfig); + +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/router/cluster_specifiers/lua/config.h b/source/extensions/router/cluster_specifiers/lua/config.h new file mode 100644 index 000000000000..2b9793b08099 --- /dev/null +++ b/source/extensions/router/cluster_specifiers/lua/config.h @@ -0,0 +1,28 @@ +#pragma once + +#include "source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +class LuaClusterSpecifierPluginFactoryConfig + : public Envoy::Router::ClusterSpecifierPluginFactoryConfig { +public: + LuaClusterSpecifierPluginFactoryConfig() = default; + Envoy::Router::ClusterSpecifierPluginSharedPtr + createClusterSpecifierPlugin(const Protobuf::Message& config, + Server::Configuration::CommonFactoryContext&) override; + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + + std::string name() const override { return "envoy.router.cluster_specifier_plugin.lua"; } +}; + +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.cc b/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.cc new file mode 100644 index 000000000000..c226a78c4a0a --- /dev/null +++ b/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.cc @@ -0,0 +1,93 @@ +#include "source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h" + +#include "source/common/router/config_impl.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +PerLuaCodeSetup::PerLuaCodeSetup(const std::string& lua_code, ThreadLocal::SlotAllocator& tls) + : lua_state_(lua_code, tls) { + lua_state_.registerType(); + lua_state_.registerType(); + + const Filters::Common::Lua::InitializerList initializers; + + cluster_function_slot_ = lua_state_.registerGlobal("envoy_on_route", initializers); + if (lua_state_.getGlobalRef(cluster_function_slot_) == LUA_REFNIL) { + throw EnvoyException( + "envoy_on_route() function not found. Lua will not hook cluster specifier."); + } +} + +int HeaderMapWrapper::luaGet(lua_State* state) { + absl::string_view key = Filters::Common::Lua::getStringViewFromLuaString(state, 2); + const Envoy::Http::HeaderUtility::GetAllOfHeaderAsStringResult value = + Envoy::Http::HeaderUtility::getAllOfHeaderAsString(headers_, + Envoy::Http::LowerCaseString(key)); + if (value.result().has_value()) { + lua_pushlstring(state, value.result().value().data(), value.result().value().size()); + return 1; + } else { + return 0; + } +} + +int RouteHandleWrapper::luaHeaders(lua_State* state) { + if (headers_wrapper_.get() != nullptr) { + headers_wrapper_.pushStack(); + } else { + headers_wrapper_.reset(HeaderMapWrapper::create(state, headers_), true); + } + return 1; +} + +LuaClusterSpecifierConfig::LuaClusterSpecifierConfig( + const LuaClusterSpecifierConfigProto& config, + Server::Configuration::CommonFactoryContext& context) + : main_thread_dispatcher_(context.mainThreadDispatcher()), + default_cluster_(config.default_cluster()) { + const std::string code_str = Config::DataSource::read(config.source_code(), true, context.api()); + per_lua_code_setup_ptr_ = std::make_unique(code_str, context.threadLocal()); +} + +LuaClusterSpecifierPlugin::LuaClusterSpecifierPlugin(LuaClusterSpecifierConfigSharedPtr config) + : config_(config), + function_ref_(config_->perLuaCodeSetup() ? config_->perLuaCodeSetup()->clusterFunctionRef() + : LUA_REFNIL) {} + +std::string LuaClusterSpecifierPlugin::startLua(const Http::HeaderMap& headers) const { + if (function_ref_ == LUA_REFNIL) { + return config_->defaultCluster(); + } + Filters::Common::Lua::CoroutinePtr coroutine = config_->perLuaCodeSetup()->createCoroutine(); + + RouteHandleRef handle; + handle.reset(RouteHandleWrapper::create(coroutine->luaState(), headers), true); + + TRY_NEEDS_AUDIT { + coroutine->start(function_ref_, 1, []() {}); + } + END_TRY catch (const Filters::Common::Lua::LuaException& e) { + ENVOY_LOG(error, "script log: {}, use default cluster", e.what()); + return config_->defaultCluster(); + } + if (!lua_isstring(coroutine->luaState(), -1)) { + ENVOY_LOG(error, "script log: return value is not string, use default cluster"); + return config_->defaultCluster(); + } + return std::string(Filters::Common::Lua::getStringViewFromLuaString(coroutine->luaState(), -1)); +} + +Envoy::Router::RouteConstSharedPtr +LuaClusterSpecifierPlugin::route(Envoy::Router::RouteConstSharedPtr parent, + const Http::RequestHeaderMap& headers) const { + return std::make_shared( + dynamic_cast(parent.get()), parent, + startLua(headers)); +} +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h b/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h new file mode 100644 index 000000000000..5a6ddb9d6a08 --- /dev/null +++ b/source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h @@ -0,0 +1,119 @@ +#pragma once + +#include "envoy/extensions/router/cluster_specifiers/lua/v3/lua.pb.h" +#include "envoy/router/cluster_specifier_plugin.h" + +#include "source/common/config/datasource.h" +#include "source/extensions/filters/common/lua/wrappers.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +using LuaClusterSpecifierConfigProto = + envoy::extensions::router::cluster_specifiers::lua::v3::LuaConfig; + +class PerLuaCodeSetup : Logger::Loggable { +public: + PerLuaCodeSetup(const std::string& lua_code, ThreadLocal::SlotAllocator& tls); + + Extensions::Filters::Common::Lua::CoroutinePtr createCoroutine() { + return lua_state_.createCoroutine(); + } + + int clusterFunctionRef() { return lua_state_.getGlobalRef(cluster_function_slot_); } + +private: + uint64_t cluster_function_slot_{}; + + Filters::Common::Lua::ThreadLocalState lua_state_; +}; + +using PerLuaCodeSetupPtr = std::unique_ptr; + +class HeaderMapWrapper : public Filters::Common::Lua::BaseLuaObject { +public: + HeaderMapWrapper(const Http::HeaderMap& headers) : headers_(headers) {} + + static ExportedFunctions exportedFunctions() { return {{"get", static_luaGet}}; } + +private: + /** + * Get a header value from the map. + * @param 1 (string): header name. + * @return string value if found or nil. + */ + DECLARE_LUA_FUNCTION(HeaderMapWrapper, luaGet); + + const Http::HeaderMap& headers_; +}; + +using HeaderMapRef = Filters::Common::Lua::LuaDeathRef; + +class RouteHandleWrapper : public Filters::Common::Lua::BaseLuaObject { +public: + RouteHandleWrapper(const Http::HeaderMap& headers) : headers_(headers) {} + + static ExportedFunctions exportedFunctions() { return {{"headers", static_luaHeaders}}; } + +private: + /** + * @return a handle to the headers. + */ + DECLARE_LUA_FUNCTION(RouteHandleWrapper, luaHeaders); + + const Http::HeaderMap& headers_; + HeaderMapRef headers_wrapper_; +}; + +using RouteHandleRef = Filters::Common::Lua::LuaDeathRef; + +class LuaClusterSpecifierConfig : Logger::Loggable { +public: + LuaClusterSpecifierConfig(const LuaClusterSpecifierConfigProto& config, + Server::Configuration::CommonFactoryContext& context); + + ~LuaClusterSpecifierConfig() { + // The design of the TLS system does not allow TLS state to be modified in worker threads. + // However, when the route configuration is dynamically updated via RDS, the old + // LuaClusterSpecifierConfig object may be destructed in a random worker thread. Therefore, to + // ensure thread safety, ownership of per_lua_code_setup_ptr_ must be transferred to the main + // thread and destroyed when the LuaClusterSpecifierConfig object is not destructed in the main + // thread. + if (per_lua_code_setup_ptr_ && !main_thread_dispatcher_.isThreadSafe()) { + auto shared_ptr_wrapper = + std::make_shared(std::move(per_lua_code_setup_ptr_)); + main_thread_dispatcher_.post([shared_ptr_wrapper] { shared_ptr_wrapper->reset(); }); + } + } + + PerLuaCodeSetup* perLuaCodeSetup() const { return per_lua_code_setup_ptr_.get(); } + const std::string& defaultCluster() const { return default_cluster_; } + +private: + Event::Dispatcher& main_thread_dispatcher_; + PerLuaCodeSetupPtr per_lua_code_setup_ptr_; + const std::string default_cluster_; +}; + +using LuaClusterSpecifierConfigSharedPtr = std::shared_ptr; + +class LuaClusterSpecifierPlugin : public Envoy::Router::ClusterSpecifierPlugin, + Logger::Loggable { +public: + LuaClusterSpecifierPlugin(LuaClusterSpecifierConfigSharedPtr config); + Envoy::Router::RouteConstSharedPtr route(Envoy::Router::RouteConstSharedPtr parent, + const Http::RequestHeaderMap& header) const override; + +private: + std::string startLua(const Http::HeaderMap& headers) const; + + LuaClusterSpecifierConfigSharedPtr config_; + const int function_ref_; +}; + +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/router/cluster_specifiers/lua/BUILD b/test/extensions/router/cluster_specifiers/lua/BUILD new file mode 100644 index 000000000000..f086f868f56c --- /dev/null +++ b/test/extensions/router/cluster_specifiers/lua/BUILD @@ -0,0 +1,35 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "lua_cluster_specifier_test", + srcs = ["lua_cluster_specifier_test.cc"], + extension_names = ["envoy.router.cluster_specifier_plugin.lua"], + deps = [ + "//source/extensions/router/cluster_specifiers/lua:lua_cluster_specifier_lib", + "//test/mocks/router:router_mocks", + "//test/mocks/server:factory_context_mocks", + "//test/test_common:utility_lib", + ], +) + +envoy_extension_cc_test( + name = "config_test", + srcs = ["config_test.cc"], + extension_names = ["envoy.router.cluster_specifier_plugin.lua"], + deps = [ + "//source/extensions/router/cluster_specifiers/lua:config", + "//test/mocks/server:factory_context_mocks", + "//test/test_common:utility_lib", + ], +) diff --git a/test/extensions/router/cluster_specifiers/lua/config_test.cc b/test/extensions/router/cluster_specifiers/lua/config_test.cc new file mode 100644 index 000000000000..ff23f0a556b6 --- /dev/null +++ b/test/extensions/router/cluster_specifiers/lua/config_test.cc @@ -0,0 +1,69 @@ +#include "source/extensions/router/cluster_specifiers/lua/config.h" + +#include "test/mocks/server/factory_context.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +TEST(LuaClusterSpecifierPluginConfigTest, EmptyConfig) { + LuaClusterSpecifierPluginFactoryConfig factory; + + ProtobufTypes::MessagePtr empty_config = factory.createEmptyConfigProto(); + EXPECT_NE(nullptr, empty_config); +} + +TEST(LuaClusterSpecifierPluginConfigTest, NormalConfig) { + const std::string normal_lua_config_yaml = R"EOF( + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: default_service + )EOF"; + + LuaClusterSpecifierConfigProto proto_config{}; + TestUtility::loadFromYaml(normal_lua_config_yaml, proto_config); + NiceMock context; + LuaClusterSpecifierPluginFactoryConfig factory; + Envoy::Router::ClusterSpecifierPluginSharedPtr plugin = + factory.createClusterSpecifierPlugin(proto_config, context); + EXPECT_NE(nullptr, plugin); +} + +TEST(LuaClusterSpecifierPluginConfigTest, NoOnRouteConfig) { + const std::string normal_lua_config_yaml = R"EOF( + source_code: + inline_string: | + function envoy_on_no_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: default_service + )EOF"; + + LuaClusterSpecifierConfigProto proto_config{}; + TestUtility::loadFromYaml(normal_lua_config_yaml, proto_config); + NiceMock context; + LuaClusterSpecifierPluginFactoryConfig factory; + EXPECT_THROW_WITH_MESSAGE( + factory.createClusterSpecifierPlugin(proto_config, context), Envoy::EnvoyException, + "envoy_on_route() function not found. Lua will not hook cluster specifier."); +} + +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/router/cluster_specifiers/lua/lua_cluster_specifier_test.cc b/test/extensions/router/cluster_specifiers/lua/lua_cluster_specifier_test.cc new file mode 100644 index 000000000000..08e9480b769a --- /dev/null +++ b/test/extensions/router/cluster_specifiers/lua/lua_cluster_specifier_test.cc @@ -0,0 +1,144 @@ +#include "source/extensions/router/cluster_specifiers/lua/lua_cluster_specifier.h" + +#include "test/mocks/router/mocks.h" +#include "test/mocks/server/factory_context.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Router { +namespace Lua { + +using testing::InSequence; +using testing::NiceMock; +using testing::Return; + +class LuaClusterSpecifierPluginTest : public testing::Test { +public: + void setUpTest(const std::string& yaml) { + LuaClusterSpecifierConfigProto proto_config{}; + TestUtility::loadFromYaml(yaml, proto_config); + + config_ = std::make_shared(proto_config, server_factory_context_); + + plugin_ = std::make_unique(config_); + } + + const std::string normal_lua_config_yaml_ = R"EOF( + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: default_service + )EOF"; + + const std::string error_lua_config_yaml_ = R"EOF( + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get({}) + if header_value == "fake" then + return "fake_service" + end + return "web_service" + end + default_cluster: default_service + )EOF"; + + const std::string return_type_not_string_lua_config_yaml_ = R"EOF( + source_code: + inline_string: | + function envoy_on_route(route_handle) + local header_value = route_handle:headers():get("header_key") + if header_value == "fake" then + return "fake_service" + end + return {} + end + default_cluster: default_service + )EOF"; + + NiceMock server_factory_context_; + std::unique_ptr plugin_; + LuaClusterSpecifierConfigSharedPtr config_; +}; + +// Normal lua code test. +TEST_F(LuaClusterSpecifierPluginTest, NormalLuaCode) { + setUpTest(normal_lua_config_yaml_); + + auto mock_route = std::make_shared>(); + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "fake"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("fake_service", route->routeEntry()->clusterName()); + } + + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "header_value"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("web_service", route->routeEntry()->clusterName()); + } +} + +// Error lua code test. +TEST_F(LuaClusterSpecifierPluginTest, ErrorLuaCode) { + setUpTest(error_lua_config_yaml_); + + auto mock_route = std::make_shared>(); + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "fake"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("default_service", route->routeEntry()->clusterName()); + } + + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "header_value"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("default_service", route->routeEntry()->clusterName()); + } +} + +// Return type not string lua code test. +TEST_F(LuaClusterSpecifierPluginTest, ReturnTypeNotStringLuaCode) { + setUpTest(return_type_not_string_lua_config_yaml_); + + auto mock_route = std::make_shared>(); + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "fake"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("fake_service", route->routeEntry()->clusterName()); + } + + { + Http::TestRequestHeaderMapImpl headers{{":path", "/"}, {"header_key", "header_value"}}; + auto route = plugin_->route(mock_route, headers); + EXPECT_EQ("default_service", route->routeEntry()->clusterName()); + } +} + +TEST_F(LuaClusterSpecifierPluginTest, DestructLuaClusterSpecifierConfig) { + setUpTest(normal_lua_config_yaml_); + InSequence s; + EXPECT_CALL(server_factory_context_.dispatcher_, isThreadSafe()).WillOnce(Return(false)); + EXPECT_CALL(server_factory_context_.dispatcher_, post(_)); + EXPECT_CALL(server_factory_context_.dispatcher_, isThreadSafe()).WillOnce(Return(true)); + EXPECT_CALL(server_factory_context_.dispatcher_, post(_)).Times(0); + + LuaClusterSpecifierConfigProto proto_config{}; + TestUtility::loadFromYaml(normal_lua_config_yaml_, proto_config); + config_ = std::make_shared(proto_config, server_factory_context_); + config_.reset(); +} + +} // namespace Lua +} // namespace Router +} // namespace Extensions +} // namespace Envoy From 2991c1d78ab6724cb06d6da53cfdd47de44ace08 Mon Sep 17 00:00:00 2001 From: Zhewei Hu Date: Thu, 28 Dec 2023 08:04:32 -0800 Subject: [PATCH 054/126] [ZK filter] Remove EnvoyException on data plane 2nd attempt (#31485) Signed-off-by: Zhewei Hu --- .../network/zookeeper_proxy/decoder.cc | 791 +++++++++++++----- .../filters/network/zookeeper_proxy/decoder.h | 84 +- .../filters/network/zookeeper_proxy/filter.cc | 33 +- .../filters/network/zookeeper_proxy/filter.h | 10 +- .../filters/network/zookeeper_proxy/utils.cc | 63 +- .../filters/network/zookeeper_proxy/utils.h | 39 +- 6 files changed, 715 insertions(+), 305 deletions(-) diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.cc b/source/extensions/filters/network/zookeeper_proxy/decoder.cc index 968dc798b321..02d7d0b7074b 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.cc +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.cc @@ -42,15 +42,26 @@ const char* createFlagsToString(CreateFlags flags) { return "unknown"; } -absl::optional DecoderImpl::decodeOnData(Buffer::Instance& data, uint64_t& offset) { +absl::StatusOr> DecoderImpl::decodeOnData(Buffer::Instance& data, + uint64_t& offset) { ENVOY_LOG(trace, "zookeeper_proxy: decoding request with {} bytes at offset {}", data.length(), offset); // Check message length. - const int32_t len = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with len {} at offset {}", len, offset); - ensureMinLength(len, XID_LENGTH + INT_LENGTH); // xid + opcode - ensureMaxLength(len); + const absl::StatusOr len = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + len, fmt::format("peekInt32 for len: {}", len.status().message())); + + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with len {} at offset {}", len.value(), + offset); + + absl::Status status = ensureMinLength(len.value(), XID_LENGTH + INT_LENGTH); // xid + opcode + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("ensureMinLength: {}", status.message())); + + status = ensureMaxLength(len.value()); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("ensureMaxLength: {}", status.message())); auto start_time = time_source_.monotonicTime(); @@ -64,26 +75,40 @@ absl::optional DecoderImpl::decodeOnData(Buffer::Instance& data, uint64 // ZooKeeper server to the next. Thus, the special xid. // However, some client implementations might expose setWatches // as a regular data request, so we support that as well. - const int32_t xid = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with xid {} at offset {}", xid, offset); - switch (static_cast(xid)) { + const absl::StatusOr xid = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + xid, fmt::format("peerInt32 for xid: {}", xid.status().message())); + + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with xid {} at offset {}", xid.value(), + offset); + + switch (static_cast(xid.value())) { case XidCodes::ConnectXid: - parseConnect(data, offset, len); - control_requests_by_xid_[xid].push({OpCodes::Connect, std::move(start_time)}); + status = parseConnect(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseConnect: {}", status.message())); + + control_requests_by_xid_[xid.value()].push({OpCodes::Connect, std::move(start_time)}); return OpCodes::Connect; case XidCodes::PingXid: offset += OPCODE_LENGTH; callbacks_.onPing(); - control_requests_by_xid_[xid].push({OpCodes::Ping, std::move(start_time)}); + control_requests_by_xid_[xid.value()].push({OpCodes::Ping, std::move(start_time)}); return OpCodes::Ping; case XidCodes::AuthXid: - parseAuthRequest(data, offset, len); - control_requests_by_xid_[xid].push({OpCodes::SetAuth, std::move(start_time)}); + status = parseAuthRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseAuthRequest: {}", status.message())); + + control_requests_by_xid_[xid.value()].push({OpCodes::SetAuth, std::move(start_time)}); return OpCodes::SetAuth; case XidCodes::SetWatchesXid: offset += OPCODE_LENGTH; - parseSetWatchesRequest(data, offset, len); - control_requests_by_xid_[xid].push({OpCodes::SetWatches, std::move(start_time)}); + status = parseSetWatchesRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseSetWatchesRequest: {}", status.message())); + + control_requests_by_xid_[xid.value()].push({OpCodes::SetWatches, std::move(start_time)}); return OpCodes::SetWatches; default: // WATCH_XID is generated by the server, so that and everything @@ -97,100 +122,164 @@ absl::optional DecoderImpl::decodeOnData(Buffer::Instance& data, uint64 // for two cases: auth requests can happen at any time and ping requests // must happen every 1/3 of the negotiated session timeout, to keep // the session alive. - const int32_t oc = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding request with opcode {} at offset {}", oc, offset); - const auto opcode = static_cast(oc); + const absl::StatusOr oc = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + oc, fmt::format("peekInt32 for opcode: {}", oc.status().message())); + + ENVOY_LOG(trace, "zookeeper_proxy: decoding request with opcode {} at offset {}", oc.value(), + offset); + + const auto opcode = static_cast(oc.value()); switch (opcode) { case OpCodes::GetData: - parseGetDataRequest(data, offset, len); + status = parseGetDataRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseGetDataRequest: {}", status.message())); break; case OpCodes::Create: case OpCodes::Create2: case OpCodes::CreateContainer: case OpCodes::CreateTtl: - parseCreateRequest(data, offset, len, static_cast(opcode)); + status = parseCreateRequest(data, offset, len.value(), static_cast(opcode)); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseCreateRequest: {}", status.message())); break; case OpCodes::SetData: - parseSetRequest(data, offset, len); + status = parseSetRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseSetRequest: {}", status.message())); break; case OpCodes::GetChildren: - parseGetChildrenRequest(data, offset, len, false); + status = parseGetChildrenRequest(data, offset, len.value(), false); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseGetChildrenRequest: {}", status.message())); break; case OpCodes::GetChildren2: - parseGetChildrenRequest(data, offset, len, true); + status = parseGetChildrenRequest(data, offset, len.value(), true); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseGetChildrenRequest: {}", status.message())); break; case OpCodes::Delete: - parseDeleteRequest(data, offset, len); + status = parseDeleteRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseDeleteRequest: {}", status.message())); break; case OpCodes::Exists: - parseExistsRequest(data, offset, len); + status = parseExistsRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseExistsRequest: {}", status.message())); break; case OpCodes::GetAcl: - parseGetAclRequest(data, offset, len); + status = parseGetAclRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseGetAclRequest: {}", status.message())); break; case OpCodes::SetAcl: - parseSetAclRequest(data, offset, len); + status = parseSetAclRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseSetAclRequest: {}", status.message())); break; case OpCodes::Sync: - callbacks_.onSyncRequest(pathOnlyRequest(data, offset, len)); + status = callbacks_.onSyncRequest(pathOnlyRequest(data, offset, len.value())); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("onSyncRequest: {}", status.message())); break; case OpCodes::Check: - parseCheckRequest(data, offset, len); + status = parseCheckRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseCheckRequest: {}", status.message())); break; case OpCodes::Multi: - parseMultiRequest(data, offset, len); + status = parseMultiRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseMultiRequest: {}", status.message())); break; case OpCodes::Reconfig: - parseReconfigRequest(data, offset, len); + status = parseReconfigRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseReconfigRequest: {}", status.message())); break; case OpCodes::SetWatches: - parseSetWatchesRequest(data, offset, len); + status = parseSetWatchesRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseSetWatchesRequest: {}", status.message())); break; case OpCodes::SetWatches2: - parseSetWatches2Request(data, offset, len); + status = parseSetWatches2Request(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseSetWatches2Request: {}", status.message())); break; case OpCodes::AddWatch: - parseAddWatchRequest(data, offset, len); + status = parseAddWatchRequest(data, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseAddWatchRequest: {}", status.message())); break; case OpCodes::CheckWatches: - parseXWatchesRequest(data, offset, len, OpCodes::CheckWatches); + status = parseXWatchesRequest(data, offset, len.value(), OpCodes::CheckWatches); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseXWatchesRequest (check watches): {}", status.message())); break; case OpCodes::RemoveWatches: - parseXWatchesRequest(data, offset, len, OpCodes::RemoveWatches); + status = parseXWatchesRequest(data, offset, len.value(), OpCodes::RemoveWatches); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseXWatchesRequest (remove watches): {}", status.message())); break; case OpCodes::GetEphemerals: - callbacks_.onGetEphemeralsRequest(pathOnlyRequest(data, offset, len)); + status = callbacks_.onGetEphemeralsRequest(pathOnlyRequest(data, offset, len.value())); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("onGetEphemeralsRequest: {}", status.message())); break; case OpCodes::GetAllChildrenNumber: - callbacks_.onGetAllChildrenNumberRequest(pathOnlyRequest(data, offset, len)); + status = callbacks_.onGetAllChildrenNumberRequest(pathOnlyRequest(data, offset, len.value())); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("onGetAllChildrenNumberRequest: {}", status.message())); break; case OpCodes::Close: callbacks_.onCloseRequest(); break; default: - throw EnvoyException(fmt::format("Unknown opcode: {}", enumToSignedInt(opcode))); + ENVOY_LOG(debug, "zookeeper_proxy: decodeOnData failed: unknown opcode {}", + enumToSignedInt(opcode)); + callbacks_.onDecodeError(); + return absl::nullopt; } - requests_by_xid_[xid] = {opcode, std::move(start_time)}; + requests_by_xid_[xid.value()] = {opcode, std::move(start_time)}; return opcode; } -absl::optional DecoderImpl::decodeOnWrite(Buffer::Instance& data, uint64_t& offset) { +absl::StatusOr> DecoderImpl::decodeOnWrite(Buffer::Instance& data, + uint64_t& offset) { ENVOY_LOG(trace, "zookeeper_proxy: decoding response with {} bytes at offset {}", data.length(), offset); // Check message length. - const int32_t len = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding response with len {} at offset {}", len, offset); - ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + INT_LENGTH); // xid + zxid + err - ensureMaxLength(len); + const absl::StatusOr len = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + len, fmt::format("peekInt32 for len: {}", len.status().message())); + + ENVOY_LOG(trace, "zookeeper_proxy: decoding response with len.value() {} at offset {}", + len.value(), offset); + + absl::Status status = + ensureMinLength(len.value(), XID_LENGTH + ZXID_LENGTH + INT_LENGTH); // xid + zxid + err + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("ensureMinLength: {}", status.message())); + + status = ensureMaxLength(len.value()); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("ensureMaxLength: {}", status.message())); - const auto xid = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding response with xid {} at offset {}", xid, offset); - const auto xid_code = static_cast(xid); + const absl::StatusOr xid = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + xid, fmt::format("peekInt32 for xid: {}", xid.status().message())); - std::chrono::milliseconds latency; + ENVOY_LOG(trace, "zookeeper_proxy: decoding response with xid {} at offset {}", xid.value(), + offset); + const auto xid_code = static_cast(xid.value()); + + absl::StatusOr latency; OpCodes opcode; switch (xid_code) { @@ -201,321 +290,516 @@ absl::optional DecoderImpl::decodeOnWrite(Buffer::Instance& data, uint6 case XidCodes::AuthXid: ABSL_FALLTHROUGH_INTENDED; case XidCodes::SetWatchesXid: - latency = fetchControlRequestData(xid, opcode); + latency = fetchControlRequestData(xid.value(), opcode); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + latency, fmt::format("fetchControlRequestData: {}", latency.status().message())); break; case XidCodes::WatchXid: // WATCH_XID is generated by the server, no need to fetch opcode and latency here. break; default: - latency = fetchDataRequestData(xid, opcode); + latency = fetchDataRequestData(xid.value(), opcode); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + latency, fmt::format("fetchDataRequestData: {}", latency.status().message())); } // Connect responses are special, they have no full reply header // but just an XID with no zxid nor error fields like the ones // available for all other server generated messages. if (xid_code == XidCodes::ConnectXid) { - parseConnectResponse(data, offset, len, latency); + status = parseConnectResponse(data, offset, len.value(), latency.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("parseConnectResponse: {}", status.message())) return opcode; } // Control responses that aren't connect, with XIDs <= 0. - const auto zxid = helper_.peekInt64(data, offset); - const auto error = helper_.peekInt32(data, offset); - ENVOY_LOG(trace, "zookeeper_proxy: decoding response with zxid {} and error {} at offset {}", - zxid, error, offset); + const absl::StatusOr zxid = helper_.peekInt64(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + zxid, fmt::format("peekInt64 for zxid: {}", zxid.status().message())); + + const absl::StatusOr error = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + error, fmt::format("peekInt32 for error: {}", error.status().message())); + + ENVOY_LOG(trace, + "zookeeper_proxy: decoding response with zxid.value() {} and error {} at offset {}", + zxid.value(), error.value(), offset); + switch (xid_code) { case XidCodes::PingXid: - callbacks_.onResponse(OpCodes::Ping, xid, zxid, error, latency); + callbacks_.onResponse(OpCodes::Ping, xid.value(), zxid.value(), error.value(), latency.value()); return opcode; case XidCodes::AuthXid: - callbacks_.onResponse(OpCodes::SetAuth, xid, zxid, error, latency); + callbacks_.onResponse(OpCodes::SetAuth, xid.value(), zxid.value(), error.value(), + latency.value()); return opcode; case XidCodes::SetWatchesXid: - callbacks_.onResponse(OpCodes::SetWatches, xid, zxid, error, latency); + callbacks_.onResponse(OpCodes::SetWatches, xid.value(), zxid.value(), error.value(), + latency.value()); return opcode; case XidCodes::WatchXid: - parseWatchEvent(data, offset, len, zxid, error); + status = parseWatchEvent(data, offset, len.value(), zxid.value(), error.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, + fmt::format("parseWatchEvent: {}", status.message())); + return absl::nullopt; // WATCH_XID is generated by the server, it has no corresponding opcode. default: break; } - callbacks_.onResponse(opcode, xid, zxid, error, latency); - offset += (len - (XID_LENGTH + ZXID_LENGTH + INT_LENGTH)); + callbacks_.onResponse(opcode, xid.value(), zxid.value(), error.value(), latency.value()); + offset += (len.value() - (XID_LENGTH + ZXID_LENGTH + INT_LENGTH)); return opcode; } -void DecoderImpl::ensureMinLength(const int32_t len, const int32_t minlen) const { +absl::Status DecoderImpl::ensureMinLength(const int32_t len, const int32_t minlen) const { if (len < minlen) { - throw EnvoyException("Packet is too small"); + return absl::InvalidArgumentError("packet is too small"); } + return absl::OkStatus(); } -void DecoderImpl::ensureMaxLength(const int32_t len) const { +absl::Status DecoderImpl::ensureMaxLength(const int32_t len) const { if (static_cast(len) > max_packet_bytes_) { - throw EnvoyException("Packet is too big"); + return absl::InvalidArgumentError("packet is too big"); } + return absl::OkStatus(); } -void DecoderImpl::parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); +absl::Status DecoderImpl::parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + absl::Status status = + ensureMinLength(len, XID_LENGTH + ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Skip zxid, timeout, and session id. offset += ZXID_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH; // Skip password. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const bool readonly = maybeReadBool(data, offset); + const absl::StatusOr readonly = maybeReadBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(readonly, + readonly.status().message()); - callbacks_.onConnect(readonly); -} + callbacks_.onConnect(readonly.value()); -void DecoderImpl::parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + INT_LENGTH + INT_LENGTH); + return absl::OkStatus(); +} +absl::Status DecoderImpl::parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + absl::Status status = + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + INT_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Skip opcode + type. offset += OPCODE_LENGTH + INT_LENGTH; - const std::string scheme = helper_.peekString(data, offset); + + const absl::StatusOr scheme = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(scheme, scheme.status().message()); + // Skip credential. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + callbacks_.onAuthRequest(scheme.value()); - callbacks_.onAuthRequest(scheme); + return absl::OkStatus(); } -void DecoderImpl::parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); +absl::Status DecoderImpl::parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const std::string path = helper_.peekString(data, offset); - const bool watch = helper_.peekBool(data, offset); + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - callbacks_.onGetDataRequest(path, watch); + const absl::StatusOr watch = helper_.peekBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); + + callbacks_.onGetDataRequest(path.value(), watch.value()); + + return absl::OkStatus(); } -void DecoderImpl::skipAcls(Buffer::Instance& data, uint64_t& offset) { - const int32_t count = helper_.peekInt32(data, offset); +absl::Status DecoderImpl::skipAcls(Buffer::Instance& data, uint64_t& offset) { + const absl::StatusOr count = helper_.peekInt32(data, offset); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(count, + fmt::format("skipAcls: {}", count.status().message())); - for (int i = 0; i < count; ++i) { + for (int i = 0; i < count.value(); ++i) { // Perms. - helper_.peekInt32(data, offset); + absl::StatusOr perms = helper_.peekInt32(data, offset); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(perms, + fmt::format("skipAcls: {}", perms.status().message())); // Skip scheme. - skipString(data, offset); + absl::Status status = skipString(data, offset); + ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); // Skip cred. - skipString(data, offset); + status = skipString(data, offset); + ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); } + + return absl::OkStatus(); } -void DecoderImpl::parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - OpCodes opcode) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (4 * INT_LENGTH)); +absl::Status DecoderImpl::parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + OpCodes opcode) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (4 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const std::string path = helper_.peekString(data, offset); + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); // Skip data. - skipString(data, offset); - skipAcls(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + status = skipAcls(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + absl::StatusOr flag_data = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(flag_data, + flag_data.status().message()); - const CreateFlags flags = static_cast(helper_.peekInt32(data, offset)); - callbacks_.onCreateRequest(path, flags, opcode); + const CreateFlags flags = static_cast(flag_data.value()); + status = callbacks_.onCreateRequest(path.value(), flags, opcode); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + return absl::OkStatus(); } -void DecoderImpl::parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); +absl::Status DecoderImpl::parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - const std::string path = helper_.peekString(data, offset); // Skip data. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Ignore version. - helper_.peekInt32(data, offset); + absl::StatusOr version = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); - callbacks_.onSetRequest(path); + callbacks_.onSetRequest(path.value()); + + return absl::OkStatus(); } -void DecoderImpl::parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const bool two) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); +absl::Status DecoderImpl::parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len, const bool two) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + + const absl::StatusOr watch = helper_.peekBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); - const std::string path = helper_.peekString(data, offset); - const bool watch = helper_.peekBool(data, offset); + callbacks_.onGetChildrenRequest(path.value(), watch.value(), two); - callbacks_.onGetChildrenRequest(path, watch, two); + return absl::OkStatus(); } -void DecoderImpl::parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); +absl::Status DecoderImpl::parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const std::string path = helper_.peekString(data, offset); - const int32_t version = helper_.peekInt32(data, offset); + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - callbacks_.onDeleteRequest(path, version); + const absl::StatusOr version = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); + + callbacks_.onDeleteRequest(path.value(), version.value()); + + return absl::OkStatus(); } -void DecoderImpl::parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); +absl::Status DecoderImpl::parseExistsRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH + BOOL_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - const std::string path = helper_.peekString(data, offset); - const bool watch = helper_.peekBool(data, offset); + const absl::StatusOr watch = helper_.peekBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch, watch.status().message()); - callbacks_.onExistsRequest(path, watch); + callbacks_.onExistsRequest(path.value(), watch.value()); + + return absl::OkStatus(); } -void DecoderImpl::parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); +absl::Status DecoderImpl::parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - const std::string path = helper_.peekString(data, offset); + callbacks_.onGetAclRequest(path.value()); - callbacks_.onGetAclRequest(path); + return absl::OkStatus(); } -void DecoderImpl::parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); +absl::Status DecoderImpl::parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const std::string path = helper_.peekString(data, offset); - skipAcls(data, offset); - const int32_t version = helper_.peekInt32(data, offset); + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - callbacks_.onSetAclRequest(path, version); + status = skipAcls(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr version = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); + + callbacks_.onSetAclRequest(path.value(), version.value()); + + return absl::OkStatus(); } -std::string DecoderImpl::pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); +absl::StatusOr DecoderImpl::pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + status, fmt::format("zookeeper_proxy: pathOnlyRequest failed: {}", status.message())); + return helper_.peekString(data, offset); } -void DecoderImpl::parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); +absl::Status DecoderImpl::parseCheckRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + + const absl::StatusOr version = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(version, version.status().message()); - const std::string path = helper_.peekString(data, offset); - const int32_t version = helper_.peekInt32(data, offset); + callbacks_.onCheckRequest(path.value(), version.value()); - callbacks_.onCheckRequest(path, version); + return absl::OkStatus(); } -void DecoderImpl::parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { +absl::Status DecoderImpl::parseMultiRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { // Treat empty transactions as a decoding error, there should be at least 1 header. - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + MULTI_HEADER_LENGTH); + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + MULTI_HEADER_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); while (true) { - const int32_t opcode = helper_.peekInt32(data, offset); - const bool done = helper_.peekBool(data, offset); + const absl::StatusOr opcode = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(opcode, opcode.status().message()); + + const absl::StatusOr done = helper_.peekBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(done, done.status().message()); + // Ignore error field. - helper_.peekInt32(data, offset); + const absl::StatusOr error = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(error, error.status().message()); - if (done) { + if (done.value()) { break; } - switch (static_cast(opcode)) { + switch (static_cast(opcode.value())) { case OpCodes::Create: - parseCreateRequest(data, offset, len, OpCodes::Create); + status = parseCreateRequest(data, offset, len, OpCodes::Create); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); break; case OpCodes::SetData: - parseSetRequest(data, offset, len); + status = parseSetRequest(data, offset, len); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); break; case OpCodes::Check: - parseCheckRequest(data, offset, len); + status = parseCheckRequest(data, offset, len); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); break; case OpCodes::Delete: - parseDeleteRequest(data, offset, len); + status = parseDeleteRequest(data, offset, len); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); break; default: - throw EnvoyException(fmt::format("Unknown opcode within a transaction: {}", opcode)); + callbacks_.onDecodeError(); + return absl::InvalidArgumentError( + fmt::format("unknown opcode within a transaction: {}", opcode.value())); } } callbacks_.onMultiRequest(); + + return absl::OkStatus(); } -void DecoderImpl::parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH) + LONG_LENGTH); +absl::Status DecoderImpl::parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (3 * INT_LENGTH) + LONG_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Skip joining. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Skip leaving. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Skip new members. - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Read config id. - helper_.peekInt64(data, offset); + absl::StatusOr config_id = helper_.peekInt64(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(config_id, + config_id.status().message()); callbacks_.onReconfigRequest(); + + return absl::OkStatus(); } -void DecoderImpl::parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (3 * INT_LENGTH)); +absl::Status DecoderImpl::parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (3 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Ignore relative Zxid. - helper_.peekInt64(data, offset); + absl::StatusOr zxid = helper_.peekInt64(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(zxid, zxid.status().message()); + // Data watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Exist watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Child watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); callbacks_.onSetWatchesRequest(); + + return absl::OkStatus(); } -void DecoderImpl::parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (5 * INT_LENGTH)); +absl::Status DecoderImpl::parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = + ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + LONG_LENGTH + (5 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); // Ignore relative Zxid. - helper_.peekInt64(data, offset); + absl::StatusOr zxid = helper_.peekInt64(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(zxid, zxid.status().message()); + // Data watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Exist watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Child watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Persistent watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + // Persistent recursive watches. - skipStrings(data, offset); + status = skipStrings(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); callbacks_.onSetWatches2Request(); + + return absl::OkStatus(); } -void DecoderImpl::parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); +absl::Status DecoderImpl::parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + + const absl::StatusOr mode = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(mode, mode.status().message()); - const std::string path = helper_.peekString(data, offset); - const int32_t mode = helper_.peekInt32(data, offset); + callbacks_.onAddWatchRequest(path.value(), mode.value()); - callbacks_.onAddWatchRequest(path, mode); + return absl::OkStatus(); } -void DecoderImpl::parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, - OpCodes opcode) { - ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); +absl::Status DecoderImpl::parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len, OpCodes opcode) { + absl::Status status = ensureMinLength(len, XID_LENGTH + OPCODE_LENGTH + (2 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const std::string path = helper_.peekString(data, offset); - const int32_t type = helper_.peekInt32(data, offset); + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + + const absl::StatusOr watch_type = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(watch_type, + watch_type.status().message()); if (opcode == OpCodes::CheckWatches) { - callbacks_.onCheckWatchesRequest(path, type); + callbacks_.onCheckWatchesRequest(path.value(), watch_type.value()); } else { - callbacks_.onRemoveWatchesRequest(path, type); + callbacks_.onRemoveWatchesRequest(path.value(), watch_type.value()); } + + return absl::OkStatus(); } -void DecoderImpl::skipString(Buffer::Instance& data, uint64_t& offset) { - const int32_t slen = helper_.peekInt32(data, offset); - if (slen < 0) { +absl::Status DecoderImpl::skipString(Buffer::Instance& data, uint64_t& offset) { + const absl::StatusOr slen = helper_.peekInt32(data, offset); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(slen, + fmt::format("skipString: {}", slen.status().message())); + + if (slen.value() < 0) { ENVOY_LOG(trace, "zookeeper_proxy: decoding response with negative string length {} at offset {}", - slen, offset); - return; + slen.value(), offset); + return absl::OkStatus(); } - helper_.skip(slen, offset); + + helper_.skip(slen.value(), offset); + + return absl::OkStatus(); } -void DecoderImpl::skipStrings(Buffer::Instance& data, uint64_t& offset) { - const int32_t count = helper_.peekInt32(data, offset); +absl::Status DecoderImpl::skipStrings(Buffer::Instance& data, uint64_t& offset) { + const absl::StatusOr count = helper_.peekInt32(data, offset); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(count, + fmt::format("skipStrings: {}", count.status().message())); - for (int i = 0; i < count; ++i) { - skipString(data, offset); + for (int i = 0; i < count.value(); ++i) { + absl::Status status = skipString(data, offset); + ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status); } + + return absl::OkStatus(); } Network::FilterStatus DecoderImpl::onData(Buffer::Instance& data) { @@ -529,9 +813,14 @@ Network::FilterStatus DecoderImpl::onWrite(Buffer::Instance& data) { Network::FilterStatus DecoderImpl::decodeAndBuffer(Buffer::Instance& data, DecodeType dtype, Buffer::OwnedImpl& zk_filter_buffer) { const uint32_t zk_filter_buffer_len = zk_filter_buffer.length(); + absl::Status status; if (zk_filter_buffer_len == 0) { - decodeAndBufferHelper(data, dtype, zk_filter_buffer); + status = decodeAndBufferHelper(data, dtype, zk_filter_buffer); + if (!status.ok()) { + ENVOY_LOG(debug, "zookeeper_proxy: decodeAndBufferHelper failed: {}", status.message()); + } + return Network::FilterStatus::Continue; } @@ -539,19 +828,25 @@ Network::FilterStatus DecoderImpl::decodeAndBuffer(Buffer::Instance& data, Decod // Prepending ZooKeeper filter buffer to the current network filter buffer can help to generate // full packets. data.prepend(zk_filter_buffer); - decodeAndBufferHelper(data, dtype, zk_filter_buffer); + + status = decodeAndBufferHelper(data, dtype, zk_filter_buffer); + if (!status.ok()) { + ENVOY_LOG(debug, "zookeeper_proxy: decodeAndBufferHelper failed: {}", status.message()); + } + // Drain the prepended ZooKeeper filter buffer. data.drain(zk_filter_buffer_len); return Network::FilterStatus::Continue; } -void DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, - Buffer::OwnedImpl& zk_filter_buffer) { +absl::Status DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, + Buffer::OwnedImpl& zk_filter_buffer) { ASSERT(dtype == DecodeType::READ || dtype == DecodeType::WRITE); const uint32_t data_len = data.length(); uint64_t offset = 0; - uint32_t len = 0; + absl::StatusOr len = 0; + absl::Status status; // Boolean to check whether there is at least one full packet in the network filter buffer (to // which the ZooKeeper filter buffer is prepended). bool has_full_packets = false; @@ -560,31 +855,39 @@ void DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype TRY_NEEDS_AUDIT { // Peek packet length. len = helper_.peekInt32(data, offset); - ensureMinLength(len, dtype == DecodeType::READ ? XID_LENGTH + INT_LENGTH - : XID_LENGTH + ZXID_LENGTH + INT_LENGTH); - ensureMaxLength(len); - offset += len; + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK( + len, fmt::format("peekInt32 for len: {}", len.status().message())); + + status = ensureMinLength(len.value(), dtype == DecodeType::READ + ? XID_LENGTH + INT_LENGTH + : XID_LENGTH + ZXID_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + status = ensureMaxLength(len.value()); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + offset += len.value(); if (offset <= data_len) { has_full_packets = true; } } END_TRY catch (const EnvoyException& e) { - ENVOY_LOG(debug, "zookeeper_proxy: decoding exception {}", e.what()); + IS_ENVOY_BUG(fmt::format("zookeeper_proxy: decodeAndBufferHelper failed: {}", e.what())); callbacks_.onDecodeError(); - return; + return absl::OkStatus(); } } if (offset == data_len) { decode(data, dtype, offset); - return; + return absl::OkStatus(); } ASSERT(offset > data_len); std::string temp_data; if (has_full_packets) { - offset -= INT_LENGTH + len; + offset -= INT_LENGTH + len.value(); ASSERT(offset < data_len); // Decode full packets. // offset here represents the length of all full packets. @@ -601,6 +904,8 @@ void DecoderImpl::decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype data.copyOut(0, data_len, temp_data.data()); zk_filter_buffer.add(temp_data.data(), temp_data.length()); } + + return absl::OkStatus(); } void DecoderImpl::decode(Buffer::Instance& data, DecodeType dtype, uint64_t full_packets_len) { @@ -618,70 +923,99 @@ void DecoderImpl::decode(Buffer::Instance& data, DecodeType dtype, uint64_t full helper_.reset(); const uint64_t current = offset; - absl::optional opcode; + absl::StatusOr> opcode; switch (dtype) { case DecodeType::READ: opcode = decodeOnData(data, offset); - callbacks_.onRequestBytes(opcode, offset - current); - break; + if (opcode.ok()) { + callbacks_.onRequestBytes(opcode.value(), offset - current); + break; + } + ENVOY_LOG(debug, "zookeeper_proxy: decodeOnData failed: {}", opcode.status().message()); + return; case DecodeType::WRITE: opcode = decodeOnWrite(data, offset); - callbacks_.onResponseBytes(opcode, offset - current); - break; + if (opcode.ok()) { + callbacks_.onResponseBytes(opcode.value(), offset - current); + break; + } + ENVOY_LOG(debug, "zookeeper_proxy: decodeOnWrite failed: {}", opcode.status().message()); + return; } } } END_TRY catch (const EnvoyException& e) { - ENVOY_LOG(debug, "zookeeper_proxy: decoding exception {}", e.what()); + IS_ENVOY_BUG(fmt::format("zookeeper_proxy: decode failed: {}", e.what())); callbacks_.onDecodeError(); } } -void DecoderImpl::parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const std::chrono::milliseconds latency) { - ensureMinLength(len, PROTOCOL_VERSION_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); +absl::Status DecoderImpl::parseConnectResponse(Buffer::Instance& data, uint64_t& offset, + uint32_t len, + const std::chrono::milliseconds latency) { + absl::Status status = + ensureMinLength(len, PROTOCOL_VERSION_LENGTH + TIMEOUT_LENGTH + SESSION_LENGTH + INT_LENGTH); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); - const auto timeout = helper_.peekInt32(data, offset); + const absl::StatusOr timeout = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(timeout, timeout.status().message()); // Skip session id + password. offset += SESSION_LENGTH; - skipString(data, offset); + status = skipString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr readonly = maybeReadBool(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(readonly, + readonly.status().message()); - const bool readonly = maybeReadBool(data, offset); + callbacks_.onConnectResponse(0, timeout.value(), readonly.value(), latency); - callbacks_.onConnectResponse(0, timeout, readonly, latency); + return absl::OkStatus(); } -void DecoderImpl::parseWatchEvent(Buffer::Instance& data, uint64_t& offset, const uint32_t len, - const int64_t zxid, const int32_t error) { - ensureMinLength(len, SERVER_HEADER_LENGTH + (3 * INT_LENGTH)); +absl::Status DecoderImpl::parseWatchEvent(Buffer::Instance& data, uint64_t& offset, + const uint32_t len, const int64_t zxid, + const int32_t error) { + absl::Status status = ensureMinLength(len, SERVER_HEADER_LENGTH + (3 * INT_LENGTH)); + EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status); + + const absl::StatusOr event_type = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(event_type, + event_type.status().message()); + + const absl::StatusOr client_state = helper_.peekInt32(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(client_state, + client_state.status().message()); + + const absl::StatusOr path = helper_.peekString(data, offset); + EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); - const auto event_type = helper_.peekInt32(data, offset); - const auto client_state = helper_.peekInt32(data, offset); - const auto path = helper_.peekString(data, offset); + callbacks_.onWatchEvent(event_type.value(), client_state.value(), path.value(), zxid, error); - callbacks_.onWatchEvent(event_type, client_state, path, zxid, error); + return absl::OkStatus(); } -bool DecoderImpl::maybeReadBool(Buffer::Instance& data, uint64_t& offset) { +absl::StatusOr DecoderImpl::maybeReadBool(Buffer::Instance& data, uint64_t& offset) { if (data.length() >= offset + 1) { return helper_.peekBool(data, offset); } return false; } -std::chrono::milliseconds DecoderImpl::fetchControlRequestData(const int32_t xid, OpCodes& opcode) { +absl::StatusOr DecoderImpl::fetchControlRequestData(const int32_t xid, + OpCodes& opcode) { // Find the corresponding request queue for this XID. const auto it = control_requests_by_xid_.find(xid); // If this fails, it's either a server-side bug or a malformed packet. if (it == control_requests_by_xid_.end()) { - throw EnvoyException(fmt::format("control request xid {} not found", xid)); + return absl::InvalidArgumentError(fmt::format("control request xid {} not found", xid)); } std::queue& rq_queue = it->second; if (rq_queue.empty()) { - throw EnvoyException(fmt::format("control request queue for {} is empty", xid)); + return absl::InvalidArgumentError(fmt::format("control request queue for {} is empty", xid)); } std::chrono::milliseconds latency = std::chrono::duration_cast( @@ -692,13 +1026,14 @@ std::chrono::milliseconds DecoderImpl::fetchControlRequestData(const int32_t xid return latency; } -std::chrono::milliseconds DecoderImpl::fetchDataRequestData(const int32_t xid, OpCodes& opcode) { +absl::StatusOr DecoderImpl::fetchDataRequestData(const int32_t xid, + OpCodes& opcode) { // Find the corresponding request for this XID. const auto it = requests_by_xid_.find(xid); // If this fails, it's either a server-side bug or a malformed packet. if (it == requests_by_xid_.end()) { - throw EnvoyException(fmt::format("xid {} not found", xid)); + return absl::InvalidArgumentError(fmt::format("data request xid {} not found", xid)); } std::chrono::milliseconds latency = std::chrono::duration_cast( diff --git a/source/extensions/filters/network/zookeeper_proxy/decoder.h b/source/extensions/filters/network/zookeeper_proxy/decoder.h index 34ad9b4d32ff..8718a8d9d6b1 100644 --- a/source/extensions/filters/network/zookeeper_proxy/decoder.h +++ b/source/extensions/filters/network/zookeeper_proxy/decoder.h @@ -12,6 +12,7 @@ #include "source/extensions/filters/network/zookeeper_proxy/utils.h" #include "absl/container/node_hash_map.h" +#include "absl/status/statusor.h" namespace Envoy { namespace Extensions { @@ -85,16 +86,17 @@ class DecoderCallbacks { virtual void onPing() PURE; virtual void onAuthRequest(const std::string& scheme) PURE; virtual void onGetDataRequest(const std::string& path, bool watch) PURE; - virtual void onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) PURE; + virtual absl::Status onCreateRequest(const std::string& path, CreateFlags flags, + OpCodes opcode) PURE; virtual void onSetRequest(const std::string& path) PURE; virtual void onGetChildrenRequest(const std::string& path, bool watch, bool v2) PURE; - virtual void onGetEphemeralsRequest(const std::string& path) PURE; - virtual void onGetAllChildrenNumberRequest(const std::string& path) PURE; + virtual absl::Status onGetEphemeralsRequest(const absl::StatusOr& path) PURE; + virtual absl::Status onGetAllChildrenNumberRequest(const absl::StatusOr& path) PURE; virtual void onDeleteRequest(const std::string& path, int32_t version) PURE; virtual void onExistsRequest(const std::string& path, bool watch) PURE; virtual void onGetAclRequest(const std::string& path) PURE; virtual void onSetAclRequest(const std::string& path, int32_t version) PURE; - virtual void onSyncRequest(const std::string& path) PURE; + virtual absl::Status onSyncRequest(const absl::StatusOr& path) PURE; virtual void onCheckRequest(const std::string& path, int32_t version) PURE; virtual void onMultiRequest() PURE; virtual void onReconfigRequest() PURE; @@ -151,44 +153,50 @@ class DecoderImpl : public Decoder, Logger::Loggable { // (4) removes the prepended data. Network::FilterStatus decodeAndBuffer(Buffer::Instance& data, DecodeType dtype, Buffer::OwnedImpl& zk_filter_buffer); - void decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, - Buffer::OwnedImpl& zk_filter_buffer); + absl::Status decodeAndBufferHelper(Buffer::Instance& data, DecodeType dtype, + Buffer::OwnedImpl& zk_filter_buffer); void decode(Buffer::Instance& data, DecodeType dtype, uint64_t full_packets_len); // decodeOnData and decodeOnWrite return ZooKeeper opcode or absl::nullopt. // absl::nullopt indicates WATCH_XID, which is generated by the server and has no corresponding // opcode. - absl::optional decodeOnData(Buffer::Instance& data, uint64_t& offset); - absl::optional decodeOnWrite(Buffer::Instance& data, uint64_t& offset); - void parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, OpCodes opcode); - void skipAcls(Buffer::Instance& data, uint64_t& offset); - void parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, bool two); - void parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, OpCodes opcode); - void skipString(Buffer::Instance& data, uint64_t& offset); - void skipStrings(Buffer::Instance& data, uint64_t& offset); - void ensureMinLength(int32_t len, int32_t minlen) const; - void ensureMaxLength(int32_t len) const; - std::string pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); - void parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, - const std::chrono::milliseconds latency); - void parseWatchEvent(Buffer::Instance& data, uint64_t& offset, uint32_t len, int64_t zxid, - int32_t error); - bool maybeReadBool(Buffer::Instance& data, uint64_t& offset); - std::chrono::milliseconds fetchControlRequestData(const int32_t xid, OpCodes& opcode); - std::chrono::milliseconds fetchDataRequestData(const int32_t xid, OpCodes& opcode); + absl::StatusOr> decodeOnData(Buffer::Instance& data, uint64_t& offset); + absl::StatusOr> decodeOnWrite(Buffer::Instance& data, uint64_t& offset); + absl::Status parseConnect(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseAuthRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseGetDataRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseCreateRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + OpCodes opcode); + absl::Status skipAcls(Buffer::Instance& data, uint64_t& offset); + absl::Status parseSetRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseGetChildrenRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + bool two); + absl::Status parseDeleteRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseExistsRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseGetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseSetAclRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseCheckRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseMultiRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseReconfigRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseSetWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseSetWatches2Request(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseAddWatchRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len); + absl::Status parseXWatchesRequest(Buffer::Instance& data, uint64_t& offset, uint32_t len, + OpCodes opcode); + absl::Status skipString(Buffer::Instance& data, uint64_t& offset); + absl::Status skipStrings(Buffer::Instance& data, uint64_t& offset); + absl::Status ensureMinLength(int32_t len, int32_t minlen) const; + absl::Status ensureMaxLength(int32_t len) const; + absl::StatusOr pathOnlyRequest(Buffer::Instance& data, uint64_t& offset, + uint32_t len); + absl::Status parseConnectResponse(Buffer::Instance& data, uint64_t& offset, uint32_t len, + const std::chrono::milliseconds latency); + absl::Status parseWatchEvent(Buffer::Instance& data, uint64_t& offset, uint32_t len, int64_t zxid, + int32_t error); + absl::StatusOr maybeReadBool(Buffer::Instance& data, uint64_t& offset); + absl::StatusOr fetchControlRequestData(const int32_t xid, + OpCodes& opcode); + absl::StatusOr fetchDataRequestData(const int32_t xid, + OpCodes& opcode); DecoderCallbacks& callbacks_; const uint32_t max_packet_bytes_; diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.cc b/source/extensions/filters/network/zookeeper_proxy/filter.cc index 013bea03b1e0..817fa14077d4 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.cc +++ b/source/extensions/filters/network/zookeeper_proxy/filter.cc @@ -293,8 +293,8 @@ void ZooKeeperFilter::onGetDataRequest(const std::string& path, const bool watch setDynamicMetadata({{"opname", "getdata"}, {"path", path}, {"watch", watch ? "true" : "false"}}); } -void ZooKeeperFilter::onCreateRequest(const std::string& path, const CreateFlags flags, - const OpCodes opcode) { +absl::Status ZooKeeperFilter::onCreateRequest(const std::string& path, const CreateFlags flags, + const OpCodes opcode) { std::string opname; switch (opcode) { @@ -315,12 +315,14 @@ void ZooKeeperFilter::onCreateRequest(const std::string& path, const CreateFlags config_->stats_.createttl_rq_.inc(); break; default: - throw EnvoyException(fmt::format("Unknown opcode: {}", enumToSignedInt(opcode))); + return absl::InvalidArgumentError(fmt::format("unknown opcode: {}", enumToSignedInt(opcode))); break; } setDynamicMetadata( {{"opname", opname}, {"path", path}, {"create_type", createFlagsToString(flags)}}); + + return absl::OkStatus(); } void ZooKeeperFilter::onSetRequest(const std::string& path) { @@ -362,9 +364,13 @@ void ZooKeeperFilter::onSetAclRequest(const std::string& path, const int32_t ver setDynamicMetadata({{"opname", "setacl"}, {"path", path}, {"version", std::to_string(version)}}); } -void ZooKeeperFilter::onSyncRequest(const std::string& path) { +absl::Status ZooKeeperFilter::onSyncRequest(const absl::StatusOr& path) { + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + config_->stats_.sync_rq_.inc(); - setDynamicMetadata({{"opname", "sync"}, {"path", path}}); + setDynamicMetadata({{"opname", "sync"}, {"path", path.value()}}); + + return absl::OkStatus(); } void ZooKeeperFilter::onCheckRequest(const std::string&, const int32_t) { @@ -406,14 +412,23 @@ void ZooKeeperFilter::onAddWatchRequest(const std::string& path, const int32_t m setDynamicMetadata({{"opname", "addwatch"}, {"path", path}, {"mode", std::to_string(mode)}}); } -void ZooKeeperFilter::onGetEphemeralsRequest(const std::string& path) { +absl::Status ZooKeeperFilter::onGetEphemeralsRequest(const absl::StatusOr& path) { + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + config_->stats_.getephemerals_rq_.inc(); - setDynamicMetadata({{"opname", "getephemerals"}, {"path", path}}); + setDynamicMetadata({{"opname", "getephemerals"}, {"path", path.value()}}); + + return absl::OkStatus(); } -void ZooKeeperFilter::onGetAllChildrenNumberRequest(const std::string& path) { +absl::Status +ZooKeeperFilter::onGetAllChildrenNumberRequest(const absl::StatusOr& path) { + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(path, path.status().message()); + config_->stats_.getallchildrennumber_rq_.inc(); - setDynamicMetadata({{"opname", "getallchildrennumber"}, {"path", path}}); + setDynamicMetadata({{"opname", "getallchildrennumber"}, {"path", path.value()}}); + + return absl::OkStatus(); } void ZooKeeperFilter::onCloseRequest() { diff --git a/source/extensions/filters/network/zookeeper_proxy/filter.h b/source/extensions/filters/network/zookeeper_proxy/filter.h index 294d8a3119da..94f47506b211 100644 --- a/source/extensions/filters/network/zookeeper_proxy/filter.h +++ b/source/extensions/filters/network/zookeeper_proxy/filter.h @@ -17,6 +17,8 @@ #include "source/common/stats/symbol_table.h" #include "source/extensions/filters/network/zookeeper_proxy/decoder.h" +#include "absl/status/statusor.h" + namespace Envoy { namespace Extensions { namespace NetworkFilters { @@ -340,14 +342,14 @@ class ZooKeeperFilter : public Network::Filter, void onPing() override; void onAuthRequest(const std::string& scheme) override; void onGetDataRequest(const std::string& path, bool watch) override; - void onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) override; + absl::Status onCreateRequest(const std::string& path, CreateFlags flags, OpCodes opcode) override; void onSetRequest(const std::string& path) override; void onGetChildrenRequest(const std::string& path, bool watch, bool v2) override; void onDeleteRequest(const std::string& path, int32_t version) override; void onExistsRequest(const std::string& path, bool watch) override; void onGetAclRequest(const std::string& path) override; void onSetAclRequest(const std::string& path, int32_t version) override; - void onSyncRequest(const std::string& path) override; + absl::Status onSyncRequest(const absl::StatusOr& path) override; void onCheckRequest(const std::string& path, int32_t version) override; void onMultiRequest() override; void onReconfigRequest() override; @@ -356,8 +358,8 @@ class ZooKeeperFilter : public Network::Filter, void onAddWatchRequest(const std::string& path, const int32_t mode) override; void onCheckWatchesRequest(const std::string& path, int32_t type) override; void onRemoveWatchesRequest(const std::string& path, int32_t type) override; - void onGetEphemeralsRequest(const std::string& path) override; - void onGetAllChildrenNumberRequest(const std::string& path) override; + absl::Status onGetEphemeralsRequest(const absl::StatusOr& path) override; + absl::Status onGetAllChildrenNumberRequest(const absl::StatusOr& path) override; void onCloseRequest() override; void onResponseBytes(const absl::optional opcode, const uint64_t bytes) override; void onConnectResponse(int32_t proto_version, int32_t timeout, bool readonly, diff --git a/source/extensions/filters/network/zookeeper_proxy/utils.cc b/source/extensions/filters/network/zookeeper_proxy/utils.cc index cf1c77a8bf19..8d6fe89a8dd4 100644 --- a/source/extensions/filters/network/zookeeper_proxy/utils.cc +++ b/source/extensions/filters/network/zookeeper_proxy/utils.cc @@ -7,24 +7,36 @@ namespace Extensions { namespace NetworkFilters { namespace ZooKeeperProxy { -int32_t BufferHelper::peekInt32(Buffer::Instance& buffer, uint64_t& offset) { - ensureMaxLen(sizeof(int32_t)); +absl::StatusOr BufferHelper::peekInt32(Buffer::Instance& buffer, uint64_t& offset) { + absl::Status status = ensureMinLen(buffer, offset, sizeof(int32_t)); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt32: {}", status.message())); + + status = ensureMaxLen(sizeof(int32_t)); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt32: {}", status.message())); const int32_t val = buffer.peekBEInt(offset); offset += sizeof(int32_t); return val; } -int64_t BufferHelper::peekInt64(Buffer::Instance& buffer, uint64_t& offset) { - ensureMaxLen(sizeof(int64_t)); +absl::StatusOr BufferHelper::peekInt64(Buffer::Instance& buffer, uint64_t& offset) { + absl::Status status = ensureMinLen(buffer, offset, sizeof(int64_t)); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt64: {}", status.message())); + + status = ensureMaxLen(sizeof(int64_t)); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekInt64: {}", status.message())); const int64_t val = buffer.peekBEInt(offset); offset += sizeof(int64_t); return val; } -bool BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& offset) { - ensureMaxLen(1); +absl::StatusOr BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& offset) { + absl::Status status = ensureMinLen(buffer, offset, 1); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekBool: {}", status.message())); + + status = ensureMaxLen(1); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekBool: {}", status.message())); const char byte = buffer.peekInt(offset); const bool val = static_cast(byte); @@ -32,24 +44,26 @@ bool BufferHelper::peekBool(Buffer::Instance& buffer, uint64_t& offset) { return val; } -std::string BufferHelper::peekString(Buffer::Instance& buffer, uint64_t& offset) { +absl::StatusOr BufferHelper::peekString(Buffer::Instance& buffer, uint64_t& offset) { std::string val; - const uint32_t len = peekInt32(buffer, offset); + const absl::StatusOr len = peekInt32(buffer, offset); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(len, + fmt::format("peekString: {}", len.status().message())); - if (len == 0) { + if (len.value() == 0) { return val; } - if (buffer.length() < (offset + len)) { - throw EnvoyException("peekString: buffer is smaller than string length"); - } + absl::Status status = ensureMinLen(buffer, offset, len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekString: {}", status.message())); - ensureMaxLen(len); + status = ensureMaxLen(len.value()); + RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, fmt::format("peekString: {}", status.message())); - std::unique_ptr data(new char[len]); - buffer.copyOut(offset, len, data.get()); - val.assign(data.get(), len); - offset += len; + std::unique_ptr data(new char[len.value()]); + buffer.copyOut(offset, len.value(), data.get()); + val.assign(data.get(), len.value()); + offset += len.value(); return val; } @@ -59,12 +73,23 @@ void BufferHelper::skip(const uint32_t len, uint64_t& offset) { current_ += len; } -void BufferHelper::ensureMaxLen(const uint32_t size) { +absl::Status BufferHelper::ensureMaxLen(const uint32_t size) { current_ += size; if (current_ > max_len_) { - throw EnvoyException("read beyond max length"); + return absl::InvalidArgumentError("read beyond max length"); } + + return absl::OkStatus(); +} + +absl::Status BufferHelper::ensureMinLen(const Buffer::Instance& buffer, const uint64_t offset, + const uint32_t size) { + if (buffer.length() < (offset + size)) { + return absl::InvalidArgumentError("read beyond buffer size"); + } + + return absl::OkStatus(); } } // namespace ZooKeeperProxy diff --git a/source/extensions/filters/network/zookeeper_proxy/utils.h b/source/extensions/filters/network/zookeeper_proxy/utils.h index dc699afaf548..e851d8ab49ec 100644 --- a/source/extensions/filters/network/zookeeper_proxy/utils.h +++ b/source/extensions/filters/network/zookeeper_proxy/utils.h @@ -9,6 +9,8 @@ #include "source/common/common/byte_order.h" #include "source/common/common/logger.h" +#include "absl/status/statusor.h" + namespace Envoy { namespace Extensions { namespace NetworkFilters { @@ -17,8 +19,8 @@ namespace ZooKeeperProxy { /** * Helper for extracting ZooKeeper data from a buffer. * - * If at any point a peek is tried beyond max_len, an EnvoyException - * will be thrown. This is important to protect Envoy against malformed + * If at any point a peek is tried beyond max_len, an invalid argument error + * will be returned. This is important to protect Envoy against malformed * requests (e.g.: when the declared and actual length don't match). * * Note: ZooKeeper's protocol uses network byte ordering (big-endian). @@ -27,20 +29,43 @@ class BufferHelper : public Logger::Loggable { public: BufferHelper(uint32_t max_len) : max_len_(max_len) {} - int32_t peekInt32(Buffer::Instance& buffer, uint64_t& offset); - int64_t peekInt64(Buffer::Instance& buffer, uint64_t& offset); - std::string peekString(Buffer::Instance& buffer, uint64_t& offset); - bool peekBool(Buffer::Instance& buffer, uint64_t& offset); + absl::StatusOr peekInt32(Buffer::Instance& buffer, uint64_t& offset); + absl::StatusOr peekInt64(Buffer::Instance& buffer, uint64_t& offset); + absl::StatusOr peekString(Buffer::Instance& buffer, uint64_t& offset); + absl::StatusOr peekBool(Buffer::Instance& buffer, uint64_t& offset); void skip(uint32_t len, uint64_t& offset); void reset() { current_ = 0; } private: - void ensureMaxLen(uint32_t size); + absl::Status ensureMaxLen(const uint32_t size); + absl::Status ensureMinLen(const Buffer::Instance& buffer, const uint64_t offset, + const uint32_t size); const uint32_t max_len_; uint32_t current_{}; }; +#define ABSL_STATUS_RETURN_IF_STATUS_NOT_OK(status) \ + if (!status.ok()) { \ + return status; \ + } + +#define EMIT_DECODER_ERR_AND_RETURN_IF_STATUS_NOT_OK(status) \ + if (!status.ok()) { \ + callbacks_.onDecodeError(); \ + return status; \ + } + +#define RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, message) \ + if (!status.ok()) { \ + return absl::InvalidArgumentError(message); \ + } + +#define EMIT_DECODER_ERR_AND_RETURN_INVALID_ARG_ERR_IF_STATUS_NOT_OK(status, message) \ + if (!status.ok()) { \ + callbacks_.onDecodeError(); \ + return absl::InvalidArgumentError(message); \ + } } // namespace ZooKeeperProxy } // namespace NetworkFilters } // namespace Extensions From d1d6be37c00e0be95b3a1c4cbfea441f1af88559 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 28 Dec 2023 18:54:57 +0000 Subject: [PATCH 055/126] examples: New utility and host util installs (#31542) Signed-off-by: Ryan Northey --- .github/workflows/_stage_verify.yml | 3 ++- examples/verify-common.sh | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index 5f68de975347..9c98c6c278ac 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -84,5 +84,6 @@ jobs: # Install expected host packages export DEBIAN_FRONTEND=noninteractive sudo apt-get -qq update -y - sudo apt-get -qq install -y --no-install-recommends expect + sudo apt-get -qq install -y --no-install-recommends expect gettext whois + sudo snap install yq shell: bash diff --git a/examples/verify-common.sh b/examples/verify-common.sh index 540add9fe21d..c6c0692b944c 100644 --- a/examples/verify-common.sh +++ b/examples/verify-common.sh @@ -119,6 +119,10 @@ cleanup () { bring_down_example + if type -t finally &> /dev/null; then + finally + fi + if [[ "$code" -ne 0 ]]; then run_log Failed else @@ -142,14 +146,23 @@ _curl () { } } +move_if_exists () { + if [ -e "$1" ]; then + mv "$1" "$2" + else + echo "Warning: $1 does not exist. Skipping move operation." + fi +} + responds_with () { local expected response expected="$1" shift response=$(_curl "${@}") - grep -s "$expected" <<< "$response" || { + grep -Fs "$expected" <<< "$response" || { echo "ERROR: curl (${*})" >&2 - echo "EXPECTED: $expected" >&2 + echo "EXPECTED:" >&2 + echo "$expected" >&2 echo "RECEIVED:" >&2 echo "$response" >&2 return 1 @@ -178,7 +191,8 @@ responds_with_header () { response=$(_curl --head "${@}") grep -s "$expected" <<< "$response" || { echo "ERROR: curl (${*})" >&2 - echo "EXPECTED HEADER: $expected" >&2 + echo "EXPECTED HEADER:" >&2 + echo "$expected" >&2 echo "RECEIVED:" >&2 echo "$response" >&2 return 1 From 251dcaffc1b6bc71f7589b1941d868e76b957f6a Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Thu, 28 Dec 2023 22:39:16 +0100 Subject: [PATCH 056/126] Setup scorecard workflow and pin actions versions (#31543) Signed-off-by: Matthieu MOREL --- .github/workflows/_cache.yml | 10 ++--- .github/workflows/_finish.yml | 8 ++-- .github/workflows/_load.yml | 10 ++--- .github/workflows/_load_env.yml | 8 ++-- .github/workflows/_precheck_deps.yml | 4 +- .github/workflows/_request.yml | 10 ++--- .github/workflows/_run.yml | 16 +++---- .github/workflows/_stage_publish.yml | 8 ++-- .github/workflows/_stage_verify.yml | 8 ++-- .github/workflows/_start.yml | 10 ++--- .github/workflows/codeql-daily.yml | 6 +-- .github/workflows/codeql-push.yml | 8 ++-- .github/workflows/command.yml | 6 +-- .github/workflows/envoy-dependency.yml | 22 ++++----- .github/workflows/envoy-release.yml | 16 +++---- .github/workflows/envoy-sync.yml | 4 +- .github/workflows/envoy-windows.yml | 4 +- .github/workflows/mobile-android_build.yml | 12 ++--- .../workflows/mobile-compile_time_options.yml | 2 +- .github/workflows/mobile-format.yml | 2 +- .github/workflows/mobile-ios_build.yml | 4 +- .github/workflows/mobile-release.yml | 4 +- .github/workflows/mobile-traffic_director.yml | 2 +- .github/workflows/pr_notifier.yml | 2 +- .github/workflows/scorecard.yml | 45 +++++++++++++++++++ .github/workflows/stale.yml | 2 +- README.md | 1 + 27 files changed, 140 insertions(+), 94 deletions(-) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/_cache.yml b/.github/workflows/_cache.yml index 81b5b3333531..b2fa26c3e2f6 100644 --- a/.github/workflows/_cache.yml +++ b/.github/workflows/_cache.yml @@ -29,7 +29,7 @@ on: # For a job that does, you can restore with something like: # # steps: -# - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.0.5 +# - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 # with: # key: "${{ needs.env.outputs.build-image }}" # @@ -39,20 +39,20 @@ jobs: docker: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: appauth name: Appauth (mutex lock) with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/docker/cache/prime@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: docker name: Prime Docker cache (${{ inputs.image-tag }}) with: image-tag: ${{ inputs.image-tag }} lock-token: ${{ steps.appauth.outputs.token }} lock-repository: ${{ inputs.lock-repository }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: data name: Cache data with: @@ -60,7 +60,7 @@ jobs: input: | cached: ${{ steps.docker.outputs.cached }} key: ${{ inputs.image-tag }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/json/table@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Summary with: json: ${{ steps.data.outputs.value }} diff --git a/.github/workflows/_finish.yml b/.github/workflows/_finish.yml index 37d0b445b7df..5aae4ba0c9aa 100644 --- a/.github/workflows/_finish.yml +++ b/.github/workflows/_finish.yml @@ -36,7 +36,7 @@ jobs: actions: read contents: read steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Incoming data id: needs with: @@ -87,7 +87,7 @@ jobs: summary: "Check has finished", text: $text}}}} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Print summary with: input: ${{ toJSON(steps.needs.outputs.value).summary-title }} @@ -95,13 +95,13 @@ jobs: "## \(.)" options: -Rr output-path: GITHUB_STEP_SUMMARY - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checks@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Update check with: action: update diff --git a/.github/workflows/_load.yml b/.github/workflows/_load.yml index de34daa521df..ae8b21646189 100644 --- a/.github/workflows/_load.yml +++ b/.github/workflows/_load.yml @@ -91,7 +91,7 @@ jobs: # Handle any failure in triggering job # Remove any `checks` we dont care about # Prepare a check request - - uses: envoyproxy/toolshed/gh-actions/github/env/load@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/env/load@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Load env id: data with: @@ -102,13 +102,13 @@ jobs: GH_TOKEN: ${{ github.token }} # Update the check - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checks@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Update check if: ${{ fromJSON(steps.data.outputs.data).data.check.action == 'RUN' }} with: @@ -116,7 +116,7 @@ jobs: checks: ${{ toJSON(fromJSON(steps.data.outputs.data).checks) }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Print request summary with: input: | @@ -136,7 +136,7 @@ jobs: | $summary.summary as $summary | "${{ inputs.template-request-summary }}" - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: request-output name: Load request with: diff --git a/.github/workflows/_load_env.yml b/.github/workflows/_load_env.yml index ed9dd669babc..b5d19f3ab7e2 100644 --- a/.github/workflows/_load_env.yml +++ b/.github/workflows/_load_env.yml @@ -63,18 +63,18 @@ jobs: request: ${{ steps.env.outputs.data }} trusted: true steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: checkout name: Checkout Envoy repository - name: Generate environment variables - uses: envoyproxy/toolshed/gh-actions/envoy/ci/env@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/env@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: env with: branch-name: ${{ inputs.branch-name }} @@ -86,7 +86,7 @@ jobs: - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} diff --git a/.github/workflows/_precheck_deps.yml b/.github/workflows/_precheck_deps.yml index a4553eed64dd..df9157fe84c5 100644 --- a/.github/workflows/_precheck_deps.yml +++ b/.github/workflows/_precheck_deps.yml @@ -50,9 +50,9 @@ jobs: if: ${{ inputs.dependency-review }} steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ fromJSON(inputs.request).request.sha }} persist-credentials: false - name: Dependency Review - uses: actions/dependency-review-action@v3 + uses: actions/dependency-review-action@01bc87099ba56df1e897b6874784491ea6309bc4 # v3.1.4 diff --git a/.github/workflows/_request.yml b/.github/workflows/_request.yml index 5b9f183d0551..11b1b945767d 100644 --- a/.github/workflows/_request.yml +++ b/.github/workflows/_request.yml @@ -40,14 +40,14 @@ jobs: env: ${{ steps.data.outputs.value }} config: ${{ steps.config.outputs.config }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: started name: Create timestamp with: options: -r filter: | now - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -60,7 +60,7 @@ jobs: # *ALL* variables collected should be treated as untrusted and should be sanitized before # use - name: Generate environment variables from commit - uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/envoy/ci/request@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: env with: branch-name: ${{ steps.checkout.outputs.branch-name }} @@ -71,7 +71,7 @@ jobs: vars: ${{ toJSON(vars) }} - name: Request summary id: summary - uses: envoyproxy/toolshed/gh-actions/github/env/summary@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/env/summary@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: actor: ${{ toJSON(fromJSON(steps.env.outputs.data).request.actor) }} base-sha: ${{ fromJSON(steps.env.outputs.data).request.base-sha }} @@ -87,7 +87,7 @@ jobs: target-branch: ${{ fromJSON(steps.env.outputs.data).request.target-branch }} - name: Environment data - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: data with: input: | diff --git a/.github/workflows/_run.yml b/.github/workflows/_run.yml index 579efafa33d8..2670d17a7ae7 100644 --- a/.github/workflows/_run.yml +++ b/.github/workflows/_run.yml @@ -94,7 +94,7 @@ on: summary-post: type: string default: | - - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/run/summary@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: context: %{{ inputs.context }} steps-pre: @@ -155,7 +155,7 @@ jobs: name: ${{ inputs.command }} ${{ inputs.target }} timeout-minutes: ${{ inputs.timeout-minutes }} steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: started name: Create timestamp with: @@ -163,7 +163,7 @@ jobs: filter: | now # This controls which input vars are exposed to the run action (and related steps) - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Context id: context with: @@ -184,11 +184,11 @@ jobs: | . * {$config, $check} - if: ${{ inputs.cache-build-image }} name: Restore Docker cache ${{ inputs.cache-build-image && format('({0})', inputs.cache-build-image) || '' }} - uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/docker/cache/restore@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: image_tag: ${{ inputs.cache-build-image }} - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: appauth name: Appauth if: ${{ inputs.trusted }} @@ -199,7 +199,7 @@ jobs: # - the workaround is to allow the token to be passed through. token: ${{ github.token }} token-ok: true - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -216,7 +216,7 @@ jobs: token: ${{ inputs.trusted && steps.appauth.outputs.token || github.token }} # This is currently only use by mobile-docs and can be removed once they are updated to the newer website - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: checkout-extra name: Checkout extra repository (for publishing) if: ${{ inputs.checkout-extra }} @@ -224,7 +224,7 @@ jobs: config: ${{ inputs.checkout-extra }} ssh-key: ${{ inputs.trusted && inputs.ssh-key-extra || '' }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/run@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Run CI ${{ inputs.command }} ${{ inputs.target }} with: args: ${{ inputs.args != '--' && inputs.args || inputs.target }} diff --git a/.github/workflows/_stage_publish.yml b/.github/workflows/_stage_publish.yml index 27996ebdffa2..374cf0e6e1fa 100644 --- a/.github/workflows/_stage_publish.yml +++ b/.github/workflows/_stage_publish.yml @@ -63,7 +63,7 @@ jobs: export ENVOY_PUBLISH_DRY_RUN=${{ (fromJSON(inputs.request).request.version.dev || ! inputs.trusted) && 1 || '' }} steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: options: -Rr input: >- @@ -80,7 +80,7 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)/\($path)" - - uses: envoyproxy/toolshed/gh-actions/fetch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/fetch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: url: %{{ steps.url.outputs.value }} path: %{{ runner.temp }}/release.signed @@ -98,12 +98,12 @@ jobs: needs: - publish steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/dispatch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: ref: main repository: ${{ fromJSON(inputs.request).request.version.dev && 'envoyproxy/envoy-website' || 'envoyproxy/archive' }} diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index 9c98c6c278ac..bbac64e90c7c 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -50,7 +50,7 @@ jobs: rbe: false steps-pre: | - id: url - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: options: -Rr input: >- @@ -66,15 +66,15 @@ jobs: end | . as $bucket | "https://storage.googleapis.com/\($bucket)/\($sha)" - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy.tar variant: dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy-contrib.tar variant: contrib-dev - - uses: envoyproxy/toolshed/gh-actions/docker/fetch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/docker/fetch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: url: %{{ steps.url.outputs.value }}/docker/envoy-google-vrp.tar variant: google-vrp-dev diff --git a/.github/workflows/_start.yml b/.github/workflows/_start.yml index 318660ba4ddc..7f084737130d 100644 --- a/.github/workflows/_start.yml +++ b/.github/workflows/_start.yml @@ -54,7 +54,7 @@ jobs: start: runs-on: ubuntu-22.04 steps: - - uses: envoyproxy/toolshed/gh-actions/jq@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/jq@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: check-config name: Prepare check data with: @@ -77,13 +77,13 @@ jobs: | .skipped.output.summary = "${{ inputs.skipped-summary }}" | .skipped.output.text = "" - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Appauth id: appauth with: app_id: ${{ secrets.app-id }} key: ${{ secrets.app-key }} - - uses: envoyproxy/toolshed/gh-actions/github/checks@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checks@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Start checks id: checks with: @@ -94,7 +94,7 @@ jobs: ${{ fromJSON(inputs.env).summary.summary }} token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/json/table@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/json/table@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Summary with: collapse-open: true @@ -118,7 +118,7 @@ jobs: output-path: GITHUB_STEP_SUMMARY title: Checks started/skipped - - uses: envoyproxy/toolshed/gh-actions/github/env/save@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/env/save@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Save env id: data with: diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 9e42157377a3..498ab423ffb9 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -20,11 +20,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -55,4 +55,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index a2390f264f3f..64d239b2a6c8 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -26,13 +26,13 @@ jobs: steps: - name: Pre-cleanup - uses: envoyproxy/toolshed/gh-actions/diskspace@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/diskspace@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: to_remove: | /usr/local/lib/android - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get build targets run: | @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -76,4 +76,4 @@ jobs: - name: Perform CodeQL Analysis if: env.BUILD_TARGETS != '' - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 diff --git a/.github/workflows/command.yml b/.github/workflows/command.yml index 1d26266237f1..fb8d3e144117 100644 --- a/.github/workflows/command.yml +++ b/.github/workflows/command.yml @@ -28,7 +28,7 @@ jobs: && github.actor != 'dependabot[bot]' }} steps: - - uses: envoyproxy/toolshed/gh-actions/github/command@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/command@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Parse command from comment id: command with: @@ -37,14 +37,14 @@ jobs: ^/(retest) # /retest - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 if: ${{ steps.command.outputs.command == 'retest' }} id: appauth-retest name: Appauth (retest) with: key: ${{ secrets.ENVOY_CI_APP_KEY }} app_id: ${{ secrets.ENVOY_CI_APP_ID }} - - uses: envoyproxy/toolshed/gh-actions/retest@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/retest@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 if: ${{ steps.command.outputs.command == 'retest' }} name: Retest with: diff --git a/.github/workflows/envoy-dependency.yml b/.github/workflows/envoy-dependency.yml index 8113ddaa810d..623aa1a2a586 100644 --- a/.github/workflows/envoy-dependency.yml +++ b/.github/workflows/envoy-dependency.yml @@ -50,16 +50,16 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: token: ${{ steps.appauth.outputs.token }} - - uses: envoyproxy/toolshed/gh-actions/bson@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/bson@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: update name: Update dependency (${{ inputs.dependency }}) with: @@ -94,13 +94,13 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: envoyproxy/toolshed/gh-actions/upload/diff@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/upload/diff@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Upload diff with: name: ${{ inputs.dependency }}-${{ steps.update.outputs.output }} - name: Create a PR if: ${{ inputs.pr }} - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/pr@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: base: main body: | @@ -131,11 +131,11 @@ jobs: steps: - id: appauth name: Appauth - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_DEP_APP_ID }} key: ${{ secrets.ENVOY_CI_DEP_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: checkout name: Checkout Envoy repository with: @@ -143,7 +143,7 @@ jobs: path: envoy fetch-depth: 0 token: ${{ steps.appauth.outputs.token }} - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 name: Checkout Envoy build tools repository with: repository: envoyproxy/envoy-build-tools @@ -177,7 +177,7 @@ jobs: - name: Check Docker SHAs id: build-images - uses: envoyproxy/toolshed/gh-actions/docker/shas@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/docker/shas@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: images: | sha: envoyproxy/envoy-build-ubuntu:${{ steps.build-tools.outputs.tag }} @@ -206,7 +206,7 @@ jobs: name: Update SHAs working-directory: envoy - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/pr@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: base: main body: Created by Envoy dependency bot @@ -235,7 +235,7 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Run dependency checker run: | TODAY_DATE=$(date -u -I"date") diff --git a/.github/workflows/envoy-release.yml b/.github/workflows/envoy-release.yml index af108a20d9d5..d4743a7cf45e 100644 --- a/.github/workflows/envoy-release.yml +++ b/.github/workflows/envoy-release.yml @@ -55,7 +55,7 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} @@ -77,10 +77,10 @@ jobs: name: Check changelog summary - if: ${{ inputs.author }} name: Validate signoff email - uses: envoyproxy/toolshed/gh-actions/email/validate@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/email/validate@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: email: ${{ inputs.author }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/run@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Create release with: source: | @@ -105,7 +105,7 @@ jobs: name: Release version id: release - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/pr@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: base: ${{ github.ref_name }} commit: false @@ -130,13 +130,13 @@ jobs: steps: - id: checkout name: Checkout Envoy repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} committer-name: ${{ env.COMMITTER_NAME }} committer-email: ${{ env.COMMITTER_EMAIL }} - - uses: envoyproxy/toolshed/gh-actions/github/run@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/github/run@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 name: Sync version histories with: command: >- @@ -146,7 +146,7 @@ jobs: -- --signoff="${{ env.COMMITTER_NAME }} <${{ env.COMMITTER_EMAIL }}>" - name: Create a PR - uses: envoyproxy/toolshed/gh-actions/github/pr@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/pr@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: append-commit-message: true base: ${{ github.ref_name }} @@ -176,7 +176,7 @@ jobs: name: Create release branch steps: - name: Checkout repository - uses: envoyproxy/toolshed/gh-actions/github/checkout@actions-v0.2.20 + uses: envoyproxy/toolshed/gh-actions/github/checkout@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app_id: ${{ secrets.ENVOY_CI_PUBLISH_APP_ID }} app_key: ${{ secrets.ENVOY_CI_PUBLISH_APP_KEY }} diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml index 2f726ecade76..09fa027d64b9 100644 --- a/.github/workflows/envoy-sync.yml +++ b/.github/workflows/envoy-sync.yml @@ -28,12 +28,12 @@ jobs: - data-plane-api - mobile-website steps: - - uses: envoyproxy/toolshed/gh-actions/appauth@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/appauth@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 id: appauth with: app_id: ${{ secrets.ENVOY_CI_SYNC_APP_ID }} key: ${{ secrets.ENVOY_CI_SYNC_APP_KEY }} - - uses: envoyproxy/toolshed/gh-actions/dispatch@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/dispatch@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: repository: "envoyproxy/${{ matrix.downstream }}" ref: main diff --git a/.github/workflows/envoy-windows.yml b/.github/workflows/envoy-windows.yml index 21d9a992da25..17be3ff309e8 100644 --- a/.github/workflows/envoy-windows.yml +++ b/.github/workflows/envoy-windows.yml @@ -97,10 +97,10 @@ jobs: image-tag: ltsc2022 runs-on: ${{ matrix.runs-on }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ needs.load.outputs.repo_ref }} - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: windows.release - run: | diff --git a/.github/workflows/mobile-android_build.yml b/.github/workflows/mobile-android_build.yml index 452d63d11fb5..76d8b368fbcc 100644 --- a/.github/workflows/mobile-android_build.yml +++ b/.github/workflows/mobile-android_build.yml @@ -75,9 +75,9 @@ jobs: target: kotlin-hello-world runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: apk: bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity @@ -104,7 +104,7 @@ jobs: target: ${{ matrix.target }} runs-on: envoy-x64-small steps-pre: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/pre@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 steps-post: ${{ matrix.steps-post }} timeout-minutes: 50 trusted: ${{ fromJSON(needs.load.outputs.trusted) }} @@ -115,7 +115,7 @@ jobs: include: - name: java-hello-world steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: apk: bazel-bin/examples/java/hello_world/hello_envoy.apk app: io.envoyproxy.envoymobile.helloenvoy/.MainActivity @@ -134,7 +134,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/baseline:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: apk: bazel-bin/test/kotlin/apps/baseline/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoybaselinetest/.MainActivity @@ -149,7 +149,7 @@ jobs: --config=mobile-remote-release-clang-android //test/kotlin/apps/experimental:hello_envoy_kt steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/android/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: apk: bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk app: io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity diff --git a/.github/workflows/mobile-compile_time_options.yml b/.github/workflows/mobile-compile_time_options.yml index e3beea357452..9ea03ea16079 100644 --- a/.github/workflows/mobile-compile_time_options.yml +++ b/.github/workflows/mobile-compile_time_options.yml @@ -107,7 +107,7 @@ jobs: echo "ANDROID_NDK_HOME=${ANDROID_NDK_HOME}" >> $GITHUB_ENV export ANDROID_NDK_HOME steps-pre: | - - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 + - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0 with: java-version: '8' java-package: jdk diff --git a/.github/workflows/mobile-format.yml b/.github/workflows/mobile-format.yml index f661761eef1c..3f09ce951087 100644 --- a/.github/workflows/mobile-format.yml +++ b/.github/workflows/mobile-format.yml @@ -122,7 +122,7 @@ jobs: export DEVELOPER_DIR=/Applications/Xcode_14.1.app ./ci/mac_ci_setup.sh steps-pre: | - - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 + - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0 with: java-version: '8' java-package: jdk diff --git a/.github/workflows/mobile-ios_build.yml b/.github/workflows/mobile-ios_build.yml index 2aafe766d43c..11625c4a1430 100644 --- a/.github/workflows/mobile-ios_build.yml +++ b/.github/workflows/mobile-ios_build.yml @@ -86,7 +86,7 @@ jobs: ./ci/mac_ci_setup.sh ./bazelw shutdown steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} @@ -127,7 +127,7 @@ jobs: source: | ./ci/mac_ci_setup.sh steps-post: | - - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@actions-v0.2.20 + - uses: envoyproxy/toolshed/gh-actions/envoy/ios/post@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 with: app: ${{ matrix.app }} args: ${{ matrix.args || '--config=mobile-remote-ci-macos-ios' }} diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index e3eaf65704c0..d051821814f0 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -95,12 +95,12 @@ jobs: - output: envoy - output: envoy_xds steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: fetch-depth: 0 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: ${{ matrix.output }}_android_aar_sources path: . diff --git a/.github/workflows/mobile-traffic_director.yml b/.github/workflows/mobile-traffic_director.yml index 79459cef6e6f..4458469f0636 100644 --- a/.github/workflows/mobile-traffic_director.yml +++ b/.github/workflows/mobile-traffic_director.yml @@ -30,7 +30,7 @@ jobs: timeout-minutes: 120 steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Add safe directory run: git config --global --add safe.directory /__w/envoy/envoy - name: 'Run GcpTrafficDirectorIntegrationTest' diff --git a/.github/workflows/pr_notifier.yml b/.github/workflows/pr_notifier.yml index ab42bcd08a48..95083e527889 100644 --- a/.github/workflows/pr_notifier.yml +++ b/.github/workflows/pr_notifier.yml @@ -22,7 +22,7 @@ jobs: || !contains(github.actor, '[bot]')) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Notify about PRs run: | ARGS=() diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 000000000000..8c4bb04b2ba0 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,45 @@ +name: Scorecard supply-chain security +on: + branch_protection_rule: + schedule: + - cron: '33 13 * * 5' + push: + branches: + - "main" + +permissions: + contents: read + + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-22.04 + permissions: + security-events: write + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: "Upload artifact" + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + with: + sarif_file: results.sarif diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b83ccd54d95f..aed93868a897 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Prune Stale - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Different amounts of days for issues/PRs are not currently supported but there is a PR diff --git a/README.md b/README.md index b3325ef8bdb1..5d292c80d5dd 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ involved and how Envoy plays a role, read the CNCF [announcement](https://www.cncf.io/blog/2017/09/13/cncf-hosts-envoy/). [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1266/badge)](https://bestpractices.coreinfrastructure.org/projects/1266) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/envoyproxy/envoy/badge)](https://api.securityscorecards.dev/projects/github.com/envoyproxy/envoy) [![Azure Pipelines](https://dev.azure.com/cncf/envoy/_apis/build/status/11?branchName=main)](https://dev.azure.com/cncf/envoy/_build/latest?definitionId=11&branchName=main) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/envoy.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:envoy) [![Jenkins](https://powerci.osuosl.org/buildStatus/icon?job=build-envoy-static-master&subject=ppc64le%20build)](https://powerci.osuosl.org/job/build-envoy-static-master/) From 21323d483ed163155fb8ceba0935c33c6dae7a2f Mon Sep 17 00:00:00 2001 From: Ilya Nemakov Date: Fri, 29 Dec 2023 03:49:03 +0400 Subject: [PATCH 057/126] redis: Add GETDEL command support (#31448) Add GETDEL command support Signed-off-by: Ilya Nemakov --- changelogs/current.yaml | 3 +++ .../arch_overview/other_protocols/redis.rst | 1 + .../network/common/redis/supported_commands.h | 24 +++++++++---------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 86c12032c43b..2579e7acee36 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -323,6 +323,9 @@ new_features: - area: lua change: | Added lua extension of router cluster specifier plugin to support selecting cluster dynamically by lua code. +- area: redis + change: | + Added support for the getdel command. deprecated: - area: wasm diff --git a/docs/root/intro/arch_overview/other_protocols/redis.rst b/docs/root/intro/arch_overview/other_protocols/redis.rst index b9db6d3186be..1b38fd8c887a 100644 --- a/docs/root/intro/arch_overview/other_protocols/redis.rst +++ b/docs/root/intro/arch_overview/other_protocols/redis.rst @@ -238,6 +238,7 @@ For details on each command's usage see the official DECRBY, String GET, String GETBIT, String + GETDEL, String GETRANGE, String GETSET, String INCR, String diff --git a/source/extensions/filters/network/common/redis/supported_commands.h b/source/extensions/filters/network/common/redis/supported_commands.h index 9ea4ed55c35e..560689eba715 100644 --- a/source/extensions/filters/network/common/redis/supported_commands.h +++ b/source/extensions/filters/network/common/redis/supported_commands.h @@ -22,12 +22,12 @@ struct SupportedCommands { CONSTRUCT_ON_FIRST_USE( absl::flat_hash_set, "append", "bitcount", "bitfield", "bitpos", "decr", "decrby", "dump", "expire", "expireat", "geoadd", "geodist", "geohash", "geopos", - "georadius_ro", "georadiusbymember_ro", "get", "getbit", "getrange", "getset", "hdel", - "hexists", "hget", "hgetall", "hincrby", "hincrbyfloat", "hkeys", "hlen", "hmget", "hmset", - "hscan", "hset", "hsetnx", "hstrlen", "hvals", "incr", "incrby", "incrbyfloat", "lindex", - "linsert", "llen", "lmove", "lpop", "lpush", "lpushx", "lrange", "lrem", "lset", "ltrim", - "persist", "pexpire", "pexpireat", "pfadd", "pfcount", "psetex", "pttl", "restore", "rpop", - "rpush", "rpushx", "sadd", "scard", "set", "setbit", "setex", "setnx", "setrange", + "georadius_ro", "georadiusbymember_ro", "get", "getbit", "getdel", "getrange", "getset", + "hdel", "hexists", "hget", "hgetall", "hincrby", "hincrbyfloat", "hkeys", "hlen", "hmget", + "hmset", "hscan", "hset", "hsetnx", "hstrlen", "hvals", "incr", "incrby", "incrbyfloat", + "lindex", "linsert", "llen", "lmove", "lpop", "lpush", "lpushx", "lrange", "lrem", "lset", + "ltrim", "persist", "pexpire", "pexpireat", "pfadd", "pfcount", "psetex", "pttl", "restore", + "rpop", "rpush", "rpushx", "sadd", "scard", "set", "setbit", "setex", "setnx", "setrange", "sismember", "smembers", "spop", "srandmember", "srem", "sscan", "strlen", "ttl", "type", "watch", "zadd", "zcard", "zcount", "zincrby", "zlexcount", "zpopmin", "zpopmax", "zrange", "zrangebylex", "zrangebyscore", "zrank", "zrem", "zremrangebylex", "zremrangebyrank", @@ -92,12 +92,12 @@ struct SupportedCommands { static const absl::flat_hash_set& writeCommands() { CONSTRUCT_ON_FIRST_USE(absl::flat_hash_set, "append", "bitfield", "decr", "decrby", "del", "discard", "exec", "expire", "expireat", "eval", "evalsha", - "geoadd", "hdel", "hincrby", "hincrbyfloat", "hmset", "hset", "hsetnx", - "incr", "incrby", "incrbyfloat", "linsert", "lmove", "lpop", "lpush", - "lpushx", "lrem", "lset", "ltrim", "mset", "multi", "persist", "pexpire", - "pexpireat", "pfadd", "psetex", "restore", "rpop", "rpush", "rpushx", - "sadd", "set", "setbit", "setex", "setnx", "setrange", "spop", "srem", - "zadd", "zincrby", "touch", "zpopmin", "zpopmax", "zrem", + "geoadd", "getdel", "hdel", "hincrby", "hincrbyfloat", "hmset", "hset", + "hsetnx", "incr", "incrby", "incrbyfloat", "linsert", "lmove", "lpop", + "lpush", "lpushx", "lrem", "lset", "ltrim", "mset", "multi", "persist", + "pexpire", "pexpireat", "pfadd", "psetex", "restore", "rpop", "rpush", + "rpushx", "sadd", "set", "setbit", "setex", "setnx", "setrange", "spop", + "srem", "zadd", "zincrby", "touch", "zpopmin", "zpopmax", "zrem", "zremrangebylex", "zremrangebyrank", "zremrangebyscore", "unlink"); } From b15ca09a9293f98a4a0977c5a0769742ba72688d Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Fri, 29 Dec 2023 13:30:51 +0100 Subject: [PATCH 058/126] fix github/codeql-action version in comments (#31554) Signed-off-by: Matthieu MOREL --- .github/workflows/codeql-daily.yml | 4 ++-- .github/workflows/codeql-push.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 498ab423ffb9..87aec4bd24d6 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -24,7 +24,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -55,4 +55,4 @@ jobs: git clean -xdf - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index 64d239b2a6c8..c21542a34e50 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 # Override language selection by uncommenting this and choosing your languages with: languages: cpp @@ -76,4 +76,4 @@ jobs: - name: Perform CodeQL Analysis if: env.BUILD_TARGETS != '' - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 From 448cbd60ee4e1af1f869f9f519095680b233f1e2 Mon Sep 17 00:00:00 2001 From: zirain Date: Sat, 30 Dec 2023 00:06:20 +0800 Subject: [PATCH 059/126] add format task for vscode (#31369) Signed-off-by: zirain --- .vscode/tasks.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 39267d2a1ca0..bb9133367ce8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -32,6 +32,12 @@ "type": "shell", "command": "EXCLUDE_CONTRIB=true tools/vscode/refresh_compdb.sh", "problemMatcher": [] + }, + { + "label": "Local Fix Format", + "type": "shell", + "command": "tools/local_fix_format.sh -all", + "problemMatcher": [] } ] } From 51cd6b95cb74c37321baadaa326eebd42e6d624d Mon Sep 17 00:00:00 2001 From: code Date: Tue, 2 Jan 2024 14:42:02 +0800 Subject: [PATCH 060/126] generic proxy: application specific status support (#31498) Signed-off-by: wbpcode --- .../network/source/codecs/dubbo/config.cc | 68 ++++--------------- .../network/source/codecs/dubbo/config.h | 10 +-- .../filters/network/source/interface/stream.h | 47 ++++++++++++- .../network/test/codecs/dubbo/config_test.cc | 36 ++++------ .../filters/network/test/fake_codec.h | 17 +++-- .../filters/network/test/integration_test.cc | 24 +++---- .../filters/network/test/proxy_test.cc | 7 +- 7 files changed, 101 insertions(+), 108 deletions(-) diff --git a/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.cc b/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.cc index 00b3d2db575f..4bbfa68e1b06 100644 --- a/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.cc +++ b/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.cc @@ -16,28 +16,6 @@ namespace Dubbo { namespace { constexpr absl::string_view VERSION_KEY = "version"; -constexpr absl::string_view UNKNOWN_RESPONSE_STATUS = "UnknownResponseStatus"; - -#define ENUM_TO_STRING_VIEW(X) \ - case Common::Dubbo::ResponseStatus::X: \ - static constexpr absl::string_view X##_VIEW = #X; \ - return X##_VIEW; - -absl::string_view responseStatusToStringView(Common::Dubbo::ResponseStatus status) { - switch (status) { - ENUM_TO_STRING_VIEW(Ok); - ENUM_TO_STRING_VIEW(ClientTimeout); - ENUM_TO_STRING_VIEW(ServerTimeout); - ENUM_TO_STRING_VIEW(BadRequest); - ENUM_TO_STRING_VIEW(BadResponse); - ENUM_TO_STRING_VIEW(ServiceNotFound); - ENUM_TO_STRING_VIEW(ServiceError); - ENUM_TO_STRING_VIEW(ServerError); - ENUM_TO_STRING_VIEW(ClientError); - ENUM_TO_STRING_VIEW(ServerThreadpoolExhaustedError); - } - return UNKNOWN_RESPONSE_STATUS; -} Common::Dubbo::ResponseStatus genericStatusToStatus(StatusCode code) { switch (code) { @@ -50,29 +28,6 @@ Common::Dubbo::ResponseStatus genericStatusToStatus(StatusCode code) { } } -StatusCode statusToGenericStatus(Common::Dubbo::ResponseStatus status) { - switch (status) { - case Common::Dubbo::ResponseStatus::Ok: - return StatusCode::kOk; - case Common::Dubbo::ResponseStatus::ClientTimeout: - case Common::Dubbo::ResponseStatus::ServerTimeout: - return StatusCode::kUnknown; - case Common::Dubbo::ResponseStatus::BadRequest: - return StatusCode::kInvalidArgument; - case Common::Dubbo::ResponseStatus::BadResponse: - return StatusCode::kUnknown; - case Common::Dubbo::ResponseStatus::ServiceNotFound: - return StatusCode::kNotFound; - case Common::Dubbo::ResponseStatus::ServiceError: - case Common::Dubbo::ResponseStatus::ServerError: - case Common::Dubbo::ResponseStatus::ClientError: - return StatusCode::kUnavailable; - case Common::Dubbo::ResponseStatus::ServerThreadpoolExhaustedError: - return StatusCode::kResourceExhausted; - } - return StatusCode::kUnavailable; -} - } // namespace void DubboRequest::forEach(IterateCallback callback) const { @@ -121,7 +76,7 @@ void DubboRequest::erase(absl::string_view key) { typed_request->mutableAttachment()->remove(key); } -void DubboResponse::refreshGenericStatus() { +void DubboResponse::refreshStatus() { ASSERT(inner_metadata_ != nullptr); ASSERT(inner_metadata_->hasResponse() && inner_metadata_->hasResponseStatus()); @@ -130,19 +85,22 @@ void DubboResponse::refreshGenericStatus() { const auto status = inner_metadata_->context().responseStatus(); const auto optional_type = inner_metadata_->response().responseType(); + // The final status is not ok if the response status is not ResponseStatus::Ok + // anyway. + bool response_ok = (status == Common::Dubbo::ResponseStatus::Ok); + + // The final status is not ok if the response type is ResponseWithException or + // ResponseWithExceptionWithAttachments even if the response status is Ok. if (status == Common::Dubbo::ResponseStatus::Ok) { ASSERT(optional_type.has_value()); auto type = optional_type.value_or(RpcResponseType::ResponseWithException); if (type == RpcResponseType::ResponseWithException || type == RpcResponseType::ResponseWithExceptionWithAttachments) { - status_ = Status(StatusCode::kUnavailable, "exception_via_upstream"); - return; + response_ok = false; } - status_ = absl::OkStatus(); - return; } - status_ = Status(statusToGenericStatus(status), responseStatusToStringView(status)); + status_ = StreamStatus(static_cast(status), response_ok); } DubboCodecBase::DubboCodecBase(Common::Dubbo::DubboCodecPtr codec) : codec_(std::move(codec)) {} @@ -152,15 +110,15 @@ ResponsePtr DubboServerCodec::respond(Status status, absl::string_view, const auto* typed_request = dynamic_cast(&origin_request); ASSERT(typed_request != nullptr); - Common::Dubbo::ResponseStatus response_status; + Common::Dubbo::ResponseStatus response_status = genericStatusToStatus(status.code()); + absl::optional optional_type; absl::string_view content; - if (status.ok()) { - response_status = Common::Dubbo::ResponseStatus::Ok; + + if (response_status == Common::Dubbo::ResponseStatus::Ok) { optional_type.emplace(Common::Dubbo::RpcResponseType::ResponseWithException); content = "exception_via_proxy"; } else { - response_status = genericStatusToStatus(status.code()); content = status.message(); } diff --git a/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.h b/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.h index 51fdec751ce9..6ef3932be244 100644 --- a/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.h +++ b/contrib/generic_proxy/filters/network/source/codecs/dubbo/config.h @@ -55,21 +55,21 @@ class DubboResponse : public Response { ASSERT(inner_metadata_ != nullptr); ASSERT(inner_metadata_->hasContext()); ASSERT(inner_metadata_->hasResponse()); - refreshGenericStatus(); + refreshStatus(); } - void refreshGenericStatus(); + void refreshStatus(); // Response. absl::string_view protocol() const override { return DubboProtocolName; } - Status status() const override { return status_; } + StreamStatus status() const override { return status_; } // StreamFrame FrameFlags frameFlags() const override { return stream_frame_flags_; } FrameFlags stream_frame_flags_; - Status status_; + StreamStatus status_; Common::Dubbo::MessageMetadataSharedPtr inner_metadata_; }; @@ -151,7 +151,7 @@ class DubboServerCodec public: using DubboDecoderBase::DubboDecoderBase; - ResponsePtr respond(Status status, absl::string_view short_response_flags, + ResponsePtr respond(absl::Status status, absl::string_view short_response_flags, const Request& request) override; }; diff --git a/contrib/generic_proxy/filters/network/source/interface/stream.h b/contrib/generic_proxy/filters/network/source/interface/stream.h index 128eeafc91a5..fcd7debb7660 100644 --- a/contrib/generic_proxy/filters/network/source/interface/stream.h +++ b/contrib/generic_proxy/filters/network/source/interface/stream.h @@ -80,9 +80,12 @@ class FrameFlags { * same for all frames of the same stream. * @param stream_flags StreamFlags of the stream. * @param end_stream whether the current frame is the last frame of the request or response. + * @param frame_tags frame tags of the current frame. The meaning of the frame tags is + * application protocol specific. */ - FrameFlags(StreamFlags stream_flags = StreamFlags(), bool end_stream = true) - : stream_flags_(stream_flags), end_stream_(end_stream) {} + FrameFlags(StreamFlags stream_flags = StreamFlags(), bool end_stream = true, + uint32_t frame_tags = 0) + : stream_flags_(stream_flags), end_stream_(end_stream), frame_tags_(frame_tags) {} /** * Get flags of stream that the frame belongs to. The flags MUST be same for all frames of the @@ -96,11 +99,22 @@ class FrameFlags { */ bool endStream() const { return end_stream_; } + /** + * @return frame tags of the current frame. The meaning of the frame tags is application + * protocol specific. This allows the creator of the frame to attach additional information to the + * frame and get it by the receiver of the frame without parsing the frame payload or dynamic + * cast. + * For example, the frame tags could be used to indicate the type of the frame by the server + * codec. Then the client codec could get the frame type without dynamic cast. + */ + uint32_t frameTags() const { return frame_tags_; } + private: StreamFlags stream_flags_{}; // Default to true for backward compatibility. bool end_stream_{true}; + uint32_t frame_tags_{}; }; /** @@ -218,9 +232,36 @@ enum class Event { ConnectionFailure, }; +/** + * The Status type is used by the generic proxy to indicate statuses or error types + * to the application protocol codec. This is application protocol independent. + */ using Status = absl::Status; using StatusCode = absl::StatusCode; +/** + * Generic stream status. The Status is used by the application protocol codec to + * indicate the status of the response. The meaning of status code is application + * protocol specific. + */ +struct StreamStatus { +public: + StreamStatus() = default; + StreamStatus(uint32_t code, bool ok) : code_(code), ok_(ok) {} + + // Returns true if the status indicates success. This will be used for tracing, logging + // or stats purposes. + ABSL_MUST_USE_RESULT bool ok() const { return ok_; } + + // Returns the status code value. The code will be used for tracing, logging or stats + // purposes. The specific code value is application protocol specific. + ABSL_MUST_USE_RESULT uint32_t code() const { return code_; } + +private: + uint32_t code_{}; + bool ok_{true}; +}; + /** * Interface of generic response. This is derived from StreamFrame that contains the response * specific information. First frame of the response MUST be a StreamResponse. @@ -232,7 +273,7 @@ class StreamResponse : public StreamBase { * * @return generic response status. */ - virtual Status status() const { return {}; } + virtual StreamStatus status() const { return {}; } }; using StreamResponsePtr = std::unique_ptr; diff --git a/contrib/generic_proxy/filters/network/test/codecs/dubbo/config_test.cc b/contrib/generic_proxy/filters/network/test/codecs/dubbo/config_test.cc index 0d5209780398..6a4e3abb8614 100644 --- a/contrib/generic_proxy/filters/network/test/codecs/dubbo/config_test.cc +++ b/contrib/generic_proxy/filters/network/test/codecs/dubbo/config_test.cc @@ -107,73 +107,61 @@ TEST(DubboResponseTest, DubboResponseTest) { { DubboResponse response( createDubboResponse(request, ResponseStatus::Ok, RpcResponseType::ResponseWithValue)); - EXPECT_EQ(StatusCode::kOk, response.status().code()); + EXPECT_EQ(20, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::Ok, RpcResponseType::ResponseWithException)); - EXPECT_EQ(StatusCode::kUnavailable, response.status().code()); - EXPECT_EQ("exception_via_upstream", response.status().message()); + EXPECT_EQ(20, response.status().code()); } { DubboResponse response(createDubboResponse( request, ResponseStatus::Ok, RpcResponseType::ResponseWithExceptionWithAttachments)); - EXPECT_EQ(StatusCode::kUnavailable, response.status().code()); - EXPECT_EQ("exception_via_upstream", response.status().message()); + EXPECT_EQ(20, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ClientTimeout, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnknown, response.status().code()); - EXPECT_EQ("ClientTimeout", response.status().message()); + EXPECT_EQ(30, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ServerTimeout, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnknown, response.status().code()); - EXPECT_EQ(StatusCode::kUnknown, response.status().code()); - EXPECT_EQ("ServerTimeout", response.status().message()); + EXPECT_EQ(31, response.status().code()); } { DubboResponse response(createDubboResponse(request, ResponseStatus::BadRequest, absl::nullopt)); - EXPECT_EQ(StatusCode::kInvalidArgument, response.status().code()); - EXPECT_EQ("BadRequest", response.status().message()); + EXPECT_EQ(40, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::BadResponse, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnknown, response.status().code()); - EXPECT_EQ("BadResponse", response.status().message()); + EXPECT_EQ(50, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ServiceNotFound, absl::nullopt)); - EXPECT_EQ(StatusCode::kNotFound, response.status().code()); - EXPECT_EQ("ServiceNotFound", response.status().message()); + EXPECT_EQ(60, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ServiceError, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnavailable, response.status().code()); - EXPECT_EQ("ServiceError", response.status().message()); + EXPECT_EQ(70, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ServerError, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnavailable, response.status().code()); - EXPECT_EQ("ServerError", response.status().message()); + EXPECT_EQ(80, response.status().code()); } { DubboResponse response( createDubboResponse(request, ResponseStatus::ClientError, absl::nullopt)); - EXPECT_EQ(StatusCode::kUnavailable, response.status().code()); - EXPECT_EQ("ClientError", response.status().message()); + EXPECT_EQ(90, response.status().code()); } { DubboResponse response(createDubboResponse( request, ResponseStatus::ServerThreadpoolExhaustedError, absl::nullopt)); - EXPECT_EQ(StatusCode::kResourceExhausted, response.status().code()); - EXPECT_EQ("ServerThreadpoolExhaustedError", response.status().message()); + EXPECT_EQ(100, response.status().code()); } // Getter and setter do nothing for response. diff --git a/contrib/generic_proxy/filters/network/test/fake_codec.h b/contrib/generic_proxy/filters/network/test/fake_codec.h index 28a683c5585c..702abb47d25e 100644 --- a/contrib/generic_proxy/filters/network/test/fake_codec.h +++ b/contrib/generic_proxy/filters/network/test/fake_codec.h @@ -63,10 +63,11 @@ class FakeStreamCodecFactory : public CodecFactory { class FakeResponse : public FakeStreamBase { public: absl::string_view protocol() const override { return protocol_; } - Status status() const override { return status_; } + StreamStatus status() const override { return status_; } std::string protocol_; - Status status_; + StreamStatus status_; + std::string message_; }; class FakeServerCodec : public ServerCodec { @@ -145,14 +146,13 @@ class FakeStreamCodecFactory : public CodecFactory { std::string body; body.reserve(512); - body = typed_response->protocol_ + "|" + std::string(typed_response->status_.message()) + "|"; + body = typed_response->protocol_ + "|" + typed_response->message_ + "|"; for (const auto& pair : typed_response->data_) { body += pair.first + ":" + pair.second + ";"; } // Additional 4 bytes for status. encoding_buffer_.writeBEInt(body.size() + 4); - encoding_buffer_.writeBEInt( - static_cast(typed_response->status_.raw_code())); + encoding_buffer_.writeBEInt(static_cast(typed_response->status_.code())); encoding_buffer_.add(body); callback.onEncodingSuccess(encoding_buffer_, response.frameFlags().endStream()); @@ -160,7 +160,9 @@ class FakeStreamCodecFactory : public CodecFactory { ResponsePtr respond(Status status, absl::string_view, const Request&) override { auto response = std::make_unique(); - response->status_ = status; + response->status_ = {static_cast(status.code()), + status.code() == absl::StatusCode::kOk}; + response->message_ = status.message(); response->protocol_ = "fake_protocol_for_test"; return response; } @@ -190,7 +192,8 @@ class FakeStreamCodecFactory : public CodecFactory { } auto response = std::make_unique(); - response->status_ = Status(StatusCode(status_code), result[1]); + response->status_ = {static_cast(status_code), + static_cast(status_code) == absl::StatusCode::kOk}; response->protocol_ = std::string(result[0]); for (absl::string_view pair_str : absl::StrSplit(result[2], ';', absl::SkipEmpty())) { auto pair = absl::StrSplit(pair_str, absl::MaxSplits(':', 1)); diff --git a/contrib/generic_proxy/filters/network/test/integration_test.cc b/contrib/generic_proxy/filters/network/test/integration_test.cc index f006844a3fe9..65a15c246caf 100644 --- a/contrib/generic_proxy/filters/network/test/integration_test.cc +++ b/contrib/generic_proxy/filters/network/test/integration_test.cc @@ -332,8 +332,8 @@ TEST_P(IntegrationTest, RequestRouteNotFound) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[0].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[0].response_->status().message(), - "route_not_found"); + EXPECT_EQ(response_decoder_callback_->responses_[0].response_->status().code(), + static_cast(absl::StatusCode::kNotFound)); cleanup(); } @@ -362,7 +362,7 @@ TEST_P(IntegrationTest, RequestAndResponse) { FakeStreamCodecFactory::FakeResponse response; response.protocol_ = "fake_fake_fake"; - response.status_ = Status(); + response.status_ = StreamStatus(); response.data_["zzzz"] = "xxxx"; sendResponseForTest(response); @@ -371,7 +371,7 @@ TEST_P(IntegrationTest, RequestAndResponse) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[0].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[0].response_->status().code(), StatusCode::kOk); + EXPECT_EQ(response_decoder_callback_->responses_[0].response_->status().code(), 0); EXPECT_EQ(response_decoder_callback_->responses_[0].response_->get("zzzz"), "xxxx"); cleanup(); @@ -464,7 +464,7 @@ TEST_P(IntegrationTest, MultipleRequests) { FakeStreamCodecFactory::FakeResponse response_2; response_2.protocol_ = "fake_fake_fake"; - response_2.status_ = Status(); + response_2.status_ = StreamStatus(); response_2.data_["zzzz"] = "xxxx"; response_2.data_["stream_id"] = "2"; @@ -474,13 +474,13 @@ TEST_P(IntegrationTest, MultipleRequests) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[2].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[2].response_->status().code(), StatusCode::kOk); + EXPECT_EQ(response_decoder_callback_->responses_[2].response_->status().code(), 0); EXPECT_EQ(response_decoder_callback_->responses_[2].response_->get("zzzz"), "xxxx"); EXPECT_EQ(response_decoder_callback_->responses_[2].response_->get("stream_id"), "2"); FakeStreamCodecFactory::FakeResponse response_1; response_1.protocol_ = "fake_fake_fake"; - response_1.status_ = Status(); + response_1.status_ = StreamStatus(); response_1.data_["zzzz"] = "yyyy"; response_1.data_["stream_id"] = "1"; @@ -490,7 +490,7 @@ TEST_P(IntegrationTest, MultipleRequests) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[1].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[1].response_->status().code(), StatusCode::kOk); + EXPECT_EQ(response_decoder_callback_->responses_[1].response_->status().code(), 0); EXPECT_EQ(response_decoder_callback_->responses_[1].response_->get("zzzz"), "yyyy"); EXPECT_EQ(response_decoder_callback_->responses_[1].response_->get("stream_id"), "1"); @@ -589,7 +589,7 @@ TEST_P(IntegrationTest, MultipleRequestsWithMultipleFrames) { FakeStreamCodecFactory::FakeResponse response_2; response_2.protocol_ = "fake_fake_fake"; - response_2.status_ = Status(); + response_2.status_ = StreamStatus(); response_2.data_["zzzz"] = "xxxx"; response_2.data_["stream_id"] = "2"; response_2.data_["end_stream"] = "false"; @@ -605,13 +605,13 @@ TEST_P(IntegrationTest, MultipleRequestsWithMultipleFrames) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[2].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[2].response_->status().code(), StatusCode::kOk); + EXPECT_EQ(response_decoder_callback_->responses_[2].response_->status().code(), 0); EXPECT_EQ(response_decoder_callback_->responses_[2].response_->get("zzzz"), "xxxx"); EXPECT_EQ(response_decoder_callback_->responses_[2].response_->get("stream_id"), "2"); FakeStreamCodecFactory::FakeResponse response_1; response_1.protocol_ = "fake_fake_fake"; - response_1.status_ = Status(); + response_1.status_ = StreamStatus(); response_1.data_["zzzz"] = "yyyy"; response_1.data_["stream_id"] = "1"; response_1.data_["end_stream"] = "false"; @@ -627,7 +627,7 @@ TEST_P(IntegrationTest, MultipleRequestsWithMultipleFrames) { "unexpected timeout"); EXPECT_NE(response_decoder_callback_->responses_[1].response_, nullptr); - EXPECT_EQ(response_decoder_callback_->responses_[1].response_->status().code(), StatusCode::kOk); + EXPECT_EQ(response_decoder_callback_->responses_[1].response_->status().code(), 0); EXPECT_EQ(response_decoder_callback_->responses_[1].response_->get("zzzz"), "yyyy"); EXPECT_EQ(response_decoder_callback_->responses_[1].response_->get("stream_id"), "1"); diff --git a/contrib/generic_proxy/filters/network/test/proxy_test.cc b/contrib/generic_proxy/filters/network/test/proxy_test.cc index 1fdeddb4bc6f..ecd06a1b344d 100644 --- a/contrib/generic_proxy/filters/network/test/proxy_test.cc +++ b/contrib/generic_proxy/filters/network/test/proxy_test.cc @@ -631,7 +631,9 @@ TEST_F(FilterTest, ActiveStreamSendLocalReply) { EXPECT_CALL(*server_codec_, respond(_, _, _)) .WillOnce(Invoke([&](Status status, absl::string_view, const Request&) -> ResponsePtr { auto response = std::make_unique(); - response->status_ = std::move(status); + response->status_ = {static_cast(status.code()), + status.code() == StatusCode::kOk}; + response->message_ = status.message(); return response; })); @@ -640,7 +642,8 @@ TEST_F(FilterTest, ActiveStreamSendLocalReply) { EXPECT_CALL(*server_codec_, encode(_, _)) .WillOnce(Invoke([&](const StreamFrame& response, EncodingCallbacks& callback) { Buffer::OwnedImpl buffer; - EXPECT_EQ(dynamic_cast(&response)->status().message(), "test_detail"); + EXPECT_EQ(dynamic_cast(&response)->status().code(), + static_cast(StatusCode::kUnknown)); buffer.add("test"); callback.onEncodingSuccess(buffer, true); })); From b1d18159184b5feff32fdbcbb16d5fa71cd07e36 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 2 Jan 2024 08:45:14 -0500 Subject: [PATCH 061/126] mobile: more lifetime tests (#31381) Signed-off-by: Alyssa Wilk --- .../integration/client_integration_test.cc | 54 ++++++++++++++++++- test/integration/autonomous_upstream.cc | 13 +++++ test/integration/autonomous_upstream.h | 5 ++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 98429dbd3147..5b29a57ec944 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -547,7 +547,7 @@ TEST_P(ClientIntegrationTest, InvalidDomain) { ASSERT_EQ(cc_.on_headers_calls, 0); } -TEST_P(ClientIntegrationTest, BasicReset) { +TEST_P(ClientIntegrationTest, BasicBeforeResponseHeaders) { initialize(); default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_REQUEST, "yes"); @@ -559,6 +559,58 @@ TEST_P(ClientIntegrationTest, BasicReset) { ASSERT_EQ(cc_.on_headers_calls, 0); } +TEST_P(ClientIntegrationTest, ResetAfterResponseHeaders) { + autonomous_allow_incomplete_streams_ = true; + initialize(); + + default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); + default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_error_calls, 1); +} + +TEST_P(ClientIntegrationTest, ResetAfterHeaderOnlyResponse) { + autonomous_allow_incomplete_streams_ = true; + initialize(); + + default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_HEADERS, "yes"); + default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "0"); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), false); + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_error_calls, 1); +} + +TEST_P(ClientIntegrationTest, ResetBetweenDataChunks) { + autonomous_allow_incomplete_streams_ = true; + initialize(); + + default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); + default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "2"); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_error_calls, 1); +} + +TEST_P(ClientIntegrationTest, ResetAfterData) { + autonomous_allow_incomplete_streams_ = true; + initialize(); + + default_request_headers_.addCopy(AutonomousStream::RESET_AFTER_RESPONSE_DATA, "yes"); + default_request_headers_.addCopy(AutonomousStream::RESPONSE_DATA_BLOCKS, "1"); + + stream_->sendHeaders(envoyToMobileHeaders(default_request_headers_), true); + terminal_callback_.waitReady(); + + ASSERT_EQ(cc_.on_error_calls, 1); +} + TEST_P(ClientIntegrationTest, CancelBeforeRequestHeadersSent) { autonomous_upstream_ = false; initialize(); diff --git a/test/integration/autonomous_upstream.cc b/test/integration/autonomous_upstream.cc index 94ae18094589..8b05a02b5cb7 100644 --- a/test/integration/autonomous_upstream.cc +++ b/test/integration/autonomous_upstream.cc @@ -21,6 +21,8 @@ const char AutonomousStream::RESPONSE_SIZE_BYTES[] = "response_size_bytes"; const char AutonomousStream::RESPONSE_DATA_BLOCKS[] = "response_data_blocks"; const char AutonomousStream::EXPECT_REQUEST_SIZE_BYTES[] = "expect_request_size_bytes"; const char AutonomousStream::RESET_AFTER_REQUEST[] = "reset_after_request"; +const char AutonomousStream::RESET_AFTER_RESPONSE_HEADERS[] = "reset_after_response_headers"; +const char AutonomousStream::RESET_AFTER_RESPONSE_DATA[] = "reset_after_response_data"; const char AutonomousStream::CLOSE_AFTER_RESPONSE[] = "close_after_response"; const char AutonomousStream::NO_TRAILERS[] = "no_trailers"; const char AutonomousStream::NO_END_STREAM[] = "no_end_stream"; @@ -87,6 +89,12 @@ void AutonomousStream::sendResponse() { } encodeHeaders(upstream_.responseHeaders(), headers_only_response); + + if (!headers.get_(RESET_AFTER_RESPONSE_HEADERS).empty()) { + encodeResetStream(); + return; + } + if (!headers_only_response) { if (upstream_.responseBody().has_value()) { encodeData(*upstream_.responseBody(), !send_trailers); @@ -94,6 +102,11 @@ void AutonomousStream::sendResponse() { for (int32_t i = 0; i < response_data_blocks; ++i) { encodeData(response_body_length, i == (response_data_blocks - 1) && !send_trailers && end_stream); + + if (!headers.get_(RESET_AFTER_RESPONSE_DATA).empty()) { + encodeResetStream(); + return; + } } } if (send_trailers) { diff --git a/test/integration/autonomous_upstream.h b/test/integration/autonomous_upstream.h index 4d1dd9671bd7..9aeb88a90587 100644 --- a/test/integration/autonomous_upstream.h +++ b/test/integration/autonomous_upstream.h @@ -21,6 +21,11 @@ class AutonomousStream : public FakeStream { // If set, the stream will reset when the request is complete, rather than // sending a response. static const char RESET_AFTER_REQUEST[]; + // If set, the stream will reset when the response headers are sent. + static const char RESET_AFTER_RESPONSE_HEADERS[]; + // If set, the stream will reset after the first data chunk. Note by default + // there is only one data chunk. + static const char RESET_AFTER_RESPONSE_DATA[]; // Prevents upstream from sending trailers. static const char NO_TRAILERS[]; // Prevents upstream from finishing response. From e17f491376d75ab8dbef40279acf5550cde4ceca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E6=B3=BD=E8=BD=A9?= Date: Tue, 2 Jan 2024 21:47:45 +0800 Subject: [PATCH 062/126] docs(access_log): only one param is allowed in command operators (#31559) Signed-off-by: spacewander --- docs/root/configuration/observability/access_log/usage.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/root/configuration/observability/access_log/usage.rst b/docs/root/configuration/observability/access_log/usage.rst index 03483c0fd49f..eb9a1056c885 100644 --- a/docs/root/configuration/observability/access_log/usage.rst +++ b/docs/root/configuration/observability/access_log/usage.rst @@ -157,7 +157,9 @@ The following command operators are supported: .. code-block:: none - %START_TIME(%Y/%m/%dT%H:%M:%S%z %s)% + %START_TIME(%Y/%m/%dT%H:%M:%S%z)% + + %START_TIME(%s)% # To include millisecond fraction of the second (.000 ... .999). E.g. 1527590590.528. %START_TIME(%s.%3f)% From a2ffda214294fa36cd281a83783b50508e2c309f Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Tue, 2 Jan 2024 09:47:01 -0500 Subject: [PATCH 063/126] mobile: Remove unneeded lock scope in test (#31525) Signed-off-by: Ali Beyad --- mobile/test/common/integration/client_integration_test.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index 5b29a57ec944..de58db3390cb 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -402,11 +402,9 @@ void ClientIntegrationTest::explicitFlowControlWithCancels(const uint32_t body_s } if (terminate_engine && request_for_engine_termination == i) { - { - absl::MutexLock l(&engine_lock_); - ASSERT_EQ(engine_->terminate(), ENVOY_SUCCESS); - engine_.reset(); - } + absl::MutexLock l(&engine_lock_); + ASSERT_EQ(engine_->terminate(), ENVOY_SUCCESS); + engine_.reset(); break; } } From 4adc79bcfb7db39ce28f8688e245be7768d90b6a Mon Sep 17 00:00:00 2001 From: "Adi (Suissa) Peleg" Date: Tue, 2 Jan 2024 09:54:54 -0500 Subject: [PATCH 064/126] HttpUri: cap timeout (#31246) Signed-off-by: Adi Suissa-Peleg --- api/envoy/config/core/v3/http_uri.proto | 1 + .../jwt_authn/jwt_authn_corpus/large_timeout | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 test/extensions/filters/http/jwt_authn/jwt_authn_corpus/large_timeout diff --git a/api/envoy/config/core/v3/http_uri.proto b/api/envoy/config/core/v3/http_uri.proto index 93b63093e377..bac37c0d5839 100644 --- a/api/envoy/config/core/v3/http_uri.proto +++ b/api/envoy/config/core/v3/http_uri.proto @@ -52,6 +52,7 @@ message HttpUri { // Sets the maximum duration in milliseconds that a response can take to arrive upon request. google.protobuf.Duration timeout = 3 [(validate.rules).duration = { required: true + lt {seconds: 4294967296} gte {} }]; } diff --git a/test/extensions/filters/http/jwt_authn/jwt_authn_corpus/large_timeout b/test/extensions/filters/http/jwt_authn/jwt_authn_corpus/large_timeout new file mode 100644 index 000000000000..78a98a70280a --- /dev/null +++ b/test/extensions/filters/http/jwt_authn/jwt_authn_corpus/large_timeout @@ -0,0 +1,35 @@ +config { + providers { + key: "\005" + value { + remote_jwks { + http_uri { + uri: "https:/pubkey_server/pubkey_phttps:/pubkey_server/pubkey_pathath" + cluster: "2" + timeout { + seconds: 68719476736 + } + } + } + } + } + rules { + match { + prefix: "" + } + requires { + allow_missing { + } + } + } +} +request_data { + headers { + headers { + key: "authorization" + value: "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4cGxlLmNvbSIsImF1ZCI6ImV4YW1wbGVfc2VydmljZSIsImV4cCI6MjAwMTAwMTAwMX0.n45uWZfIBZwCIPiL0K8Ca3tmm-ZlsDrC79_vXCspPwk5oxdSn983tuC9GfVWKXWUMHe11DsB02b19Ow-fmoEzooTFn65Ml7G34nW07amyM6lETiMhNzyiunctplOr6xKKJHmzTUhfTirvDeG-q9n24-8lH7GP8GgHvDlgSM9OY7TGp81bRcnZBmxim_UzHoYO3_c8OP4ZX3xG5PfihVk5G0g6wcHrO70w0_64JgkKRCrLHMJSrhIgp9NHel_CNOnL0AjQKe9IGblJrMuouqYYS0zEWwmOVUWUSxQkoLpldQUVefcfjQeGjz8IlvktRa77FYexfP590ACPyXrivtsxg" + } + } +} +remote_jwks: "{\"keys\":[{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"62a93512c9ee4c7f8067b5a216dade2763d32a47\",\"n\":\"0YWnm_eplO9BFtUUUUUUU\0055H8mYDW11HolzZmTQpRoLV8ZoHbHEaTfqX_aYahIw\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"alg\":\"RS256\",\"use\":\"sig\",\"kid\":\"b3319a147514df7ee5e4bcdee51350cc890cc89e\",\"n\":\"qDi7Tx4DhNDDdk0iUtJSPZliUHJBI_pj8M-2Mn_oA8jBuI8YKwBqYkZCN2I95Q\",\"e\":\"AQAB\"}]}" +num_calls: 4 From 7f3da8ea87ff5a5f57e000ed0ea8a1810d086b03 Mon Sep 17 00:00:00 2001 From: phlax Date: Tue, 2 Jan 2024 15:12:42 +0000 Subject: [PATCH 065/126] dependabot: Group updates (#31550) Signed-off-by: Ryan Northey --- .github/dependabot.yml | 104 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c41a85fcaed4..03641ba10b21 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,24 +11,40 @@ updates: - package-ecosystem: "pip" directory: "/examples/grpc-bridge/client" + groups: + examples-grpc-bridge: + patterns: + - "*" schedule: interval: "daily" time: "06:00" - package-ecosystem: "pip" directory: "/examples/cache" + groups: + examples-cache: + patterns: + - "*" schedule: interval: "daily" time: "06:00" - package-ecosystem: "pip" directory: "/examples/shared/python/aiohttp" + groups: + examples-shared-python: + patterns: + - "*" schedule: interval: "daily" time: "06:00" - package-ecosystem: "pip" directory: "/examples/shared/python/postgres" + groups: + examples-postgres: + patterns: + - "*" schedule: interval: "daily" time: "06:00" @@ -54,6 +70,10 @@ updates: - package-ecosystem: "docker" directory: "/examples/ext_authz" + groups: + examples-ext-authz: + patterns: + - "*" schedule: interval: daily time: "06:00" @@ -66,24 +86,40 @@ updates: - package-ecosystem: "docker" directory: "/examples/golang-network" + groups: + examples-golang-network: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "docker" directory: "/examples/grpc-bridge" + groups: + examples-grpc-bridge: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "docker" directory: "/examples/kafka" + groups: + examples-kafka: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "docker" directory: "/examples/local_ratelimit" + groups: + examples-local-ratelimit: + patterns: + - "*" schedule: interval: daily time: "06:00" @@ -193,54 +229,90 @@ updates: - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/basic" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/dummy" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/echo" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/metric" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/passthrough" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/access_log" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/action" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/buffer" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/contrib/golang/filters/http/test/test_data/routeconfig" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" @@ -252,43 +324,71 @@ updates: time: "06:00" - package-ecosystem: "gomod" - directory: "/contrib/golang/router/cluster_specifier/test/test_data/simple" + directory: "/contrib/golang/filters/network/test/test_data" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" - directory: "/contrib/golang/filters/network/test/test_data" + directory: "/contrib/golang/router/cluster_specifier/test/test_data/simple" + groups: + contrib-golang: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/examples/ext_authz/auth/grpc-service" + groups: + examples-ext-authz: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/examples/load-reporting-service" + groups: + examples-load-reporting: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/examples/grpc-bridge/server" + groups: + examples-grpc-bridge: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/examples/golang-http/simple" + groups: + examples-golang-http: + patterns: + - "*" schedule: interval: daily time: "06:00" - package-ecosystem: "gomod" directory: "/examples/golang-network/simple" + groups: + examples-golang-network: + patterns: + - "*" schedule: interval: daily time: "06:00" From 09db63504527a8e291d1395abb49ee8ee288ad71 Mon Sep 17 00:00:00 2001 From: Raven Black Date: Tue, 2 Jan 2024 12:25:07 -0500 Subject: [PATCH 066/126] Make hotrestart_handoff test also test QUIC (#31225) * Make hotrestart_handoff test also test QUIC --------- Signed-off-by: Raven Black --- test/integration/BUILD | 14 +- test/integration/hotrestart_handoff_test.py | 303 ++++++++++++++++---- 2 files changed, 261 insertions(+), 56 deletions(-) diff --git a/test/integration/BUILD b/test/integration/BUILD index a662e62a6773..2cd45af6b497 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -366,7 +366,18 @@ envoy_py_test( "//bazel:disable_hot_restart_or_admin": ["null_test.py"], "//conditions:default": ["hotrestart_handoff_test.py"], }), - data = [":hotrestart_main"], + args = [ + "--envoy-binary=$(location :hotrestart_main)", + "--h3-request=$(location //tools/h3_request)", + "--ca-certs=$(location //test/config/integration/certs:cacert.pem)", + "--ca-key=$(location //test/config/integration/certs:cakey.pem)", + ], + data = [ + ":hotrestart_main", + "//test/config/integration/certs:cacert.pem", + "//test/config/integration/certs:cakey.pem", + "//tools/h3_request", + ], main = select({ "//bazel:disable_hot_restart_or_admin": "null_test.py", "//conditions:default": "hotrestart_handoff_test.py", @@ -379,6 +390,7 @@ envoy_py_test( ], deps = [ requirement("aiohttp"), + requirement("cryptography"), ], ) diff --git a/test/integration/hotrestart_handoff_test.py b/test/integration/hotrestart_handoff_test.py index ab88bb7dd73c..7d975bd7dda7 100644 --- a/test/integration/hotrestart_handoff_test.py +++ b/test/integration/hotrestart_handoff_test.py @@ -7,13 +7,17 @@ TODO(ravenblack): perform the same tests for QUIC connections once they will work as expected. """ +import abc +import argparse import asyncio +from functools import cached_property import logging import os import pathlib import random import sys -from typing import AsyncIterator +import tempfile +from typing import Awaitable import unittest from datetime import datetime, timedelta from aiohttp import client_exceptions, web, ClientSession @@ -58,7 +62,6 @@ def random_loopback_host(): # the socket path too long. SOCKET_PATH = f"@envoy_domain_socket_{os.getpid()}" SOCKET_MODE = 0 -ENVOY_BINARY = "./test/integration/hotrestart_main" # This log config makes logs interleave with other test output, which # is useful since with all the async operations it can be hard to figure @@ -80,7 +83,7 @@ def __init__(self, fast_version=False): self.port = UPSTREAM_FAST_PORT if fast_version else UPSTREAM_SLOW_PORT self.app = web.Application() self.app.add_routes([ - web.get('/', self.fast_response) if fast_version else web.get('/', self.slow_response), + web.get("/", self.fast_response) if fast_version else web.get("/", self.slow_response), ]) async def start(self): @@ -96,12 +99,16 @@ async def stop(self): async def fast_response(self, request): return web.Response( - status=200, reason='OK', headers={'content-type': 'text/plain'}, body='fast instance') + status=200, + reason="OK", + headers={"content-type": "text/plain"}, + body="fast instance", + ) async def slow_response(self, request): log.debug("slow request received") response = web.StreamResponse( - status=200, reason='OK', headers={'content-type': 'text/plain'}) + status=200, reason="OK", headers={"content-type": "text/plain"}) await response.prepare(request) await response.write(b"start\n") await asyncio.sleep(STARTUP_TOLERANCE_SECONDS + 0.5) @@ -110,17 +117,84 @@ async def slow_response(self, request): return response -async def _http_request(url) -> AsyncIterator[str]: - # Separate session per request is against aiohttp idioms, but is - # intentional here because the point of the test is verifying - # where connections go - reusing a connection would do the wrong thing. - async with ClientSession() as session: - async with session.get(url) as response: - async for line in response.content: - yield line +class LineGenerator: + + @cached_property + def _queue(self) -> asyncio.Queue[str]: + return asyncio.Queue() + + @cached_property + def _task(self): + return asyncio.create_task(self.generator()) + + @abc.abstractmethod + async def generator(self) -> None: + raise NotImplementedError + + def __init__(self): + self._task + + async def join(self) -> int: + await self._task + return self._queue.qsize() + + async def line(self) -> str: + line = await self._queue.get() + self._queue.task_done() + return line + + +class Http3RequestLineGenerator(LineGenerator): + + def __init__(self, url): + self._url = url + super().__init__() + + async def generator(self) -> None: + proc = await asyncio.create_subprocess_exec( + IntegrationTest.h3_request, + f"--ca-certs={IntegrationTest.ca_certs}", + self._url, + stdout=asyncio.subprocess.PIPE, + ) + async for line in proc.stdout: + await self._queue.put(line) + await proc.wait() -async def _full_http_request(url: str) -> str: +class HttpRequestLineGenerator(LineGenerator): + + def __init__(self, url): + self._url = url + super().__init__() + + async def generator(self) -> None: + # Separate session per request is against aiohttp idioms, but is + # intentional here because the point of the test is verifying + # where connections go - reusing a connection would do the wrong thing. + async with ClientSession() as session: + async with session.get(self._url) as response: + async for line in response.content: + await self._queue.put(line) + + +async def _full_http3_request_task(url: str) -> str: + proc = await asyncio.create_subprocess_exec( + IntegrationTest.h3_request, + f"--ca-certs={IntegrationTest.ca_certs}", + url, + stdout=asyncio.subprocess.PIPE, + ) + (stdout, _) = await proc.communicate() + await proc.wait() + return stdout.decode("utf-8") + + +def _full_http3_request(url: str) -> Awaitable[str]: + return asyncio.create_task(_full_http3_request_task(url)) + + +async def _full_http_request_task(url: str) -> str: # Separate session per request is against aiohttp idioms, but is # intentional here because the point of the test is verifying # where connections go - reusing a connection would do the wrong thing. @@ -129,29 +203,19 @@ async def _full_http_request(url: str) -> str: return await response.text() -def _make_envoy_config_yaml(upstream_port, file_path): - file_path.write_text( - f""" -admin: - address: - socket_address: - address: {ENVOY_HOST} - port_value: {ENVOY_ADMIN_PORT} +def _full_http_request(url: str) -> Awaitable[str]: + return asyncio.create_task(_full_http_request_task(url)) -static_resources: - listeners: - - name: listener_0 - address: - socket_address: - address: {ENVOY_HOST} - port_value: {ENVOY_PORT} + +def filter_chains(codec_type: str = "AUTO") -> str: + return f""" filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http - codec_type: AUTO + codec_type: {codec_type} route_config: name: local_route virtual_hosts: @@ -166,6 +230,48 @@ def _make_envoy_config_yaml(upstream_port, file_path): - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router +""" + + +def _make_envoy_config_yaml(upstream_port: int, file_path: pathlib.Path): + file_path.write_text( + f""" +admin: + address: + socket_address: + address: {ENVOY_HOST} + port_value: {ENVOY_ADMIN_PORT} + +static_resources: + listeners: + - name: listener_quic + address: + socket_address: + protocol: UDP + address: {ENVOY_HOST} + port_value: {ENVOY_PORT} +{filter_chains("HTTP3")} + transport_socket: + name: "envoy.transport_sockets.quic" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.quic.v3.QuicDownstreamTransport" + downstream_tls_context: + common_tls_context: + tls_certificates: + - certificate_chain: + filename: "{IntegrationTest.server_cert}" + private_key: + filename: "{IntegrationTest.server_key}" + udp_listener_config: + quic_options: {"{}"} + downstream_socket_config: + prefer_gro: true + - name: listener_http + address: + socket_address: + address: {ENVOY_HOST} + port_value: {ENVOY_PORT} +{filter_chains()} clusters: - name: some_service connect_timeout: 0.25s @@ -202,6 +308,11 @@ async def _wait_for_envoy_epoch(i: int): class IntegrationTest(unittest.IsolatedAsyncioTestCase): + server_cert: pathlib.Path + server_key: pathlib.Path + ca_certs: pathlib.Path + h3_request: pathlib.Path + envoy_binary: pathlib.Path async def asyncSetUp(self) -> None: print(os.environ) @@ -212,13 +323,13 @@ async def asyncSetUp(self) -> None: _make_envoy_config_yaml(upstream_port=UPSTREAM_SLOW_PORT, file_path=self.slow_config_path) _make_envoy_config_yaml(upstream_port=UPSTREAM_FAST_PORT, file_path=self.fast_config_path) self.base_envoy_args = [ - ENVOY_BINARY, + IntegrationTest.envoy_binary, "--socket-path", SOCKET_PATH, "--socket-mode", str(SOCKET_MODE), ] - log.info("starting upstreams") + log.info(f"starting upstreams on https://{ENVOY_HOST}:{ENVOY_PORT}/") await super().asyncSetUp() self.slow_upstream = Upstream() await self.slow_upstream.start() @@ -242,16 +353,18 @@ async def test_connection_handoffs(self) -> None: "-c", self.slow_config_path, ) + log.info(f"cert path = {IntegrationTest.server_cert}") log.info("waiting for envoy ready") await _wait_for_envoy_epoch(0) log.info("making requests") + request_url = f"http://{ENVOY_HOST}:{ENVOY_PORT}/" + srequest_url = f"https://{ENVOY_HOST}:{ENVOY_PORT}/" slow_responses = [ - _http_request(f"http://{ENVOY_HOST}:{ENVOY_PORT}/") for i in range(PARALLEL_REQUESTS) - # TODO(ravenblack): add http3 slow requests - ] + HttpRequestLineGenerator(request_url) for i in range(PARALLEL_REQUESTS) + ] + [Http3RequestLineGenerator(srequest_url) for i in range(PARALLEL_REQUESTS)] log.info("waiting for responses to begin") for response in slow_responses: - self.assertEqual(await anext(response, None), b"start\n") + self.assertEqual(await response.line(), b"start\n") base_id = int(self.base_id_path.read_text()) log.info(f"starting envoy hot restart for base id {base_id}") envoy_process_2 = await asyncio.create_subprocess_exec( @@ -268,45 +381,125 @@ async def test_connection_handoffs(self) -> None: log.info("waiting for new envoy instance to begin") await _wait_for_envoy_epoch(1) log.info("sending request to fast upstream") - fast_responses = [ - _full_http_request(f"http://{ENVOY_HOST}:{ENVOY_PORT}/") - for i in range(PARALLEL_REQUESTS) - # TODO(ravenblack): add http3 requests - ] + fast_responses = [_full_http_request(request_url) for i in range(PARALLEL_REQUESTS) + ] + [_full_http3_request(srequest_url) for i in range(PARALLEL_REQUESTS)] for response in fast_responses: self.assertEqual( - await response, "fast instance", - "new requests after hot restart begins should go to new cluster") + await response, + "fast instance", + "new requests after hot restart begins should go to new cluster", + ) # Now wait for the slow request to complete, and make sure it still gets the # response from the old instance. log.info("waiting for completion of original slow request") t1 = datetime.now() for response in slow_responses: - self.assertEqual(await anext(response, None), b"end\n") + self.assertEqual(await response.line(), b"end\n") t2 = datetime.now() self.assertGreater( - (t2 - t1).total_seconds(), 0.5, - "slow request should be incomplete when the test waits for it, otherwise the test is not necessarily validating during-drain behavior" + (t2 - t1).total_seconds(), + 0.5, + "slow request should be incomplete when the test waits for it, otherwise the test is not necessarily validating during-drain behavior", ) for response in slow_responses: - self.assertIsNone(await anext(response, None)) + self.assertEquals(await response.join(), 0) log.info("waiting for parent instance to terminate") await envoy_process_1.wait() log.info("sending second request to fast upstream") - fast_responses = [ - _full_http_request(f"http://{ENVOY_HOST}:{ENVOY_PORT}/") - for i in range(PARALLEL_REQUESTS) - # TODO(ravenblack): add http3 requests - ] + fast_responses = [_full_http_request(request_url) for i in range(PARALLEL_REQUESTS) + ] + [_full_http3_request(srequest_url) for i in range(PARALLEL_REQUESTS)] for response in fast_responses: self.assertEqual( - await response, "fast instance", - "new requests after old instance terminates should go to new cluster") + await response, + "fast instance", + "new requests after old instance terminates should go to new cluster", + ) log.info("shutting child instance down") envoy_process_2.terminate() await envoy_process_2.wait() -if __name__ == '__main__': +def generate_server_cert( + ca_key_path: pathlib.Path, + ca_cert_path: pathlib.Path) -> "tuple[pathlib.Path, pathlib.Path]": + """Generates a temporary key and cert pem file and returns the paths. + + This is necessary because the http3 client validates that the server + certificate matches the host of the request, and our host is an + arbitrary randomized 127.x.y.z IP address to reduce the likelihood + of port collisions during testing. We therefore must use a generated + certificate that really matches the host IP. + """ + + from cryptography import x509 + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import rsa + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import serialization + from ipaddress import ip_address + + with open(ca_key_path, "rb") as ca_key_file: + ca_key = serialization.load_pem_private_key( + ca_key_file.read(), + password=None, + ) + with open(ca_cert_path, "rb") as ca_cert_file: + ca_cert = x509.load_pem_x509_certificate(ca_cert_file.read()) + + key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend(), + ) + + hostname = "testhost" + name = x509.Name([x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, hostname)]) + alt_names = [x509.DNSName(hostname)] + alt_names.append(x509.IPAddress(ip_address(ENVOY_HOST))) + san = x509.SubjectAlternativeName(alt_names) + basic_constraints = x509.BasicConstraints(ca=True, path_length=0) + now = datetime.utcnow() + cert = ( + x509.CertificateBuilder() # Comment to keep linter from uglifying! + .subject_name(name).issuer_name(ca_cert.subject).public_key(key.public_key()).serial_number( + 1).not_valid_before(now).not_valid_after(now + timedelta(days=30)).add_extension( + basic_constraints, + False).add_extension(san, False).sign(ca_key, hashes.SHA256(), default_backend())) + cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM) + key_pem = key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + cert_file = tempfile.NamedTemporaryFile( + suffix="_key.pem", delete=False, dir=os.environ["TEST_TMPDIR"]) + cert_file.write(cert_pem) + cert_file.close() + key_file = tempfile.NamedTemporaryFile( + suffix="_cert.pem", delete=False, dir=os.environ["TEST_TMPDIR"]) + key_file.write(key_pem) + key_file.close() + return key_file.name, cert_file.name + + +def main(): + parser = argparse.ArgumentParser(description="Hot restart handoff test") + parser.add_argument("--envoy-binary", type=str, required=True) + parser.add_argument("--h3-request", type=str, required=True) + parser.add_argument("--ca-certs", type=str, required=True) + parser.add_argument("--ca-key", type=str, required=True) + # unittest also parses some args, so we strip out the ones we're using + # and leave the rest for unittest to consume. + (args, sys.argv[1:]) = parser.parse_known_args() + (IntegrationTest.server_key, + IntegrationTest.server_cert) = generate_server_cert(args.ca_key, args.ca_certs) + IntegrationTest.ca_certs = args.ca_certs + IntegrationTest.h3_request = args.h3_request + IntegrationTest.envoy_binary = args.envoy_binary + unittest.main() + + +if __name__ == "__main__": + main() From 917d6c9266f93b870c12d3eef94f03f39d6a7938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20R=2E=20Sede=C3=B1o?= Date: Tue, 2 Jan 2024 13:01:26 -0500 Subject: [PATCH 067/126] Update QUICHE from 28317b632 to 0860476f3 (#31571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/google/quiche/compare/28317b632..0860476f3 ``` $ git log 28317b632..0860476f3 --date=short --no-merges --format="%ad %al %s" 2023-12-28 martinduke Added logging and code counts for Connection ID collisions. 2023-12-27 vasilvv Fix QUICHE CI build. 2023-12-27 martinduke Add basic MoQT OBJECT sending capability. This is the result of a little bit of interop with Alan's chat client. 2023-12-26 dschinazi Allow sending additional headers with masque_client ``` Signed-off-by: Alejandro R Sedeño --- bazel/repository_locations.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index b2317039cee5..1a49998ab707 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1175,12 +1175,12 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "QUICHE", project_desc = "QUICHE (QUIC, HTTP/2, Etc) is Google‘s implementation of QUIC and related protocols", project_url = "https://github.com/google/quiche", - version = "28317b63250a6d8e0fa5a621fd6898479692dd2b", - sha256 = "4e64ed3b61353912923cc2389adc63bc0977e29418c0ef88dd9c394be33f01dd", + version = "0860476f3e59c023bc96e8cea1f18b11e241fda7", + sha256 = "05d1210e4a3e381cf682564a3d350adb702aacc60c098434b6470301df2613f0", urls = ["https://github.com/google/quiche/archive/{version}.tar.gz"], strip_prefix = "quiche-{version}", use_category = ["controlplane", "dataplane_core"], - release_date = "2023-12-21", + release_date = "2023-12-28", cpe = "N/A", license = "BSD-3-Clause", license_url = "https://github.com/google/quiche/blob/{version}/LICENSE", From a585f2d1b4a8da21272e613c5df06c49e6e87721 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Tue, 2 Jan 2024 13:38:26 -0500 Subject: [PATCH 068/126] mobile: Force the dfp_mixed_scheme flag to true in Envoy Mobile (#31586) Envoy Mobile always requires dfp_mixed_scheme for the TLS and cleartext DFP clusters. While dfp_mixed_scheme defaults to true, some environments (like within Google), force it to false for the Envoy use case, so we force it back to true here in Envoy Mobile, so we don't break the mobile integration tests. Once general use of dfp_mixed_scheme is fixed everywhere, we can revert this commit. Tested by changing dfp_mixed_scheme to FALSE_RUNTIME_GUARD and running the mobile xDS integration tests: cd mobile bazelisk test --test_output=streamed --cache_test_results=no //test/common/integration:rtds_integration_test Signed-off-by: Ali Beyad --- mobile/library/common/BUILD | 1 + mobile/library/common/engine.cc | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/mobile/library/common/BUILD b/mobile/library/common/BUILD index 0d449478c095..9969ada7b673 100644 --- a/mobile/library/common/BUILD +++ b/mobile/library/common/BUILD @@ -37,6 +37,7 @@ envoy_cc_library( "//library/common/types:c_types_lib", "@envoy//envoy/server:lifecycle_notifier_interface", "@envoy//envoy/stats:stats_interface", + "@envoy//source/common/runtime:runtime_lib", "@envoy_build_config//:extension_registry", ], ) diff --git a/mobile/library/common/engine.cc b/mobile/library/common/engine.cc index bdb9b40055bf..b7e6e2e4a423 100644 --- a/mobile/library/common/engine.cc +++ b/mobile/library/common/engine.cc @@ -2,6 +2,7 @@ #include "source/common/api/os_sys_calls_impl.h" #include "source/common/common/lock_guard.h" +#include "source/common/runtime/runtime_features.h" #include "library/common/bridge/utility.h" #include "library/common/data/utility.h" @@ -19,6 +20,11 @@ Engine::Engine(envoy_engine_callbacks callbacks, envoy_logger logger, // registry may lead to crashes at Engine shutdown. To be figured out as part of // https://github.com/envoyproxy/envoy-mobile/issues/332 Envoy::Api::External::registerApi(std::string(envoy_event_tracker_api_name), &event_tracker_); + // Envoy Mobile always requires dfp_mixed_scheme for the TLS and cleartext DFP clusters. + // While dfp_mixed_scheme defaults to true, some environments force it to false (e.g. within + // Google), so we force it back to true in Envoy Mobile. + // TODO(abeyad): Remove once this is no longer needed. + Runtime::maybeSetRuntimeGuard("envoy.reloadable_features.dfp_mixed_scheme", true); } envoy_status_t Engine::run(const std::string config, const std::string log_level) { From ea71e737298a03298f478489c181395629a21ce3 Mon Sep 17 00:00:00 2001 From: Youngchul Bang Date: Wed, 3 Jan 2024 04:49:03 +0900 Subject: [PATCH 069/126] stats: properly extract tag for connection limit filter (#31530) Signed-off-by: Youngchul Bang --- changelogs/current.yaml | 5 +++++ source/common/config/well_known_names.cc | 3 +++ source/common/config/well_known_names.h | 2 ++ test/common/stats/tag_extractor_impl_test.cc | 7 +++++++ .../connection_limit/connection_limit_integration_test.cc | 8 +------- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 2579e7acee36..04f7339493fc 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -22,6 +22,11 @@ behavior_changes: Fixed tag extraction so that :ref:`stat_prefix ` is properly extracted. This changes the Prometheus name from dns_filter_myprefix_local_a_record_answers{} to dns_filter_local_a_record_answers{envoy.dns_filter_prefix="myprefix"}. +- area: stats connection_limit + change: | + Fixed tag extraction so that :ref:`stat_prefix ` + is properly extracted. This changes the Prometheus name from ``envoy_connection_limit_myprefix_limited_connections{}`` to + ``envoy_connection_limit_limited_connections{envoy_connection_limit_prefix="myprefix"}``. - area: http2 change: | Changes the default value of ``envoy.reloadable_features.http2_use_oghttp2`` to true. This changes the codec used for HTTP/2 diff --git a/source/common/config/well_known_names.cc b/source/common/config/well_known_names.cc index 4221bf884d8a..7fa39a3f4358 100644 --- a/source/common/config/well_known_names.cc +++ b/source/common/config/well_known_names.cc @@ -201,6 +201,9 @@ TagNameValues::TagNameValues() { // dns_filter.(.).** addTokenized(DNS_FILTER_PREFIX, "dns_filter.$.**"); + + // connection_limit.(.)* + addTokenized(CONNECTION_LIMIT_PREFIX, "connection_limit.$.**"); } void TagNameValues::addRe2(const std::string& name, const std::string& regex, diff --git a/source/common/config/well_known_names.h b/source/common/config/well_known_names.h index e0e3549cda4e..1a9da7161f8f 100644 --- a/source/common/config/well_known_names.h +++ b/source/common/config/well_known_names.h @@ -119,6 +119,8 @@ class TagNameValues { const std::string LOCAL_LISTENER_RATELIMIT_PREFIX = "envoy.local_listener_ratelimit_prefix"; // Stats prefix for the dns filter const std::string DNS_FILTER_PREFIX = "envoy.dns_filter_prefix"; + // Stats prefix for the Connection limit filter + const std::string CONNECTION_LIMIT_PREFIX = "envoy.connection_limit_prefix"; // Stats prefix for the TCP Proxy network filter const std::string TCP_PREFIX = "envoy.tcp_prefix"; // Stats prefix for the UDP Proxy network filter diff --git a/test/common/stats/tag_extractor_impl_test.cc b/test/common/stats/tag_extractor_impl_test.cc index 902682752c11..f75f1ccfa0cb 100644 --- a/test/common/stats/tag_extractor_impl_test.cc +++ b/test/common/stats/tag_extractor_impl_test.cc @@ -437,6 +437,13 @@ TEST(TagExtractorTest, DefaultTagExtractors) { dns_filter_prefix.value_ = "my_dns_prefix"; regex_tester.testRegex("dns_filter.my_dns_prefix.local_a_record_answers", "dns_filter.local_a_record_answers", {dns_filter_prefix}); + + // Connection Limit Filter Prefix + Tag connection_limit_prefix; + connection_limit_prefix.name_ = tag_names.CONNECTION_LIMIT_PREFIX; + connection_limit_prefix.value_ = "my_connection_limit_prefix"; + regex_tester.testRegex("connection_limit.my_connection_limit_prefix.limited_connections", + "connection_limit.limited_connections", {connection_limit_prefix}); } TEST(TagExtractorTest, ExtAuthzTagExtractors) { diff --git a/test/extensions/filters/network/connection_limit/connection_limit_integration_test.cc b/test/extensions/filters/network/connection_limit/connection_limit_integration_test.cc index 23c55b125872..ea589aa50fb9 100644 --- a/test/extensions/filters/network/connection_limit/connection_limit_integration_test.cc +++ b/test/extensions/filters/network/connection_limit/connection_limit_integration_test.cc @@ -8,13 +8,7 @@ class ConnectionLimitIntegrationTest : public Event::TestUsingSimulatedTime, public BaseIntegrationTest { public: ConnectionLimitIntegrationTest() - : BaseIntegrationTest(GetParam(), ConfigHelper::tcpProxyConfig()) { - // TODO(ggreenway): add tag extraction rules. - // Missing stat tag-extraction rule for stat - // 'connection_limit.connection_limit_stats.limited_connections' and stat_prefix - // 'connection_limit_stats'. - skip_tag_extraction_rule_check_ = true; - } + : BaseIntegrationTest(GetParam(), ConfigHelper::tcpProxyConfig()) {} void setup(const std::string& filter_yaml) { config_helper_.addNetworkFilter(filter_yaml); From a03fa3432f2a5000b89f295b01be2433e8fa2a27 Mon Sep 17 00:00:00 2001 From: David Goffredo Date: Tue, 2 Jan 2024 14:54:01 -0500 Subject: [PATCH 070/126] Datadog: fix names in Span::spawnChild (#31366) Signed-off-by: David Goffredo --- changelogs/current.yaml | 3 + source/extensions/tracers/datadog/span.cc | 7 +- test/extensions/tracers/datadog/BUILD | 1 + .../extensions/tracers/datadog/naming_test.cc | 223 ++++++++++++++++++ test/extensions/tracers/datadog/span_test.cc | 6 +- 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 test/extensions/tracers/datadog/naming_test.cc diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 04f7339493fc..6d0703199d48 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -131,6 +131,9 @@ bug_fixes: change: | Fixed a bug where a histogram bucket counts were wrong. Additionally, the number of buckets is fixed and is now one element larger than the explicit bounds elements, as required by the specification. +- area: tracing + change: | + Fixed a bug where child spans produced by the Datadog tracer would have an incorrect operation name. - area: DNS change: | Fixed a race condition that when multiple requests with the same authority header are sent to Envoy, sometimes some requests diff --git a/source/extensions/tracers/datadog/span.cc b/source/extensions/tracers/datadog/span.cc index 4e9bcc77c895..38646f5cf844 100644 --- a/source/extensions/tracers/datadog/span.cc +++ b/source/extensions/tracers/datadog/span.cc @@ -90,8 +90,13 @@ Tracing::SpanPtr Span::spawnChild(const Tracing::Config&, const std::string& nam // The OpenTracing implementation ignored the `Tracing::Config` argument, // so we will as well. + // The `name` parameter to this function more closely matches Datadog's + // concept of "resource name." Datadog's "span name," or "operation name," + // instead describes the category of operation being performed, which here + // we hard-code. datadog::tracing::SpanConfig config; - config.name = name; + config.name = "envoy.proxy"; + config.resource = name; config.start = estimateTime(start_time); return std::make_unique(span_->create_child(config)); diff --git a/test/extensions/tracers/datadog/BUILD b/test/extensions/tracers/datadog/BUILD index d292aa9c0f39..4eba5b353436 100644 --- a/test/extensions/tracers/datadog/BUILD +++ b/test/extensions/tracers/datadog/BUILD @@ -19,6 +19,7 @@ envoy_extension_cc_test( "dict_util_test.cc", "event_scheduler_test.cc", "logger_test.cc", + "naming_test.cc", "span_test.cc", "time_util_test.cc", "tracer_stats_test.cc", diff --git a/test/extensions/tracers/datadog/naming_test.cc b/test/extensions/tracers/datadog/naming_test.cc new file mode 100644 index 000000000000..0d45cde32b1a --- /dev/null +++ b/test/extensions/tracers/datadog/naming_test.cc @@ -0,0 +1,223 @@ +/** + * The tests in this file aren't specific to a class, but instead test all + * behavior related to spans' "operation name" (a.k.a. "span name"), + * "resource name," and "service name." + * + * Datadog's model of a span is different from Envoy's. Each Datadog span, + * in addition to having a "service name" and an "operation name," also has a + * "resource name." The operation name indicates the _kind_ of operation + * that is being performed by the service, whereas the resource name contains + * more specifics about what is being operated upon, or about what is doing the + * operating. Envoy has no notion of "resource name," and instead uses + * operation name and tags for this purpose. + * + * When Envoy's tracing interface indicates an operation name, the Datadog + * tracer translates it into a resource name instead. The actual Datadog + * operation name is always hard-coded to the value "envoy.proxy". + * + * Finally, each span's "service name" is derived either from the tracer's + * configuration or a hard-coded default, which is "envoy". + * + * The tests in this file verify all of this behavior for a variety of + * scenarios where spans are created or modified. + */ + +#include "source/extensions/tracers/datadog/config.h" +#include "source/extensions/tracers/datadog/span.h" +#include "source/extensions/tracers/datadog/tracer.h" + +#include "test/mocks/stream_info/mocks.h" +#include "test/mocks/thread_local/mocks.h" +#include "test/mocks/tracing/mocks.h" +#include "test/mocks/upstream/cluster_manager.h" +#include "test/test_common/simulated_time_system.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Tracers { +namespace Datadog { +namespace { + +template Config makeConfig(const std::string& yaml) { + Config result; + TestUtility::loadFromYaml(yaml, result); + return result; +} + +class DatadogTracerNamingTest : public testing::Test { +public: + DatadogTracerNamingTest(); + +protected: + /** + * Verify that a tracer configured using the specified \p config_yaml + * produces spans and child spans having the specified + * \p expected_service_name. + * @param config_yaml YAML representation of a + * \c type.googleapis.com/envoy.config.trace.v3.DatadogConfig + * @param expected_service_name service name to expect each span to have + */ + void serviceNameTest(const std::string& config_yaml, const std::string& expected_service_name); + + /** + * Assign through the specified \p result a pointer to the underlying + * \c datadog::tracing::Span to which the specified \p span refers. + * If \p span does not refer to a Datadog span, then this function triggers a + * fatal test assertion. + * An output parameter is used because the \c ASSERT_* macros require that + * the enclosing function have \c void return type. + * @param result pointer to the output value to overwrite + * @param span pointer to an Envoy span that refers to a Datadog span + */ + static void asDatadogSpan(const datadog::tracing::Span** result, const Tracing::SpanPtr& span); + + NiceMock cluster_manager_; + Stats::TestUtil::TestStore store_; + NiceMock thread_local_slot_allocator_; + Event::SimulatedTimeSystem time_; + NiceMock stream_info_; +}; + +DatadogTracerNamingTest::DatadogTracerNamingTest() { + cluster_manager_.initializeClusters({"fake_cluster"}, {}); + cluster_manager_.thread_local_cluster_.cluster_.info_->name_ = "fake_cluster"; + cluster_manager_.initializeThreadLocalClusters({"fake_cluster"}); +} + +void DatadogTracerNamingTest::asDatadogSpan(const datadog::tracing::Span** result, + const Tracing::SpanPtr& span) { + ASSERT_TRUE(span); + const auto as_dd_span_wrapper = dynamic_cast(span.get()); + ASSERT_NE(nullptr, as_dd_span_wrapper); + + const datadog::tracing::Optional& maybe_dd_span = + as_dd_span_wrapper->impl(); + ASSERT_TRUE(maybe_dd_span); + *result = &*maybe_dd_span; +} + +void DatadogTracerNamingTest::serviceNameTest(const std::string& config_yaml, + const std::string& expected_service_name) { + auto config_proto = makeConfig(config_yaml); + + Tracer tracer{config_proto.collector_cluster(), + config_proto.collector_hostname(), + DatadogTracerFactory::makeConfig(config_proto), + cluster_manager_, + *store_.rootScope(), + thread_local_slot_allocator_}; + + // Any values will do for the sake of this test. What we care about is the + // `expected_service_name`. + Tracing::Decision decision; + decision.reason = Tracing::Reason::Sampling; + decision.traced = true; + const std::string operation_name = "some.operation.name"; + Tracing::TestTraceContextImpl context{}; + + const Tracing::SpanPtr span = + tracer.startSpan(Tracing::MockConfig{}, context, stream_info_, operation_name, decision); + const datadog::tracing::Span* dd_span; + asDatadogSpan(&dd_span, span); + + EXPECT_EQ(expected_service_name, dd_span->service_name()); + + const auto child_start = time_.timeSystem().systemTime(); + const std::string child_operation_name = "some.other.operation.name"; + const Tracing::SpanPtr child = + span->spawnChild(Tracing::MockConfig{}, child_operation_name, child_start); + const datadog::tracing::Span* dd_child; + asDatadogSpan(&dd_child, child); + + EXPECT_EQ(expected_service_name, dd_child->service_name()); +} + +TEST_F(DatadogTracerNamingTest, ServiceNameConfigured) { + // If you specify a `service_name` in the tracer configuration, then spans + // created will have that service name. + serviceNameTest(R"EOF( + collector_cluster: fake_cluster + service_name: mr_bigglesworth + )EOF", + "mr_bigglesworth"); +} + +TEST_F(DatadogTracerNamingTest, ServiceNameDefault) { + // If you don't specify a `service_name` in the tracer configuration, then + // spans created will have the default service name, which is "envoy". + serviceNameTest(R"EOF( + collector_cluster: fake_cluster + )EOF", + "envoy"); +} + +TEST_F(DatadogTracerNamingTest, OperationNameAndResourceName) { + // Concerns: + // + // - The span returned by `Tracer::startSpan` has as its resource name the + // operation name passed to `Tracer::startSpan`, and has as its operation + // name "envoy.proxy". + // - The span returned by `Span::spawnChild` has as its resource name the + // operation name passed to `Tracer::spawnChild`, and has as its operation + // name "envoy.proxy". + // - `Span::setOperation` sets the resource name of the span, but does not + // change the operation name. + + auto config_proto = makeConfig(R"EOF( + collector_cluster: fake_cluster + )EOF"); + + Tracer tracer{config_proto.collector_cluster(), + config_proto.collector_hostname(), + DatadogTracerFactory::makeConfig(config_proto), + cluster_manager_, + *store_.rootScope(), + thread_local_slot_allocator_}; + + // Any values will do for the sake of this test. What we care about are the + // operation names and the resource names. + Tracing::Decision decision; + decision.reason = Tracing::Reason::Sampling; + decision.traced = true; + Tracing::TestTraceContextImpl context{}; + + const std::string operation_name = "some.operation.name"; + const Tracing::SpanPtr span = + tracer.startSpan(Tracing::MockConfig{}, context, stream_info_, operation_name, decision); + const datadog::tracing::Span* dd_span; + asDatadogSpan(&dd_span, span); + + EXPECT_EQ("envoy.proxy", dd_span->name()); + EXPECT_EQ(operation_name, dd_span->resource_name()); + + const std::string new_operation_name = "some.new.operation.name"; + span->setOperation(new_operation_name); + + EXPECT_EQ("envoy.proxy", dd_span->name()); + EXPECT_EQ(new_operation_name, dd_span->resource_name()); + + const auto child_start = time_.timeSystem().systemTime(); + const std::string child_operation_name = "some.child.operation.name"; + const Tracing::SpanPtr child = + span->spawnChild(Tracing::MockConfig{}, child_operation_name, child_start); + const datadog::tracing::Span* dd_child; + asDatadogSpan(&dd_child, child); + + EXPECT_EQ("envoy.proxy", dd_child->name()); + EXPECT_EQ(child_operation_name, dd_child->resource_name()); + + const std::string child_new_operation_name = "some.child.new.operation.name"; + child->setOperation(child_new_operation_name); + + EXPECT_EQ("envoy.proxy", dd_child->name()); + EXPECT_EQ(child_new_operation_name, dd_child->resource_name()); +} + +} // namespace +} // namespace Datadog +} // namespace Tracers +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/tracers/datadog/span_test.cc b/test/extensions/tracers/datadog/span_test.cc index 20ea40e4c26f..436685b36f3a 100644 --- a/test/extensions/tracers/datadog/span_test.cc +++ b/test/extensions/tracers/datadog/span_test.cc @@ -206,7 +206,11 @@ TEST_F(DatadogTracerSpanTest, SpawnChild) { EXPECT_NE(nullptr, child_ptr); const datadog::tracing::SpanData& child = *child_ptr; EXPECT_EQ(estimateTime(child_start).wall, child.start.wall); - EXPECT_EQ("child", child.name); + // Setting the operation name actually sets the resource name, because + // Envoy's notion of operation name more closely matches Datadog's notion of + // resource name. The actual operation name is hard-coded as "envoy.proxy". + EXPECT_EQ("child", child.resource); + EXPECT_EQ("envoy.proxy", child.name); EXPECT_EQ(id_, child.trace_id); EXPECT_EQ(id_, child.span_id); EXPECT_EQ(id_, child.parent_id); From b8d7aea7baf004d282cfc6d83a11e2137c19e316 Mon Sep 17 00:00:00 2001 From: Tianyu <72890320+tyxia@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:55:22 -0500 Subject: [PATCH 071/126] tests: Refactor the way tls custom_validator is configured (#31506) Signed-off-by: tyxia --- .../tls/integration/ssl_integration_test.cc | 24 +++++++++---------- .../integration/quic_http_integration_test.cc | 18 +++++++------- test/integration/ssl_utility.cc | 4 ++-- test/integration/ssl_utility.h | 1 + 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc index 69610c494e7b..b7548ba8ace7 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc @@ -464,8 +464,8 @@ TEST_P(SslIntegrationTest, RouterHeaderOnlyRequestAndResponseWithSni) { TEST_P(SslIntegrationTest, AsyncCertValidationSucceeds) { // Config client to use an async cert validator which defer the actual validation by 5ms. - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: @@ -475,7 +475,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" initialize(); Network::ClientConnectionPtr connection = makeSslClientConnection( - ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config)); + ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config.get())); ConnectionStatusCallbacks callbacks; connection->addConnectionCallbacks(callbacks); connection->connect(); @@ -493,8 +493,8 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(SslIntegrationTest, AsyncCertValidationSucceedsWithLocalAddress) { - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: @@ -509,7 +509,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" initialize(); Network::Address::InstanceConstSharedPtr address = getSslAddress(version_, lookupPort("http")); auto client_transport_socket_factory_ptr = createClientSslTransportSocketFactory( - ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config), + ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config.get()), *context_manager_, *api_); Network::ClientConnectionPtr connection = dispatcher_->createClientConnection( address, Network::Address::InstanceConstSharedPtr(), @@ -546,8 +546,8 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(SslIntegrationTest, AsyncCertValidationAfterTearDown) { - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: @@ -564,7 +564,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" initialize(); Network::Address::InstanceConstSharedPtr address = getSslAddress(version_, lookupPort("http")); auto client_transport_socket_factory_ptr = createClientSslTransportSocketFactory( - ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config), + ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config.get()), *context_manager_, *api_); Network::ClientConnectionPtr connection = dispatcher_->createClientConnection( address, Network::Address::InstanceConstSharedPtr(), @@ -595,8 +595,8 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(SslIntegrationTest, AsyncCertValidationAfterSslShutdown) { - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: @@ -613,7 +613,7 @@ name: "envoy.tls.cert_validator.timed_cert_validator" initialize(); Network::Address::InstanceConstSharedPtr address = getSslAddress(version_, lookupPort("http")); auto client_transport_socket_factory_ptr = createClientSslTransportSocketFactory( - ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config), + ClientSslTransportOptions().setCustomCertValidatorConfig(custom_validator_config.get()), *context_manager_, *api_); Network::ClientConnectionPtr connection = dispatcher_->createClientConnection( address, Network::Address::InstanceConstSharedPtr(), diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 75706cf7231f..54f6d2249694 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -1112,30 +1112,30 @@ TEST_P(QuicHttpIntegrationTest, NoStreams) { TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationSucceeds) { // Config the client to defer cert validation by 5ms. - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: "@type": type.googleapis.com/test.common.config.DummyConfig )EOF"), *custom_validator_config); - ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config); + ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config.get()); initialize(); codec_client_ = makeRawHttpConnection(makeClientConnection(lookupPort("http")), absl::nullopt); EXPECT_TRUE(codec_client_->connected()); } TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationAfterDisconnect) { - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: "@type": type.googleapis.com/test.common.config.DummyConfig )EOF"), *custom_validator_config); - ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config); + ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config.get()); // Change the configured cert validation to defer 1s. auto* cert_validator_factory = @@ -1166,15 +1166,15 @@ name: "envoy.tls.cert_validator.timed_cert_validator" } TEST_P(QuicHttpIntegrationTest, AsyncCertVerificationAfterTearDown) { - envoy::config::core::v3::TypedExtensionConfig* custom_validator_config = - new envoy::config::core::v3::TypedExtensionConfig(); + auto custom_validator_config = std::make_unique( + envoy::config::core::v3::TypedExtensionConfig()); TestUtility::loadFromYaml(TestEnvironment::substitute(R"EOF( name: "envoy.tls.cert_validator.timed_cert_validator" typed_config: "@type": type.googleapis.com/test.common.config.DummyConfig )EOF"), *custom_validator_config); - ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config); + ssl_client_option_.setCustomCertValidatorConfig(custom_validator_config.get()); // Change the configured cert validation to defer 1s. auto cert_validator_factory = Registry::FactoryRegistry:: diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index 6727632d99f1..1b226d79f9f7 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -85,8 +85,8 @@ void initializeUpstreamTlsContextConfig( tls_context.set_sni(options.sni_); } if (options.custom_validator_config_) { - common_context->mutable_validation_context()->set_allocated_custom_validator_config( - options.custom_validator_config_); + *common_context->mutable_validation_context()->mutable_custom_validator_config() = + *options.custom_validator_config_; } common_context->mutable_tls_params()->set_tls_minimum_protocol_version(options.tls_version_); diff --git a/test/integration/ssl_utility.h b/test/integration/ssl_utility.h index f8ffc8f5614e..3187b3b0e2ad 100644 --- a/test/integration/ssl_utility.h +++ b/test/integration/ssl_utility.h @@ -75,6 +75,7 @@ struct ClientSslTransportOptions { envoy::extensions::transport_sockets::tls::v3::TlsParameters::TLS_AUTO}; bool use_expired_spiffe_cert_{false}; bool client_with_intermediate_cert_{false}; + // It is owned by the caller that invokes `setCustomCertValidatorConfig()`. envoy::config::core::v3::TypedExtensionConfig* custom_validator_config_{nullptr}; }; From 5a15b9fc828556e1243c852a24ce3f78d0c332a6 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Tue, 2 Jan 2024 15:19:25 -0500 Subject: [PATCH 072/126] Quic refactor (#31097) Signed-off-by: Alyssa Wilk --- .../envoy_build_config/extension_registry.cc | 2 +- mobile/test/common/integration/BUILD | 1 + .../integration/client_integration_test.cc | 2 +- source/common/listener_manager/BUILD | 1 + .../listener_manager/listener_manager_impl.cc | 2 +- source/common/quic/BUILD | 36 ++++- source/common/quic/envoy_quic_proof_source.h | 2 +- .../quic_client_transport_socket_factory.cc | 66 +++++++++ .../quic_client_transport_socket_factory.h | 74 +++++++++++ .../quic_server_transport_socket_factory.cc | 43 ++++++ .../quic_server_transport_socket_factory.h | 77 +++++++++++ .../quic/quic_transport_socket_factory.cc | 84 +----------- .../quic/quic_transport_socket_factory.h | 125 ------------------ test/common/http/conn_pool_grid_test.cc | 2 +- test/common/http/http3/conn_pool_test.cc | 2 +- .../listener_manager_impl_quic_only_test.cc | 2 +- test/common/quic/BUILD | 2 + .../client_connection_factory_impl_test.cc | 2 +- .../common/quic/envoy_quic_dispatcher_test.cc | 2 +- .../quic_transport_socket_factory_test.cc | 3 +- test/integration/http_integration.cc | 2 +- ...er_extension_discovery_integration_test.cc | 2 +- .../integration/quic_http_integration_test.cc | 2 +- test/integration/utility.cc | 2 +- tools/code_format/config.yaml | 1 - 25 files changed, 314 insertions(+), 225 deletions(-) create mode 100644 source/common/quic/quic_client_transport_socket_factory.cc create mode 100644 source/common/quic/quic_client_transport_socket_factory.h create mode 100644 source/common/quic/quic_server_transport_socket_factory.cc create mode 100644 source/common/quic/quic_server_transport_socket_factory.h diff --git a/mobile/envoy_build_config/extension_registry.cc b/mobile/envoy_build_config/extension_registry.cc index 7490d51ee450..fd6178ba778c 100644 --- a/mobile/envoy_build_config/extension_registry.cc +++ b/mobile/envoy_build_config/extension_registry.cc @@ -46,7 +46,7 @@ #include "source/extensions/quic/proof_source/envoy_quic_proof_source_factory_impl.h" #include "source/extensions/udp_packet_writer/default/config.h" #endif -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #endif #include "extension_registry_platform_additions.h" diff --git a/mobile/test/common/integration/BUILD b/mobile/test/common/integration/BUILD index b155b236ce7c..cb7bb176b4b7 100644 --- a/mobile/test/common/integration/BUILD +++ b/mobile/test/common/integration/BUILD @@ -26,6 +26,7 @@ envoy_cc_test( "@envoy//source/common/quic:active_quic_listener_lib", "@envoy//source/common/quic:client_connection_factory_lib", "@envoy//source/common/quic:quic_server_factory_lib", + "@envoy//source/common/quic:quic_server_transport_socket_factory_lib", "@envoy//source/common/quic:quic_transport_socket_factory_lib", "@envoy//source/common/quic:udp_gso_batch_writer_lib", "@envoy//source/extensions/udp_packet_writer/gso:config", diff --git a/mobile/test/common/integration/client_integration_test.cc b/mobile/test/common/integration/client_integration_test.cc index de58db3390cb..14a49af1b02e 100644 --- a/mobile/test/common/integration/client_integration_test.cc +++ b/mobile/test/common/integration/client_integration_test.cc @@ -1,4 +1,4 @@ -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #include "source/common/quic/server_codec_impl.h" #include "source/extensions/http/header_formatters/preserve_case/preserve_case_formatter.h" #include "source/extensions/quic/connection_id_generator/envoy_deterministic_connection_id_generator_config.h" diff --git a/source/common/listener_manager/BUILD b/source/common/listener_manager/BUILD index 3c682e02966f..1b8e49427033 100644 --- a/source/common/listener_manager/BUILD +++ b/source/common/listener_manager/BUILD @@ -71,6 +71,7 @@ envoy_cc_library( "//source/common/quic:active_quic_listener_lib", "//source/common/quic:client_connection_factory_lib", "//source/common/quic:quic_server_factory_lib", + "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/common/quic:quic_transport_socket_factory_lib", "//source/common/quic:udp_gso_batch_writer_lib", "//source/extensions/udp_packet_writer/gso:config", diff --git a/source/common/listener_manager/listener_manager_impl.cc b/source/common/listener_manager/listener_manager_impl.cc index c503efd8ccf0..3982b72eed00 100644 --- a/source/common/listener_manager/listener_manager_impl.cc +++ b/source/common/listener_manager/listener_manager_impl.cc @@ -27,7 +27,7 @@ #include "absl/synchronization/blocking_counter.h" #if defined(ENVOY_ENABLE_QUIC) -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #endif #include "source/server/api_listener_impl.h" diff --git a/source/common/quic/BUILD b/source/common/quic/BUILD index abac729ff556..c4511a02ee53 100644 --- a/source/common/quic/BUILD +++ b/source/common/quic/BUILD @@ -108,6 +108,7 @@ envoy_cc_library( ":quic_io_handle_wrapper_lib", ":quic_transport_socket_factory_lib", "//envoy/ssl:tls_certificate_config_interface", + "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/common/stream_info:stream_info_lib", "//source/server:listener_stats", "@com_github_google_quiche//:quic_core_crypto_certificate_view_lib", @@ -436,11 +437,42 @@ envoy_cc_library( envoy_cc_library( name = "quic_transport_socket_factory_lib", - srcs = ["quic_transport_socket_factory.cc"], - hdrs = ["quic_transport_socket_factory.h"], + srcs = [ + "quic_client_transport_socket_factory.cc", + "quic_transport_socket_factory.cc", + ], + hdrs = [ + "quic_client_transport_socket_factory.h", + "quic_transport_socket_factory.h", + ], + tags = ["nofips"], + deps = [ + ":envoy_quic_proof_verifier_lib", + "//envoy/network:transport_socket_interface", + "//envoy/server:transport_socket_config_interface", + "//envoy/ssl:context_config_interface", + "//source/common/common:assert_lib", + "//source/common/network:transport_socket_options_lib", + "//source/extensions/transport_sockets/tls:context_config_lib", + "//source/extensions/transport_sockets/tls:ssl_socket_lib", + "@com_github_google_quiche//:quic_core_crypto_crypto_handshake_lib", + "@envoy_api//envoy/extensions/transport_sockets/quic/v3:pkg_cc_proto", + ], + alwayslink = LEGACY_ALWAYSLINK, +) + +envoy_cc_library( + name = "quic_server_transport_socket_factory_lib", + srcs = [ + "quic_server_transport_socket_factory.cc", + ], + hdrs = [ + "quic_server_transport_socket_factory.h", + ], tags = ["nofips"], deps = [ ":envoy_quic_proof_verifier_lib", + ":quic_transport_socket_factory_lib", "//envoy/network:transport_socket_interface", "//envoy/server:transport_socket_config_interface", "//envoy/ssl:context_config_interface", diff --git a/source/common/quic/envoy_quic_proof_source.h b/source/common/quic/envoy_quic_proof_source.h index bc3b3c127f32..d47ab9ba7bb3 100644 --- a/source/common/quic/envoy_quic_proof_source.h +++ b/source/common/quic/envoy_quic_proof_source.h @@ -1,7 +1,7 @@ #pragma once #include "source/common/quic/envoy_quic_proof_source_base.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #include "source/server/listener_stats.h" namespace Envoy { diff --git a/source/common/quic/quic_client_transport_socket_factory.cc b/source/common/quic/quic_client_transport_socket_factory.cc new file mode 100644 index 000000000000..1e0f289c319e --- /dev/null +++ b/source/common/quic/quic_client_transport_socket_factory.cc @@ -0,0 +1,66 @@ +#include "source/common/quic/quic_client_transport_socket_factory.h" + +#include + +#include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.validate.h" + +#include "source/common/quic/envoy_quic_proof_verifier.h" +#include "source/common/runtime/runtime_features.h" +#include "source/extensions/transport_sockets/tls/context_config_impl.h" + +#include "quiche/quic/core/crypto/quic_client_session_cache.h" + +namespace Envoy { +namespace Quic { + +Network::UpstreamTransportSocketFactoryPtr +QuicClientTransportSocketConfigFactory::createTransportSocketFactory( + const Protobuf::Message& config, + Server::Configuration::TransportSocketFactoryContext& context) { + auto quic_transport = MessageUtil::downcastAndValidate< + const envoy::extensions::transport_sockets::quic::v3::QuicUpstreamTransport&>( + config, context.messageValidationVisitor()); + auto client_config = std::make_unique( + quic_transport.upstream_tls_context(), context); + auto factory = + std::make_unique(std::move(client_config), context); + factory->initialize(); + return factory; +} + +QuicClientTransportSocketFactory::QuicClientTransportSocketFactory( + Ssl::ClientContextConfigPtr config, + Server::Configuration::TransportSocketFactoryContext& factory_context) + : QuicTransportSocketFactoryBase(factory_context.statsScope(), "client"), + fallback_factory_(std::make_unique( + std::move(config), factory_context.sslContextManager(), factory_context.statsScope())) {} + +ProtobufTypes::MessagePtr QuicClientTransportSocketConfigFactory::createEmptyConfigProto() { + return std::make_unique(); +} + +std::shared_ptr QuicClientTransportSocketFactory::getCryptoConfig() { + Envoy::Ssl::ClientContextSharedPtr context = sslCtx(); + // If the secrets haven't been loaded, there is no crypto config. + if (context == nullptr) { + ENVOY_LOG(warn, "SDS hasn't finished updating Ssl context config yet."); + stats_.upstream_context_secrets_not_ready_.inc(); + return nullptr; + } + + if (client_context_ != context) { + // If the context has been updated, update the crypto config. + client_context_ = context; + crypto_config_ = std::make_shared( + std::make_unique(std::move(context)), + std::make_unique()); + } + // Return the latest crypto config. + return crypto_config_; +} + +REGISTER_FACTORY(QuicClientTransportSocketConfigFactory, + Server::Configuration::UpstreamTransportSocketConfigFactory); + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/quic_client_transport_socket_factory.h b/source/common/quic/quic_client_transport_socket_factory.h new file mode 100644 index 000000000000..3abc6e18be06 --- /dev/null +++ b/source/common/quic/quic_client_transport_socket_factory.h @@ -0,0 +1,74 @@ +#pragma once + +#include "source/common/quic/quic_transport_socket_factory.h" + +namespace Envoy { +namespace Quic { + +class QuicClientTransportSocketFactory : public Network::CommonUpstreamTransportSocketFactory, + public QuicTransportSocketFactoryBase { +public: + QuicClientTransportSocketFactory( + Ssl::ClientContextConfigPtr config, + Server::Configuration::TransportSocketFactoryContext& factory_context); + + void initialize() override {} + bool implementsSecureTransport() const override { return true; } + bool supportsAlpn() const override { return true; } + absl::string_view defaultServerNameIndication() const override { + return clientContextConfig()->serverNameIndication(); + } + + // As documented above for QuicTransportSocketFactoryBase, the actual HTTP/3 + // code does not create transport sockets. + // QuicClientTransportSocketFactory::createTransportSocket is called by the + // connection grid when upstream HTTP/3 fails over to TCP, and a raw SSL socket + // is needed. In this case the QuicClientTransportSocketFactory falls over to + // using the fallback factory. + Network::TransportSocketPtr + createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options, + Upstream::HostDescriptionConstSharedPtr host) const override { + return fallback_factory_->createTransportSocket(options, host); + } + + Envoy::Ssl::ClientContextSharedPtr sslCtx() override { return fallback_factory_->sslCtx(); } + + OptRef clientContextConfig() const override { + return fallback_factory_->clientContextConfig(); + } + + // Returns a crypto config generated from the up-to-date client context config. Once the passed in + // context config gets updated, a new crypto config object will be returned by this method. + std::shared_ptr getCryptoConfig() override; + +protected: + // fallback_factory_ will update the context. + void onSecretUpdated() override {} + +private: + // The QUIC client transport socket can create TLS sockets for fallback to TCP. + std::unique_ptr fallback_factory_; + // Latch the latest client context, to determine if it has updated since last + // checked. + Envoy::Ssl::ClientContextSharedPtr client_context_; + // If client_context_ changes, client config will be updated as well. + std::shared_ptr crypto_config_; +}; + +class QuicClientTransportSocketConfigFactory + : public QuicTransportSocketConfigFactory, + public Server::Configuration::UpstreamTransportSocketConfigFactory { +public: + // Server::Configuration::UpstreamTransportSocketConfigFactory + Network::UpstreamTransportSocketFactoryPtr createTransportSocketFactory( + const Protobuf::Message& config, + Server::Configuration::TransportSocketFactoryContext& context) override; + + // Server::Configuration::TransportSocketConfigFactory + ProtobufTypes::MessagePtr createEmptyConfigProto() override; +}; + +DECLARE_FACTORY(QuicClientTransportSocketConfigFactory); + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/quic_server_transport_socket_factory.cc b/source/common/quic/quic_server_transport_socket_factory.cc new file mode 100644 index 000000000000..eaa139a0555f --- /dev/null +++ b/source/common/quic/quic_server_transport_socket_factory.cc @@ -0,0 +1,43 @@ +#include "source/common/quic/quic_server_transport_socket_factory.h" + +#include + +#include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.validate.h" + +#include "source/common/runtime/runtime_features.h" +#include "source/extensions/transport_sockets/tls/context_config_impl.h" + +namespace Envoy { +namespace Quic { + +Network::DownstreamTransportSocketFactoryPtr +QuicServerTransportSocketConfigFactory::createTransportSocketFactory( + const Protobuf::Message& config, Server::Configuration::TransportSocketFactoryContext& context, + const std::vector& /*server_names*/) { + auto quic_transport = MessageUtil::downcastAndValidate< + const envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport&>( + config, context.messageValidationVisitor()); + auto server_config = std::make_unique( + quic_transport.downstream_tls_context(), context); + // TODO(RyanTheOptimist): support TLS client authentication. + if (server_config->requireClientCertificate()) { + throwEnvoyExceptionOrPanic("TLS Client Authentication is not supported over QUIC"); + } + + auto factory = std::make_unique( + PROTOBUF_GET_WRAPPED_OR_DEFAULT(quic_transport, enable_early_data, true), + context.statsScope(), std::move(server_config)); + factory->initialize(); + return factory; +} + +ProtobufTypes::MessagePtr QuicServerTransportSocketConfigFactory::createEmptyConfigProto() { + return std::make_unique< + envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport>(); +} + +REGISTER_FACTORY(QuicServerTransportSocketConfigFactory, + Server::Configuration::DownstreamTransportSocketConfigFactory); + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/quic_server_transport_socket_factory.h b/source/common/quic/quic_server_transport_socket_factory.h new file mode 100644 index 000000000000..8e1439d526d6 --- /dev/null +++ b/source/common/quic/quic_server_transport_socket_factory.h @@ -0,0 +1,77 @@ +#pragma once + +#include "envoy/extensions/transport_sockets/quic/v3/quic_transport.pb.h" +#include "envoy/network/transport_socket.h" +#include "envoy/server/transport_socket_config.h" +#include "envoy/ssl/context_config.h" + +#include "source/common/common/assert.h" +#include "source/common/network/transport_socket_options_impl.h" +#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/extensions/transport_sockets/tls/ssl_socket.h" + +namespace Envoy { +namespace Quic { + +// TODO(danzh): when implement ProofSource, examine of it's necessary to +// differentiate server and client side context config. +class QuicServerTransportSocketFactory : public Network::DownstreamTransportSocketFactory, + public QuicTransportSocketFactoryBase { +public: + QuicServerTransportSocketFactory(bool enable_early_data, Stats::Scope& store, + Ssl::ServerContextConfigPtr config) + : QuicTransportSocketFactoryBase(store, "server"), config_(std::move(config)), + enable_early_data_(enable_early_data) {} + + // Network::DownstreamTransportSocketFactory + Network::TransportSocketPtr createDownstreamTransportSocket() const override { + PANIC("not implemented"); + } + bool implementsSecureTransport() const override { return true; } + + void initialize() override { + config_->setSecretUpdateCallback([this]() { + // The callback also updates config_ with the new secret. + onSecretUpdated(); + }); + } + + // Return TLS certificates if the context config is ready. + std::vector> + getTlsCertificates() const { + if (!config_->isReady()) { + ENVOY_LOG(warn, "SDS hasn't finished updating Ssl context config yet."); + stats_.downstream_context_secrets_not_ready_.inc(); + return {}; + } + return config_->tlsCertificates(); + } + + bool earlyDataEnabled() const { return enable_early_data_; } + +protected: + void onSecretUpdated() override { stats_.context_config_update_by_sds_.inc(); } + +private: + Ssl::ServerContextConfigPtr config_; + bool enable_early_data_; +}; + +class QuicServerTransportSocketConfigFactory + : public QuicTransportSocketConfigFactory, + public Server::Configuration::DownstreamTransportSocketConfigFactory { +public: + // Server::Configuration::DownstreamTransportSocketConfigFactory + Network::DownstreamTransportSocketFactoryPtr + createTransportSocketFactory(const Protobuf::Message& config, + Server::Configuration::TransportSocketFactoryContext& context, + const std::vector& server_names) override; + + // Server::Configuration::TransportSocketConfigFactory + ProtobufTypes::MessagePtr createEmptyConfigProto() override; +}; + +DECLARE_FACTORY(QuicServerTransportSocketConfigFactory); + +} // namespace Quic +} // namespace Envoy diff --git a/source/common/quic/quic_transport_socket_factory.cc b/source/common/quic/quic_transport_socket_factory.cc index 9b23710852c2..3893dde4b6e7 100644 --- a/source/common/quic/quic_transport_socket_factory.cc +++ b/source/common/quic/quic_transport_socket_factory.cc @@ -10,86 +10,4 @@ #include "quiche/quic/core/crypto/quic_client_session_cache.h" -namespace Envoy { -namespace Quic { - -Network::DownstreamTransportSocketFactoryPtr -QuicServerTransportSocketConfigFactory::createTransportSocketFactory( - const Protobuf::Message& config, Server::Configuration::TransportSocketFactoryContext& context, - const std::vector& /*server_names*/) { - auto quic_transport = MessageUtil::downcastAndValidate< - const envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport&>( - config, context.messageValidationVisitor()); - auto server_config = std::make_unique( - quic_transport.downstream_tls_context(), context); - // TODO(RyanTheOptimist): support TLS client authentication. - if (server_config->requireClientCertificate()) { - throwEnvoyExceptionOrPanic("TLS Client Authentication is not supported over QUIC"); - } - - auto factory = std::make_unique( - PROTOBUF_GET_WRAPPED_OR_DEFAULT(quic_transport, enable_early_data, true), - context.statsScope(), std::move(server_config)); - factory->initialize(); - return factory; -} - -ProtobufTypes::MessagePtr QuicServerTransportSocketConfigFactory::createEmptyConfigProto() { - return std::make_unique< - envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport>(); -} - -Network::UpstreamTransportSocketFactoryPtr -QuicClientTransportSocketConfigFactory::createTransportSocketFactory( - const Protobuf::Message& config, - Server::Configuration::TransportSocketFactoryContext& context) { - auto quic_transport = MessageUtil::downcastAndValidate< - const envoy::extensions::transport_sockets::quic::v3::QuicUpstreamTransport&>( - config, context.messageValidationVisitor()); - auto client_config = std::make_unique( - quic_transport.upstream_tls_context(), context); - auto factory = - std::make_unique(std::move(client_config), context); - factory->initialize(); - return factory; -} - -QuicClientTransportSocketFactory::QuicClientTransportSocketFactory( - Ssl::ClientContextConfigPtr config, - Server::Configuration::TransportSocketFactoryContext& factory_context) - : QuicTransportSocketFactoryBase(factory_context.statsScope(), "client"), - fallback_factory_(std::make_unique( - std::move(config), factory_context.sslContextManager(), factory_context.statsScope())) {} - -ProtobufTypes::MessagePtr QuicClientTransportSocketConfigFactory::createEmptyConfigProto() { - return std::make_unique(); -} - -std::shared_ptr QuicClientTransportSocketFactory::getCryptoConfig() { - Envoy::Ssl::ClientContextSharedPtr context = sslCtx(); - // If the secrets haven't been loaded, there is no crypto config. - if (context == nullptr) { - ENVOY_LOG(warn, "SDS hasn't finished updating Ssl context config yet."); - stats_.upstream_context_secrets_not_ready_.inc(); - return nullptr; - } - - if (client_context_ != context) { - // If the context has been updated, update the crypto config. - client_context_ = context; - crypto_config_ = std::make_shared( - std::make_unique(std::move(context)), - std::make_unique()); - } - // Return the latest crypto config. - return crypto_config_; -} - -REGISTER_FACTORY(QuicServerTransportSocketConfigFactory, - Server::Configuration::DownstreamTransportSocketConfigFactory); - -REGISTER_FACTORY(QuicClientTransportSocketConfigFactory, - Server::Configuration::UpstreamTransportSocketConfigFactory); - -} // namespace Quic -} // namespace Envoy +namespace Envoy {} // namespace Envoy diff --git a/source/common/quic/quic_transport_socket_factory.h b/source/common/quic/quic_transport_socket_factory.h index e9ae0288e311..ce6dbe312b48 100644 --- a/source/common/quic/quic_transport_socket_factory.h +++ b/source/common/quic/quic_transport_socket_factory.h @@ -52,100 +52,6 @@ class QuicTransportSocketFactoryBase : protected Logger::LoggablesetSecretUpdateCallback([this]() { - // The callback also updates config_ with the new secret. - onSecretUpdated(); - }); - } - - // Return TLS certificates if the context config is ready. - std::vector> - getTlsCertificates() const { - if (!config_->isReady()) { - ENVOY_LOG(warn, "SDS hasn't finished updating Ssl context config yet."); - stats_.downstream_context_secrets_not_ready_.inc(); - return {}; - } - return config_->tlsCertificates(); - } - - bool earlyDataEnabled() const { return enable_early_data_; } - -protected: - void onSecretUpdated() override { stats_.context_config_update_by_sds_.inc(); } - -private: - Ssl::ServerContextConfigPtr config_; - bool enable_early_data_; -}; - -class QuicClientTransportSocketFactory : public Network::CommonUpstreamTransportSocketFactory, - public QuicTransportSocketFactoryBase { -public: - QuicClientTransportSocketFactory( - Ssl::ClientContextConfigPtr config, - Server::Configuration::TransportSocketFactoryContext& factory_context); - - void initialize() override {} - bool implementsSecureTransport() const override { return true; } - bool supportsAlpn() const override { return true; } - absl::string_view defaultServerNameIndication() const override { - return clientContextConfig()->serverNameIndication(); - } - - // As documented above for QuicTransportSocketFactoryBase, the actual HTTP/3 - // code does not create transport sockets. - // QuicClientTransportSocketFactory::createTransportSocket is called by the - // connection grid when upstream HTTP/3 fails over to TCP, and a raw SSL socket - // is needed. In this case the QuicClientTransportSocketFactory falls over to - // using the fallback factory. - Network::TransportSocketPtr - createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options, - Upstream::HostDescriptionConstSharedPtr host) const override { - return fallback_factory_->createTransportSocket(options, host); - } - - Envoy::Ssl::ClientContextSharedPtr sslCtx() override { return fallback_factory_->sslCtx(); } - - OptRef clientContextConfig() const override { - return fallback_factory_->clientContextConfig(); - } - - // Returns a crypto config generated from the up-to-date client context config. Once the passed in - // context config gets updated, a new crypto config object will be returned by this method. - std::shared_ptr getCryptoConfig() override; - -protected: - // fallback_factory_ will update the context. - void onSecretUpdated() override {} - -private: - // The QUIC client transport socket can create TLS sockets for fallback to TCP. - std::unique_ptr fallback_factory_; - // Latch the latest client context, to determine if it has updated since last - // checked. - Envoy::Ssl::ClientContextSharedPtr client_context_; - // If client_context_ changes, client config will be updated as well. - std::shared_ptr crypto_config_; -}; - // Base class to create above QuicTransportSocketFactory for server and client // side. class QuicTransportSocketConfigFactory @@ -155,36 +61,5 @@ class QuicTransportSocketConfigFactory std::string name() const override { return "envoy.transport_sockets.quic"; } }; -class QuicServerTransportSocketConfigFactory - : public QuicTransportSocketConfigFactory, - public Server::Configuration::DownstreamTransportSocketConfigFactory { -public: - // Server::Configuration::DownstreamTransportSocketConfigFactory - Network::DownstreamTransportSocketFactoryPtr - createTransportSocketFactory(const Protobuf::Message& config, - Server::Configuration::TransportSocketFactoryContext& context, - const std::vector& server_names) override; - - // Server::Configuration::TransportSocketConfigFactory - ProtobufTypes::MessagePtr createEmptyConfigProto() override; -}; - -DECLARE_FACTORY(QuicServerTransportSocketConfigFactory); - -class QuicClientTransportSocketConfigFactory - : public QuicTransportSocketConfigFactory, - public Server::Configuration::UpstreamTransportSocketConfigFactory { -public: - // Server::Configuration::UpstreamTransportSocketConfigFactory - Network::UpstreamTransportSocketFactoryPtr createTransportSocketFactory( - const Protobuf::Message& config, - Server::Configuration::TransportSocketFactoryContext& context) override; - - // Server::Configuration::TransportSocketConfigFactory - ProtobufTypes::MessagePtr createEmptyConfigProto() override; -}; - -DECLARE_FACTORY(QuicClientTransportSocketConfigFactory); - } // namespace Quic } // namespace Envoy diff --git a/test/common/http/conn_pool_grid_test.cc b/test/common/http/conn_pool_grid_test.cc index f14c02f9ef5d..a52a6545ec8e 100644 --- a/test/common/http/conn_pool_grid_test.cc +++ b/test/common/http/conn_pool_grid_test.cc @@ -909,7 +909,7 @@ TEST_F(ConnectivityGridTest, Http3FailedRecentlyThenFailsAgain) { } // namespace Envoy #include "test/mocks/server/transport_socket_factory_context.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" namespace Envoy { namespace Http { namespace { diff --git a/test/common/http/http3/conn_pool_test.cc b/test/common/http/http3/conn_pool_test.cc index 14e110f7d47f..75f82c9336e5 100644 --- a/test/common/http/http3/conn_pool_test.cc +++ b/test/common/http/http3/conn_pool_test.cc @@ -2,7 +2,7 @@ #include #include "source/common/http/http3/conn_pool.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "test/common/http/common.h" #include "test/common/upstream/utility.h" diff --git a/test/common/listener_manager/listener_manager_impl_quic_only_test.cc b/test/common/listener_manager/listener_manager_impl_quic_only_test.cc index 422c4b8f0824..23a7d340853b 100644 --- a/test/common/listener_manager/listener_manager_impl_quic_only_test.cc +++ b/test/common/listener_manager/listener_manager_impl_quic_only_test.cc @@ -2,7 +2,7 @@ #include "envoy/config/listener/v3/listener.pb.h" #if defined(ENVOY_ENABLE_QUIC) -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #endif #include "test/common/listener_manager/listener_manager_impl_test.h" diff --git a/test/common/quic/BUILD b/test/common/quic/BUILD index e2d38d20e3a8..0d9444d28b12 100644 --- a/test/common/quic/BUILD +++ b/test/common/quic/BUILD @@ -247,6 +247,7 @@ envoy_cc_test( "//source/common/quic:envoy_quic_dispatcher_lib", "//source/common/quic:envoy_quic_proof_source_lib", "//source/common/quic:envoy_quic_server_session_lib", + "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/extensions/quic/crypto_stream:envoy_quic_crypto_server_stream_lib", "//source/server:configuration_lib", "//test/mocks/event:event_mocks", @@ -363,6 +364,7 @@ envoy_cc_test( ], tags = ["nofips"], deps = [ + "//source/common/quic:quic_server_transport_socket_factory_lib", "//source/common/quic:quic_transport_socket_factory_lib", "//source/extensions/transport_sockets/tls:context_config_lib", "//test/mocks/server:transport_socket_factory_context_mocks", diff --git a/test/common/quic/client_connection_factory_impl_test.cc b/test/common/quic/client_connection_factory_impl_test.cc index e8d8f0e6e1ac..8958dcf1d901 100644 --- a/test/common/quic/client_connection_factory_impl_test.cc +++ b/test/common/quic/client_connection_factory_impl_test.cc @@ -1,7 +1,7 @@ #include #include "source/common/quic/client_connection_factory_impl.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "test/common/upstream/utility.h" #include "test/mocks/common.h" diff --git a/test/common/quic/envoy_quic_dispatcher_test.cc b/test/common/quic/envoy_quic_dispatcher_test.cc index ea27cc687e3e..e14c36d09d9b 100644 --- a/test/common/quic/envoy_quic_dispatcher_test.cc +++ b/test/common/quic/envoy_quic_dispatcher_test.cc @@ -10,7 +10,7 @@ #include "source/common/quic/envoy_quic_dispatcher.h" #include "source/common/quic/envoy_quic_server_session.h" #include "source/common/quic/envoy_quic_utils.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #include "source/extensions/quic/crypto_stream/envoy_quic_crypto_server_stream.h" #include "source/server/configuration_impl.h" diff --git a/test/common/quic/quic_transport_socket_factory_test.cc b/test/common/quic/quic_transport_socket_factory_test.cc index 89aa18174ab1..fe67629bcfb9 100644 --- a/test/common/quic/quic_transport_socket_factory_test.cc +++ b/test/common/quic/quic_transport_socket_factory_test.cc @@ -1,4 +1,5 @@ -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #include "test/mocks/server/transport_socket_factory_context.h" #include "test/mocks/ssl/mocks.h" diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 190f4bd8104c..4bfebe84cfd2 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -29,7 +29,7 @@ #ifdef ENVOY_ENABLE_QUIC #include "source/common/quic/client_connection_factory_impl.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #endif #include "source/extensions/transport_sockets/tls/context_config_impl.h" diff --git a/test/integration/listener_extension_discovery_integration_test.cc b/test/integration/listener_extension_discovery_integration_test.cc index 29e284b6764b..acdba1d6bf5c 100644 --- a/test/integration/listener_extension_discovery_integration_test.cc +++ b/test/integration/listener_extension_discovery_integration_test.cc @@ -774,7 +774,7 @@ TEST_P(ListenerExtensionDiscoveryIntegrationTest, TwoSubscriptionsConfigDumpWith #include "quiche/quic/core/deterministic_connection_id_generator.h" #include "source/common/quic/client_connection_factory_impl.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_server_transport_socket_factory.h" #include "test/integration/utility.h" namespace Envoy { diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 54f6d2249694..7d442edf53f7 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -18,7 +18,7 @@ #include "source/common/quic/envoy_quic_packet_writer.h" #include "source/common/quic/envoy_quic_proof_verifier.h" #include "source/common/quic/envoy_quic_utils.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "source/extensions/transport_sockets/tls/context_config_impl.h" #include "test/common/config/dummy_config.pb.h" diff --git a/test/integration/utility.cc b/test/integration/utility.cc index 69d4efc965cf..6ca68e0f333d 100644 --- a/test/integration/utility.cc +++ b/test/integration/utility.cc @@ -26,7 +26,7 @@ #ifdef ENVOY_ENABLE_QUIC #include "source/common/quic/client_connection_factory_impl.h" -#include "source/common/quic/quic_transport_socket_factory.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "quiche/quic/core/deterministic_connection_id_generator.h" #endif diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 8e6299fb2831..c7e1dc6bd7c9 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -139,7 +139,6 @@ paths: - source/common/config/datasource.cc - source/common/config/utility.cc - source/common/runtime/runtime_impl.cc - - source/common/quic/quic_transport_socket_factory.cc - source/common/filter/config_discovery_impl.cc - source/common/json/json_internal.cc - source/common/router/scoped_rds.cc From 99ebb7c3b8350d50aa772e57705f3ffbf8772bdd Mon Sep 17 00:00:00 2001 From: Rohit Agrawal Date: Tue, 2 Jan 2024 17:12:29 -0800 Subject: [PATCH 073/126] ext_authz: fix body buffering feature on ExtAuthZ per-route filter (#31437) Signed-off-by: Rohit Agrawal --- changelogs/current.yaml | 3 +++ .../filters/http/ext_authz/ext_authz.cc | 27 +++++++++---------- .../filters/http/ext_authz/ext_authz.h | 4 +++ .../filters/http/ext_authz/ext_authz_test.cc | 8 +++--- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 6d0703199d48..715baf916d7e 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -146,6 +146,9 @@ bug_fixes: - area: docker change: | Updated base image to ``ubuntu:22.04`` to fix Redis memory issue (https://github.com/envoyproxy/envoy/issues/31248). +- area: ext_authz + change: | + Fixed a bug to ensure the proper functioning of the ``with_request_body`` feature within the per-route ExtAuthZ filter. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/extensions/filters/http/ext_authz/ext_authz.cc b/source/extensions/filters/http/ext_authz/ext_authz.cc index c882666f4424..fe713f7e98e4 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.cc +++ b/source/extensions/filters/http/ext_authz/ext_authz.cc @@ -104,9 +104,9 @@ void Filter::initiateCall(const Http::RequestHeaderMap& headers) { Filters::Common::ExtAuthz::CheckRequestUtils::createHttpCheck( decoder_callbacks_, headers, std::move(context_extensions), std::move(metadata_context), - std::move(route_metadata_context), check_request_, config_->maxRequestBytes(), - config_->packAsBytes(), config_->includePeerCertificate(), config_->includeTLSSession(), - config_->destinationLabels(), config_->requestHeaderMatchers()); + std::move(route_metadata_context), check_request_, max_request_bytes_, config_->packAsBytes(), + config_->includePeerCertificate(), config_->includeTLSSession(), config_->destinationLabels(), + config_->requestHeaderMatchers()); ENVOY_STREAM_LOG(trace, "ext_authz filter calling authorization server", *decoder_callbacks_); // Store start time of ext_authz filter call @@ -155,16 +155,15 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, if (buffer_data_) { ENVOY_STREAM_LOG(debug, "ext_authz filter is buffering the request", *decoder_callbacks_); - const auto allow_partial_message = - check_settings.has_with_request_body() - ? check_settings.with_request_body().allow_partial_message() - : config_->allowPartialMessage(); - const auto max_request_bytes = check_settings.has_with_request_body() - ? check_settings.with_request_body().max_request_bytes() - : config_->maxRequestBytes(); + allow_partial_message_ = check_settings.has_with_request_body() + ? check_settings.with_request_body().allow_partial_message() + : config_->allowPartialMessage(); + max_request_bytes_ = check_settings.has_with_request_body() + ? check_settings.with_request_body().max_request_bytes() + : config_->maxRequestBytes(); - if (!allow_partial_message) { - decoder_callbacks_->setDecoderBufferLimit(max_request_bytes); + if (!allow_partial_message_) { + decoder_callbacks_->setDecoderBufferLimit(max_request_bytes_); } return Http::FilterHeadersStatus::StopIteration; } @@ -479,7 +478,7 @@ void Filter::onComplete(Filters::Common::ExtAuthz::ResponsePtr&& response) { } bool Filter::isBufferFull(uint64_t num_bytes_processing) const { - if (!config_->allowPartialMessage()) { + if (!allow_partial_message_) { return false; } @@ -489,7 +488,7 @@ bool Filter::isBufferFull(uint64_t num_bytes_processing) const { num_bytes_buffered += buffer->length(); } - return num_bytes_buffered >= config_->maxRequestBytes(); + return num_bytes_buffered >= max_request_bytes_; } void Filter::continueDecoding() { diff --git a/source/extensions/filters/http/ext_authz/ext_authz.h b/source/extensions/filters/http/ext_authz/ext_authz.h index e9832dbc1434..d18aa27ccccc 100644 --- a/source/extensions/filters/http/ext_authz/ext_authz.h +++ b/source/extensions/filters/http/ext_authz/ext_authz.h @@ -386,6 +386,10 @@ class Filter : public Logger::Loggable, // The stats for the filter. ExtAuthzFilterStats stats_; + // This is used to hold the final configs after we merge them with per-route configs. + bool allow_partial_message_{}; + uint32_t max_request_bytes_; + // Used to identify if the callback to onComplete() is synchronous (on the stack) or asynchronous. bool initiating_call_{}; bool buffer_data_{}; 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 350941b2fd69..96f74729dabe 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_test.cc @@ -2974,7 +2974,7 @@ TEST_P(HttpFilterTestParam, NoCluster) { // Check that config validation for per-route filter works as expected. TEST_F(HttpFilterTest, PerRouteCheckSettingsConfigCheck) { - // Set allow_partial_message to true and max_request_bytes to 10 on the per-route filter. + // Set allow_partial_message to true and max_request_bytes to 5 on the per-route filter. envoy::extensions::filters::http::ext_authz::v3::BufferSettings buffer_settings; buffer_settings.set_max_request_bytes(5); // Set the max_request_bytes value buffer_settings.set_allow_partial_message(true); // Set the allow_partial_message value @@ -3004,7 +3004,7 @@ TEST_F(HttpFilterTest, PerRouteCheckSettingsWorks) { failure_mode_allow: false )EOF"); - // Set allow_partial_message to true and max_request_bytes to 10 on the per-route filter. + // Set allow_partial_message to true and max_request_bytes to 5 on the per-route filter. envoy::extensions::filters::http::ext_authz::v3::BufferSettings buffer_settings; buffer_settings.set_max_request_bytes(5); // Set the max_request_bytes value buffer_settings.set_allow_partial_message(true); // Set the allow_partial_message value @@ -3036,7 +3036,7 @@ TEST_F(HttpFilterTest, PerRouteCheckSettingsWorks) { data_.add(buffer1.toString()); Buffer::OwnedImpl buffer2("bar"); - EXPECT_EQ(Http::FilterDataStatus::StopIterationAndBuffer, filter_->decodeData(buffer2, false)); + EXPECT_EQ(Http::FilterDataStatus::StopIterationAndWatermark, filter_->decodeData(buffer2, true)); data_.add(buffer2.toString()); Buffer::OwnedImpl buffer3("barfoo"); @@ -3066,7 +3066,7 @@ TEST_F(HttpFilterTest, PerRouteCheckSettingsOverrideWorks) { // Set allow_partial_message to true and max_request_bytes to 10 on the per-route filter. envoy::extensions::filters::http::ext_authz::v3::BufferSettings buffer_settings; - buffer_settings.set_max_request_bytes(5); // Set the max_request_bytes value + buffer_settings.set_max_request_bytes(10); // Set the max_request_bytes value buffer_settings.set_allow_partial_message(true); // Set the allow_partial_message value // Set the per-route filter config. envoy::extensions::filters::http::ext_authz::v3::CheckSettings check_settings; From 9efaafc9518508676c93228472362eb1eafb47e7 Mon Sep 17 00:00:00 2001 From: code Date: Wed, 3 Jan 2024 15:51:44 +0800 Subject: [PATCH 074/126] generic proxy: codec validation from L7 filter (#31500) Signed-off-by: wbpcode --- .../filters/network/source/config.cc | 15 +++++++--- .../filters/network/source/config.h | 9 +++--- .../filters/network/source/interface/config.h | 10 +++++++ .../filters/network/test/config_test.cc | 29 +++++++++++++++---- .../filters/network/test/mocks/filter.h | 1 + 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/contrib/generic_proxy/filters/network/source/config.cc b/contrib/generic_proxy/filters/network/source/config.cc index dc5e07bd9fc5..d6036138abaf 100644 --- a/contrib/generic_proxy/filters/network/source/config.cc +++ b/contrib/generic_proxy/filters/network/source/config.cc @@ -49,9 +49,11 @@ Factory::routeConfigProviderFromProto(const ProxyConfig& config, } } -std::vector Factory::filtersFactoryFromProto( - const ProtobufWkt::RepeatedPtrField& filters, - const std::string stats_prefix, Envoy::Server::Configuration::FactoryContext& context) { +std::vector +Factory::filtersFactoryFromProto(const ProtobufWkt::RepeatedPtrField& filters, + const TypedExtensionConfig& codec_config, + const std::string stats_prefix, + Envoy::Server::Configuration::FactoryContext& context) { std::vector factories; bool has_terminal_filter = false; std::string terminal_filter_name; @@ -63,6 +65,10 @@ std::vector Factory::filtersFactoryFromProto( auto& factory = Config::Utility::getAndCheckFactory(filter); + // Validate codec to see if this filter is compatible with the codec. + const auto validate_codec_status = factory.validateCodec(codec_config); + THROW_IF_NOT_OK_REF(validate_codec_status); + ProtobufTypes::MessagePtr message = factory.createEmptyConfigProto(); ASSERT(message != nullptr); Envoy::Config::Utility::translateOpaqueConfig(filter.typed_config(), @@ -121,7 +127,8 @@ Factory::createFilterFactoryFromProtoTyped(const ProxyConfig& proto_config, const FilterConfigSharedPtr config = std::make_shared( proto_config.stat_prefix(), std::move(factories.first), routeConfigProviderFromProto(proto_config, context, *route_config_provider_manager), - filtersFactoryFromProto(proto_config.filters(), proto_config.stat_prefix(), context), + filtersFactoryFromProto(proto_config.filters(), proto_config.codec_config(), + proto_config.stat_prefix(), context), std::move(tracer), std::move(tracing_config), std::move(access_logs), context); return [route_config_provider_manager, tracer_manager, config, &server_context, diff --git a/contrib/generic_proxy/filters/network/source/config.h b/contrib/generic_proxy/filters/network/source/config.h index fdf04713b1c0..b6d59b69a454 100644 --- a/contrib/generic_proxy/filters/network/source/config.h +++ b/contrib/generic_proxy/filters/network/source/config.h @@ -23,7 +23,7 @@ class Factory : public Envoy::Extensions::NetworkFilters::Common::FactoryBase - factoriesFromProto(const envoy::config::core::v3::TypedExtensionConfig& codec_config, + factoriesFromProto(const TypedExtensionConfig& codec_config, Server::Configuration::FactoryContext& context); static Rds::RouteConfigProviderSharedPtr @@ -31,9 +31,10 @@ class Factory : public Envoy::Extensions::NetworkFilters::Common::FactoryBase filtersFactoryFromProto( - const ProtobufWkt::RepeatedPtrField& filters, - const std::string stats_prefix, Server::Configuration::FactoryContext& context); + static std::vector + filtersFactoryFromProto(const ProtobufWkt::RepeatedPtrField& filters, + const TypedExtensionConfig& codec_config, const std::string stats_prefix, + Server::Configuration::FactoryContext& context); }; } // namespace GenericProxy diff --git a/contrib/generic_proxy/filters/network/source/interface/config.h b/contrib/generic_proxy/filters/network/source/interface/config.h index 456f581eed83..c724f6286c01 100644 --- a/contrib/generic_proxy/filters/network/source/interface/config.h +++ b/contrib/generic_proxy/filters/network/source/interface/config.h @@ -10,6 +10,8 @@ namespace Extensions { namespace NetworkFilters { namespace GenericProxy { +using TypedExtensionConfig = envoy::config::core::v3::TypedExtensionConfig; + /** * Implemented by each generic filter and registered via Registry::registerFactory or the * convenience class RegisterFactory. @@ -41,6 +43,14 @@ class NamedFilterConfigFactory : public Config::TypedFactory { * @return bool true if this filter must be the last filter in a filter chain, false otherwise. */ virtual bool isTerminalFilter() PURE; + + /** + * @return absl::Status validate the codec config to see if it is compatible with the filter. + * If the codec config is not compatible with this filter, return an error status. + */ + virtual absl::Status validateCodec(const TypedExtensionConfig& /*config*/) { + return absl::OkStatus(); + } }; } // namespace GenericProxy diff --git a/contrib/generic_proxy/filters/network/test/config_test.cc b/contrib/generic_proxy/filters/network/test/config_test.cc index 7f0b03bddd02..873d5c2fc82d 100644 --- a/contrib/generic_proxy/filters/network/test/config_test.cc +++ b/contrib/generic_proxy/filters/network/test/config_test.cc @@ -273,6 +273,7 @@ TEST(BasicFilterConfigTest, CreatingFilterFactories) { NiceMock factory_context; ProtobufWkt::RepeatedPtrField filters_proto_config; + envoy::config::core::v3::TypedExtensionConfig codec_config; const std::string yaml_config_0 = R"EOF( name: mock_generic_proxy_filter_name_0 @@ -308,9 +309,10 @@ TEST(BasicFilterConfigTest, CreatingFilterFactories) { // No terminal filter. { - EXPECT_THROW_WITH_MESSAGE( - Factory::filtersFactoryFromProto(filters_proto_config, "test", factory_context), - EnvoyException, "A terminal L7 filter is necessary for generic proxy"); + EXPECT_THROW_WITH_MESSAGE(Factory::filtersFactoryFromProto(filters_proto_config, codec_config, + "test", factory_context), + EnvoyException, + "A terminal L7 filter is necessary for generic proxy"); } // Error terminal filter position. @@ -318,17 +320,32 @@ TEST(BasicFilterConfigTest, CreatingFilterFactories) { ON_CALL(mock_filter_config_0, isTerminalFilter()).WillByDefault(Return(true)); EXPECT_THROW_WITH_MESSAGE( - Factory::filtersFactoryFromProto(filters_proto_config, "test", factory_context), + Factory::filtersFactoryFromProto(filters_proto_config, codec_config, "test", + factory_context), EnvoyException, "Terminal filter: mock_generic_proxy_filter_name_0 must be the last generic L7 " "filter"); } + // Codec validation error. + { + ON_CALL(mock_filter_config_0, isTerminalFilter()).WillByDefault(Return(false)); + ON_CALL(mock_filter_config_0, validateCodec(_)) + .WillByDefault(Return(absl::InvalidArgumentError("codec validation error"))); + + EXPECT_THROW_WITH_MESSAGE(Factory::filtersFactoryFromProto(filters_proto_config, codec_config, + "test", factory_context), + EnvoyException, "codec validation error"); + } + { ON_CALL(mock_filter_config_0, isTerminalFilter()).WillByDefault(Return(false)); ON_CALL(mock_filter_config_1, isTerminalFilter()).WillByDefault(Return(true)); - auto factories = - Factory::filtersFactoryFromProto(filters_proto_config, "test", factory_context); + ON_CALL(mock_filter_config_0, validateCodec(_)).WillByDefault(Return(absl::OkStatus())); + ON_CALL(mock_filter_config_1, validateCodec(_)).WillByDefault(Return(absl::OkStatus())); + + auto factories = Factory::filtersFactoryFromProto(filters_proto_config, codec_config, "test", + factory_context); EXPECT_EQ(2, factories.size()); } } diff --git a/contrib/generic_proxy/filters/network/test/mocks/filter.h b/contrib/generic_proxy/filters/network/test/mocks/filter.h index a497265780ed..de1af24efd60 100644 --- a/contrib/generic_proxy/filters/network/test/mocks/filter.h +++ b/contrib/generic_proxy/filters/network/test/mocks/filter.h @@ -65,6 +65,7 @@ class MockStreamFilterConfig : public NamedFilterConfigFactory { (const Protobuf::Message&, Server::Configuration::ServerFactoryContext&, ProtobufMessage::ValidationVisitor&)); MOCK_METHOD(std::string, name, (), (const)); + MOCK_METHOD(absl::Status, validateCodec, (const TypedExtensionConfig&)); MOCK_METHOD(std::set, configTypes, ()); MOCK_METHOD(bool, isTerminalFilter, ()); }; From 39d8ef044e3fdcd6cd7e1a4f95479a5b2c72c428 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:02:24 +0000 Subject: [PATCH 075/126] build(deps): bump the examples-ext-authz group in /examples/ext_authz/auth/grpc-service with 2 updates (#31599) build(deps): bump the examples-ext-authz group Bumps the examples-ext-authz group in /examples/ext_authz/auth/grpc-service with 2 updates: [github.com/envoyproxy/go-control-plane](https://github.com/envoyproxy/go-control-plane) and [google.golang.org/grpc](https://github.com/grpc/grpc-go). Updates `github.com/envoyproxy/go-control-plane` from 0.11.1 to 0.12.0 - [Release notes](https://github.com/envoyproxy/go-control-plane/releases) - [Changelog](https://github.com/envoyproxy/go-control-plane/blob/main/CHANGELOG.md) - [Commits](https://github.com/envoyproxy/go-control-plane/compare/v0.11.1...v0.12.0) Updates `google.golang.org/grpc` from 1.60.0 to 1.60.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.60.0...v1.60.1) --- updated-dependencies: - dependency-name: github.com/envoyproxy/go-control-plane dependency-type: direct:production update-type: version-update:semver-minor dependency-group: examples-ext-authz - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: examples-ext-authz ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/ext_authz/auth/grpc-service/go.mod | 4 +-- examples/ext_authz/auth/grpc-service/go.sum | 29 +++++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/examples/ext_authz/auth/grpc-service/go.mod b/examples/ext_authz/auth/grpc-service/go.mod index aaf9ade0ca58..72ee6d16d88f 100644 --- a/examples/ext_authz/auth/grpc-service/go.mod +++ b/examples/ext_authz/auth/grpc-service/go.mod @@ -3,8 +3,8 @@ module github.com/envoyproxy/envoy/examples/ext_authz/auth/grpc-service go 1.14 require ( - github.com/envoyproxy/go-control-plane v0.11.1 + github.com/envoyproxy/go-control-plane v0.12.0 github.com/golang/protobuf v1.5.3 google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 - google.golang.org/grpc v1.60.0 + google.golang.org/grpc v1.60.1 ) diff --git a/examples/ext_authz/auth/grpc-service/go.sum b/examples/ext_authz/auth/grpc-service/go.sum index 711c4fc979f3..25019aec0e7c 100644 --- a/examples/ext_authz/auth/grpc-service/go.sum +++ b/examples/ext_authz/auth/grpc-service/go.sum @@ -219,6 +219,7 @@ cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/ cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= @@ -851,8 +852,9 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= @@ -988,6 +990,7 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1006,6 +1009,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -1034,6 +1038,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1059,6 +1064,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1079,6 +1085,7 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1093,6 +1100,7 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1214,8 +1222,10 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= -golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1246,6 +1256,7 @@ golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1346,6 +1357,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1359,6 +1371,7 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1377,6 +1390,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1675,6 +1689,7 @@ google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFl google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= @@ -1688,6 +1703,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go. google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= @@ -1700,6 +1716,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920183334-c177e329c48b/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= @@ -1751,8 +1768,9 @@ google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGO google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1771,8 +1789,9 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 886d2e1adca4a4f4ad4f8d96ae6b391bade52076 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:02:37 +0000 Subject: [PATCH 076/126] build(deps): bump the examples-load-reporting group in /examples/load-reporting-service with 2 updates (#31600) build(deps): bump the examples-load-reporting group Bumps the examples-load-reporting group in /examples/load-reporting-service with 2 updates: [github.com/envoyproxy/go-control-plane](https://github.com/envoyproxy/go-control-plane) and [google.golang.org/grpc](https://github.com/grpc/grpc-go). Updates `github.com/envoyproxy/go-control-plane` from 0.11.1 to 0.12.0 - [Release notes](https://github.com/envoyproxy/go-control-plane/releases) - [Changelog](https://github.com/envoyproxy/go-control-plane/blob/main/CHANGELOG.md) - [Commits](https://github.com/envoyproxy/go-control-plane/compare/v0.11.1...v0.12.0) Updates `google.golang.org/grpc` from 1.60.0 to 1.60.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.60.0...v1.60.1) --- updated-dependencies: - dependency-name: github.com/envoyproxy/go-control-plane dependency-type: direct:production update-type: version-update:semver-minor dependency-group: examples-load-reporting - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: examples-load-reporting ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/load-reporting-service/go.mod | 4 ++-- examples/load-reporting-service/go.sum | 29 +++++++++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/examples/load-reporting-service/go.mod b/examples/load-reporting-service/go.mod index 58434155070d..505cd31104e2 100644 --- a/examples/load-reporting-service/go.mod +++ b/examples/load-reporting-service/go.mod @@ -3,7 +3,7 @@ module github.com/envoyproxy/envoy/examples/load-reporting-service go 1.13 require ( - github.com/envoyproxy/go-control-plane v0.11.1 + github.com/envoyproxy/go-control-plane v0.12.0 github.com/golang/protobuf v1.5.3 - google.golang.org/grpc v1.60.0 + google.golang.org/grpc v1.60.1 ) diff --git a/examples/load-reporting-service/go.sum b/examples/load-reporting-service/go.sum index 711c4fc979f3..25019aec0e7c 100644 --- a/examples/load-reporting-service/go.sum +++ b/examples/load-reporting-service/go.sum @@ -219,6 +219,7 @@ cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/ cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= @@ -851,8 +852,9 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= @@ -988,6 +990,7 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1006,6 +1009,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -1034,6 +1038,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -1059,6 +1064,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1079,6 +1085,7 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1093,6 +1100,7 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1214,8 +1222,10 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= -golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1246,6 +1256,7 @@ golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1346,6 +1357,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1359,6 +1371,7 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1377,6 +1390,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1675,6 +1689,7 @@ google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFl google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= +google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= @@ -1688,6 +1703,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go. google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= @@ -1700,6 +1716,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= google.golang.org/genproto/googleapis/rpc v0.0.0-20230920183334-c177e329c48b/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= @@ -1751,8 +1768,9 @@ google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGO google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1771,8 +1789,9 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From e99c196b7d41286cad742ce476787af42f4b5f95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:03:40 +0000 Subject: [PATCH 077/126] build(deps): bump setuptools from 69.0.2 to 69.0.3 in /tools/base (#31518) Bumps [setuptools](https://github.com/pypa/setuptools) from 69.0.2 to 69.0.3. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/setuptools/compare/v69.0.2...v69.0.3) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index cfeb32a97fb4..ac2f3a76287d 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -1607,7 +1607,7 @@ zstandard==0.21.0 \ # via envoy-base-utils # The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.2 \ - --hash=sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2 \ - --hash=sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6 +setuptools==69.0.3 \ + --hash=sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05 \ + --hash=sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78 # via -r requirements.in From cc61360e28071ab60de3481cbc223098360a477f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:04:00 +0000 Subject: [PATCH 078/126] build(deps): bump the examples-kafka group in /examples/kafka with 2 updates (#31574) build(deps): bump the examples-kafka group Bumps the examples-kafka group in /examples/kafka with 2 updates: confluentinc/cp-kafka and confluentinc/cp-zookeeper. Updates `confluentinc/cp-kafka` from `269468d` to `51145a4` Updates `confluentinc/cp-zookeeper` from `9afea74` to `000f1d1` --- updated-dependencies: - dependency-name: confluentinc/cp-kafka dependency-type: direct:production dependency-group: examples-kafka - dependency-name: confluentinc/cp-zookeeper dependency-type: direct:production dependency-group: examples-kafka ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/kafka/Dockerfile-kafka | 2 +- examples/kafka/Dockerfile-zookeeper | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/kafka/Dockerfile-kafka b/examples/kafka/Dockerfile-kafka index ed9c656f045d..444c2f8ec974 100644 --- a/examples/kafka/Dockerfile-kafka +++ b/examples/kafka/Dockerfile-kafka @@ -1 +1 @@ -FROM confluentinc/cp-kafka:latest@sha256:269468d4203d0af75863720ee5fd5c0646292074cf2fde93245b560a41e33d44 +FROM confluentinc/cp-kafka:latest@sha256:51145a40d23336a11085ca695d02bdeee66fe01b582837c6d223384952226be9 diff --git a/examples/kafka/Dockerfile-zookeeper b/examples/kafka/Dockerfile-zookeeper index 0267ff74efa5..a8e9ee756ae2 100644 --- a/examples/kafka/Dockerfile-zookeeper +++ b/examples/kafka/Dockerfile-zookeeper @@ -1 +1 @@ -FROM confluentinc/cp-zookeeper:latest@sha256:9afea745c406a7c572b1b12de6656f73ec14d53060e7a9e223b1ad161f42bd52 +FROM confluentinc/cp-zookeeper:latest@sha256:000f1d11090f49fa8f67567e633bab4fea5dbd7d9119e7ee2ef259c509063593 From 365f1a492707e884240dc95e6d1b4358435495c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:05:47 +0000 Subject: [PATCH 079/126] build(deps): bump node from 21.4-bookworm-slim to 21.5-bookworm-slim in /examples/shared/node (#31477) build(deps): bump node in /examples/shared/node Bumps node from 21.4-bookworm-slim to 21.5-bookworm-slim. --- updated-dependencies: - dependency-name: node dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/node/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/node/Dockerfile b/examples/shared/node/Dockerfile index 6981d22f3072..2e2bebca866b 100644 --- a/examples/shared/node/Dockerfile +++ b/examples/shared/node/Dockerfile @@ -1,4 +1,4 @@ -FROM node:21.4-bookworm-slim@sha256:3a3b69c7013ac1233d4570f14108572e3f6dac3e2cefa8ef63be2885f702d033 as node-base +FROM node:21.5-bookworm-slim@sha256:c88704924204ee6d4e9da02275a8fd27355502f7177e4175cd0d3a4375a9c9c8 as node-base FROM node-base as node-http-auth From de79cd831c34394082ce078c3bbc81f803416a53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:05:55 +0000 Subject: [PATCH 080/126] build(deps): bump debian from `2bc5c23` to `f80c454` in /examples/shared/golang (#31442) build(deps): bump debian in /examples/shared/golang Bumps debian from `2bc5c23` to `f80c454`. --- updated-dependencies: - dependency-name: debian dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/golang/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/golang/Dockerfile b/examples/shared/golang/Dockerfile index 9af123412189..29a66a0aef95 100644 --- a/examples/shared/golang/Dockerfile +++ b/examples/shared/golang/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 as os-base +FROM debian:bookworm-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 as os-base RUN rm -f /etc/apt/apt.conf.d/docker-clean \ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' | tee /etc/apt/apt.conf.d/keep-cache From 0f2bea33c65c1fe2aa5b8d9cc39f3a828da5300b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:06:03 +0000 Subject: [PATCH 081/126] build(deps): bump debian from `2bc5c23` to `f80c454` in /examples/shared/websocket (#31441) build(deps): bump debian in /examples/shared/websocket Bumps debian from `2bc5c23` to `f80c454`. --- updated-dependencies: - dependency-name: debian dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/websocket/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/websocket/Dockerfile b/examples/shared/websocket/Dockerfile index 8b934519a2ae..86511d061002 100644 --- a/examples/shared/websocket/Dockerfile +++ b/examples/shared/websocket/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 as websocket-base +FROM debian:bookworm-slim@sha256:f80c45482c8d147da87613cb6878a7238b8642bcc24fc11bad78c7bec726f340 as websocket-base ENV DEBIAN_FRONTEND=noninteractive RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ From e587b90bd29aa7f3f65e1a9d4d740a7325dd3efa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:11:26 +0000 Subject: [PATCH 082/126] build(deps): bump google.golang.org/protobuf from 1.31.0 to 1.32.0 (#31519) Bumps google.golang.org/protobuf from 1.31.0 to 1.32.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 0ed13eb7e160..f9c5998977de 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/envoyproxy/envoy go 1.20 -require google.golang.org/protobuf v1.31.0 +require google.golang.org/protobuf v1.32.0 diff --git a/go.sum b/go.sum index 9ea5597b8346..b010a4f69c81 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,4 @@ -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= From b146134e42c86160e4ad480ec5c33453b618944a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:11:41 +0000 Subject: [PATCH 083/126] build(deps): bump google.golang.org/protobuf from 1.31.0 to 1.32.0 in /contrib/golang/filters/http/test/test_data/property (#31513) build(deps): bump google.golang.org/protobuf Bumps google.golang.org/protobuf from 1.31.0 to 1.32.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- contrib/golang/filters/http/test/test_data/property/go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/golang/filters/http/test/test_data/property/go.mod b/contrib/golang/filters/http/test/test_data/property/go.mod index 0deafbaba8fe..55ee2207f6dc 100644 --- a/contrib/golang/filters/http/test/test_data/property/go.mod +++ b/contrib/golang/filters/http/test/test_data/property/go.mod @@ -3,8 +3,8 @@ module example.com/property go 1.20 require ( - github.com/envoyproxy/envoy v1.24.0 - google.golang.org/protobuf v1.31.0 + github.com/envoyproxy/envoy v1.24.0 + google.golang.org/protobuf v1.32.0 ) replace github.com/envoyproxy/envoy => ../../../../../../../ From 70856394ad9ca8dc3c603e80fd3b1c87478e2b3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:16:15 +0000 Subject: [PATCH 084/126] build(deps): bump frozendict from 2.3.10 to 2.4.0 in /tools/base (#31562) Bumps [frozendict](https://github.com/Marco-Sulla/python-frozendict) from 2.3.10 to 2.4.0. - [Release notes](https://github.com/Marco-Sulla/python-frozendict/releases) - [Commits](https://github.com/Marco-Sulla/python-frozendict/compare/v2.3.10...v2.4.0) --- updated-dependencies: - dependency-name: frozendict dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 75 ++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index ac2f3a76287d..7c5ac4a5334c 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -542,44 +542,43 @@ flake8==6.1.0 \ # -r requirements.in # envoy-code-check # pep8-naming -frozendict==2.3.10 \ - --hash=sha256:07208e4718cb70aa259ac886c19b96a4aad1cf00e9199f211746f738951bbf7c \ - --hash=sha256:0856af4f5b4288b2270e0b74078fad5cbaf4f799326b82183865f6f367008b2c \ - --hash=sha256:08a5829d708657c9d5ad58f4a7e4baa73a3d57290f9613bdd909d481fc203a3a \ - --hash=sha256:0cdd496933ddb428f3854bea9ffdce0245bb27c27909f663ad396409fb4dffb5 \ - --hash=sha256:12b40526219f9583b30690011288bca4d6cce8724cda96b3c3ab08b67c5a7f09 \ - --hash=sha256:1c015852dacf144dbeadf203673d8c714f788fcc2b810a36504994b3c4f5a436 \ - --hash=sha256:66cded65f144393b4226bda9fe9ac2f42451d2d603e8a486015744bb566a7008 \ - --hash=sha256:6b552fffeba8e41b43ce10cc0fc467e048a7c9a71ae3241057510342132555b9 \ - --hash=sha256:6d40d0644f19365fc6cc428db31c0f113fa550bd15920262f9d77ccf6556d87b \ - --hash=sha256:6f8681c0ffe92be9aba40c9b9960c48f0ae7f6ea585af2b93fc9542cc3865969 \ - --hash=sha256:7901828700f36fe12486705afe7afc5583434390c8f69b5419de1b6c566fb00d \ - --hash=sha256:7b4d05e231dc1a2ec874f847fd7348cbee469555468efb875a89994ecde31a81 \ - --hash=sha256:809bb9c6c657bded925710a309bb2a2350bdbfdc9371df427f1a93cb8ab7ec3e \ - --hash=sha256:89218738e2122b50bf8a0444083dbe2de280402e9c2ef0929c0db0f93ff11271 \ - --hash=sha256:893205dc5a4e5c4b24e5822ceb21ef14fed8ca4afae7ac688e2fc24294c85225 \ - --hash=sha256:8c4ca4cc42bc30b20476616411d4b49aae6084760b99251f1cbdfed879ae53ea \ - --hash=sha256:8e7abf4539b73c8e5680dd2fdbd19ca4fc3e2b2f3666f80f022217839bb859fd \ - --hash=sha256:901e774629fc63f84d24b5e46b59de1eed22392ee98b7f92e694a127d541edac \ - --hash=sha256:93634af5a6d71762aebc7d78bdce92890b7e612588faf887c9eaf752dc7ccdb1 \ - --hash=sha256:99b2f47b292cc4d68f6679918e8e9e6dc5e816924d8369d07018be56b93fb20f \ - --hash=sha256:9df392b655fadaa0174c1923e6205b30ad1ccca248e8e146e63a8147a355ee01 \ - --hash=sha256:a0065db2bc76628853dd620bd08c1ca44ad0b711e92e89b4156493153add6f9d \ - --hash=sha256:aa11add43a71fd47523fbd011be5cc011df79e25ec0b0339fc0d728623aaa7ec \ - --hash=sha256:aadc83510ce82751a0bb3575231f778bc37cbb373f5f05a52b888e26cbb92f79 \ - --hash=sha256:ac41c671ff33cbefc0f06c4b2a630d18ab59f5256f45f57d5632252ae4a8c07a \ - --hash=sha256:af267bd6d98cbc10580105dc76f28f7156856fa48a5bbcadd40edb85f93657ae \ - --hash=sha256:b089c7e8c95d8b043e82e7da26e165f4220d7310efaad5e94445db7e3bc8321e \ - --hash=sha256:b10df7f5d8637b1af319434f99dc25ca6f5537e28b293e4c405ebfb4bf9581fa \ - --hash=sha256:bb9f15a5ed924be2b1cb3654b7ea3b7bae265ff39e2b5784d42bd4a6e1353e45 \ - --hash=sha256:c112024df64b8926a315d7e36b860967fcad8aae0c592b9f117589391373e893 \ - --hash=sha256:c865962216f7cfd6dac8693f4de431a9d98a7225185ff23613ecd10c42423adc \ - --hash=sha256:c9aa28ce48d848ee520409533fd0254de4caf025c5cf1b9f27c98c1dd8cf90aa \ - --hash=sha256:da22a3e873f365f97445c49afc1e6d5198ed6d172f3efaf0e9fde0edcca3cea1 \ - --hash=sha256:df2d2afa5af41bfa09dc9d5a8e6d73ae39b677a8572200c65a5ea353387ffccd \ - --hash=sha256:e78c5ac5d71f3b73f07ff9d9e3cc32dfbf7954f2c57c2d0e1fe8f1600e980b40 \ - --hash=sha256:e8bec6d11f7254e405290cb1b081caffa0c18b6aa779130da9a546349c56be83 \ - --hash=sha256:ff7a9cca3a3a1e584349e859d028388bd96a5475f76721471b73797472c6db17 +frozendict==2.4.0 \ + --hash=sha256:05c5a77957ecba4286c7ab33861a8f4f2badc7ea86fc82b834fb360d3aa4c108 \ + --hash=sha256:0615ed71570eec3cc96df063930ea6e563211efeeac86e3f3cc8bdfc9c9bfab7 \ + --hash=sha256:08d9c7c1aa92b94538b3a79c43999f999012e174588435f197794d5e5a80e0f5 \ + --hash=sha256:09ba8ee37d260adde311b8eb4cd12bf27f64071242f736757ae6a11d331eb860 \ + --hash=sha256:0b75e5e231621dedaef88334997e79fbd137dd89895543d3862fe0220fc3572c \ + --hash=sha256:1875e7b70a5724bf964354da8fd542240d2cead0d80053ac96bf4494ce3517fa \ + --hash=sha256:204f2c5c10fc018d1ba8ccc67758aa83fe769c782547bd26dc250317a7ccba71 \ + --hash=sha256:23a52bbea30c9e35b89291273944393770fb031e522a172e3aff19b62cc50047 \ + --hash=sha256:2607e82efdd2c277224a58bda3994d4cd48e49eff7fa31e404cf3066e8dbfeae \ + --hash=sha256:2804ea4bd2179bb33b99483cc8d69246630cc00632b9affe2914e8666f1cc7e5 \ + --hash=sha256:2fd4583194baabe100c135883017da76259a315d34e303eddf198541b7e02e44 \ + --hash=sha256:3909df909516cfd7bcefd9a3003948970a12a50c5648d8bbddafcef171f2117f \ + --hash=sha256:42a9b33ccf9d417b22146e59803c53d5c39d7d9151d2df8df59c235f6a1a5ed7 \ + --hash=sha256:475c65202a6f5421df8cacb8a2f29c5087134a0542b0540ae95fbf4db7af2ff9 \ + --hash=sha256:4925c8e82d2bd23d45996cd0827668a52b9c51103897c98ce409a763d0c00c61 \ + --hash=sha256:5bb5b62d4e2bce12e91800496d94de41bec8f16e4d8a7b16e8f263676ae2031a \ + --hash=sha256:809f1cffb602cf06e5186c69c0e3b74bec7a3684593145331f9aa2a65b5ba3b7 \ + --hash=sha256:8fab616e7c0fea2ac928f107c740bd9ba516fc083adfcd1c391d6bfc9164403d \ + --hash=sha256:9e530658134e88607ff8c2c8934a07b2bb5e9fffab5045f127746f6542c6c77e \ + --hash=sha256:9fc4cba1ced988ce9020dfcaae6fe3f5521eebc00c5772b511aaf691b0be91e6 \ + --hash=sha256:a1d232f092dc686e6ef23d436bde30f82c018f31cef1b89b31caef03814b1617 \ + --hash=sha256:a3f51bfa64e0c4a6608e3f2878bab1211a6b3b197de6fa57151bbe73f1184457 \ + --hash=sha256:a60f353496637ca21396289a7d969af1eb4ec4d11a7c37a0e7f25fc1761a0c97 \ + --hash=sha256:aa86325da6a6071284b4ed3d9d2cd9db068560aebad503b658d6a889a0575683 \ + --hash=sha256:b017cba5f73869b04c2977139ad08e57a7480de1e384c34193939698119baa1d \ + --hash=sha256:b666f9c6c8a9e794d2713a944b10a65480ff459579d75b5f686c75031c2c2dfc \ + --hash=sha256:bd4700c3f0aebdc8f4375c35590135794b1dbf2aca132f4756b584fa9910af2d \ + --hash=sha256:c26758198e403337933a92b01f417a8240c954f553e1d4b5e0f8e39d9c8e3f0a \ + --hash=sha256:c8af8a6a39e0050d3f3193cda56c42b43534a9b3995c44241bb9527e3c3fd451 \ + --hash=sha256:cc754117a7d60ba8e55b3c39abd67f37fbc05dd63cdcb03d1717a382fe0a3421 \ + --hash=sha256:d8d1d269874c94b1ed2b6667e5e43dcf4541838019b1caa4c48f848ac73634df \ + --hash=sha256:da4406d95c340e0b1cc43a3858fac729f52689325bcf61a9182eb94aff7451dc \ + --hash=sha256:df3819a5d48ab3aae1548e62093d0111ad7c3b62ff9392421b7bbf149c08b629 \ + --hash=sha256:efca7281184b54f7abab6980cf25837b709f72ced62791f62dabcd7b184d958a \ + --hash=sha256:f91acaff475d0ef0d3436b805c9b91fc627a6a8a281771a24f7ab7f458a0b34f \ + --hash=sha256:f9d81fb396ea81fcba3b3dde4a4b51adcb74ff31632014fbfd030f8acd5a7292 # via # -r requirements.in # aio-run-runner From 3bf19407552a4532f784c191b2a5482e54aaab68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:19:24 +0000 Subject: [PATCH 085/126] build(deps): bump mysql from `ceb9891` to `b359741` in /examples/mysql (#31461) Bumps mysql from `ceb9891` to `b359741`. --- updated-dependencies: - dependency-name: mysql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/mysql/Dockerfile-mysql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/mysql/Dockerfile-mysql b/examples/mysql/Dockerfile-mysql index ab835ddc7df2..5d0714294e84 100644 --- a/examples/mysql/Dockerfile-mysql +++ b/examples/mysql/Dockerfile-mysql @@ -1 +1 @@ -FROM mysql:8.2.0@sha256:ceb98918916bd5261b3e9866ac8271d75d276b8a4db56f1dc190770342a77a9b +FROM mysql:8.2.0@sha256:b359741e9fb794c4b6e39ea5d14047609c8ed1efcb03ababe61a239b48a165a9 From 897363a358c202996d9fbef85d27f01e75c111c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:19:33 +0000 Subject: [PATCH 086/126] build(deps): bump postgres from `1f703fa` to `ff37e66` in /examples/shared/postgres (#31418) build(deps): bump postgres in /examples/shared/postgres Bumps postgres from `1f703fa` to `ff37e66`. --- updated-dependencies: - dependency-name: postgres dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/shared/postgres/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/shared/postgres/Dockerfile b/examples/shared/postgres/Dockerfile index 0dfd66a86702..37152b74cf8b 100644 --- a/examples/shared/postgres/Dockerfile +++ b/examples/shared/postgres/Dockerfile @@ -1,3 +1,3 @@ -FROM postgres:latest@sha256:1f703fadc8993f74b82a2706712e61208b1f2bc1658f286c5b68970bbf09f0ae +FROM postgres:latest@sha256:ff37e66b0a03594086c3734d73e750f13480ca9bf64b53fafea18be4d5afb9ad COPY docker-healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["docker-healthcheck.sh"] From f2a03a49611591fdb93f427755ab161f4218a743 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 08:20:13 +0000 Subject: [PATCH 087/126] build(deps): bump redis from `396b0f0` to `a7cee7c` in /examples/redis (#31494) Bumps redis from `396b0f0` to `a7cee7c`. --- updated-dependencies: - dependency-name: redis dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/redis/Dockerfile-redis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/redis/Dockerfile-redis b/examples/redis/Dockerfile-redis index dedce55e0b60..0d6ddffdacf5 100644 --- a/examples/redis/Dockerfile-redis +++ b/examples/redis/Dockerfile-redis @@ -1 +1 @@ -FROM redis@sha256:396b0f027ba2f33bf385771a621b58c1fd834fd2c522c35c98fd24fc17863c2f +FROM redis@sha256:a7cee7c8178ff9b5297cb109e6240f5072cdaaafd775ce6b586c3c704b06458e From 05faaab8c16cf7458312347f7d08201f37762cf0 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 08:31:44 +0000 Subject: [PATCH 088/126] examples: Add shared node/yarn recipe/s (#31591) examples: Add shared node recipe Signed-off-by: Ryan Northey --- examples/shared/node/Dockerfile | 24 ++++++++++ examples/shared/node/routes.jq | 49 ++++++++++++++++++++ examples/shared/node/scripts/build-routed.sh | 11 +++++ examples/shared/node/scripts/build.sh | 4 ++ examples/shared/node/scripts/dev.sh | 4 ++ examples/shared/node/scripts/entrypoint.sh | 20 ++++++++ 6 files changed, 112 insertions(+) create mode 100644 examples/shared/node/routes.jq create mode 100755 examples/shared/node/scripts/build-routed.sh create mode 100644 examples/shared/node/scripts/build.sh create mode 100755 examples/shared/node/scripts/dev.sh create mode 100755 examples/shared/node/scripts/entrypoint.sh diff --git a/examples/shared/node/Dockerfile b/examples/shared/node/Dockerfile index 2e2bebca866b..d8d6e371dab7 100644 --- a/examples/shared/node/Dockerfile +++ b/examples/shared/node/Dockerfile @@ -9,3 +9,27 @@ ENV NODE_APP_PATH "/app/${NODE_APP_NAME}" COPY "$NODE_APP" /app # Dont use exec form to interpolate correctly CMD node $NODE_APP_PATH + + +FROM node-base as yarn +ARG SERVICE_PORT=3000 +ENV DEBIAN_FRONTEND=noninteractive \ + SERVICE_PORT=$SERVICE_PORT +COPY --chmod=755 ./scripts/entrypoint.sh /entrypoint.sh +COPY --chmod=755 ./scripts/build.sh /usr/local/bin/build.sh +COPY --chmod=755 ./scripts/dev.sh /usr/local/bin/dev.sh +COPY ./routes.jq /usr/local/share/routes.jq +RUN apt-get update \ + && apt-get -qq install -y --no-install-recommends gosu jq netcat-traditional yq +ENTRYPOINT ["/entrypoint.sh"] +CMD ["dev.sh"] +HEALTHCHECK \ + --interval=2s \ + --timeout=1s \ + --start-period=1s \ + --retries=30 \ + CMD nc -zv localhost "$SERVICE_PORT" + + +FROM yarn as yarn-routed +COPY --chmod=755 ./scripts/build-routed.sh /usr/local/bin/build.sh diff --git a/examples/shared/node/routes.jq b/examples/shared/node/routes.jq new file mode 100644 index 000000000000..f5a61d71c558 --- /dev/null +++ b/examples/shared/node/routes.jq @@ -0,0 +1,49 @@ +# Generate direct_response routes for a passed in file list +# Expects an xDS config to be passed as the `base` argument to +# inject the routes into. + +def getMimeType: + {".js": "text/javascript", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".png": "image/png", + ".gif": "image/gif", + ".svg": "image/svg+xml", + ".ico": "image/x-icon", + ".css": "text/css", + ".html": "text/html", + ".txt": "text/plain", + ".xml": "application/xml", + ".json": "application/json", + ".pdf": "application/pdf", + ".zip": "application/zip", + ".tar": "application/x-tar", + ".gz": "application/gzip" + }[match("\\.[^.]*$").string // "application/octet-stream"] +; + +def pathToDirectResponse: + . as $path + | sub("^dist/"; "/") as $asset + | $asset + | sub("^/index.html$"; "/") as $path + | if $path == "/" then + {prefix: $path} + else {$path} end + | {match: ., + direct_response: { + status: 200, + body: {filename: "/var/www/html\($asset)"} + }, + response_headers_to_add: [ + {header: { + key: "Content-Type", + value: ($asset | getMimeType)}}]} +; + +split("\n") as $assets +| ($base | fromjson) as $base +| $assets +| map(select(. != "") | pathToDirectResponse) as $routes +| $base +| .resources[0].filter_chains[0].filters[0].typed_config.route_config.virtual_hosts[0].routes = $routes diff --git a/examples/shared/node/scripts/build-routed.sh b/examples/shared/node/scripts/build-routed.sh new file mode 100755 index 000000000000..254f4dcb84b5 --- /dev/null +++ b/examples/shared/node/scripts/build-routed.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +yarn +yarn build + +BASE=$(yq -c < ../xds/lds.tmpl.yml) +ASSETS=$(find dist -type f) +echo "$ASSETS" \ + | jq --arg base "$BASE" -Rs -f /usr/local/share/routes.jq \ + > ../xds/lds.update.yml +mv -f ../xds/lds.update.yml ../xds/lds.yml diff --git a/examples/shared/node/scripts/build.sh b/examples/shared/node/scripts/build.sh new file mode 100644 index 000000000000..4c3c1994bb0b --- /dev/null +++ b/examples/shared/node/scripts/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +yarn +yarn build diff --git a/examples/shared/node/scripts/dev.sh b/examples/shared/node/scripts/dev.sh new file mode 100755 index 000000000000..fdf461a027f5 --- /dev/null +++ b/examples/shared/node/scripts/dev.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +yarn +yarn dev --host 0.0.0.0 --port 3000 diff --git a/examples/shared/node/scripts/entrypoint.sh b/examples/shared/node/scripts/entrypoint.sh new file mode 100755 index 000000000000..bea8c478a328 --- /dev/null +++ b/examples/shared/node/scripts/entrypoint.sh @@ -0,0 +1,20 @@ +#!/bin/bash -e + +# Add local user +# Either use the LOCAL_USER_ID if passed in at runtime or +# fallback + +DEFAULT_USER_NAME=node + +USER_UID=${LOCAL_UID:-1000} +USER_NAME=${LOCAL_USER_NAME:-worker} +USER_HOME=${LOCAL_USER_HOME:-"/home/${USER_NAME}"} + +echo "Starting (${*}) with user: $USER_UID $USER_NAME $USER_HOME" +usermod -l "$USER_NAME" -md "$USER_HOME" "$DEFAULT_USER_NAME" || : +chown "$USER_NAME" "$USER_HOME" +export HOME="${USER_HOME}" +export PATH=$PATH:"${HOME}/.yarn/bin/" +mkdir -p ./dist +chown -R "$USER_NAME" ./dist +exec /usr/sbin/gosu "${USER_NAME}" "$@" From 75dc5625f2c3c43e19aef0979da3b4542962e98a Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 08:35:17 +0000 Subject: [PATCH 089/126] docs/examples: Assorted cleanups (#31588) Signed-off-by: Ryan Northey --- .github/workflows/_stage_verify.yml | 2 +- .github/workflows/verify-requirements.in | 1 + .github/workflows/verify-requirements.txt | 74 +++++++++++++++++++++++ docs/root/_static/css/envoy.css | 5 ++ docs/root/start/sandboxes/setup.rst | 18 ++++++ examples/shared/python/Dockerfile | 6 +- examples/skywalking/verify.sh | 4 +- 7 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/verify-requirements.in create mode 100644 .github/workflows/verify-requirements.txt diff --git a/.github/workflows/_stage_verify.yml b/.github/workflows/_stage_verify.yml index bbac64e90c7c..31b12d98666b 100644 --- a/.github/workflows/_stage_verify.yml +++ b/.github/workflows/_stage_verify.yml @@ -85,5 +85,5 @@ jobs: export DEBIAN_FRONTEND=noninteractive sudo apt-get -qq update -y sudo apt-get -qq install -y --no-install-recommends expect gettext whois - sudo snap install yq + pip install -r ./.github/workflows/verify-requirements.txt shell: bash diff --git a/.github/workflows/verify-requirements.in b/.github/workflows/verify-requirements.in new file mode 100644 index 000000000000..87de2e955af3 --- /dev/null +++ b/.github/workflows/verify-requirements.in @@ -0,0 +1 @@ +yq diff --git a/.github/workflows/verify-requirements.txt b/.github/workflows/verify-requirements.txt new file mode 100644 index 000000000000..2c6e79d55e41 --- /dev/null +++ b/.github/workflows/verify-requirements.txt @@ -0,0 +1,74 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --allow-unsafe --generate-hashes verify-requirements.in +# +argcomplete==3.2.1 \ + --hash=sha256:30891d87f3c1abe091f2142613c9d33cac84a5e15404489f033b20399b691fec \ + --hash=sha256:437f67fb9b058da5a090df505ef9be0297c4883993f3f56cb186ff087778cfb4 + # via yq +pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f + # via yq +tomlkit==0.12.3 \ + --hash=sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4 \ + --hash=sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba + # via yq +xmltodict==0.13.0 \ + --hash=sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56 \ + --hash=sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852 + # via yq +yq==3.2.3 \ + --hash=sha256:29c8fe1d36b4f64163f4d01314c6ae217539870f610216dee6025dfb5eafafb1 \ + --hash=sha256:b50c91894dad9894d1d36ea77d5722d5495cac9482d2351e55089360a90709ae + # via -r verify-requirements.in diff --git a/docs/root/_static/css/envoy.css b/docs/root/_static/css/envoy.css index c02a65b16df9..ae805c099312 100644 --- a/docs/root/_static/css/envoy.css +++ b/docs/root/_static/css/envoy.css @@ -46,6 +46,11 @@ table.docutils div.line-block { border: solid #eee 1px; } +/* restore margin bottom on aligned images */ +.rst-content img.align-center { + margin-bottom: 24px +} + /* suppress errs on pseudo-json code highlights */ .highlight-json .highlight .err { border: inherit; diff --git a/docs/root/start/sandboxes/setup.rst b/docs/root/start/sandboxes/setup.rst index 57c34201a09f..19de3de6b066 100644 --- a/docs/root/start/sandboxes/setup.rst +++ b/docs/root/start/sandboxes/setup.rst @@ -107,6 +107,15 @@ Many of the examples use the `curl `_ utility to make ``HTTP`` Instructions for installing `curl `_ on many platforms and operating systems can be `found on the curl website `_. +.. _start_sandboxes_setup_envsubst: + +envsubst +~~~~~~~~ + +Some of the examples require the ``envsubst`` command to interpolate environment variables in templates. + +The command is a part of the GNU ‘gettext’ package, and is available through most package managers. + .. _start_sandboxes_setup_jq: jq @@ -118,6 +127,15 @@ whether it be ``HTTP`` response data, logs or statistics. Instructions for installing `jq `_ on many platforms and operating systems can be `found on the jq website `_. +.. _start_sandboxes_setup_mkpasswd: + +mkpasswd +~~~~~~~~ + +Some of the examples require the ``mkpasswd`` command to generate ~random tokens. + +The command is a part of the ‘whois’ package, and is available through most package managers. + .. _start_sandboxes_setup_netcat: netcat diff --git a/examples/shared/python/Dockerfile b/examples/shared/python/Dockerfile index 09c4b5708cc3..9f8b48a0aeaf 100644 --- a/examples/shared/python/Dockerfile +++ b/examples/shared/python/Dockerfile @@ -15,7 +15,9 @@ CMD tail -f /dev/null FROM python-base as aiohttp-service -ENV DEBIAN_FRONTEND=noninteractive +ARG SERVICE_PORT=8080 +ENV DEBIAN_FRONTEND=noninteractive \ + SERVICE_PORT=$SERVICE_PORT ADD "$PYTHON_REQUIREMENTS_FILE" /tmp/requirements.txt RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ @@ -28,7 +30,7 @@ HEALTHCHECK \ --timeout=1s \ --start-period=1s \ --retries=3 \ - CMD nc -zv localhost 8080 + CMD nc -zv localhost "$SERVICE_PORT" ENTRYPOINT ["python3", "/code/service.py"] diff --git a/examples/skywalking/verify.sh b/examples/skywalking/verify.sh index 9eca5f37e7ae..b115b7ca2d82 100755 --- a/examples/skywalking/verify.sh +++ b/examples/skywalking/verify.sh @@ -1,8 +1,8 @@ #!/bin/bash -e export NAME=skywalking -export PORT_PROXY="${SKYWALKING_PORT_PROXY:-12600}" -export PORT_UI="${SKYWALKING_PORT_UI:-12601}" +export PORT_PROXY="${SKYWALKING_PORT_PROXY:-11910}" +export PORT_UI="${SKYWALKING_PORT_UI:-11911}" # NB: This allows ES to run in a low-resource environment, # dont do this in a production environment. From 06848470cbc6db4a9801c3c229bc0b6ba81b2840 Mon Sep 17 00:00:00 2001 From: Xie Zhihao Date: Wed, 3 Jan 2024 16:43:31 +0800 Subject: [PATCH 090/126] deps: bump Boost to 1.84.0 (#31566) Signed-off-by: Xie Zhihao --- bazel/repository_locations.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 1a49998ab707..00c8b9678dc3 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -700,16 +700,16 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Boost", project_desc = "Boost C++ source libraries", project_url = "https://www.boost.org/", - version = "1.78.0", - sha256 = "94ced8b72956591c4775ae2207a9763d3600b30d9d7446562c552f0a14a63be7", + version = "1.84.0", + sha256 = "a5800f405508f5df8114558ca9855d2640a2de8f0445f051fa1c7c3383045724", strip_prefix = "boost_{underscore_version}", - urls = ["https://boostorg.jfrog.io/artifactory/main/release/{version}/source/boost_{underscore_version}.tar.gz"], + urls = ["https://archives.boost.io/release/{version}/source/boost_{underscore_version}.tar.gz"], use_category = ["dataplane_ext"], extensions = [ "envoy.matching.input_matchers.hyperscan", "envoy.regex_engines.hyperscan", ], - release_date = "2021-12-08", + release_date = "2023-12-13", cpe = "cpe:2.3:a:boost:boost:*", license = "Boost", license_url = "https://github.com/boostorg/boost/blob/boost-{version}/LICENSE_1_0.txt", From f812033a7c6093d8ac4dba6069271111f0bc6df8 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 10:24:01 +0000 Subject: [PATCH 091/126] ci/permissions: Restrict permissions for remaining workflows (#31603) Signed-off-by: Ryan Northey --- .github/workflows/codeql-daily.yml | 7 +++++++ .github/workflows/codeql-push.yml | 5 +++++ .github/workflows/envoy-sync.yml | 3 +++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 87aec4bd24d6..9eba30588dac 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -1,3 +1,8 @@ +name: CodeQL/daily + +permissions: + contents: read + on: schedule: - cron: '0 12 * * 4' @@ -6,11 +11,13 @@ concurrency: group: ${{ github.head_ref-github.workflow || github.run_id }} cancel-in-progress: true + jobs: CodeQL-Build: permissions: security-events: write # for github/codeql-action/analyze to upload SARIF results + pull-requests: read strategy: fail-fast: false diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index c21542a34e50..a3773944f4b2 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -1,5 +1,8 @@ name: CodeQL +permissions: + contents: read + on: push: paths: @@ -12,11 +15,13 @@ concurrency: group: ${{ github.head_ref-github.workflow || github.run_id }} cancel-in-progress: true + jobs: CodeQL-Build: permissions: security-events: write # for github/codeql-action/analyze to upload SARIF results + pull-requests: read strategy: fail-fast: false diff --git a/.github/workflows/envoy-sync.yml b/.github/workflows/envoy-sync.yml index 09fa027d64b9..d24ad17f2253 100644 --- a/.github/workflows/envoy-sync.yml +++ b/.github/workflows/envoy-sync.yml @@ -1,5 +1,8 @@ name: 'Sync downstream' +permissions: + contents: read + on: push: branches: From 4ed411184d999c3684f7277536c58f7a4058840f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 12:06:34 +0000 Subject: [PATCH 092/126] build(deps): bump dependatool from 0.2.2 to 0.2.3 in /tools/base (#31606) Bumps [dependatool](https://github.com/envoyproxy/toolshed) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/envoyproxy/toolshed/releases) - [Commits](https://github.com/envoyproxy/toolshed/compare/actions-v0.2.2...actions-v0.2.3) --- updated-dependencies: - dependency-name: dependatool dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/base/requirements.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 7c5ac4a5334c..9ec13dc5e4a6 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -36,9 +36,9 @@ aio-api-nist==0.0.4 \ --hash=sha256:1f2909d60ed4fdb3a3ffc37ad6012666f34078b71648394be91f5e67bbf8b6ca \ --hash=sha256:c948ee597b9e7cda7982e17bc4aca509b8aa68510899b42e2d382c10fb0d6f89 # via envoy-dependency-check -aio-core==0.10.0 \ - --hash=sha256:57e2d8dd8ee8779b0ebc2e2447492c0db8d7ed782e9ad1bb2662593740751acb \ - --hash=sha256:cb00d530b1e16228b36174c23d446c66e3f2a50ef91aa527c0e58a654316f635 +aio-core==0.10.1 \ + --hash=sha256:608cd1e5dbea8492bd7cc426ad0e280693c3ec2520da99e8545eff23f52fad0c \ + --hash=sha256:f442fdbb811cad093f8a89019b5ea768e38396f21393c5fe241eb63a2e2914a3 # via # aio-api-bazel # aio-api-github @@ -449,9 +449,9 @@ cryptography==41.0.7 \ # pyjwt # pyopenssl # service-identity -dependatool==0.2.2 \ - --hash=sha256:8e66850c79e37325735efa67ce06e2d5a939c0dab758f37b9bd3d09d0fb1f9a4 \ - --hash=sha256:dff28853a7252d6a5d670c2519165506902c0d4746cbbdac99d2ad63ed96d82d +dependatool==0.2.3 \ + --hash=sha256:04bf88d01302eec697a69e8301d14668a89d676dbd2a3914e91c610a531e9db7 \ + --hash=sha256:113a6641889d3dae7c81cb0a0483c31a2657f179474e11f4731b285963475ade # via -r requirements.in deprecated==1.2.14 \ --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ From 2ecaedf3912add8209e309ad33bfcd2c6c68a4ca Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 14:43:02 +0000 Subject: [PATCH 093/126] deps/lockfiles: Mark as binary (#31589) Signed-off-by: Ryan Northey --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitattributes b/.gitattributes index 2fc3cbf81701..8bd5b8b56f71 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,6 @@ /test/extensions/transport_sockets/tls/test_data/aes_128_key binary /test/extensions/transport_sockets/tls/test_data/ticket_key_* binary /test/**/*_corpus/* linguist-generated=true +requirements.txt binary +package.lock binary +yarn.lock binary From 07e7dfc7f1dc8e375e47d0e7e7552d8cda3c0b3c Mon Sep 17 00:00:00 2001 From: liulanyi <2646907366@qq.com> Date: Wed, 3 Jan 2024 22:56:21 +0800 Subject: [PATCH 094/126] fix generic proxy stat prefix (#31569) Signed-off-by: liulanyi <2646907366@qq.com> --- contrib/generic_proxy/filters/network/source/config.cc | 8 +++++--- contrib/generic_proxy/filters/network/source/proxy.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contrib/generic_proxy/filters/network/source/config.cc b/contrib/generic_proxy/filters/network/source/config.cc index d6036138abaf..71852d86a009 100644 --- a/contrib/generic_proxy/filters/network/source/config.cc +++ b/contrib/generic_proxy/filters/network/source/config.cc @@ -124,11 +124,13 @@ Factory::createFilterFactoryFromProtoTyped(const ProxyConfig& proto_config, access_logs.push_back(current_access_log); } + const std::string stat_prefix = fmt::format("generic_proxy.{}.", proto_config.stat_prefix()); + const FilterConfigSharedPtr config = std::make_shared( - proto_config.stat_prefix(), std::move(factories.first), + stat_prefix, std::move(factories.first), routeConfigProviderFromProto(proto_config, context, *route_config_provider_manager), - filtersFactoryFromProto(proto_config.filters(), proto_config.codec_config(), - proto_config.stat_prefix(), context), + filtersFactoryFromProto(proto_config.filters(), proto_config.codec_config(), stat_prefix, + context), std::move(tracer), std::move(tracing_config), std::move(access_logs), context); return [route_config_provider_manager, tracer_manager, config, &server_context, diff --git a/contrib/generic_proxy/filters/network/source/proxy.h b/contrib/generic_proxy/filters/network/source/proxy.h index 3dc1eeb77db4..6136065b7df0 100644 --- a/contrib/generic_proxy/filters/network/source/proxy.h +++ b/contrib/generic_proxy/filters/network/source/proxy.h @@ -57,7 +57,7 @@ class FilterConfigImpl : public FilterConfig { Tracing::ConnectionManagerTracingConfigPtr tracing_config, std::vector&& access_logs, Envoy::Server::Configuration::FactoryContext& context) - : stat_prefix_(fmt::format("generic_proxy.{}.", stat_prefix)), + : stat_prefix_(stat_prefix), stats_(GenericFilterStats::generateStats(stat_prefix_, context.scope())), codec_factory_(std::move(codec)), route_config_provider_(std::move(route_config_provider)), factories_(std::move(factories)), drain_decision_(context.drainDecision()), From bea96511f42aa3a4d89e02788affde352498229a Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 3 Jan 2024 10:07:03 -0500 Subject: [PATCH 095/126] grid: cleaning up potential zombie streams (#31346) Fixing an issue where "prefetched" H3 streams were not cleaned up promptly. Risk Level: low Testing: new e2e tests Docs Changes: n/a Release Notes: inline [Optional Runtime guard:] yes Signed-off-by: Alyssa Wilk --- changelogs/current.yaml | 4 + source/common/http/conn_pool_grid.cc | 2 + source/common/runtime/runtime_features.cc | 1 + .../http/alternate_protocols_cache/BUILD | 1 + .../filter_integration_test.cc | 183 ++++++++++++++++-- test/integration/fake_upstream.cc | 5 + test/integration/fake_upstream.h | 2 + 7 files changed, 179 insertions(+), 19 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 715baf916d7e..d80e1c719b21 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -84,6 +84,10 @@ minor_behavior_changes: bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* +- area: upstream + change: | + Fixed a bug with upstream auto-config with HTTP/3 where certain network configurations would result in zombie + streams left in the grid. Guarded by ``envoy.reloadable_features.avoid_zombie_streams``. - area: buffer change: | Fixed a bug (https://github.com/envoyproxy/envoy/issues/28760) that the internal listener causes an undefined diff --git a/source/common/http/conn_pool_grid.cc b/source/common/http/conn_pool_grid.cc index 4a3c09dc418a..3b031fb41fd0 100644 --- a/source/common/http/conn_pool_grid.cc +++ b/source/common/http/conn_pool_grid.cc @@ -148,6 +148,8 @@ void ConnectivityGrid::WrapperCallbacks::onConnectionAttemptReady( } if (callbacks != nullptr) { callbacks->onPoolReady(encoder, host, info, protocol); + } else if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.avoid_zombie_streams")) { + encoder.getStream().resetStream(StreamResetReason::LocalReset); } } diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 716b83ea8a16..bf2d2ec0a2b3 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -31,6 +31,7 @@ // problem of the bugs being found after the old code path has been removed. RUNTIME_GUARD(envoy_reloadable_features_allow_absolute_url_with_mixed_scheme); RUNTIME_GUARD(envoy_reloadable_features_append_xfh_idempotent); +RUNTIME_GUARD(envoy_reloadable_features_avoid_zombie_streams); RUNTIME_GUARD(envoy_reloadable_features_check_mep_on_first_eject); RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_convert_legacy_lb_config); diff --git a/test/extensions/filters/http/alternate_protocols_cache/BUILD b/test/extensions/filters/http/alternate_protocols_cache/BUILD index b6e4e01a9268..8b755a864107 100644 --- a/test/extensions/filters/http/alternate_protocols_cache/BUILD +++ b/test/extensions/filters/http/alternate_protocols_cache/BUILD @@ -33,6 +33,7 @@ envoy_extension_cc_test( "//test/config/integration/certs", ], extension_names = ["envoy.filters.http.alternate_protocols_cache"], + shard_count = 2, tags = [ "cpu:3", ], diff --git a/test/extensions/filters/http/alternate_protocols_cache/filter_integration_test.cc b/test/extensions/filters/http/alternate_protocols_cache/filter_integration_test.cc index 97291ef2a876..984133f88215 100644 --- a/test/extensions/filters/http/alternate_protocols_cache/filter_integration_test.cc +++ b/test/extensions/filters/http/alternate_protocols_cache/filter_integration_test.cc @@ -67,6 +67,18 @@ name: alternate_protocols_cache HttpProtocolIntegrationTest::initialize(); } + void writeAltSvcToFile(uint32_t index) { + uint32_t port = fake_upstreams_[index]->localAddress()->ip()->port(); + std::string key = absl::StrCat("https://sni.lyft.com:", port); + + size_t seconds = std::chrono::duration_cast( + timeSystem().monotonicTime().time_since_epoch()) + .count(); + std::string value = absl::StrCat("h3=\":", port, "\"; ma=", 86400 + seconds, "|0|0"); + TestEnvironment::writeStringToFileForTest( + "alt_svc_cache.txt", absl::StrCat(key.length(), "\n", key, value.length(), "\n", value)); + } + // This function will create 2 upstreams, but Envoy will only point at the // first, the HTTP/2 upstream. void createUpstreams() override { @@ -94,6 +106,9 @@ name: alternate_protocols_cache fake_upstreams_.emplace_back(std::make_unique( std::move(http3_factory), fake_upstreams_[0]->localAddress()->ip()->port(), version_, http3_config)); + if (write_alt_svc_to_file_) { + writeAltSvcToFile(1); + } return; } END_TRY @@ -105,6 +120,9 @@ name: alternate_protocols_cache } throw EnvoyException("Failed to find a port after 10 tries"); } + // If this is set to true, it pre-fills the alt-svc cache, setting up HTTP/3 + // support and pointing at the HTTP/3 upstream. + bool write_alt_svc_to_file_ = false; }; TEST_P(FilterIntegrationTest, AltSvc) { @@ -113,7 +131,7 @@ TEST_P(FilterIntegrationTest, AltSvc) { const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); Http::TestRequestHeaderMapImpl request_headers{ {":method", "POST"}, {":path", "/test/long/url"}, @@ -144,6 +162,145 @@ TEST_P(FilterIntegrationTest, AltSvc) { test_server_->waitForCounterEq("cluster.cluster_0.upstream_cx_http3_total", 1); } +TEST_P(FilterIntegrationTest, AltSvcCached) { + // Start with the alt-svc header in the cache. + write_alt_svc_to_file_ = true; + + const uint64_t request_size = 0; + const uint64_t response_size = 0; + const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; + + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + + Http::TestRequestHeaderMapImpl request_headers{ + {":method", "POST"}, {":path", "/test/long/url"}, + {":scheme", "http"}, {":authority", "sni.lyft.com"}, + {"x-lyft-user-id", "123"}, {"x-forwarded-for", "10.0.0.1"}}; + int port = fake_upstreams_[1]->localAddress()->ip()->port(); + std::string alt_svc = absl::StrCat("h3=\":", port, "\"; ma=86400"); + Http::TestResponseHeaderMapImpl response_headers{{":status", "200"}, {"alt-svc", alt_svc}}; + + // First request should go out over HTTP/3 (upstream index 1) because of the Alt-Svc information. + auto response2 = sendRequestAndWaitForResponse(request_headers, request_size, response_headers, + response_size, 1, timeout); + checkSimpleRequestSuccess(request_size, response_size, response2.get()); + test_server_->waitForCounterEq("cluster.cluster_0.upstream_cx_http3_total", 1); +} + +TEST_P(FilterIntegrationTest, AltSvcCachedH3Slow) { +#ifdef WIN32 + GTEST_SKIP() << "Skipping on Windows"; +#endif + // Start with the alt-svc header in the cache. + write_alt_svc_to_file_ = true; + + const uint64_t request_size = 0; + const uint64_t response_size = 0; + const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; + + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + + absl::Notification block_until_notify; + // Block the H3 upstream so it can't process packets. + fake_upstreams_[1]->runOnDispatcherThread([&] { block_until_notify.WaitForNotification(); }); + + ASSERT(codec_client_ != nullptr); + // Send the request to Envoy. + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + // The request should fail over to the HTTP/2 upstream (index 0) as the H3 upstream is wedged. + waitForNextUpstreamRequest(0); + + // Now unblock the HTTP/3 server and wait for the connection. + block_until_notify.Notify(); + FakeHttpConnectionPtr h3_connection; + waitForNextUpstreamConnection(std::vector{1}, TestUtility::DefaultTimeout, + h3_connection); + + // The created stream will reset. + FakeStreamPtr upstream_request2; + ASSERT_TRUE(h3_connection->waitForNewStream(*dispatcher_, upstream_request2)); + ASSERT_TRUE(upstream_request2->waitForReset()); + + // Send a second request. This should go out over the H3 connection. + FakeStreamPtr upstream_request3; + auto response2 = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + ASSERT_TRUE(h3_connection->waitForNewStream(*dispatcher_, upstream_request3)); + upstream_request3->encodeHeaders(default_response_headers_, true); + ASSERT_TRUE(response2->waitForEndStream(timeout)); + + // Now close the connection to make sure it doesn't cause problems for the + // downstream stream. + ASSERT_TRUE(h3_connection->close()); + test_server_->waitForCounterEq("cluster.cluster_0.upstream_cx_destroy", 1); + + // Finish the response. + upstream_request_->encodeHeaders(default_response_headers_, true); + // Wait for the response to be read by the codec client. + ASSERT_TRUE(response->waitForEndStream(timeout)); + + checkSimpleRequestSuccess(request_size, response_size, response.get()); + test_server_->waitForCounterEq("cluster.cluster_0.upstream_cx_http3_total", 1); +} + +TEST_P(FilterIntegrationTest, AltSvcCachedH2Slow) { +#ifdef WIN32 + // TODO: sort out what race only happens on windows and GCC. + GTEST_SKIP() << "Skipping on Windows"; +#endif +#ifdef GCC_COMPILER + GTEST_SKIP() << "Skipping on GCC"; +#endif + // Start with the alt-svc header in the cache. + write_alt_svc_to_file_ = true; + + const uint64_t request_size = 0; + const uint64_t response_size = 0; + const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; + + initialize(); + + absl::Notification block_http2; + absl::Notification block_http3; + absl::Notification http2_blocked; + absl::Notification http3_blocked; + // Block both upstreams. + fake_upstreams_[0]->runOnDispatcherThread([&] { + http2_blocked.Notify(); + block_http2.WaitForNotification(); + }); + fake_upstreams_[1]->runOnDispatcherThread([&] { + http3_blocked.Notify(); + block_http3.WaitForNotification(); + }); + + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + + // Make sure the upstreams are blocked. + http2_blocked.WaitForNotification(); + http3_blocked.WaitForNotification(); + + // Send the request to Envoy. + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + + // Wait for both connections to be attempted. + test_server_->waitForCounterEq("cluster.cluster_0.upstream_cx_total", 2); + + // Unblock Http3. + block_http3.Notify(); + // Make sure the HTTP3 connection is established. + waitForNextUpstreamRequest(1); + upstream_request_->encodeHeaders(default_response_headers_, true); + + // Unblock the H2 upstream. + block_http2.Notify(); + + // Make sure the response is completed. + ASSERT_TRUE(response->waitForEndStream(timeout)); + checkSimpleRequestSuccess(request_size, response_size, response.get()); +} + TEST_P(FilterIntegrationTest, AltSvcIgnoredWithProxyConfig) { config_helper_.addFilter("{ name: header-to-proxy-filter }"); const uint64_t request_size = 0; @@ -151,7 +308,7 @@ TEST_P(FilterIntegrationTest, AltSvcIgnoredWithProxyConfig) { const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); Http::TestRequestHeaderMapImpl request_headers{ {":method", "POST"}, {":path", "/test/long/url"}, @@ -192,7 +349,7 @@ TEST_P(FilterIntegrationTest, RetryAfterHttp3ZeroRttHandshakeFailed) { config_helper_.setConnectTimeout(std::chrono::seconds(2)); initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); int port = fake_upstreams_[0]->localAddress()->ip()->port(); std::string alt_svc = absl::StrCat("h3=\":", port, "\"; ma=86400"); @@ -257,7 +414,7 @@ TEST_P(FilterIntegrationTest, H3PostHandshakeFailoverToTcp) { const std::chrono::milliseconds timeout = TestUtility::DefaultTimeout; initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); Http::TestRequestHeaderMapImpl request_headers{ {":method", "POST"}, @@ -312,18 +469,6 @@ class MixedUpstreamIntegrationTest : public FilterIntegrationTest { protected: MixedUpstreamIntegrationTest() { default_request_headers_.setHost("sni.lyft.com"); } - void writeFile() { - uint32_t port = fake_upstreams_[0]->localAddress()->ip()->port(); - std::string key = absl::StrCat("https://sni.lyft.com:", port); - - size_t seconds = std::chrono::duration_cast( - timeSystem().monotonicTime().time_since_epoch()) - .count(); - std::string value = absl::StrCat("h3=\":", port, "\"; ma=", 86400 + seconds, "|0|0"); - TestEnvironment::writeStringToFileForTest( - "alt_svc_cache.txt", absl::StrCat(key.length(), "\n", key, value.length(), "\n", value)); - } - void createUpstreams() override { ASSERT_EQ(upstreamProtocol(), Http::CodecType::HTTP3); ASSERT_EQ(fake_upstreams_count_, 1); @@ -337,7 +482,7 @@ class MixedUpstreamIntegrationTest : public FilterIntegrationTest { auto config = configWithType(Http::CodecType::HTTP3); Network::DownstreamTransportSocketFactoryPtr factory = createUpstreamTlsContext(config); addFakeUpstream(std::move(factory), Http::CodecType::HTTP3, /*autonomous_upstream=*/false); - writeFile(); + writeAltSvcToFile(0); } } @@ -354,7 +499,7 @@ int getSrtt(std::string alt_svc, TimeSource& time_source) { // occur over HTTP/3. TEST_P(MixedUpstreamIntegrationTest, BasicRequestAutoWithHttp3) { initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); sendRequestAndWaitForResponse(default_request_headers_, 0, default_response_headers_, 0, 0); cleanupUpstreamAndDownstream(); std::string alt_svc; @@ -391,7 +536,7 @@ TEST_P(MixedUpstreamIntegrationTest, BasicRequestAutoWithHttp2) { // Only create an HTTP/2 upstream. use_http2_ = true; initialize(); - codec_client_ = makeHttpConnection(makeClientConnection((lookupPort("http")))); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); sendRequestAndWaitForResponse(default_request_headers_, 0, default_response_headers_, 0, 0); } diff --git a/test/integration/fake_upstream.cc b/test/integration/fake_upstream.cc index bfb987199f25..a6a107da712f 100644 --- a/test/integration/fake_upstream.cc +++ b/test/integration/fake_upstream.cc @@ -952,6 +952,11 @@ AssertionResult FakeUpstream::runOnDispatcherThreadAndWait(std::function cb) { + ASSERT(!dispatcher_->isThreadSafe()); + dispatcher_->post([&]() { cb(); }); +} + void FakeUpstream::sendUdpDatagram(const std::string& buffer, const Network::Address::InstanceConstSharedPtr& peer) { dispatcher_->post([this, buffer, peer] { diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index 0fd9bf07da94..597751fff41e 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -787,6 +787,8 @@ class FakeUpstream : Logger::Loggable, Event::DispatcherPtr& dispatcher() { return dispatcher_; } absl::Mutex& lock() { return lock_; } + void runOnDispatcherThread(std::function cb); + protected: const FakeUpstreamConfig& config() const { return config_; } From 48ced96b1c5bbea5f3c09b89d29888c07a6d8c99 Mon Sep 17 00:00:00 2001 From: Nigel Brittain <108375408+nbaws@users.noreply.github.com> Date: Thu, 4 Jan 2024 02:38:50 +1100 Subject: [PATCH 096/126] Implement sigv4a signing in aws_request_signing extension (#31336) Signed-off-by: Nigel Brittain --- .../v3/aws_request_signing.proto | 27 +- changelogs/current.yaml | 5 + .../aws-request-signing-filter-sigv4a.yaml | 53 ++ .../aws_request_signing_filter.rst | 20 + source/common/crypto/utility.h | 2 +- source/extensions/common/aws/BUILD | 60 +- .../{signer_impl.cc => signer_base_impl.cc} | 86 ++- .../aws/{signer_impl.h => signer_base_impl.h} | 49 +- .../common/aws/sigv4_signer_impl.cc | 70 +++ .../extensions/common/aws/sigv4_signer_impl.h | 68 +++ .../common/aws/sigv4a_key_derivation.cc | 148 +++++ .../common/aws/sigv4a_key_derivation.h | 25 + .../common/aws/sigv4a_signer_impl.cc | 88 +++ .../common/aws/sigv4a_signer_impl.h | 86 +++ .../extensions/filters/http/aws_lambda/BUILD | 2 +- .../http/aws_lambda/aws_lambda_filter.cc | 1 + .../filters/http/aws_lambda/config.cc | 6 +- .../filters/http/aws_request_signing/BUILD | 5 +- .../aws_request_signing_filter.h | 4 +- .../http/aws_request_signing/config.cc | 81 ++- .../extensions/grpc_credentials/aws_iam/BUILD | 2 +- .../grpc_credentials/aws_iam/config.cc | 6 +- test/extensions/common/aws/BUILD | 20 +- .../aws/credentials_provider_impl_test.cc | 2 - ...impl_test.cc => sigv4_signer_impl_test.cc} | 90 +-- .../common/aws/sigv4a_signer_impl_test.cc | 527 ++++++++++++++++++ .../http/aws_request_signing/config_test.cc | 164 +++++- tools/spelling/spelling_dictionary.txt | 5 + 28 files changed, 1551 insertions(+), 151 deletions(-) create mode 100644 docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-sigv4a.yaml rename source/extensions/common/aws/{signer_impl.cc => signer_base_impl.cc} (51%) rename source/extensions/common/aws/{signer_impl.h => signer_base_impl.h} (66%) create mode 100644 source/extensions/common/aws/sigv4_signer_impl.cc create mode 100644 source/extensions/common/aws/sigv4_signer_impl.h create mode 100644 source/extensions/common/aws/sigv4a_key_derivation.cc create mode 100644 source/extensions/common/aws/sigv4a_key_derivation.h create mode 100644 source/extensions/common/aws/sigv4a_signer_impl.cc create mode 100644 source/extensions/common/aws/sigv4a_signer_impl.h rename test/extensions/common/aws/{signer_impl_test.cc => sigv4_signer_impl_test.cc} (75%) create mode 100644 test/extensions/common/aws/sigv4a_signer_impl_test.cc diff --git a/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto b/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto index df4633ce63ee..05ea85e2ac6f 100644 --- a/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto +++ b/api/envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.proto @@ -19,11 +19,19 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#extension: envoy.filters.http.aws_request_signing] // Top level configuration for the AWS request signing filter. -// [#next-free-field: 6] +// [#next-free-field: 7] message AwsRequestSigning { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.http.aws_request_signing.v2alpha.AwsRequestSigning"; + enum SigningAlgorithm { + // Use SigV4 for signing + AWS_SIGV4 = 0; + + // Use SigV4A for signing + AWS_SIGV4A = 1; + } + // The `service namespace // `_ // of the HTTP endpoint. @@ -31,10 +39,20 @@ message AwsRequestSigning { // Example: s3 string service_name = 1 [(validate.rules).string = {min_len: 1}]; - // The `region `_ hosting the HTTP - // endpoint. + // When signing_algorithm is set to ``AWS_SIGV4`` the region is a standard AWS `region `_ string for the service + // hosting the HTTP endpoint. // // Example: us-west-2 + // + // When signing_algorithm is set to ``AWS_SIGV4A`` the region is used as a region set. + // + // A region set is a comma separated list of AWS regions, such as ``us-east-1,us-east-2`` or wildcard ``*`` + // or even region strings containing wildcards such as ``us-east-*`` + // + // Example: '*' + // + // By configuring a region set, a sigv4a signed request can be sent to multiple regions, rather than being + // valid for only a single region destination. string region = 2 [(validate.rules).string = {min_len: 1}]; // Indicates that before signing headers, the host header will be swapped with @@ -63,6 +81,9 @@ message AwsRequestSigning { // - exact: bar // When applied, all headers that start with "x-envoy" and headers "foo" and "bar" will not be signed. repeated type.matcher.v3.StringMatcher match_excluded_headers = 5; + + // Optional Signing algorithm specifier, either ``AWS_SIGV4`` or ``AWS_SIGV4A``, defaulting to ``AWS_SIGV4``. + SigningAlgorithm signing_algorithm = 6; } message AwsRequestSigningPerRoute { diff --git a/changelogs/current.yaml b/changelogs/current.yaml index d80e1c719b21..974bf913f70f 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -320,6 +320,11 @@ new_features: - area: access_log change: | Added new access log command operator ``%EMIT_TIME%`` to get the time when the log entry is emitted. +- area: aws_request_signing + change: | + added support for specifying the aws signing algorithm, either ``AWS_SIGV4`` or ``AWS_SIGV4A`` via + :ref:`signing_algorithm ` + config API. - area: access_log change: | Added support for listener metadata in ``%METADATA%`` formatter. diff --git a/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-sigv4a.yaml b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-sigv4a.yaml new file mode 100644 index 000000000000..479a84aa5f6c --- /dev/null +++ b/docs/root/configuration/http/http_filters/_include/aws-request-signing-filter-sigv4a.yaml @@ -0,0 +1,53 @@ +static_resources: + listeners: + - address: + socket_address: + address: 0.0.0.0 + port_value: 80 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + codec_type: AUTO + stat_prefix: ingress_http + route_config: + name: local_route + virtual_hosts: + - name: app + domains: + - "*" + routes: + - match: + prefix: "/" + route: + cluster: versioned-cluster + http_filters: + - name: envoy.filters.http.aws_request_signing + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.aws_request_signing.v3.AwsRequestSigning + service_name: vpc-lattice-svcs + signing_algorithm: AWS_SIGV4A + region: '*' + use_unsigned_payload: true + match_excluded_headers: + - prefix: x-envoy + - prefix: x-forwarded + - exact: x-amzn-trace-id + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + + clusters: + - name: versioned-cluster + type: STRICT_DNS + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: versioned-cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 8080 diff --git a/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst b/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst index 208dd5006cb4..2cc45b72030d 100644 --- a/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst +++ b/docs/root/configuration/http/http_filters/aws_request_signing_filter.rst @@ -15,6 +15,8 @@ The HTTP AWS request signing filter is used to access authenticated AWS services existing AWS Credential Provider to get the secrets used for generating the required headers. +This filter can be used to communicate with both AWS API endpoints and customer API endpoints, such as AWS API Gateway +hosted APIs or AWS VPC Lattice services. The :ref:`use_unsigned_payload ` option determines whether or not requests are buffered so the request body can be used to compute the payload hash. Some @@ -29,6 +31,15 @@ The :ref:`match_excluded_headers ` +can be specified as ``AWS_SIGV4`` or ``AWS_SIGV4A``. If the signing algorithm is unspecified, this filter will default to ``AWS_SIGV4``. +If ``AWS_SIGV4`` is unspecified, or explicitly specified, the :ref:`signing_algorithm ` parameter +is used to define the region to which the sigv4 calculation is addressed to. +If ``AWS_SIGV4A`` is explicitly specified, the :ref:`signing_algorithm ` parameter +is used as a region set. A region set is a single region, or comma seperated list of regions. Regions in a region set can also include wildcards, +such as ``us-east-*`` or even ``*``. By using ``AWS_SIGV4A`` and wildcarded regions it is possible to simplify the overall envoy configuration for +multi-region implementations. + Example configuration --------------------- @@ -52,6 +63,15 @@ Note that this filter also supports per route configuration: Above shows an example of route-level config overriding the config on the virtual-host level. +An example of configuring this filter to use ``AWS_SIGV4A`` signing with a wildcarded region set, to a AWS VPC Lattice service: + +.. literalinclude:: _include/aws-request-signing-filter-sigv4a.yaml + :language: yaml + :lines: 26-36 + :lineno-start: 26 + :linenos: + :caption: :download:`aws-request-signing-filter-sigv4a.yaml <_include/aws-request-signing-filter-sigv4a.yaml>` + .. include:: _include/aws_credentials.rst Statistics diff --git a/source/common/crypto/utility.h b/source/common/crypto/utility.h index 2dbc4427e8da..6179de61042b 100644 --- a/source/common/crypto/utility.h +++ b/source/common/crypto/utility.h @@ -41,7 +41,7 @@ class Utility { /** * Computes the SHA-256 HMAC for a given key and message. * @param key the HMAC function key. - * @param message message data for the HMAC function. + * @param message string_view message data for the HMAC function. * @return a vector of bytes for the computed HMAC. */ virtual std::vector getSha256Hmac(const std::vector& key, diff --git a/source/extensions/common/aws/BUILD b/source/extensions/common/aws/BUILD index 1be1caab105d..5f41708a39f7 100644 --- a/source/extensions/common/aws/BUILD +++ b/source/extensions/common/aws/BUILD @@ -18,9 +18,9 @@ envoy_cc_library( ) envoy_cc_library( - name = "signer_impl_lib", - srcs = ["signer_impl.cc"], - hdrs = ["signer_impl.h"], + name = "signer_base_impl", + srcs = ["signer_base_impl.cc"], + hdrs = ["signer_base_impl.h"], deps = [ ":credentials_provider_interface", ":signer_interface", @@ -31,6 +31,60 @@ envoy_cc_library( "//source/common/common:utility_lib", "//source/common/crypto:utility_lib", "//source/common/http:message_lib", + ], +) + +envoy_cc_library( + name = "sigv4_signer_impl_lib", + srcs = ["sigv4_signer_impl.cc"], + hdrs = [ + "signer_base_impl.h", + "sigv4_signer_impl.h", + ], + deps = [ + ":credentials_provider_interface", + ":signer_base_impl", + ":signer_interface", + ":utility_lib", + "//source/common/singleton:const_singleton", + ], +) + +envoy_cc_library( + name = "sigv4a_signer_impl_lib", + srcs = ["sigv4a_signer_impl.cc"], + hdrs = [ + "signer_base_impl.h", + "sigv4a_signer_impl.h", + ], + deps = [ + ":credentials_provider_interface", + ":signer_base_impl", + ":signer_interface", + ":sigv4a_key_derivation_lib", + ":utility_lib", + "//source/common/singleton:const_singleton", + ], +) + +envoy_cc_library( + name = "sigv4a_key_derivation_lib", + srcs = ["sigv4a_key_derivation.cc"], + hdrs = [ + "sigv4a_key_derivation.h", + "sigv4a_signer_impl.h", + ], + deps = [ + ":credentials_provider_interface", + ":signer_base_impl", + ":signer_interface", + ":utility_lib", + "//source/common/buffer:buffer_lib", + "//source/common/common:hex_lib", + "//source/common/common:logger_lib", + "//source/common/common:utility_lib", + "//source/common/crypto:utility_lib", + "//source/common/http:message_lib", "//source/common/singleton:const_singleton", ], ) diff --git a/source/extensions/common/aws/signer_impl.cc b/source/extensions/common/aws/signer_base_impl.cc similarity index 51% rename from source/extensions/common/aws/signer_impl.cc rename to source/extensions/common/aws/signer_base_impl.cc index fa4206b79832..33442ce1223f 100644 --- a/source/extensions/common/aws/signer_impl.cc +++ b/source/extensions/common/aws/signer_base_impl.cc @@ -1,4 +1,8 @@ -#include "source/extensions/common/aws/signer_impl.h" +#include "source/extensions/common/aws/signer_base_impl.h" + +#include + +#include #include "envoy/common/exception.h" @@ -16,29 +20,38 @@ namespace Extensions { namespace Common { namespace Aws { -void SignerImpl::sign(Http::RequestMessage& message, bool sign_body, - const absl::string_view override_region) { +void SignerBaseImpl::sign(Http::RequestMessage& message, bool sign_body, + const absl::string_view override_region) { + const auto content_hash = createContentHash(message, sign_body); auto& headers = message.headers(); sign(headers, content_hash, override_region); } -void SignerImpl::signEmptyPayload(Http::RequestHeaderMap& headers, - const absl::string_view override_region) { +void SignerBaseImpl::signEmptyPayload(Http::RequestHeaderMap& headers, + const absl::string_view override_region) { headers.setReference(SignatureHeaders::get().ContentSha256, SignatureConstants::get().HashedEmptyString); sign(headers, SignatureConstants::get().HashedEmptyString, override_region); } -void SignerImpl::signUnsignedPayload(Http::RequestHeaderMap& headers, - const absl::string_view override_region) { +void SignerBaseImpl::signUnsignedPayload(Http::RequestHeaderMap& headers, + const absl::string_view override_region) { headers.setReference(SignatureHeaders::get().ContentSha256, SignatureConstants::get().UnsignedPayload); sign(headers, SignatureConstants::get().UnsignedPayload, override_region); } -void SignerImpl::sign(Http::RequestHeaderMap& headers, const std::string& content_hash, - const absl::string_view override_region) { +// Required only for sigv4a +void SignerBaseImpl::addRegionHeader( + ABSL_ATTRIBUTE_UNUSED Http::RequestHeaderMap& headers, + ABSL_ATTRIBUTE_UNUSED const absl::string_view override_region) const {} + +std::string SignerBaseImpl::getRegion() const { return region_; } + +void SignerBaseImpl::sign(Http::RequestHeaderMap& headers, const std::string& content_hash, + const absl::string_view override_region) { + headers.setReferenceKey(SignatureHeaders::get().ContentSha256, content_hash); const auto& credentials = credentials_provider_->getCredentials(); if (!credentials.accessKeyId() || !credentials.secretAccessKey()) { @@ -54,25 +67,32 @@ void SignerImpl::sign(Http::RequestHeaderMap& headers, const std::string& conten if (path_header == nullptr) { throw EnvoyException("Message is missing :path header"); } + if (credentials.sessionToken()) { headers.addCopy(SignatureHeaders::get().SecurityToken, credentials.sessionToken().value()); } const auto long_date = long_date_formatter_.now(time_source_); const auto short_date = short_date_formatter_.now(time_source_); headers.addCopy(SignatureHeaders::get().Date, long_date); + + addRegionHeader(headers, override_region); + // Phase 1: Create a canonical request const auto canonical_headers = Utility::canonicalizeHeaders(headers, excluded_header_matchers_); const auto canonical_request = Utility::createCanonicalRequest( service_name_, method_header->value().getStringView(), path_header->value().getStringView(), canonical_headers, content_hash); ENVOY_LOG(debug, "Canonical request:\n{}", canonical_request); + // Phase 2: Create a string to sign const auto credential_scope = createCredentialScope(short_date, override_region); const auto string_to_sign = createStringToSign(canonical_request, long_date, credential_scope); ENVOY_LOG(debug, "String to sign:\n{}", string_to_sign); + // Phase 3: Create a signature - const auto signature = createSignature(credentials.secretAccessKey().value(), short_date, - string_to_sign, override_region); + const auto signature = + createSignature(credentials.accessKeyId().value(), credentials.secretAccessKey().value(), + short_date, string_to_sign, override_region); // Phase 4: Sign request const auto authorization_header = createAuthorizationHeader( credentials.accessKeyId().value(), credential_scope, canonical_headers, signature); @@ -80,7 +100,7 @@ void SignerImpl::sign(Http::RequestHeaderMap& headers, const std::string& conten headers.addCopy(Http::CustomHeaders::get().Authorization, authorization_header); } -std::string SignerImpl::createContentHash(Http::RequestMessage& message, bool sign_body) const { +std::string SignerBaseImpl::createContentHash(Http::RequestMessage& message, bool sign_body) const { if (!sign_body) { return SignatureConstants::get().HashedEmptyString; } @@ -91,48 +111,6 @@ std::string SignerImpl::createContentHash(Http::RequestMessage& message, bool si return content_hash; } -std::string SignerImpl::createCredentialScope(absl::string_view short_date, - absl::string_view override_region) const { - return fmt::format(fmt::runtime(SignatureConstants::get().CredentialScopeFormat), short_date, - override_region.empty() ? region_ : override_region, service_name_); -} - -std::string SignerImpl::createStringToSign(absl::string_view canonical_request, - absl::string_view long_date, - absl::string_view credential_scope) const { - auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); - return fmt::format( - fmt::runtime(SignatureConstants::get().StringToSignFormat), long_date, credential_scope, - Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); -} - -std::string SignerImpl::createSignature(absl::string_view secret_access_key, - absl::string_view short_date, - absl::string_view string_to_sign, - absl::string_view override_region) const { - auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); - const auto secret_key = - absl::StrCat(SignatureConstants::get().SignatureVersion, secret_access_key); - const auto date_key = crypto_util.getSha256Hmac( - std::vector(secret_key.begin(), secret_key.end()), short_date); - const auto region_key = - crypto_util.getSha256Hmac(date_key, override_region.empty() ? region_ : override_region); - const auto service_key = crypto_util.getSha256Hmac(region_key, service_name_); - const auto signing_key = - crypto_util.getSha256Hmac(service_key, SignatureConstants::get().Aws4Request); - return Hex::encode(crypto_util.getSha256Hmac(signing_key, string_to_sign)); -} - -std::string -SignerImpl::createAuthorizationHeader(absl::string_view access_key_id, - absl::string_view credential_scope, - const std::map& canonical_headers, - absl::string_view signature) const { - const auto signed_headers = Utility::joinCanonicalHeaderNames(canonical_headers); - return fmt::format(fmt::runtime(SignatureConstants::get().AuthorizationHeaderFormat), - access_key_id, credential_scope, signed_headers, signature); -} - } // namespace Aws } // namespace Common } // namespace Extensions diff --git a/source/extensions/common/aws/signer_impl.h b/source/extensions/common/aws/signer_base_impl.h similarity index 66% rename from source/extensions/common/aws/signer_impl.h rename to source/extensions/common/aws/signer_base_impl.h index 57695356a3ed..058e84fe8d73 100644 --- a/source/extensions/common/aws/signer_impl.h +++ b/source/extensions/common/aws/signer_base_impl.h @@ -27,13 +27,8 @@ using SignatureHeaders = ConstSingleton; class SignatureConstantValues { public: const std::string Aws4Request{"aws4_request"}; - const std::string AuthorizationHeaderFormat{ - "AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}"}; - const std::string CredentialScopeFormat{"{}/{}/{}/aws4_request"}; const std::string HashedEmptyString{ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}; - const std::string SignatureVersion{"AWS4"}; - const std::string StringToSignFormat{"AWS4-HMAC-SHA256\n{}\n{}\n{}"}; const std::string LongDateFormat{"%Y%m%dT%H%M00Z"}; const std::string ShortDateFormat{"%Y%m%d"}; @@ -42,17 +37,17 @@ class SignatureConstantValues { using SignatureConstants = ConstSingleton; -using AwsSigV4HeaderExclusionVector = std::vector; +using AwsSigningHeaderExclusionVector = std::vector; /** * Implementation of the Signature V4 signing process. * See https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html */ -class SignerImpl : public Signer, public Logger::Loggable { +class SignerBaseImpl : public Signer, public Logger::Loggable { public: - SignerImpl(absl::string_view service_name, absl::string_view region, - const CredentialsProviderSharedPtr& credentials_provider, TimeSource& time_source, - const AwsSigV4HeaderExclusionVector& matcher_config) + SignerBaseImpl(absl::string_view service_name, absl::string_view region, + const CredentialsProviderSharedPtr& credentials_provider, TimeSource& time_source, + const AwsSigningHeaderExclusionVector& matcher_config) : service_name_(service_name), region_(region), credentials_provider_(credentials_provider), time_source_(time_source), long_date_formatter_(SignatureConstants::get().LongDateFormat), short_date_formatter_(SignatureConstants::get().ShortDateFormat) { @@ -72,23 +67,32 @@ class SignerImpl : public Signer, public Logger::Loggable { void signUnsignedPayload(Http::RequestHeaderMap& headers, const absl::string_view override_region = "") override; -private: +protected: + std::string getRegion() const; + std::string createContentHash(Http::RequestMessage& message, bool sign_body) const; - std::string createCredentialScope(absl::string_view short_date, - const absl::string_view override_region) const; + virtual void addRegionHeader(Http::RequestHeaderMap& headers, + const absl::string_view override_region) const; + + virtual std::string createCredentialScope(const absl::string_view short_date, + const absl::string_view override_region) const PURE; - std::string createStringToSign(absl::string_view canonical_request, absl::string_view long_date, - absl::string_view credential_scope) const; + virtual std::string createStringToSign(const absl::string_view canonical_request, + const absl::string_view long_date, + const absl::string_view credential_scope) const PURE; - std::string createSignature(absl::string_view secret_access_key, absl::string_view short_date, - absl::string_view string_to_sign, - const absl::string_view override_region) const; + virtual std::string createSignature(const absl::string_view access_key_id, + const absl::string_view secret_access_key, + const absl::string_view short_date, + const absl::string_view string_to_sign, + const absl::string_view override_region) const PURE; - std::string createAuthorizationHeader(absl::string_view access_key_id, - absl::string_view credential_scope, - const std::map& canonical_headers, - absl::string_view signature) const; + virtual std::string + createAuthorizationHeader(const absl::string_view access_key_id, + const absl::string_view credential_scope, + const std::map& canonical_headers, + const absl::string_view signature) const PURE; std::vector defaultMatchers() const { std::vector matcher_ptrs{}; @@ -112,6 +116,7 @@ class SignerImpl : public Signer, public Logger::Loggable { TimeSource& time_source_; DateFormatter long_date_formatter_; DateFormatter short_date_formatter_; + const std::string blank_str_; }; } // namespace Aws diff --git a/source/extensions/common/aws/sigv4_signer_impl.cc b/source/extensions/common/aws/sigv4_signer_impl.cc new file mode 100644 index 000000000000..bd1e5f699569 --- /dev/null +++ b/source/extensions/common/aws/sigv4_signer_impl.cc @@ -0,0 +1,70 @@ +#include "source/extensions/common/aws/sigv4_signer_impl.h" + +#include + +#include + +#include "envoy/common/exception.h" + +#include "source/common/buffer/buffer_impl.h" +#include "source/common/common/fmt.h" +#include "source/common/common/hex.h" +#include "source/common/crypto/utility.h" +#include "source/common/http/headers.h" +#include "source/extensions/common/aws/utility.h" + +#include "absl/strings/str_join.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +std::string SigV4SignerImpl::createCredentialScope(absl::string_view short_date, + absl::string_view override_region) const { + return fmt::format(fmt::runtime(SigV4SignatureConstants::get().SigV4CredentialScopeFormat), + short_date, override_region.empty() ? region_ : override_region, + service_name_); +} + +std::string SigV4SignerImpl::createStringToSign(absl::string_view canonical_request, + absl::string_view long_date, + absl::string_view credential_scope) const { + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + return fmt::format( + fmt::runtime(SigV4SignatureConstants::get().SigV4StringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); +} + +std::string SigV4SignerImpl::createSignature( + ABSL_ATTRIBUTE_UNUSED const absl::string_view access_key_id, + const absl::string_view secret_access_key, const absl::string_view short_date, + const absl::string_view string_to_sign, const absl::string_view override_region) const { + + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + const auto secret_key = + absl::StrCat(SigV4SignatureConstants::get().SigV4SignatureVersion, secret_access_key); + const auto date_key = crypto_util.getSha256Hmac( + std::vector(secret_key.begin(), secret_key.end()), short_date); + const auto region_key = + crypto_util.getSha256Hmac(date_key, override_region.empty() ? region_ : override_region); + const auto service_key = crypto_util.getSha256Hmac(region_key, service_name_); + const auto signing_key = + crypto_util.getSha256Hmac(service_key, SigV4SignatureConstants::get().Aws4Request); + return Hex::encode(crypto_util.getSha256Hmac(signing_key, string_to_sign)); +} + +std::string SigV4SignerImpl::createAuthorizationHeader( + absl::string_view access_key_id, absl::string_view credential_scope, + const std::map& canonical_headers, + absl::string_view signature) const { + const auto signed_headers = Utility::joinCanonicalHeaderNames(canonical_headers); + return fmt::format(fmt::runtime(SigV4SignatureConstants::get().SigV4AuthorizationHeaderFormat), + access_key_id, credential_scope, signed_headers, signature); +} + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/common/aws/sigv4_signer_impl.h b/source/extensions/common/aws/sigv4_signer_impl.h new file mode 100644 index 000000000000..d764999aadf7 --- /dev/null +++ b/source/extensions/common/aws/sigv4_signer_impl.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +#include "source/common/common/logger.h" +#include "source/common/common/matchers.h" +#include "source/common/common/utility.h" +#include "source/common/http/headers.h" +#include "source/common/singleton/const_singleton.h" +#include "source/extensions/common/aws/credentials_provider.h" +#include "source/extensions/common/aws/signer.h" +#include "source/extensions/common/aws/signer_base_impl.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +using SigV4SignatureHeaders = ConstSingleton; + +class SigV4SignatureConstantValues : public SignatureConstantValues { +public: + const std::string SigV4AuthorizationHeaderFormat{ + "AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}"}; + const std::string SigV4CredentialScopeFormat{"{}/{}/{}/aws4_request"}; + const std::string SigV4SignatureVersion{"AWS4"}; + const std::string SigV4StringToSignFormat{"AWS4-HMAC-SHA256\n{}\n{}\n{}"}; +}; + +using SigV4SignatureConstants = ConstSingleton; + +using AwsSigningHeaderExclusionVector = std::vector; + +/** + * Implementation of the Signature V4 signing process. + * See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html + */ +class SigV4SignerImpl : public SignerBaseImpl { +public: + SigV4SignerImpl(absl::string_view service_name, absl::string_view region, + const CredentialsProviderSharedPtr& credentials_provider, TimeSource& time_source, + const AwsSigningHeaderExclusionVector& matcher_config) + : SignerBaseImpl(service_name, region, credentials_provider, time_source, matcher_config) {} + +private: + std::string createCredentialScope(const absl::string_view short_date, + const absl::string_view override_region) const override; + + std::string createStringToSign(const absl::string_view canonical_request, + const absl::string_view long_date, + const absl::string_view credential_scope) const override; + + std::string createSignature(ABSL_ATTRIBUTE_UNUSED const absl::string_view access_key_id, + const absl::string_view secret_access_key, + const absl::string_view short_date, + const absl::string_view string_to_sign, + const absl::string_view override_region) const override; + + std::string createAuthorizationHeader(const absl::string_view access_key_id, + const absl::string_view credential_scope, + const std::map& canonical_headers, + const absl::string_view signature) const override; +}; + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/common/aws/sigv4a_key_derivation.cc b/source/extensions/common/aws/sigv4a_key_derivation.cc new file mode 100644 index 000000000000..904f1a5b70da --- /dev/null +++ b/source/extensions/common/aws/sigv4a_key_derivation.cc @@ -0,0 +1,148 @@ +#include "source/extensions/common/aws/sigv4a_key_derivation.h" + +#include + +#include "source/common/common/logger.h" +#include "source/common/crypto/utility.h" +#include "source/extensions/common/aws/sigv4a_signer_impl.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +EC_KEY* SigV4AKeyDerivation::derivePrivateKey(absl::string_view access_key_id, + absl::string_view secret_access_key) { + + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + const uint8_t key_length = 32; // AWS_CAL_ECDSA_P256 + std::vector private_key_buf(key_length); + + const uint8_t access_key_length = access_key_id.length(); + const uint8_t required_fixed_input_length = 32 + access_key_length; + std::vector fixed_input(required_fixed_input_length); + + const auto secret_key = + absl::StrCat(SigV4ASignatureConstants::get().SigV4ASignatureVersion, secret_access_key); + + enum SigV4AKeyDerivationResult result = AkdrNextCounter; + uint8_t external_counter = 1; + + BIGNUM* priv_key_num; + EC_KEY* ec_key; + + while ((result == AkdrNextCounter) && + (external_counter <= 254)) // MAX_KEY_DERIVATION_COUNTER_VALUE + { + fixed_input.clear(); + + fixed_input.insert(fixed_input.begin(), {0x00, 0x00, 0x00, 0x01}); + fixed_input.insert(fixed_input.end(), SigV4ASignatureConstants::get().SigV4ALabel.begin(), + SigV4ASignatureConstants::get().SigV4ALabel.end()); + fixed_input.insert(fixed_input.end(), 0x00); + fixed_input.insert(fixed_input.end(), access_key_id.begin(), access_key_id.end()); + fixed_input.insert(fixed_input.end(), external_counter); + fixed_input.insert(fixed_input.end(), {0x00, 0x00, 0x01, 0x00}); + + auto k0 = crypto_util.getSha256Hmac( + std::vector(secret_key.begin(), secret_key.end()), + absl::string_view(reinterpret_cast(fixed_input.data()), fixed_input.size())); + + // ECDSA q - 2 + std::vector s_n_minus_2 = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, + 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x4F, + }; + + // check that k0 < s_n_minus_2 + bool lt_result = constantTimeLessThanOrEqualTo(k0, s_n_minus_2); + + if (!lt_result) { + // Loop if k0 >= s_n_minus_2 and the counter will cause a new hmac to be generated + external_counter++; + } else { + result = SigV4AKeyDerivationResult::AkdrSuccess; + // PrivateKey d = c+1 + constantTimeAddOne(&k0); + + priv_key_num = BN_bin2bn(k0.data(), k0.size(), nullptr); + + // Create a new OpenSSL EC_KEY by curve nid for secp256r1 (NIST P-256) + ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + + // And set the private key we calculated above + if (!EC_KEY_set_private_key(ec_key, priv_key_num)) { + ENVOY_LOG(debug, "Failed to set openssl private key"); + BN_free(priv_key_num); + OPENSSL_free(ec_key); + return nullptr; + } + BN_free(priv_key_num); + } + } + + if (result == SigV4AKeyDerivationResult::AkdrNextCounter) { + ENVOY_LOG(debug, "Key derivation exceeded retries, returning no signature"); + return nullptr; + } + + return ec_key; +} + +bool SigV4AKeyDerivation::derivePublicKey(EC_KEY* ec_key) { + + const BIGNUM* priv_key_num = EC_KEY_get0_private_key(ec_key); + const EC_GROUP* group = EC_KEY_get0_group(ec_key); + EC_POINT* point = EC_POINT_new(group); + + EC_POINT_mul(group, point, priv_key_num, nullptr, nullptr, nullptr); + + EC_KEY_set_public_key(ec_key, point); + + EC_POINT_free(point); + return true; +} + +// code based on aws sdk key derivation constant time implementations +// https://github.com/awslabs/aws-c-auth/blob/baeffa791d9d1cf61460662a6d9ac2186aaf05df/source/key_derivation.c#L152 + +bool SigV4AKeyDerivation::constantTimeLessThanOrEqualTo(std::vector lhs_raw_be_bigint, + std::vector rhs_raw_be_bigint) { + + volatile uint8_t gt = 0; + volatile uint8_t eq = 1; + + for (uint8_t i = 0; i < lhs_raw_be_bigint.size(); ++i) { + volatile int32_t lhs_digit = lhs_raw_be_bigint[i]; + volatile int32_t rhs_digit = rhs_raw_be_bigint[i]; + + gt = gt | (((rhs_digit - lhs_digit) >> 31) & eq); + eq = eq & ((((lhs_digit ^ rhs_digit) - 1) >> 31) & 0x01); + } + return (gt + gt + eq - 1) <= 0; +} + +void SigV4AKeyDerivation::constantTimeAddOne(std::vector* raw_be_bigint) { + + const uint8_t byte_count = raw_be_bigint->size(); + + volatile uint32_t carry = 1; + + for (size_t i = 0; i < byte_count; ++i) { + const size_t index = byte_count - i - 1; + + volatile uint32_t current_digit = (*raw_be_bigint)[index]; + current_digit = current_digit + carry; + + carry = (current_digit >> 8) & 0x01; + + (*raw_be_bigint)[index] = (current_digit & 0xFF); + } +} + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/common/aws/sigv4a_key_derivation.h b/source/extensions/common/aws/sigv4a_key_derivation.h new file mode 100644 index 000000000000..c34dae26f981 --- /dev/null +++ b/source/extensions/common/aws/sigv4a_key_derivation.h @@ -0,0 +1,25 @@ +#pragma once + +#include "source/extensions/common/aws/sigv4a_signer_impl.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +class SigV4AKeyDerivation : public Logger::Loggable { +public: + static EC_KEY* derivePrivateKey(absl::string_view access_key_id, + absl::string_view secret_access_key); + static bool derivePublicKey(EC_KEY* ec_key); + +private: + static bool constantTimeLessThanOrEqualTo(std::vector lhs_raw_be_bigint, + std::vector rhs_raw_be_bigint); + static void constantTimeAddOne(std::vector* raw_be_bigint); +}; + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/common/aws/sigv4a_signer_impl.cc b/source/extensions/common/aws/sigv4a_signer_impl.cc new file mode 100644 index 000000000000..c4dd913eea4b --- /dev/null +++ b/source/extensions/common/aws/sigv4a_signer_impl.cc @@ -0,0 +1,88 @@ +#include "source/extensions/common/aws/sigv4a_signer_impl.h" + +#include + +#include + +#include "envoy/common/exception.h" + +#include "source/common/buffer/buffer_impl.h" +#include "source/common/common/fmt.h" +#include "source/common/common/hex.h" +#include "source/common/crypto/utility.h" +#include "source/common/http/headers.h" +#include "source/extensions/common/aws/sigv4a_key_derivation.h" +#include "source/extensions/common/aws/utility.h" + +#include "absl/strings/str_join.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +std::string SigV4ASignerImpl::createAuthorizationHeader( + const absl::string_view access_key_id, const absl::string_view credential_scope, + const std::map& canonical_headers, + absl::string_view signature) const { + const auto signed_headers = Utility::joinCanonicalHeaderNames(canonical_headers); + return fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AAuthorizationHeaderFormat), + access_key_id, credential_scope, signed_headers, signature); +} + +std::string SigV4ASignerImpl::createCredentialScope( + const absl::string_view short_date, + ABSL_ATTRIBUTE_UNUSED const absl::string_view override_region) const { + return fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4ACredentialScopeFormat), + short_date, service_name_); +} + +std::string SigV4ASignerImpl::createStringToSign(const absl::string_view canonical_request, + const absl::string_view long_date, + const absl::string_view credential_scope) const { + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + return fmt::format( + fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); +} + +void SigV4ASignerImpl::addRegionHeader(Http::RequestHeaderMap& headers, + const absl::string_view override_region) const { + headers.addCopy(SigV4ASignatureHeaders::get().RegionSet, + override_region.empty() ? getRegion() : override_region); +} + +std::string SigV4ASignerImpl::createSignature( + const absl::string_view access_key_id, const absl::string_view secret_access_key, + ABSL_ATTRIBUTE_UNUSED const absl::string_view short_date, + const absl::string_view string_to_sign, + ABSL_ATTRIBUTE_UNUSED const absl::string_view override_region) const { + + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey(access_key_id, secret_access_key); + if (!ec_key) { + ENVOY_LOG(debug, "SigV4A key derivation failed"); + return blank_str_; + } + + std::vector signature(ECDSA_size(ec_key)); + unsigned int signature_size; + + // Sign the SHA256 hash of our calculated string_to_sign + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + + ECDSA_sign(0, hash.data(), hash.size(), signature.data(), &signature_size, ec_key); + + EC_KEY_free(ec_key); + std::string encoded_signature( + Hex::encode(std::vector(signature.data(), signature.data() + signature_size))); + + return encoded_signature; +} + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/common/aws/sigv4a_signer_impl.h b/source/extensions/common/aws/sigv4a_signer_impl.h new file mode 100644 index 000000000000..8b099de301fb --- /dev/null +++ b/source/extensions/common/aws/sigv4a_signer_impl.h @@ -0,0 +1,86 @@ +#pragma once + +#include + +#include "source/common/common/logger.h" +#include "source/common/common/matchers.h" +#include "source/common/common/utility.h" +#include "source/common/http/headers.h" +#include "source/common/singleton/const_singleton.h" +#include "source/extensions/common/aws/credentials_provider.h" +#include "source/extensions/common/aws/signer.h" +#include "source/extensions/common/aws/signer_base_impl.h" + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { + +class SigV4ASignatureHeaderValues : public SignatureHeaderValues { +public: + const Http::LowerCaseString RegionSet{"x-amz-region-set"}; +}; + +using SigV4ASignatureHeaders = ConstSingleton; + +class SigV4ASignatureConstantValues : public SignatureConstantValues { +public: + const std::string SigV4AAuthorizationHeaderFormat{ + "AWS4-ECDSA-P256-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}"}; + const std::string SigV4ACredentialScopeFormat{"{}/{}/aws4_request"}; + const std::string HashedEmptyString{ + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}; + const std::string SigV4ASignatureVersion{"AWS4A"}; + const std::string SigV4AStringToSignFormat{"AWS4-ECDSA-P256-SHA256\n{}\n{}\n{}"}; + const std::string SigV4ALabel = "AWS4-ECDSA-P256-SHA256"; +}; + +enum SigV4AKeyDerivationResult { + AkdrSuccess, + AkdrNextCounter, + AkdrFailure, +}; + +using SigV4ASignatureConstants = ConstSingleton; + +using AwsSigningHeaderExclusionVector = std::vector; + +/** + * Implementation of the Signature V4A signing process. + * See https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html + */ + +class SigV4ASignerImpl : public SignerBaseImpl { +public: + SigV4ASignerImpl(absl::string_view service_name, absl::string_view region, + const CredentialsProviderSharedPtr& credentials_provider, + TimeSource& time_source, const AwsSigningHeaderExclusionVector& matcher_config) + : SignerBaseImpl(service_name, region, credentials_provider, time_source, matcher_config) {} + +private: + void addRegionHeader(Http::RequestHeaderMap& headers, + const absl::string_view override_region) const override; + + std::string createCredentialScope(const absl::string_view short_date, + const absl::string_view override_region) const override; + + std::string createStringToSign(const absl::string_view canonical_request, + const absl::string_view long_date, + const absl::string_view credential_scope) const override; + + std::string + createSignature(const absl::string_view access_key_id, const absl::string_view secret_access_key, + ABSL_ATTRIBUTE_UNUSED const absl::string_view short_date, + const absl::string_view string_to_sign, + ABSL_ATTRIBUTE_UNUSED const absl::string_view override_region) const override; + + std::string createAuthorizationHeader(const absl::string_view access_key_id, + const absl::string_view credential_scope, + const std::map& canonical_headers, + const absl::string_view signature) const override; +}; + +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/filters/http/aws_lambda/BUILD b/source/extensions/filters/http/aws_lambda/BUILD index 200a2e573b8d..af0e39ce33c7 100644 --- a/source/extensions/filters/http/aws_lambda/BUILD +++ b/source/extensions/filters/http/aws_lambda/BUILD @@ -27,7 +27,7 @@ envoy_cc_library( "//envoy/http:filter_interface", "//source/common/common:base64_lib", "//source/extensions/common/aws:credentials_provider_impl_lib", - "//source/extensions/common/aws:signer_impl_lib", + "//source/extensions/common/aws:sigv4_signer_impl_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", ], ) diff --git a/source/extensions/filters/http/aws_lambda/aws_lambda_filter.cc b/source/extensions/filters/http/aws_lambda/aws_lambda_filter.cc index d4132605b439..0b9f862059b6 100644 --- a/source/extensions/filters/http/aws_lambda/aws_lambda_filter.cc +++ b/source/extensions/filters/http/aws_lambda/aws_lambda_filter.cc @@ -112,6 +112,7 @@ bool isContentTypeTextual(const Http::RequestOrResponseHeaderMap& headers) { } // namespace +// TODO(nbaws) Implement Sigv4a support Filter::Filter(const FilterSettings& settings, const FilterStats& stats, const std::shared_ptr& sigv4_signer) : settings_(settings), stats_(stats), sigv4_signer_(sigv4_signer) {} diff --git a/source/extensions/filters/http/aws_lambda/config.cc b/source/extensions/filters/http/aws_lambda/config.cc index 9110bf8e0394..30992163a8b5 100644 --- a/source/extensions/filters/http/aws_lambda/config.cc +++ b/source/extensions/filters/http/aws_lambda/config.cc @@ -8,7 +8,7 @@ #include "source/common/common/fmt.h" #include "source/extensions/common/aws/credentials_provider_impl.h" -#include "source/extensions/common/aws/signer_impl.h" +#include "source/extensions/common/aws/sigv4_signer_impl.h" #include "source/extensions/common/aws/utility.h" #include "source/extensions/filters/http/aws_lambda/aws_lambda_filter.h" @@ -50,12 +50,12 @@ Http::FilterFactoryCb AwsLambdaFilterFactory::createFilterFactoryFromProtoTyped( server_context.api(), makeOptRef(server_context), region, Extensions::Common::Aws::Utility::fetchMetadata); - auto signer = std::make_shared( + auto signer = std::make_shared( service_name, region, std::move(credentials_provider), server_context.mainThreadDispatcher().timeSource(), // TODO: extend API to allow specifying header exclusion. ref: // https://github.com/envoyproxy/envoy/pull/18998 - Extensions::Common::Aws::AwsSigV4HeaderExclusionVector{}); + Extensions::Common::Aws::AwsSigningHeaderExclusionVector{}); FilterSettings filter_settings{*arn, getInvocationMode(proto_config), proto_config.payload_passthrough()}; diff --git a/source/extensions/filters/http/aws_request_signing/BUILD b/source/extensions/filters/http/aws_request_signing/BUILD index 7f76c5393959..1f189efcaeba 100644 --- a/source/extensions/filters/http/aws_request_signing/BUILD +++ b/source/extensions/filters/http/aws_request_signing/BUILD @@ -19,7 +19,8 @@ envoy_cc_library( deps = [ "//envoy/http:filter_interface", "//source/extensions/common/aws:credentials_provider_impl_lib", - "//source/extensions/common/aws:signer_impl_lib", + "//source/extensions/common/aws:sigv4_signer_impl_lib", + "//source/extensions/common/aws:sigv4a_signer_impl_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", "@envoy_api//envoy/extensions/filters/http/aws_request_signing/v3:pkg_cc_proto", ], @@ -34,7 +35,7 @@ envoy_cc_extension( "//envoy/registry", "//source/common/common:matchers_lib", "//source/extensions/common/aws:credentials_provider_impl_lib", - "//source/extensions/common/aws:signer_impl_lib", + "//source/extensions/common/aws:sigv4_signer_impl_lib", "//source/extensions/filters/http/common:factory_base_lib", "@envoy_api//envoy/extensions/filters/http/aws_request_signing/v3:pkg_cc_proto", ], diff --git a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h index c0a70106b619..aa3059976694 100644 --- a/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h +++ b/source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h @@ -31,6 +31,8 @@ struct FilterStats { ALL_AWS_REQUEST_SIGNING_FILTER_STATS(GENERATE_COUNTER_STRUCT) }; +enum class SigningAlgorithm { SIGV4, SIGV4A }; + /** * Abstract filter configuration. */ @@ -54,7 +56,7 @@ class FilterConfig : public Router::RouteSpecificFilterConfig { virtual const std::string& hostRewrite() const PURE; /** - * @return whether or not to buffer and sign the payload. + * @return whether or not to buffer and sign the payload. */ virtual bool useUnsignedPayload() const PURE; }; diff --git a/source/extensions/filters/http/aws_request_signing/config.cc b/source/extensions/filters/http/aws_request_signing/config.cc index 0efdba970916..67ea8df9f7ca 100644 --- a/source/extensions/filters/http/aws_request_signing/config.cc +++ b/source/extensions/filters/http/aws_request_signing/config.cc @@ -1,12 +1,16 @@ #include "source/extensions/filters/http/aws_request_signing/config.h" +#include +#include + #include "envoy/common/optref.h" #include "envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.pb.h" #include "envoy/extensions/filters/http/aws_request_signing/v3/aws_request_signing.pb.validate.h" #include "envoy/registry/registry.h" #include "source/extensions/common/aws/credentials_provider_impl.h" -#include "source/extensions/common/aws/signer_impl.h" +#include "source/extensions/common/aws/sigv4_signer_impl.h" +#include "source/extensions/common/aws/sigv4a_signer_impl.h" #include "source/extensions/common/aws/utility.h" #include "source/extensions/filters/http/aws_request_signing/aws_request_signing_filter.h" @@ -15,6 +19,33 @@ namespace Extensions { namespace HttpFilters { namespace AwsRequestSigningFilter { +bool isARegionSet(std::string region) { + for (const char& c : "*,") { + if (region.find(c) != std::string::npos) { + return true; + } + } + return false; +} + +SigningAlgorithm getSigningAlgorithm( + const envoy::extensions::filters::http::aws_request_signing::v3::AwsRequestSigning& config) { + using namespace envoy::extensions::filters::http::aws_request_signing::v3; + auto& logger = Logger::Registry::getLog(Logger::Id::filter); + + switch (config.signing_algorithm()) { + PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; + case AwsRequestSigning_SigningAlgorithm_AWS_SIGV4: + ENVOY_LOG_TO_LOGGER(logger, debug, "Signing Algorithm is SigV4"); + return SigningAlgorithm::SIGV4; + + case AwsRequestSigning_SigningAlgorithm_AWS_SIGV4A: + ENVOY_LOG_TO_LOGGER(logger, debug, "Signing Algorithm is SigV4A"); + return SigningAlgorithm::SIGV4A; + } + PANIC_DUE_TO_CORRUPT_ENUM; +} + Http::FilterFactoryCb AwsRequestSigningFilterFactory::createFilterFactoryFromProtoTyped( const AwsRequestSigningProtoConfig& config, const std::string& stats_prefix, Server::Configuration::FactoryContext& context) { @@ -25,11 +56,26 @@ Http::FilterFactoryCb AwsRequestSigningFilterFactory::createFilterFactoryFromPro std::make_shared( server_context.api(), makeOptRef(server_context), config.region(), Extensions::Common::Aws::Utility::fetchMetadata); - const auto matcher_config = Extensions::Common::Aws::AwsSigV4HeaderExclusionVector( + const auto matcher_config = Extensions::Common::Aws::AwsSigningHeaderExclusionVector( config.match_excluded_headers().begin(), config.match_excluded_headers().end()); - auto signer = std::make_unique( - config.service_name(), config.region(), credentials_provider, - server_context.mainThreadDispatcher().timeSource(), matcher_config); + + std::unique_ptr signer; + + if (getSigningAlgorithm(config) == SigningAlgorithm::SIGV4A) { + signer = std::make_unique( + config.service_name(), config.region(), credentials_provider, + server_context.mainThreadDispatcher().timeSource(), matcher_config); + } else { + // Verify that we have not specified a region set formatted region for sigv4 algorithm + if (isARegionSet(config.region())) { + throw EnvoyException("SigV4 region string cannot contain wildcards or commas. Region sets " + "can be specified when using signing_algorithm: AWS_SIGV4A."); + } + signer = std::make_unique( + config.service_name(), config.region(), credentials_provider, + server_context.mainThreadDispatcher().timeSource(), matcher_config); + } + auto filter_config = std::make_shared(std::move(signer), stats_prefix, context.scope(), config.host_rewrite(), config.use_unsigned_payload()); @@ -47,13 +93,28 @@ AwsRequestSigningFilterFactory::createRouteSpecificFilterConfigTyped( std::make_shared( context.api(), makeOptRef(context), per_route_config.aws_request_signing().region(), Extensions::Common::Aws::Utility::fetchMetadata); - const auto matcher_config = Extensions::Common::Aws::AwsSigV4HeaderExclusionVector( + const auto matcher_config = Extensions::Common::Aws::AwsSigningHeaderExclusionVector( per_route_config.aws_request_signing().match_excluded_headers().begin(), per_route_config.aws_request_signing().match_excluded_headers().end()); - auto signer = std::make_unique( - per_route_config.aws_request_signing().service_name(), - per_route_config.aws_request_signing().region(), credentials_provider, - context.mainThreadDispatcher().timeSource(), matcher_config); + std::unique_ptr signer; + + if (getSigningAlgorithm(per_route_config.aws_request_signing()) == SigningAlgorithm::SIGV4A) { + signer = std::make_unique( + per_route_config.aws_request_signing().service_name(), + per_route_config.aws_request_signing().region(), credentials_provider, + context.mainThreadDispatcher().timeSource(), matcher_config); + } else { + // Verify that we have not specified a region set formatted region for sigv4 algorithm + if (isARegionSet(per_route_config.aws_request_signing().region())) { + throw EnvoyException("SigV4 region string cannot contain wildcards or commas. Region sets " + "can be specified when using signing_algorithm: AWS_SIGV4A."); + } + signer = std::make_unique( + per_route_config.aws_request_signing().service_name(), + per_route_config.aws_request_signing().region(), credentials_provider, + context.mainThreadDispatcher().timeSource(), matcher_config); + } + return std::make_shared( std::move(signer), per_route_config.stat_prefix(), context.scope(), per_route_config.aws_request_signing().host_rewrite(), diff --git a/source/extensions/grpc_credentials/aws_iam/BUILD b/source/extensions/grpc_credentials/aws_iam/BUILD index ac63c34674e6..ac86fedb65ba 100644 --- a/source/extensions/grpc_credentials/aws_iam/BUILD +++ b/source/extensions/grpc_credentials/aws_iam/BUILD @@ -25,7 +25,7 @@ envoy_cc_extension( "//source/common/http:utility_lib", "//source/extensions/common/aws:credentials_provider_impl_lib", "//source/extensions/common/aws:region_provider_impl_lib", - "//source/extensions/common/aws:signer_impl_lib", + "//source/extensions/common/aws:sigv4_signer_impl_lib", "//source/extensions/common/aws:utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/config/grpc_credential/v3:pkg_cc_proto", diff --git a/source/extensions/grpc_credentials/aws_iam/config.cc b/source/extensions/grpc_credentials/aws_iam/config.cc index 9e3dab6454eb..e0cf47cb1651 100644 --- a/source/extensions/grpc_credentials/aws_iam/config.cc +++ b/source/extensions/grpc_credentials/aws_iam/config.cc @@ -13,7 +13,7 @@ #include "source/common/protobuf/message_validator_impl.h" #include "source/extensions/common/aws/credentials_provider_impl.h" #include "source/extensions/common/aws/region_provider_impl.h" -#include "source/extensions/common/aws/signer_impl.h" +#include "source/extensions/common/aws/sigv4_signer_impl.h" #include "source/extensions/common/aws/utility.h" namespace Envoy { @@ -54,11 +54,11 @@ std::shared_ptr AwsIamGrpcCredentialsFactory::getChann auto credentials_provider = std::make_shared( api, absl::nullopt /*Empty factory context*/, region, Common::Aws::Utility::fetchMetadata); - auto signer = std::make_unique( + auto signer = std::make_unique( config.service_name(), region, credentials_provider, api.timeSource(), // TODO: extend API to allow specifying header exclusion. ref: // https://github.com/envoyproxy/envoy/pull/18998 - Common::Aws::AwsSigV4HeaderExclusionVector{}); + Common::Aws::AwsSigningHeaderExclusionVector{}); std::shared_ptr new_call_creds = grpc::MetadataCredentialsFromPlugin( std::make_unique(std::move(signer))); if (call_creds == nullptr) { diff --git a/test/extensions/common/aws/BUILD b/test/extensions/common/aws/BUILD index 63440356fae7..69b7469b8ae1 100644 --- a/test/extensions/common/aws/BUILD +++ b/test/extensions/common/aws/BUILD @@ -24,12 +24,26 @@ envoy_cc_mock( ) envoy_cc_test( - name = "signer_impl_test", - srcs = ["signer_impl_test.cc"], + name = "sigv4_signer_impl_test", + srcs = ["sigv4_signer_impl_test.cc"], deps = [ "//source/common/buffer:buffer_lib", "//source/common/http:message_lib", - "//source/extensions/common/aws:signer_impl_lib", + "//source/extensions/common/aws:sigv4_signer_impl_lib", + "//test/extensions/common/aws:aws_mocks", + "//test/test_common:simulated_time_system_lib", + "//test/test_common:utility_lib", + ], +) + +envoy_cc_test( + name = "sigv4a_signer_impl_test", + srcs = ["sigv4a_signer_impl_test.cc"], + deps = [ + "//source/common/buffer:buffer_lib", + "//source/common/http:message_lib", + "//source/extensions/common/aws:sigv4a_key_derivation_lib", + "//source/extensions/common/aws:sigv4a_signer_impl_lib", "//test/extensions/common/aws:aws_mocks", "//test/test_common:simulated_time_system_lib", "//test/test_common:utility_lib", diff --git a/test/extensions/common/aws/credentials_provider_impl_test.cc b/test/extensions/common/aws/credentials_provider_impl_test.cc index a48a16bd0c54..819181ae1ce8 100644 --- a/test/extensions/common/aws/credentials_provider_impl_test.cc +++ b/test/extensions/common/aws/credentials_provider_impl_test.cc @@ -13,9 +13,7 @@ #include "test/test_common/simulated_time_system.h" #include "test/test_common/test_runtime.h" -using Envoy::Extensions::Common::Aws::MetadataFetcher; using Envoy::Extensions::Common::Aws::MetadataFetcherPtr; -using Envoy::Extensions::Common::Aws::MockMetadataFetcher; using testing::_; using testing::Eq; using testing::InSequence; diff --git a/test/extensions/common/aws/signer_impl_test.cc b/test/extensions/common/aws/sigv4_signer_impl_test.cc similarity index 75% rename from test/extensions/common/aws/signer_impl_test.cc rename to test/extensions/common/aws/sigv4_signer_impl_test.cc index 9b8ea8cf85ab..f667d71ef0cf 100644 --- a/test/extensions/common/aws/signer_impl_test.cc +++ b/test/extensions/common/aws/sigv4_signer_impl_test.cc @@ -1,6 +1,6 @@ #include "source/common/buffer/buffer_impl.h" #include "source/common/http/message_impl.h" -#include "source/extensions/common/aws/signer_impl.h" +#include "source/extensions/common/aws/sigv4_signer_impl.h" #include "source/extensions/common/aws/utility.h" #include "test/extensions/common/aws/mocks.h" @@ -16,13 +16,13 @@ namespace Common { namespace Aws { namespace { -class SignerImplTest : public testing::Test { +class SigV4SignerImplTest : public testing::Test { public: - SignerImplTest() + SigV4SignerImplTest() : credentials_provider_(new NiceMock()), message_(new Http::RequestMessageImpl()), signer_("service", "region", CredentialsProviderSharedPtr{credentials_provider_}, - time_system_, Extensions::Common::Aws::AwsSigV4HeaderExclusionVector{}), + time_system_, Extensions::Common::Aws::AwsSigningHeaderExclusionVector{}), credentials_("akid", "secret"), token_credentials_("akid", "secret", "token") { // 20180102T030405Z time_system_.setSystemTime(std::chrono::milliseconds(1514862245000)); @@ -48,8 +48,9 @@ class SignerImplTest : public testing::Test { headers.setPath("/"); headers.addCopy(Http::LowerCaseString("host"), "www.example.com"); - SignerImpl signer(service_name, "region", CredentialsProviderSharedPtr{credentials_provider}, - time_system_, Extensions::Common::Aws::AwsSigV4HeaderExclusionVector{}); + SigV4SignerImpl signer(service_name, "region", + CredentialsProviderSharedPtr{credentials_provider}, time_system_, + Extensions::Common::Aws::AwsSigningHeaderExclusionVector{}); if (use_unsigned_payload) { signer.signUnsignedPayload(headers, override_region); } else { @@ -63,27 +64,27 @@ class SignerImplTest : public testing::Test { signature), headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView()); EXPECT_EQ(payload, - headers.get(SignatureHeaders::get().ContentSha256)[0]->value().getStringView()); + headers.get(SigV4SignatureHeaders::get().ContentSha256)[0]->value().getStringView()); } NiceMock* credentials_provider_; Event::SimulatedTimeSystem time_system_; Http::RequestMessagePtr message_; - SignerImpl signer_; + SigV4SignerImpl signer_; Credentials credentials_; Credentials token_credentials_; absl::optional region_; }; // No authorization header should be present when the credentials are empty -TEST_F(SignerImplTest, AnonymousCredentials) { +TEST_F(SigV4SignerImplTest, AnonymousCredentials) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(Credentials())); signer_.sign(*message_); EXPECT_TRUE(message_->headers().get(Http::CustomHeaders::get().Authorization).empty()); } // HTTP :method header is required -TEST_F(SignerImplTest, MissingMethodException) { +TEST_F(SigV4SignerImplTest, MissingMethodException) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); EXPECT_THROW_WITH_MESSAGE(signer_.sign(*message_), EnvoyException, "Message is missing :method header"); @@ -91,7 +92,7 @@ TEST_F(SignerImplTest, MissingMethodException) { } // HTTP :path header is required -TEST_F(SignerImplTest, MissingPathException) { +TEST_F(SigV4SignerImplTest, MissingPathException) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("GET"); EXPECT_THROW_WITH_MESSAGE(signer_.sign(*message_), EnvoyException, @@ -100,14 +101,14 @@ TEST_F(SignerImplTest, MissingPathException) { } // Verify we sign the date header -TEST_F(SignerImplTest, SignDateHeader) { +TEST_F(SigV4SignerImplTest, SignDateHeader) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("GET"); addPath("/"); signer_.sign(*message_); - EXPECT_FALSE(message_->headers().get(SignatureHeaders::get().ContentSha256).empty()); + EXPECT_FALSE(message_->headers().get(SigV4SignatureHeaders::get().ContentSha256).empty()); EXPECT_EQ("20180102T030400Z", - message_->headers().get(SignatureHeaders::get().Date)[0]->value().getStringView()); + message_->headers().get(SigV4SignatureHeaders::get().Date)[0]->value().getStringView()); EXPECT_EQ("AWS4-HMAC-SHA256 Credential=akid/20180102/region/service/aws4_request, " "SignedHeaders=x-amz-content-sha256;x-amz-date, " "Signature=4ee6aa9355259c18133f150b139ea9aeb7969c9408ad361b2151f50a516afe42", @@ -118,14 +119,15 @@ TEST_F(SignerImplTest, SignDateHeader) { } // Verify we sign the security token header if the token is present in the credentials -TEST_F(SignerImplTest, SignSecurityTokenHeader) { +TEST_F(SigV4SignerImplTest, SignSecurityTokenHeader) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(token_credentials_)); addMethod("GET"); addPath("/"); signer_.sign(*message_); - EXPECT_EQ( - "token", - message_->headers().get(SignatureHeaders::get().SecurityToken)[0]->value().getStringView()); + EXPECT_EQ("token", message_->headers() + .get(SigV4SignatureHeaders::get().SecurityToken)[0] + ->value() + .getStringView()); EXPECT_EQ("AWS4-HMAC-SHA256 Credential=akid/20180102/region/service/aws4_request, " "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-security-token, " "Signature=1d42526aabf7d8b6d7d33d9db43b03537300cc7e6bb2817e349749e0a08f5b5e", @@ -136,14 +138,16 @@ TEST_F(SignerImplTest, SignSecurityTokenHeader) { } // Verify we sign the content header as the hashed empty string if the body is empty -TEST_F(SignerImplTest, SignEmptyContentHeader) { +TEST_F(SigV4SignerImplTest, SignEmptyContentHeader) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("GET"); addPath("/"); signer_.sign(*message_, true); - EXPECT_EQ( - SignatureConstants::get().HashedEmptyString, - message_->headers().get(SignatureHeaders::get().ContentSha256)[0]->value().getStringView()); + EXPECT_EQ(SigV4SignatureConstants::get().HashedEmptyString, + message_->headers() + .get(SigV4SignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); EXPECT_EQ("AWS4-HMAC-SHA256 Credential=akid/20180102/region/service/aws4_request, " "SignedHeaders=x-amz-content-sha256;x-amz-date, " "Signature=4ee6aa9355259c18133f150b139ea9aeb7969c9408ad361b2151f50a516afe42", @@ -154,15 +158,17 @@ TEST_F(SignerImplTest, SignEmptyContentHeader) { } // Verify we sign the content header correctly when we have a body -TEST_F(SignerImplTest, SignContentHeader) { +TEST_F(SigV4SignerImplTest, SignContentHeader) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("POST"); addPath("/"); setBody("test1234"); signer_.sign(*message_, true); - EXPECT_EQ( - "937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", - message_->headers().get(SignatureHeaders::get().ContentSha256)[0]->value().getStringView()); + EXPECT_EQ("937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", + message_->headers() + .get(SigV4SignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); EXPECT_EQ("AWS4-HMAC-SHA256 Credential=akid/20180102/region/service/aws4_request, " "SignedHeaders=x-amz-content-sha256;x-amz-date, " "Signature=4eab89c36f45f2032d6010ba1adab93f8510ddd6afe540821f3a05bb0253e27b", @@ -173,15 +179,17 @@ TEST_F(SignerImplTest, SignContentHeader) { } // Verify we sign the content header correctly when we have a body with region override -TEST_F(SignerImplTest, SignContentHeaderOverrideRegion) { +TEST_F(SigV4SignerImplTest, SignContentHeaderOverrideRegion) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("POST"); addPath("/"); setBody("test1234"); signer_.sign(*message_, true, "region1"); - EXPECT_EQ( - "937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", - message_->headers().get(SignatureHeaders::get().ContentSha256)[0]->value().getStringView()); + EXPECT_EQ("937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", + message_->headers() + .get(SigV4SignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); EXPECT_EQ("AWS4-HMAC-SHA256 Credential=akid/20180102/region1/service/aws4_request, " "SignedHeaders=x-amz-content-sha256;x-amz-date, " "Signature=fe8136ed21972d8618171e051f4023b7c06b85d61b4d4325be869846f404b399", @@ -192,7 +200,7 @@ TEST_F(SignerImplTest, SignContentHeaderOverrideRegion) { } // Verify we sign some extra headers -TEST_F(SignerImplTest, SignExtraHeaders) { +TEST_F(SigV4SignerImplTest, SignExtraHeaders) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("GET"); addPath("/"); @@ -210,7 +218,7 @@ TEST_F(SignerImplTest, SignExtraHeaders) { } // Verify signing a host header -TEST_F(SignerImplTest, SignHostHeader) { +TEST_F(SigV4SignerImplTest, SignHostHeader) { EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); addMethod("GET"); addPath("/"); @@ -226,25 +234,25 @@ TEST_F(SignerImplTest, SignHostHeader) { } // Verify signing headers for services. -TEST_F(SignerImplTest, SignHeadersByService) { +TEST_F(SigV4SignerImplTest, SignHeadersByService) { expectSignHeaders("s3", "d97cae067345792b78d2bad746f25c729b9eb4701127e13a7c80398f8216a167", - SignatureConstants::get().UnsignedPayload, true); + SigV4SignatureConstants::get().UnsignedPayload, true); expectSignHeaders("service", "d9fd9be575a254c924d843964b063d770181d938ae818f5b603ef0575a5ce2cd", - SignatureConstants::get().HashedEmptyString, false); + SigV4SignatureConstants::get().HashedEmptyString, false); expectSignHeaders("es", "0fd9c974bb2ad16c8d8a314dca4f6db151d32cbd04748d9c018afee2a685a02e", - SignatureConstants::get().UnsignedPayload, true); + SigV4SignatureConstants::get().UnsignedPayload, true); expectSignHeaders("glacier", "8d1f241d77c64cda57b042cd312180f16e98dbd7a96e5545681430f8dbde45a0", - SignatureConstants::get().UnsignedPayload, true); + SigV4SignatureConstants::get().UnsignedPayload, true); // with override region expectSignHeaders("s3", "70b80eaedfe73d9cf18a9d2f786f02a7dab013780a8cdc42a7c819a27bfd943c", - SignatureConstants::get().UnsignedPayload, true, "region1"); + SigV4SignatureConstants::get().UnsignedPayload, true, "region1"); expectSignHeaders("service", "297ca067391806a1e3cdb25723082063d0bf66a6472b902dd986d540a2058a13", - SignatureConstants::get().HashedEmptyString, false, "region1"); + SigV4SignatureConstants::get().HashedEmptyString, false, "region1"); expectSignHeaders("es", "cec43f0777c0d4cb2f3799a5c755dc4c3b893c23e268c1bd4e34f770fba3c1ca", - SignatureConstants::get().UnsignedPayload, true, "region1"); + SigV4SignatureConstants::get().UnsignedPayload, true, "region1"); expectSignHeaders("glacier", "0792940297330f2930dc1c18d0b99c0b85429865c09e836f5c086f7f182e2809", - SignatureConstants::get().UnsignedPayload, true, "region1"); + SigV4SignatureConstants::get().UnsignedPayload, true, "region1"); } } // namespace diff --git a/test/extensions/common/aws/sigv4a_signer_impl_test.cc b/test/extensions/common/aws/sigv4a_signer_impl_test.cc new file mode 100644 index 000000000000..14bda0b82634 --- /dev/null +++ b/test/extensions/common/aws/sigv4a_signer_impl_test.cc @@ -0,0 +1,527 @@ +#include "source/common/buffer/buffer_impl.h" +#include "source/common/crypto/utility.h" +#include "source/common/http/message_impl.h" +#include "source/extensions/common/aws/sigv4a_key_derivation.h" +#include "source/extensions/common/aws/sigv4a_signer_impl.h" +#include "source/extensions/common/aws/utility.h" + +#include "test/extensions/common/aws/mocks.h" +#include "test/test_common/simulated_time_system.h" +#include "test/test_common/utility.h" + +using testing::NiceMock; +using testing::Return; + +namespace Envoy { +namespace Extensions { +namespace Common { +namespace Aws { +namespace { + +class SigV4ASignerImplTest : public testing::Test { +public: + SigV4ASignerImplTest() + : credentials_provider_(new NiceMock()), + message_(new Http::RequestMessageImpl()), + signer_("service", "region", CredentialsProviderSharedPtr{credentials_provider_}, + time_system_, Extensions::Common::Aws::AwsSigningHeaderExclusionVector{}), + credentials_("akid", "secret"), token_credentials_("akid", "secret", "token") { + // 20180102T030405Z + time_system_.setSystemTime(std::chrono::milliseconds(1514862245000)); + } + + void addMethod(const std::string& method) { message_->headers().setMethod(method); } + + void addPath(const std::string& path) { message_->headers().setPath(path); } + + void addHeader(const std::string& key, const std::string& value) { + message_->headers().addCopy(Http::LowerCaseString(key), value); + } + + void setBody(const std::string& body) { message_->body().add(body); } + + NiceMock* credentials_provider_; + Event::SimulatedTimeSystem time_system_; + Http::RequestMessagePtr message_; + SigV4ASignerImpl signer_; + Credentials credentials_; + Credentials token_credentials_; + absl::optional region_; +}; + +// No authorization header should be present when the credentials are empty +TEST_F(SigV4ASignerImplTest, AnonymousCredentials) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(Credentials())); + signer_.sign(*message_); + EXPECT_TRUE(message_->headers().get(Http::CustomHeaders::get().Authorization).empty()); +} + +// HTTP :method header is required +TEST_F(SigV4ASignerImplTest, MissingMethodException) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + EXPECT_THROW_WITH_MESSAGE(signer_.sign(*message_), EnvoyException, + "Message is missing :method header"); + EXPECT_TRUE(message_->headers().get(Http::CustomHeaders::get().Authorization).empty()); +} + +// HTTP :path header is required +TEST_F(SigV4ASignerImplTest, MissingPathException) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("GET"); + EXPECT_THROW_WITH_MESSAGE(signer_.sign(*message_), EnvoyException, + "Message is missing :path header"); + EXPECT_TRUE(message_->headers().get(Http::CustomHeaders::get().Authorization).empty()); +} + +// Verify we sign the date header +TEST_F(SigV4ASignerImplTest, SignDateHeader) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("GET"); + addPath("/"); + signer_.sign(*message_); + EXPECT_FALSE(message_->headers().get(SigV4ASignatureHeaders::get().ContentSha256).empty()); + EXPECT_EQ( + "20180102T030400Z", + message_->headers().get(SigV4ASignatureHeaders::get().Date)[0]->value().getStringView()); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +// Verify we sign the security token header if the token is present in the credentials +TEST_F(SigV4ASignerImplTest, SignSecurityTokenHeader) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(token_credentials_)); + addMethod("GET"); + addPath("/"); + signer_.sign(*message_); + EXPECT_EQ("token", message_->headers() + .get(SigV4ASignatureHeaders::get().SecurityToken)[0] + ->value() + .getStringView()); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith( + "AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-region-set;x-amz-security-token, " + "Signature=")); +} + +// Verify we sign the content header as the hashed empty string if the body is empty +TEST_F(SigV4ASignerImplTest, SignEmptyContentHeader) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("GET"); + addPath("/"); + signer_.sign(*message_, true); + EXPECT_EQ(SigV4ASignatureConstants::get().HashedEmptyString, + message_->headers() + .get(SigV4ASignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +// Verify we sign the content header correctly when we have a body +TEST_F(SigV4ASignerImplTest, SignContentHeader) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("POST"); + addPath("/"); + setBody("test1234"); + signer_.sign(*message_, true); + EXPECT_EQ("937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", + message_->headers() + .get(SigV4ASignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +// Verify we sign the content header correctly when we have a body with region override +TEST_F(SigV4ASignerImplTest, SignContentHeaderOverrideRegion) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("POST"); + addPath("/"); + setBody("test1234"); + signer_.sign(*message_, true, "region1"); + EXPECT_EQ("937e8d5fbb48bd4949536cd65b8d35c426b80d2f830c5c308e2cdec422ae2244", + message_->headers() + .get(SigV4ASignatureHeaders::get().ContentSha256)[0] + ->value() + .getStringView()); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +// Verify we sign some extra headers +TEST_F(SigV4ASignerImplTest, SignExtraHeaders) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("GET"); + addPath("/"); + addHeader("a", "a_value"); + addHeader("b", "b_value"); + addHeader("c", "c_value"); + signer_.sign(*message_); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=a;b;c;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +// Verify signing a host header +TEST_F(SigV4ASignerImplTest, SignHostHeader) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + addMethod("GET"); + addPath("/"); + addHeader("host", "www.example.com"); + signer_.sign(*message_); + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerify) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + + addMethod("GET"); + addPath("/"); + addHeader("host", "www.example.com"); + + // Sign the message using our signing algorithm + signer_.sign(*message_, false, "ap-southeast-2"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2 + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerifyMultiRegion) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + + addMethod("GET"); + addPath("/"); + addHeader("host", "www.example.com"); + + // Sign the message using our signing algorithm + signer_.sign(*message_, false, "ap-southeast-2,us-east-1"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2,us-east-1 + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + message_->headers().get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerifyUnsignedPayload) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + Http::TestRequestHeaderMapImpl headers{}; + + headers.setMethod("GET"); + headers.setPath("/"); + headers.addCopy(Http::LowerCaseString("host"), "www.example.com"); + + // Sign the message using our signing algorithm + signer_.signUnsignedPayload(headers, "ap-southeast-2"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:UNSIGNED-PAYLOAD +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2 + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +UNSIGNED-PAYLOAD)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerifyUnsignedPayloadMultiRegion) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + + Http::TestRequestHeaderMapImpl headers{}; + + headers.setMethod("GET"); + headers.setPath("/"); + headers.addCopy(Http::LowerCaseString("host"), "www.example.com"); + + // Sign the message using our signing algorithm + signer_.signUnsignedPayload(headers, "ap-southeast-2,us-east-*"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:UNSIGNED-PAYLOAD +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2,us-east-* + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +UNSIGNED-PAYLOAD)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerifyEmptyPayload) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + Http::TestRequestHeaderMapImpl headers{}; + + headers.setMethod("GET"); + headers.setPath("/"); + headers.addCopy(Http::LowerCaseString("host"), "www.example.com"); + + // Sign the message using our signing algorithm + signer_.signEmptyPayload(headers, "ap-southeast-2"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2 + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +TEST_F(SigV4ASignerImplTest, SignAndVerifyEmptyPayloadMultiRegion) { + EXPECT_CALL(*credentials_provider_, getCredentials()).WillOnce(Return(credentials_)); + auto& crypto_util = Envoy::Common::Crypto::UtilitySingleton::get(); + + EC_KEY* ec_key = SigV4AKeyDerivation::derivePrivateKey( + absl::string_view(credentials_.accessKeyId()->data(), credentials_.accessKeyId()->size()), + absl::string_view(credentials_.secretAccessKey()->data(), + credentials_.secretAccessKey()->size())); + SigV4AKeyDerivation::derivePublicKey(ec_key); + + Http::TestRequestHeaderMapImpl headers{}; + + headers.setMethod("GET"); + headers.setPath("/"); + headers.addCopy(Http::LowerCaseString("host"), "www.example.com"); + + // Sign the message using our signing algorithm + signer_.signEmptyPayload(headers, "ap-southeast-2,us-east-*"); + + // Now manually sign the same string_to_sign + std::string canonical_request = R"EOF(GET +/ + +host:www.example.com +x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +x-amz-date:20180102T030400Z +x-amz-region-set:ap-southeast-2,us-east-* + +host;x-amz-content-sha256;x-amz-date;x-amz-region-set +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855)EOF"; + + std::string short_date = "20180102"; + std::string credential_scope = fmt::format(fmt::runtime("{}/service/aws4_request"), short_date); + std::string long_date = "20180102T030400Z"; + std::string string_to_sign = + fmt::format(fmt::runtime(SigV4ASignatureConstants::get().SigV4AStringToSignFormat), long_date, + credential_scope, + Hex::encode(crypto_util.getSha256Digest(Buffer::OwnedImpl(canonical_request)))); + auto hash = crypto_util.getSha256Digest(Buffer::OwnedImpl(string_to_sign)); + // Extract the signature that is generated + EXPECT_THAT( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + testing::StartsWith("AWS4-ECDSA-P256-SHA256 Credential=akid/20180102/service/aws4_request, " + "SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-region-set, " + "Signature=")); + std::vector v = absl::StrSplit( + headers.get(Http::CustomHeaders::get().Authorization)[0]->value().getStringView(), + "Signature="); + std::vector signature = Hex::decode(v[1]); + // Check that the signature generated by our algorithm can be verified by the matching public key + EXPECT_EQ(1, + ECDSA_verify(0, hash.data(), hash.size(), signature.data(), signature.size(), ec_key)); + EC_KEY_free(ec_key); +} + +} // namespace +} // namespace Aws +} // namespace Common +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/aws_request_signing/config_test.cc b/test/extensions/filters/http/aws_request_signing/config_test.cc index a3e581ffe73e..6194f7c1771b 100644 --- a/test/extensions/filters/http/aws_request_signing/config_test.cc +++ b/test/extensions/filters/http/aws_request_signing/config_test.cc @@ -52,10 +52,119 @@ host_rewrite: new-host cb(filter_callbacks); } -TEST(AwsRequestSigningFilterConfigTest, RouteSpecificFilterConfig) { +TEST(AwsRequestSigningFilterConfigTest, SimpleConfigExplicitSigningAlgorithm) { + const std::string yaml = R"EOF( +service_name: s3 +signing_algorithm: AWS_SIGV4 +region: us-west-2 +host_rewrite: new-host +match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar + )EOF"; + + AwsRequestSigningProtoConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + AwsRequestSigningProtoConfig expected_config; + expected_config.set_service_name("s3"); + expected_config.set_region("us-west-2"); + expected_config.set_host_rewrite("new-host"); + expected_config.set_signing_algorithm(envoy::extensions::filters::http::aws_request_signing::v3:: + AwsRequestSigning_SigningAlgorithm_AWS_SIGV4); + expected_config.add_match_excluded_headers()->set_prefix("x-envoy"); + expected_config.add_match_excluded_headers()->set_exact("foo"); + expected_config.add_match_excluded_headers()->set_exact("bar"); + + Protobuf::util::MessageDifferencer differencer; + differencer.set_message_field_comparison(Protobuf::util::MessageDifferencer::EQUAL); + differencer.set_repeated_field_comparison(Protobuf::util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(expected_config, proto_config)); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + Http::FilterFactoryCb cb = + factory.createFilterFactoryFromProto(proto_config, "stats", context).value(); + Http::MockFilterChainFactoryCallbacks filter_callbacks; + EXPECT_CALL(filter_callbacks, addStreamDecoderFilter(_)); + cb(filter_callbacks); +} + +TEST(AwsRequestSigningFilterConfigTest, InvalidRegionExplicitSigningAlgorithm) { + const std::string yaml = R"EOF( +service_name: s3 +signing_algorithm: AWS_SIGV4 +region: us-west-1,us-west-2 +host_rewrite: new-host +match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar + )EOF"; + + AwsRequestSigningProtoConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + EXPECT_THROW( + { + Http::FilterFactoryCb cb = + factory.createFilterFactoryFromProto(proto_config, "stats", context).value(); + Http::MockFilterChainFactoryCallbacks filter_callbacks; + cb(filter_callbacks); + }, + EnvoyException); +} + +TEST(AwsRequestSigningFilterConfigTest, SimpleConfigSigV4A) { + const std::string yaml = R"EOF( +service_name: s3 +region: '*' +host_rewrite: new-host +signing_algorithm: AWS_SIGV4A +match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar + )EOF"; + + AwsRequestSigningProtoConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + AwsRequestSigningProtoConfig expected_config; + expected_config.set_service_name("s3"); + expected_config.set_region("*"); + expected_config.set_host_rewrite("new-host"); + expected_config.set_signing_algorithm(envoy::extensions::filters::http::aws_request_signing::v3:: + AwsRequestSigning_SigningAlgorithm_AWS_SIGV4A); + expected_config.add_match_excluded_headers()->set_prefix("x-envoy"); + expected_config.add_match_excluded_headers()->set_exact("foo"); + expected_config.add_match_excluded_headers()->set_exact("bar"); + + Protobuf::util::MessageDifferencer differencer; + differencer.set_message_field_comparison(Protobuf::util::MessageDifferencer::EQUAL); + differencer.set_repeated_field_comparison(Protobuf::util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(expected_config, proto_config)); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + Http::FilterFactoryCb cb = + factory.createFilterFactoryFromProto(proto_config, "stats", context).value(); + Http::MockFilterChainFactoryCallbacks filter_callbacks; + EXPECT_CALL(filter_callbacks, addStreamDecoderFilter(_)); + cb(filter_callbacks); +} + +TEST(AwsRequestSigningFilterConfigTest, RouteSpecificFilterConfigSigV4) { const std::string yaml = R"EOF( aws_request_signing: service_name: s3 + signing_algorithm: AWS_SIGV4 region: us-west-2 host_rewrite: new-host match_excluded_headers: @@ -76,6 +185,59 @@ stat_prefix: foo_prefix ASSERT_NE(route_config, nullptr); } +TEST(AwsRequestSigningFilterConfigTest, RouteSpecificFilterConfigSigV4A) { + const std::string yaml = R"EOF( +aws_request_signing: + service_name: s3 + signing_algorithm: AWS_SIGV4A + region: '*' + host_rewrite: new-host + match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar +stat_prefix: foo_prefix + )EOF"; + + AwsRequestSigningProtoPerRouteConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + const auto route_config = factory.createRouteSpecificFilterConfig( + proto_config, context, ProtobufMessage::getNullValidationVisitor()); + ASSERT_NE(route_config, nullptr); +} + +TEST(AwsRequestSigningFilterConfigTest, InvalidRegionRouteSpecificFilterConfigSigV4) { + const std::string yaml = R"EOF( +aws_request_signing: + service_name: s3 + signing_algorithm: AWS_SIGV4 + region: '*' + host_rewrite: new-host + match_excluded_headers: + - prefix: x-envoy + - exact: foo + - exact: bar +stat_prefix: foo_prefix + )EOF"; + + AwsRequestSigningProtoPerRouteConfig proto_config; + TestUtility::loadFromYamlAndValidate(yaml, proto_config); + + testing::NiceMock context; + AwsRequestSigningFilterFactory factory; + + EXPECT_THROW( + { + const auto route_config = factory.createRouteSpecificFilterConfig( + proto_config, context, ProtobufMessage::getNullValidationVisitor()); + }, + EnvoyException); +} + } // namespace AwsRequestSigningFilter } // namespace HttpFilters } // namespace Extensions diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index 9b4bb4e93856..d7f46a9d8c08 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -26,6 +26,8 @@ BACKTRACE BEL BBR BIDIRECTIONAL +NID +NIST bm BSON BPF @@ -1239,6 +1241,9 @@ sigactions sigaltstack siginfo signalstack +sigv +sigv4 +sigv4a siloed sim sinked From aa46602ba44becedd16f78f679428c7494bec650 Mon Sep 17 00:00:00 2001 From: Youngchul Bang Date: Thu, 4 Jan 2024 01:56:30 +0900 Subject: [PATCH 097/126] stats: add tag extraction rule for RBAC network filter (#31598) Signed-off-by: Youngchul Bang --- changelogs/current.yaml | 5 ++ source/common/config/well_known_names.cc | 3 + source/common/config/well_known_names.h | 2 + .../extensions/filters/common/rbac/utility.cc | 2 +- test/common/stats/tag_extractor_impl_test.cc | 6 ++ .../filters/http/rbac/rbac_filter_test.cc | 80 +++++++++---------- .../filters/network/rbac/integration_test.cc | 6 +- 7 files changed, 58 insertions(+), 46 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 974bf913f70f..294007a5dd2e 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -27,6 +27,11 @@ behavior_changes: Fixed tag extraction so that :ref:`stat_prefix ` is properly extracted. This changes the Prometheus name from ``envoy_connection_limit_myprefix_limited_connections{}`` to ``envoy_connection_limit_limited_connections{envoy_connection_limit_prefix="myprefix"}``. +- area: stats rbac + change: | + Fixed tag extraction so that :ref:`stat_prefix ` + is properly extracted. This changes the Prometheus name from ``envoy_myprefixrbac_allowed{}`` to + ``envoy_rbac_allowed{envoy_rbac_prefix="myprefix"}``. - area: http2 change: | Changes the default value of ``envoy.reloadable_features.http2_use_oghttp2`` to true. This changes the codec used for HTTP/2 diff --git a/source/common/config/well_known_names.cc b/source/common/config/well_known_names.cc index 7fa39a3f4358..4e390568c31d 100644 --- a/source/common/config/well_known_names.cc +++ b/source/common/config/well_known_names.cc @@ -204,6 +204,9 @@ TagNameValues::TagNameValues() { // connection_limit.(.)* addTokenized(CONNECTION_LIMIT_PREFIX, "connection_limit.$.**"); + + // (.).rbac.** + addTokenized(RBAC_PREFIX, "$.rbac.**"); } void TagNameValues::addRe2(const std::string& name, const std::string& regex, diff --git a/source/common/config/well_known_names.h b/source/common/config/well_known_names.h index 1a9da7161f8f..a0a40cc79496 100644 --- a/source/common/config/well_known_names.h +++ b/source/common/config/well_known_names.h @@ -121,6 +121,8 @@ class TagNameValues { const std::string DNS_FILTER_PREFIX = "envoy.dns_filter_prefix"; // Stats prefix for the Connection limit filter const std::string CONNECTION_LIMIT_PREFIX = "envoy.connection_limit_prefix"; + // Stats prefix for the RBAC network filter + const std::string RBAC_PREFIX = "envoy.rbac_prefix"; // Stats prefix for the TCP Proxy network filter const std::string TCP_PREFIX = "envoy.tcp_prefix"; // Stats prefix for the UDP Proxy network filter diff --git a/source/extensions/filters/common/rbac/utility.cc b/source/extensions/filters/common/rbac/utility.cc index a581de80131b..710342d7b8fd 100644 --- a/source/extensions/filters/common/rbac/utility.cc +++ b/source/extensions/filters/common/rbac/utility.cc @@ -12,7 +12,7 @@ namespace RBAC { RoleBasedAccessControlFilterStats generateStats(const std::string& prefix, const std::string& shadow_prefix, Stats::Scope& scope) { - const std::string final_prefix = prefix + "rbac."; + const std::string final_prefix = Envoy::statPrefixJoin(prefix, "rbac."); return {ENFORCE_RBAC_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix)) SHADOW_RBAC_FILTER_STATS(POOL_COUNTER_PREFIX(scope, final_prefix + shadow_prefix))}; } diff --git a/test/common/stats/tag_extractor_impl_test.cc b/test/common/stats/tag_extractor_impl_test.cc index f75f1ccfa0cb..43e74080a685 100644 --- a/test/common/stats/tag_extractor_impl_test.cc +++ b/test/common/stats/tag_extractor_impl_test.cc @@ -444,6 +444,12 @@ TEST(TagExtractorTest, DefaultTagExtractors) { connection_limit_prefix.value_ = "my_connection_limit_prefix"; regex_tester.testRegex("connection_limit.my_connection_limit_prefix.limited_connections", "connection_limit.limited_connections", {connection_limit_prefix}); + + // RBAC Filter Prefix + Tag rbac_prefix; + rbac_prefix.name_ = tag_names.RBAC_PREFIX; + rbac_prefix.value_ = "my_rbac_prefix"; + regex_tester.testRegex("my_rbac_prefix.rbac.allowed", "rbac.allowed", {rbac_prefix}); } TEST(TagExtractorTest, ExtAuthzTagExtractors) { diff --git a/test/extensions/filters/http/rbac/rbac_filter_test.cc b/test/extensions/filters/http/rbac/rbac_filter_test.cc index 7d31b7ddb799..87f633f1a70c 100644 --- a/test/extensions/filters/http/rbac/rbac_filter_test.cc +++ b/test/extensions/filters/http/rbac/rbac_filter_test.cc @@ -249,10 +249,10 @@ TEST_F(RoleBasedAccessControlFilterTest, Allowed) { EXPECT_EQ(Http::FilterMetadataStatus::Continue, filter_->decodeMetadata(metadata_map)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(1U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -273,10 +273,10 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerName) { EXPECT_EQ(0U, config_->stats().denied_.value()); EXPECT_EQ(0U, config_->stats().shadow_allowed_.value()); EXPECT_EQ(1U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -318,10 +318,10 @@ TEST_F(RoleBasedAccessControlFilterTest, Denied) { EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(headers_, true)); EXPECT_EQ(1U, config_->stats().denied_.value()); EXPECT_EQ(1U, config_->stats().shadow_allowed_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.filters.http.rbac"); EXPECT_EQ("allowed", filter_meta.fields().at("prefix_shadow_engine_result").string_value()); @@ -363,10 +363,10 @@ TEST_F(RoleBasedAccessControlFilterTest, MatcherAllowed) { EXPECT_EQ(Http::FilterMetadataStatus::Continue, filter_->decodeMetadata(metadata_map)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(1U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -387,10 +387,10 @@ TEST_F(RoleBasedAccessControlFilterTest, RequestedServerNameMatcher) { EXPECT_EQ(0U, config_->stats().denied_.value()); EXPECT_EQ(0U, config_->stats().shadow_allowed_.value()); EXPECT_EQ(1U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -432,10 +432,10 @@ TEST_F(RoleBasedAccessControlFilterTest, MatcherDenied) { EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(headers_, true)); EXPECT_EQ(1U, config_->stats().denied_.value()); EXPECT_EQ(1U, config_->stats().shadow_allowed_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); auto filter_meta = req_info_.dynamicMetadata().filter_metadata().at("envoy.filters.http.rbac"); EXPECT_EQ("allowed", filter_meta.fields().at("prefix_shadow_engine_result").string_value()); @@ -485,10 +485,10 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldLog) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers_, false)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -506,10 +506,10 @@ TEST_F(RoleBasedAccessControlFilterTest, ShouldNotLog) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers_, false)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -527,10 +527,10 @@ TEST_F(RoleBasedAccessControlFilterTest, MatcherShouldLog) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers_, false)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); @@ -548,10 +548,10 @@ TEST_F(RoleBasedAccessControlFilterTest, MatcherShouldNotLog) { EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_->decodeHeaders(headers_, false)); EXPECT_EQ(1U, config_->stats().allowed_.value()); EXPECT_EQ(0U, config_->stats().shadow_denied_.value()); - EXPECT_EQ("testrbac.allowed", config_->stats().allowed_.name()); - EXPECT_EQ("testrbac.denied", config_->stats().denied_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); - EXPECT_EQ("testrbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); + EXPECT_EQ("test.rbac.allowed", config_->stats().allowed_.name()); + EXPECT_EQ("test.rbac.denied", config_->stats().denied_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_allowed", config_->stats().shadow_allowed_.name()); + EXPECT_EQ("test.rbac.prefix_.shadow_denied", config_->stats().shadow_denied_.name()); Buffer::OwnedImpl data(""); EXPECT_EQ(Http::FilterDataStatus::Continue, filter_->decodeData(data, false)); diff --git a/test/extensions/filters/network/rbac/integration_test.cc b/test/extensions/filters/network/rbac/integration_test.cc index f499f6f62bd5..f8018eaff5db 100644 --- a/test/extensions/filters/network/rbac/integration_test.cc +++ b/test/extensions/filters/network/rbac/integration_test.cc @@ -25,11 +25,7 @@ class RoleBasedAccessControlNetworkFilterIntegrationTest public BaseIntegrationTest { public: RoleBasedAccessControlNetworkFilterIntegrationTest() - : BaseIntegrationTest(GetParam(), rbac_config) { - // TODO(ggreenway): add tag extraction rules. - // Missing stat tag-extraction rule for stat 'tcp.shadow_denied' and stat_prefix 'tcp.'. - skip_tag_extraction_rule_check_ = true; - } + : BaseIntegrationTest(GetParam(), rbac_config) {} static void SetUpTestSuite() { // NOLINT(readability-identifier-naming) rbac_config = absl::StrCat(ConfigHelper::baseConfig(), R"EOF( From 8f00d1f4a6d0418534e2c85dfedad815a813da27 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 17:32:56 +0000 Subject: [PATCH 098/126] go/deps: Fix bad update (#31609) Signed-off-by: Ryan Northey --- examples/golang-http/simple/go.mod | 12 ++--- examples/golang-http/simple/go.sum | 64 +++++---------------------- examples/golang-network/simple/go.mod | 10 ++--- examples/golang-network/simple/go.sum | 60 +++++-------------------- go.mod | 21 ++++++++- go.sum | 36 ++++++++++++++- 6 files changed, 87 insertions(+), 116 deletions(-) diff --git a/examples/golang-http/simple/go.mod b/examples/golang-http/simple/go.mod index 2862ede61690..de772564f44d 100644 --- a/examples/golang-http/simple/go.mod +++ b/examples/golang-http/simple/go.mod @@ -5,16 +5,16 @@ go 1.20 // NOTICE: these lines could be generated automatically by "go mod tidy" require ( - github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa github.com/envoyproxy/envoy v1.24.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 ) require ( - github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect ) // TODO: remove when #26173 lands. diff --git a/examples/golang-http/simple/go.sum b/examples/golang-http/simple/go.sum index 67cbb674021e..1e61a638aab7 100644 --- a/examples/golang-http/simple/go.sum +++ b/examples/golang-http/simple/go.sum @@ -1,58 +1,18 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/examples/golang-network/simple/go.mod b/examples/golang-network/simple/go.mod index 19bb4281e315..17886eea7c47 100644 --- a/examples/golang-network/simple/go.mod +++ b/examples/golang-network/simple/go.mod @@ -5,16 +5,16 @@ go 1.18 // NOTICE: these lines could be generated automatically by "go mod tidy" require ( - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa github.com/envoyproxy/envoy v1.24.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 ) require ( - github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.5.9 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect ) // TODO: remove when #26173 lands. diff --git a/examples/golang-network/simple/go.sum b/examples/golang-network/simple/go.sum index 31c4080a6846..1e61a638aab7 100644 --- a/examples/golang-network/simple/go.sum +++ b/examples/golang-network/simple/go.sum @@ -1,58 +1,18 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/go.mod b/go.mod index f9c5998977de..424fa576908f 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,23 @@ module github.com/envoyproxy/envoy go 1.20 -require google.golang.org/protobuf v1.32.0 +require ( + github.com/census-instrumentation/opencensus-proto v0.4.1 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa + github.com/envoyproxy/go-control-plane v0.12.0 + github.com/envoyproxy/protoc-gen-validate v1.0.2 + github.com/golang/protobuf v1.5.3 + github.com/prometheus/client_model v0.5.0 + go.opentelemetry.io/proto/otlp v1.0.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 +) + +require ( + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect +) diff --git a/go.sum b/go.sum index b010a4f69c81..2f7bac1bdc8c 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,36 @@ -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= From 80673abb094d32e87df398120547b81f39dfe925 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 19:03:28 +0000 Subject: [PATCH 099/126] chore(deps): update ubuntu:22.04 docker digest to 6042500 (#31616) Signed-off-by: Ryan Northey Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- ci/Dockerfile-envoy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/Dockerfile-envoy b/ci/Dockerfile-envoy index 9902045cbf4f..10e95e2fbcfb 100644 --- a/ci/Dockerfile-envoy +++ b/ci/Dockerfile-envoy @@ -1,5 +1,5 @@ ARG BUILD_OS=ubuntu -ARG BUILD_TAG=22.04@sha256:8eab65df33a6de2844c9aefd19efe8ddb87b7df5e9185a4ab73af936225685bb +ARG BUILD_TAG=22.04@sha256:6042500cf4b44023ea1894effe7890666b0c5c7871ed83a97c36c76ae560bb9b ARG ENVOY_VRP_BASE_IMAGE=envoy-base From 222285a316ef13dcae006614f2f9b79289b98d5d Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 19:53:21 +0000 Subject: [PATCH 100/126] configs: Fix `dynamic_resources` API version (#31621) Signed-off-by: Ryan Northey --- .../quick-start/_include/envoy-dynamic-filesystem-demo.yaml | 3 +++ .../start/quick-start/configuration-dynamic-filesystem.rst | 4 ++-- examples/dynamic-config-fs/envoy.yaml | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/root/start/quick-start/_include/envoy-dynamic-filesystem-demo.yaml b/docs/root/start/quick-start/_include/envoy-dynamic-filesystem-demo.yaml index 182eeac9de8e..e35807d0a1cc 100644 --- a/docs/root/start/quick-start/_include/envoy-dynamic-filesystem-demo.yaml +++ b/docs/root/start/quick-start/_include/envoy-dynamic-filesystem-demo.yaml @@ -4,10 +4,13 @@ node: dynamic_resources: cds_config: + resource_api_version: V3 path: /var/lib/envoy/cds.yaml lds_config: + resource_api_version: V3 path: /var/lib/envoy/lds.yaml + admin: address: socket_address: diff --git a/docs/root/start/quick-start/configuration-dynamic-filesystem.rst b/docs/root/start/quick-start/configuration-dynamic-filesystem.rst index 4c7e9dc2f270..43906c34ab66 100644 --- a/docs/root/start/quick-start/configuration-dynamic-filesystem.rst +++ b/docs/root/start/quick-start/configuration-dynamic-filesystem.rst @@ -41,8 +41,8 @@ The :ref:`node ` should s .. literalinclude:: _include/envoy-dynamic-filesystem-demo.yaml :language: yaml :linenos: - :lines: 1-5 - :emphasize-lines: 1-3 + :lines: 1-7 + :emphasize-lines: 1-5 :caption: :download:`envoy-dynamic-filesystem-demo.yaml <_include/envoy-dynamic-filesystem-demo.yaml>` .. _start_quick_start_dynamic_fs_dynamic_resources: diff --git a/examples/dynamic-config-fs/envoy.yaml b/examples/dynamic-config-fs/envoy.yaml index d496dad71643..f5dd7ca5ff04 100644 --- a/examples/dynamic-config-fs/envoy.yaml +++ b/examples/dynamic-config-fs/envoy.yaml @@ -4,9 +4,11 @@ node: dynamic_resources: cds_config: + resource_api_version: V3 path_config_source: path: /var/lib/envoy/cds.yaml lds_config: + resource_api_version: V3 path_config_source: path: /var/lib/envoy/lds.yaml From 4b857dca2c47a34cdb7d97afd3c053aa76f37743 Mon Sep 17 00:00:00 2001 From: IssaAbuKalbein <86603440+IssaAbuKalbein@users.noreply.github.com> Date: Wed, 3 Jan 2024 22:12:54 +0200 Subject: [PATCH 101/126] [UDP Proxy] Add CONNECTION_ID command operator and StreamIdleTimeout response flag (#31125) Signed-off-by: Issa Abu Kalbein --- changelogs/current.yaml | 3 ++ .../filters/udp/udp_proxy/udp_proxy_filter.cc | 17 +++++--- .../filters/udp/udp_proxy/udp_proxy_filter.h | 3 +- .../udp/udp_proxy/udp_proxy_filter_test.cc | 26 ++++++++++--- test/integration/BUILD | 1 + .../udp_tunneling_integration_test.cc | 39 +++++++++++++++++-- 6 files changed, 75 insertions(+), 14 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 294007a5dd2e..eec55c3b936c 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -351,6 +351,9 @@ new_features: - area: redis change: | Added support for the getdel command. +- area: access_log + change: | + Added support for ``%CONNECTION_ID%`` command operator for UDP session access log. deprecated: - area: wasm diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc index 45c331540bee..b257f9c96e90 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.cc @@ -280,13 +280,11 @@ UdpProxyFilter::ActiveSession::ActiveSession(ClusterInfo& cluster, Network::UdpRecvData::LocalPeerAddresses&& addresses, const Upstream::HostConstSharedPtr& host) : cluster_(cluster), addresses_(std::move(addresses)), host_(host), + session_id_(next_global_session_id_++), idle_timer_(cluster.filter_.read_callbacks_->udpListener().dispatcher().createTimer( [this] { onIdleTimer(); })), - udp_session_info_( - StreamInfo::StreamInfoImpl(cluster_.filter_.config_->timeSource(), - std::make_shared( - addresses_.local_, addresses_.peer_))), - session_id_(next_global_session_id_++) { + udp_session_info_(StreamInfo::StreamInfoImpl(cluster_.filter_.config_->timeSource(), + CreateDownstreamConnectionInfoProvider())) { udp_session_info_.setUpstreamInfo(std::make_shared()); cluster_.filter_.config_->stats().downstream_sess_total_.inc(); cluster_.filter_.config_->stats().downstream_sess_active_.inc(); @@ -339,6 +337,14 @@ void UdpProxyFilter::ActiveSession::onSessionComplete() { on_session_complete_called_ = true; } +std::shared_ptr +UdpProxyFilter::ActiveSession::CreateDownstreamConnectionInfoProvider() { + auto downstream_connection_info_provider = + std::make_shared(addresses_.local_, addresses_.peer_); + downstream_connection_info_provider->setConnectionID(session_id_); + return downstream_connection_info_provider; +} + void UdpProxyFilter::ActiveSession::fillSessionStreamInfo() { ProtobufWkt::Struct stats_obj; auto& fields_map = *stats_obj.mutable_fields(); @@ -1069,6 +1075,7 @@ void UdpProxyFilter::TunnelingActiveSession::onUpstreamData(Buffer::Instance& da void UdpProxyFilter::TunnelingActiveSession::onIdleTimer() { ENVOY_LOG(debug, "session idle timeout: downstream={} local={}", addresses_.peer_->asStringView(), addresses_.local_->asStringView()); + udp_session_info_.setResponseFlag(StreamInfo::ResponseFlag::StreamIdleTimeout); cluster_.filter_.config_->stats().idle_timeout_.inc(); upstream_->onDownstreamEvent(Network::ConnectionEvent::LocalClose); cluster_.removeSession(this); diff --git a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h index cd66e5031178..9f7da664bc97 100644 --- a/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h +++ b/source/extensions/filters/udp/udp_proxy/udp_proxy_filter.h @@ -597,6 +597,7 @@ class UdpProxyFilter : public Network::UdpListenerReadFilter, ClusterInfo& cluster_; const Network::UdpRecvData::LocalPeerAddresses addresses_; Upstream::HostConstSharedPtr host_; + uint64_t session_id_; // TODO(mattklein123): Consider replacing an idle timer for each session with a last used // time stamp and a periodic scan of all sessions to look for timeouts. This solution is simple, // though it might not perform well for high volume traffic. Note that this is how TCP proxy @@ -607,11 +608,11 @@ class UdpProxyFilter : public Network::UdpListenerReadFilter, UdpProxySessionStats session_stats_{}; StreamInfo::StreamInfoImpl udp_session_info_; - uint64_t session_id_; std::list read_filters_; std::list write_filters_; private: + std::shared_ptr CreateDownstreamConnectionInfoProvider(); void onAccessLogFlushInterval(); void rearmAccessLogFlushTimer(); void disableAccessLogFlushTimer(); diff --git a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc index 571b4816d4bb..02f4dfff74b0 100644 --- a/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc +++ b/test/extensions/filters/udp/udp_proxy/udp_proxy_filter_test.cc @@ -428,7 +428,7 @@ class UdpProxyFilterIpv4Ipv6Test : public UdpProxyFilterIpv6Test { } }; -// Basic UDP proxy flow with a single session. Also test disabling GRO. +// Basic UDP proxy flow with two sessions. Also test disabling GRO. TEST_F(UdpProxyFilterTest, BasicFlow) { InSequence s; @@ -437,6 +437,7 @@ TEST_F(UdpProxyFilterTest, BasicFlow) { "%DYNAMIC_METADATA(udp.proxy.session:datagrams_received)% " "%DYNAMIC_METADATA(udp.proxy.session:bytes_sent)% " "%DYNAMIC_METADATA(udp.proxy.session:datagrams_sent)% " + "%CONNECTION_ID% " "%DOWNSTREAM_REMOTE_ADDRESS% " "%DOWNSTREAM_LOCAL_ADDRESS% " "%UPSTREAM_HOST% " @@ -467,6 +468,10 @@ stat_prefix: foo session_access_log_format, proxy_access_log_format), true, false); + // Allow for two sessions. + factory_context_.server_factory_context_.cluster_manager_.thread_local_cluster_.cluster_.info_ + ->resetResourceManager(2, 0, 0, 0, 0); + expectSessionCreate(upstream_address_); test_sessions_[0].expectWriteToUpstream("hello", 0, nullptr, true); recvDataFromDownstream("10.0.0.1:1000", "10.0.0.2:80", "hello"); @@ -488,15 +493,26 @@ stat_prefix: foo test_sessions_[0].recvDataFromUpstream("world3"); checkTransferStats(17 /*rx_bytes*/, 3 /*rx_datagrams*/, 17 /*tx_bytes*/, 3 /*tx_datagrams*/); + expectSessionCreate(upstream_address_); + test_sessions_[1].expectWriteToUpstream("hello4", 0, nullptr, true); + recvDataFromDownstream("10.0.0.3:1000", "10.0.0.2:80", "hello4"); + EXPECT_EQ(2, config_->stats().downstream_sess_total_.value()); + EXPECT_EQ(2, config_->stats().downstream_sess_active_.value()); + checkTransferStats(23 /*rx_bytes*/, 4 /*rx_datagrams*/, 17 /*tx_bytes*/, 3 /*tx_datagrams*/); + test_sessions_[1].recvDataFromUpstream("world4"); + checkTransferStats(23 /*rx_bytes*/, 4 /*rx_datagrams*/, 23 /*tx_bytes*/, 4 /*tx_datagrams*/); + filter_.reset(); - EXPECT_EQ(output_.size(), 2); - EXPECT_EQ(output_.front(), "17 3 17 3 0 1 0"); + EXPECT_EQ(output_.size(), 3); + EXPECT_EQ(output_[0], "23 4 23 4 0 2 0"); + const std::string session_access_log_regex = - "17 3 17 3 10.0.0.1:1000 10.0.0.2:80 20.0.0.1:443 " + "(17 3 17 3 0|6 1 6 1 1) 10.0.0.(1|3):1000 10.0.0.2:80 20.0.0.1:443 " "[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12} " + AccessLogType_Name(AccessLog::AccessLogType::UdpSessionEnd); - EXPECT_TRUE(std::regex_match(output_.back(), std::regex(session_access_log_regex))); + EXPECT_TRUE(std::regex_match(output_[1], std::regex(session_access_log_regex))); + EXPECT_TRUE(std::regex_match(output_[2], std::regex(session_access_log_regex))); } // Route with source IP. diff --git a/test/integration/BUILD b/test/integration/BUILD index 2cd45af6b497..39f09bce4476 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -1856,6 +1856,7 @@ envoy_cc_test( deps = [ ":http_integration_lib", ":http_protocol_integration_lib", + "//source/common/stream_info:utility_lib", "//source/extensions/filters/udp/udp_proxy:config", "//source/extensions/filters/udp/udp_proxy/session_filters/http_capsule:config", "//source/extensions/upstreams/http/udp:config", diff --git a/test/integration/udp_tunneling_integration_test.cc b/test/integration/udp_tunneling_integration_test.cc index cf8fa2b38276..1809d117a52f 100644 --- a/test/integration/udp_tunneling_integration_test.cc +++ b/test/integration/udp_tunneling_integration_test.cc @@ -6,6 +6,8 @@ #include "envoy/extensions/filters/udp/udp_proxy/v3/udp_proxy.pb.h" #include "envoy/extensions/upstreams/http/udp/v3/udp_connection_pool.pb.h" +#include "source/common/stream_info/utility.h" + #include "test/integration/http_integration.h" #include "test/integration/http_protocol_integration.h" @@ -571,7 +573,30 @@ TEST_P(UdpTunnelingIntegrationTest, TwoConsecutiveDownstreamSessions) { } TEST_P(UdpTunnelingIntegrationTest, IdleTimeout) { - TestConfig config{"host.com", "target.com", 1, 30, false, "", BufferOptions{1, 30}, "0.5s"}; + const std::string access_log_filename = + TestEnvironment::temporaryPath(TestUtility::uniqueFilename()); + + const std::string session_access_log_config = fmt::format(R"EOF( + access_log: + - name: envoy.access_loggers.file + typed_config: + '@type': type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: {} + log_format: + text_format_source: + inline_string: "%RESPONSE_FLAGS%\n" +)EOF", + access_log_filename); + + const TestConfig config{"host.com", + "target.com", + 1, + 30, + false, + "", + BufferOptions{1, 30}, + "0.5s", + session_access_log_config}; setup(config); const std::string datagram = "hello"; @@ -583,6 +608,9 @@ TEST_P(UdpTunnelingIntegrationTest, IdleTimeout) { test_server_->waitForCounterEq("udp.foo.idle_timeout", 1); ASSERT_TRUE(upstream_request_->waitForReset()); test_server_->waitForGaugeEq("udp.foo.downstream_sess_active", 0); + + EXPECT_THAT(waitForAccessLog(access_log_filename), + testing::HasSubstr(StreamInfo::ResponseFlagUtils::STREAM_IDLE_TIMEOUT)); } TEST_P(UdpTunnelingIntegrationTest, BufferOverflowDueToCapacity) { @@ -710,7 +738,10 @@ TEST_P(UdpTunnelingIntegrationTest, FailureOnBadResponseHeaders) { test_server_->waitForCounterEq("cluster.cluster_0.udp.sess_tunnel_success", 0); test_server_->waitForGaugeEq("udp.foo.downstream_sess_active", 0); - EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr("1 UF,URX")); + const std::string expected_log = + "1 " + std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_CONNECTION_FAILURE) + "," + + std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_RETRY_LIMIT_EXCEEDED); + EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr(expected_log)); } TEST_P(UdpTunnelingIntegrationTest, ConnectionAttemptRetry) { @@ -766,7 +797,9 @@ TEST_P(UdpTunnelingIntegrationTest, ConnectionAttemptRetry) { sendCapsuleDownstream("response", true); test_server_->waitForGaugeEq("udp.foo.downstream_sess_active", 0); - EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr("2 UF")); + const std::string expected_log = + "2 " + std::string(StreamInfo::ResponseFlagUtils::UPSTREAM_CONNECTION_FAILURE); + EXPECT_THAT(waitForAccessLog(access_log_filename), testing::HasSubstr(expected_log)); } TEST_P(UdpTunnelingIntegrationTest, PropagateValidResponseHeaders) { From 3d67a3f940db59057a6f22db81fae8ecf2bcf5d3 Mon Sep 17 00:00:00 2001 From: phlax Date: Wed, 3 Jan 2024 20:15:18 +0000 Subject: [PATCH 102/126] oauth2: Add default expiry for RFC compliance (#31499) Signed-off-by: Ryan Northey --- .../filters/http/oauth2/v3/oauth.proto | 9 ++- changelogs/current.yaml | 6 ++ source/common/protobuf/utility.h | 6 ++ .../extensions/filters/http/oauth2/config.cc | 4 +- .../extensions/filters/http/oauth2/filter.cc | 3 +- .../extensions/filters/http/oauth2/filter.h | 3 +- .../filters/http/oauth2/oauth_client.cc | 16 +++- .../filters/http/oauth2/oauth_client.h | 6 +- .../filters/http/oauth2/oauth_test.cc | 73 ++++++++++++++++++- 9 files changed, 114 insertions(+), 12 deletions(-) diff --git a/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto b/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto index 8e0574afe4b1..666ebab58d33 100644 --- a/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto +++ b/api/envoy/extensions/filters/http/oauth2/v3/oauth.proto @@ -7,6 +7,7 @@ import "envoy/config/route/v3/route_components.proto"; import "envoy/extensions/transport_sockets/tls/v3/secret.proto"; import "envoy/type/matcher/v3/path.proto"; +import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; @@ -73,7 +74,7 @@ message OAuth2Credentials { // OAuth config // -// [#next-free-field: 13] +// [#next-free-field: 14] message OAuth2Config { enum AuthType { // The ``client_id`` and ``client_secret`` will be sent in the URL encoded request body. @@ -130,6 +131,12 @@ message OAuth2Config { // `RFC 6749 section 6 `_), provided that the OAuth server supports that. // Default value is false. google.protobuf.BoolValue use_refresh_token = 12; + + // The default lifetime in seconds of the access token, if omitted by the authorization server. + // + // If this value is not set, it will default to ``0s``. In this case, the expiry must be set by + // the authorization server or the OAuth flow will fail. + google.protobuf.Duration default_expires_in = 13; } // Filter config. diff --git a/changelogs/current.yaml b/changelogs/current.yaml index eec55c3b936c..47a871a78008 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -158,6 +158,12 @@ bug_fixes: - area: ext_authz change: | Fixed a bug to ensure the proper functioning of the ``with_request_body`` feature within the per-route ExtAuthZ filter. +- area: oauth + change: | + Add :ref:`default_expires_in ` configuration + setting. The OAuth spec does not dictate that an authorization server must respond with an expiry. Envoy currently + fails any OAuth flow if the expiry is not set. This setting allows you to provide a default in this case to ensure + the OAuth flow can succeed. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/protobuf/utility.h b/source/common/protobuf/utility.h index 4d9c5bbdffcb..092624c6a3ad 100644 --- a/source/common/protobuf/utility.h +++ b/source/common/protobuf/utility.h @@ -61,6 +61,12 @@ return DurationUtil::durationToMilliseconds(msg.field_name()); \ }((message))) +// Obtain the milliseconds value of a google.protobuf.Duration field if set. Otherwise, return the +// default value. +#define PROTOBUF_GET_SECONDS_OR_DEFAULT(message, field_name, default_value) \ + ((message).has_##field_name() ? DurationUtil::durationToSeconds((message).field_name()) \ + : (default_value)) + // Obtain the seconds value of a google.protobuf.Duration field if set. Otherwise, throw an // EnvoyException. #define PROTOBUF_GET_SECONDS_REQUIRED(message, field_name) \ diff --git a/source/extensions/filters/http/oauth2/config.cc b/source/extensions/filters/http/oauth2/config.cc index 3a52657c7bf7..98fd1f7dd6d8 100644 --- a/source/extensions/filters/http/oauth2/config.cc +++ b/source/extensions/filters/http/oauth2/config.cc @@ -72,8 +72,8 @@ Http::FilterFactoryCb OAuth2Config::createFilterFactoryFromProtoTyped( return [&context, config, &cluster_manager](Http::FilterChainFactoryCallbacks& callbacks) -> void { - std::unique_ptr oauth_client = - std::make_unique(cluster_manager, config->oauthTokenEndpoint()); + std::unique_ptr oauth_client = std::make_unique( + cluster_manager, config->oauthTokenEndpoint(), config->defaultExpiresIn()); callbacks.addStreamFilter(std::make_shared( config, std::move(oauth_client), context.serverFactoryContext().timeSource())); }; diff --git a/source/extensions/filters/http/oauth2/filter.cc b/source/extensions/filters/http/oauth2/filter.cc index 33b509d6d620..d451be546e9d 100644 --- a/source/extensions/filters/http/oauth2/filter.cc +++ b/source/extensions/filters/http/oauth2/filter.cc @@ -196,7 +196,8 @@ FilterConfig::FilterConfig( pass_through_header_matchers_(headerMatchers(proto_config.pass_through_matcher())), cookie_names_(proto_config.credentials().cookie_names()), auth_type_(getAuthType(proto_config.auth_type())), - use_refresh_token_(proto_config.use_refresh_token().value()) { + use_refresh_token_(proto_config.use_refresh_token().value()), + default_expires_in_(PROTOBUF_GET_SECONDS_OR_DEFAULT(proto_config, default_expires_in, 0)) { if (!cluster_manager.clusters().hasCluster(oauth_token_endpoint_.cluster())) { throw EnvoyException(fmt::format("OAuth2 filter: unknown cluster '{}' in config. Please " "specify which cluster to direct OAuth requests to.", diff --git a/source/extensions/filters/http/oauth2/filter.h b/source/extensions/filters/http/oauth2/filter.h index b47d0c2ce873..3e86351fc98b 100644 --- a/source/extensions/filters/http/oauth2/filter.h +++ b/source/extensions/filters/http/oauth2/filter.h @@ -142,7 +142,6 @@ class FilterConfig { const std::vector& passThroughMatchers() const { return pass_through_header_matchers_; } - const envoy::config::core::v3::HttpUri& oauthTokenEndpoint() const { return oauth_token_endpoint_; } @@ -160,6 +159,7 @@ class FilterConfig { const CookieNames& cookieNames() const { return cookie_names_; } const AuthType& authType() const { return auth_type_; } bool useRefreshToken() const { return use_refresh_token_; } + std::chrono::seconds defaultExpiresIn() const { return default_expires_in_; } private: static FilterStats generateStats(const std::string& prefix, Stats::Scope& scope); @@ -182,6 +182,7 @@ class FilterConfig { const CookieNames cookie_names_; const AuthType auth_type_; const bool use_refresh_token_{}; + const std::chrono::seconds default_expires_in_; }; using FilterConfigSharedPtr = std::shared_ptr; diff --git a/source/extensions/filters/http/oauth2/oauth_client.cc b/source/extensions/filters/http/oauth2/oauth_client.cc index b7be673c761d..3b3daccdedf9 100644 --- a/source/extensions/filters/http/oauth2/oauth_client.cc +++ b/source/extensions/filters/http/oauth2/oauth_client.cc @@ -16,6 +16,8 @@ #include "source/common/protobuf/utility.h" #include "source/extensions/filters/http/oauth2/oauth_response.pb.h" +using namespace std::chrono_literals; + namespace Envoy { namespace Extensions { namespace HttpFilters { @@ -156,8 +158,8 @@ void OAuth2ClientImpl::onSuccess(const Http::AsyncClient::Request&, // TODO(snowp): Should this be a pgv validation instead? A more readable log // message might be good enough reason to do this manually? - if (!response.has_access_token() || !response.has_expires_in()) { - ENVOY_LOG(debug, "No access token or expiration after asyncGetAccessToken"); + if (!response.has_access_token()) { + ENVOY_LOG(debug, "No access token after asyncGetAccessToken"); parent_->sendUnauthorizedResponse(); return; } @@ -166,7 +168,15 @@ void OAuth2ClientImpl::onSuccess(const Http::AsyncClient::Request&, const std::string id_token{PROTOBUF_GET_WRAPPED_OR_DEFAULT(response, id_token, EMPTY_STRING)}; const std::string refresh_token{ PROTOBUF_GET_WRAPPED_OR_DEFAULT(response, refresh_token, EMPTY_STRING)}; - const std::chrono::seconds expires_in{PROTOBUF_GET_WRAPPED_REQUIRED(response, expires_in)}; + std::chrono::seconds expires_in = default_expires_in_; + if (response.has_expires_in()) { + expires_in = std::chrono::seconds{response.expires_in().value()}; + } + if (expires_in <= 0s) { + ENVOY_LOG(debug, "No default or explicit access token expiration after asyncGetAccessToken"); + parent_->sendUnauthorizedResponse(); + return; + } switch (oldState) { case OAuthState::PendingAccessToken: diff --git a/source/extensions/filters/http/oauth2/oauth_client.h b/source/extensions/filters/http/oauth2/oauth_client.h index d18823c0ccbf..21161c916f1a 100644 --- a/source/extensions/filters/http/oauth2/oauth_client.h +++ b/source/extensions/filters/http/oauth2/oauth_client.h @@ -43,8 +43,9 @@ class OAuth2Client : public Http::AsyncClient::Callbacks { class OAuth2ClientImpl : public OAuth2Client, Logger::Loggable { public: - OAuth2ClientImpl(Upstream::ClusterManager& cm, const envoy::config::core::v3::HttpUri& uri) - : cm_(cm), uri_(uri) {} + OAuth2ClientImpl(Upstream::ClusterManager& cm, const envoy::config::core::v3::HttpUri& uri, + const std::chrono::seconds default_expires_in) + : cm_(cm), uri_(uri), default_expires_in_(default_expires_in) {} ~OAuth2ClientImpl() override { if (in_flight_request_ != nullptr) { @@ -79,6 +80,7 @@ class OAuth2ClientImpl : public OAuth2Client, Logger::Loggableset_seconds(1); cm_.initializeThreadLocalClusters({"auth"}); - client_ = std::make_shared(cm_, uri); + client_ = std::make_shared(cm_, uri, 0s); } ABSL_MUST_USE_RESULT @@ -101,7 +103,74 @@ TEST_F(OAuth2ClientTest, RequestAccessTokenSuccess) { client_->setCallbacks(*mock_callbacks_); client_->asyncGetAccessToken("a", "b", "c", "d"); EXPECT_EQ(1, callbacks_.size()); - EXPECT_CALL(*mock_callbacks_, onGetAccessTokenSuccess(_, _, _, _)); + EXPECT_CALL(*mock_callbacks_, onGetAccessTokenSuccess("golden ticket", _, _, 1000s)); + Http::MockAsyncClientRequest request(&cm_.thread_local_cluster_.async_client_); + ASSERT_TRUE(popPendingCallback( + [&](auto* callback) { callback->onSuccess(request, std::move(mock_response)); })); +} + +TEST_F(OAuth2ClientTest, RequestAccessTokenMissingExpiresIn) { + std::string json = R"EOF( + { + "access_token": "golden ticket" + } + )EOF"; + Http::ResponseHeaderMapPtr mock_response_headers{new Http::TestResponseHeaderMapImpl{ + {Http::Headers::get().Status.get(), "200"}, + {Http::Headers::get().ContentType.get(), "application/json"}, + }}; + Http::ResponseMessagePtr mock_response( + new Http::ResponseMessageImpl(std::move(mock_response_headers))); + mock_response->body().add(json); + + EXPECT_CALL(cm_.thread_local_cluster_.async_client_, send_(_, _, _)) + .WillRepeatedly( + Invoke([&](Http::RequestMessagePtr&, Http::AsyncClient::Callbacks& cb, + const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { + callbacks_.push_back(&cb); + return &request_; + })); + + client_->setCallbacks(*mock_callbacks_); + client_->asyncGetAccessToken("a", "b", "c", "d"); + EXPECT_EQ(1, callbacks_.size()); + EXPECT_CALL(*mock_callbacks_, sendUnauthorizedResponse()); + Http::MockAsyncClientRequest request(&cm_.thread_local_cluster_.async_client_); + ASSERT_TRUE(popPendingCallback( + [&](auto* callback) { callback->onSuccess(request, std::move(mock_response)); })); +} + +TEST_F(OAuth2ClientTest, RequestAccessTokenDefaultExpiresIn) { + std::string json = R"EOF( + { + "access_token": "golden ticket" + } + )EOF"; + Http::ResponseHeaderMapPtr mock_response_headers{new Http::TestResponseHeaderMapImpl{ + {Http::Headers::get().Status.get(), "200"}, + {Http::Headers::get().ContentType.get(), "application/json"}, + }}; + Http::ResponseMessagePtr mock_response( + new Http::ResponseMessageImpl(std::move(mock_response_headers))); + mock_response->body().add(json); + + EXPECT_CALL(cm_.thread_local_cluster_.async_client_, send_(_, _, _)) + .WillRepeatedly( + Invoke([&](Http::RequestMessagePtr&, Http::AsyncClient::Callbacks& cb, + const Http::AsyncClient::RequestOptions&) -> Http::AsyncClient::Request* { + callbacks_.push_back(&cb); + return &request_; + })); + + envoy::config::core::v3::HttpUri uri; + uri.set_cluster("auth"); + uri.set_uri("auth.com/oauth/token"); + uri.mutable_timeout()->set_seconds(1); + client_ = std::make_shared(cm_, uri, 2000s); + client_->setCallbacks(*mock_callbacks_); + client_->asyncGetAccessToken("a", "b", "c", "d"); + EXPECT_EQ(1, callbacks_.size()); + EXPECT_CALL(*mock_callbacks_, onGetAccessTokenSuccess("golden ticket", _, _, 2000s)); Http::MockAsyncClientRequest request(&cm_.thread_local_cluster_.async_client_); ASSERT_TRUE(popPendingCallback( [&](auto* callback) { callback->onSuccess(request, std::move(mock_response)); })); From 7fc9415b750f16242cb508fcfd6608427cc0f3fb Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Wed, 3 Jan 2024 23:04:29 -0500 Subject: [PATCH 103/126] quic: fixing a test flake (#31613) Signed-off-by: Alyssa Wilk --- .../http/buffer/buffer_filter_integration_test.cc | 1 + test/integration/http_integration.cc | 10 +++++++++- test/integration/protocol_integration_test.cc | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc b/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc index ee3d5607dc0f..915b1b997c4c 100644 --- a/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc +++ b/test/extensions/filters/http/buffer/buffer_filter_integration_test.cc @@ -132,6 +132,7 @@ TEST_P(BufferIntegrationTest, RouterRequestBufferLimitExceeded) { ASSERT_TRUE(response->waitForEndStream()); ASSERT_TRUE(response->complete()); EXPECT_EQ("413", response->headers().getStatusValue()); + cleanupUpstreamAndDownstream(); } ConfigHelper::HttpModifierFunction overrideConfig(const std::string& json_config) { diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 4bfebe84cfd2..59e3c6bbac9e 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -349,7 +349,15 @@ void HttpIntegrationTest::useAccessLog( ASSERT_TRUE(config_helper_.setAccessLog(access_log_name_, format, formatters)); } -HttpIntegrationTest::~HttpIntegrationTest() { cleanupUpstreamAndDownstream(); } +HttpIntegrationTest::~HttpIntegrationTest() { + // Make sure any open streams have been closed. If there's an open stream, the decoder will + // be out of scope, and so open streams result in writing to freed memory. + if (codec_client_) { + EXPECT_EQ(codec_client_->numActiveRequests(), 0) + << "test requires explicit cleanupUpstreamAndDownstream"; + } + cleanupUpstreamAndDownstream(); +} void HttpIntegrationTest::initialize() { if (downstream_protocol_ != Http::CodecType::HTTP3) { diff --git a/test/integration/protocol_integration_test.cc b/test/integration/protocol_integration_test.cc index 0a58b55ce8df..271c020b15ac 100644 --- a/test/integration/protocol_integration_test.cc +++ b/test/integration/protocol_integration_test.cc @@ -255,11 +255,13 @@ TEST_P(DownstreamProtocolIntegrationTest, AddInvalidEncodedData) { initialize(); codec_client_ = makeHttpConnection(lookupPort("http")); default_request_headers_.setCopy(Envoy::Http::LowerCaseString("invalid-encode"), "yes"); - auto response = std::move((codec_client_->startRequest(default_request_headers_)).second); + auto encoder_decoder = codec_client_->startRequest(default_request_headers_); + auto response = std::move(encoder_decoder.second); ASSERT_TRUE(response->waitForEndStream()); EXPECT_EQ("502", response->headers().getStatusValue()); EXPECT_THAT(waitForAccessLog(access_log_name_), HasSubstr("filter_added_invalid_response_data")); + cleanupUpstreamAndDownstream(); }, "Invalid response data"); } From ec4faf01d9da2a971623d79b2c28714b278d34db Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Thu, 4 Jan 2024 00:04:08 -0500 Subject: [PATCH 104/126] mobile: Remove redundant check in Client::getStream() (#31625) Signed-off-by: Ali Beyad --- mobile/library/common/http/client.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/library/common/http/client.cc b/mobile/library/common/http/client.cc index 2ca3a7901342..2eb8390298f0 100644 --- a/mobile/library/common/http/client.cc +++ b/mobile/library/common/http/client.cc @@ -659,7 +659,7 @@ Client::DirectStreamSharedPtr Client::getStream(envoy_stream_t stream, if (direct_stream_pair_it != streams_.end()) { return direct_stream_pair_it->second; } - if (direct_stream_pair_it == streams_.end() && get_stream_filters == ALLOW_FOR_ALL_STREAMS) { + if (get_stream_filters == ALLOW_FOR_ALL_STREAMS) { direct_stream_pair_it = closed_streams_.find(stream); if (direct_stream_pair_it != closed_streams_.end()) { return direct_stream_pair_it->second; From bf5f5a61f41606bc0dd52e8e1ce34a512f347a5f Mon Sep 17 00:00:00 2001 From: River <6375745+RiverPhillips@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:04:55 +0000 Subject: [PATCH 105/126] chore(deps): bump `rules_rust` -> 0.35.0 (#31539) Signed-off-by: River Phillips Co-authored-by: Ryan Northey --- bazel/repository_locations.bzl | 13 +++++++++---- bazel/rules_rust.patch | 28 ++++------------------------ 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 00c8b9678dc3..2514184a9171 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1446,13 +1446,18 @@ REPOSITORY_LOCATIONS_SPEC = dict( project_name = "Bazel rust rules", project_desc = "Bazel rust rules (used by Wasm)", project_url = "https://github.com/bazelbuild/rules_rust", - version = "0.27.0", + version = "0.35.0", strip_prefix = "rules_rust-{version}", - sha256 = "d9a3981f4ef18ced850341bc05c7e2a506006a47a0207b6f7191f271cb893233", + sha256 = "3120c7aa3a146dfe6be8d5f23f4cf10af7d0f74a5aed8b94a818f88643bd24c3", urls = ["https://github.com/bazelbuild/rules_rust/archive/{version}.tar.gz"], - use_category = ["dataplane_ext"], + use_category = [ + "controlplane", + "dataplane_core", + "dataplane_ext", + ], + implied_untracked_deps = ["rules_cc"], extensions = ["envoy.wasm.runtime.wasmtime"], - release_date = "2023-08-31", + release_date = "2023-12-27", cpe = "N/A", license = "Apache-2.0", license_url = "https://github.com/bazelbuild/rules_rust/blob/{version}/LICENSE.txt", diff --git a/bazel/rules_rust.patch b/bazel/rules_rust.patch index 484e8109ad22..e00bfdfd006d 100644 --- a/bazel/rules_rust.patch +++ b/bazel/rules_rust.patch @@ -1,29 +1,9 @@ -# https://github.com/bazelbuild/rules_rust/pull/1259 - ---- rust/platform/triple_mappings.bzl -+++ rust/platform/triple_mappings.bzl -@@ -269,6 +269,13 @@ def triple_to_constraint_set(target_triple): - "@rules_rust//rust/platform/os:unknown", - ] - -+ # Workaround for https://github.com/bazelbuild/bazel/issues/14982 -+ if target_triple in ("armv7-linux-androideabi", "thumbv7neon-linux-androideabi"): -+ return [ -+ "@platforms//cpu:arm", -+ "@platforms//os:android", -+ ] -+ - triple_struct = triple(target_triple) - - constraint_set = [] - - --- rust/private/rustc.bzl +++ rust/private/rustc.bzl -@@ -1024,7 +1024,7 @@ def rustc_compile_action( - ), - ] - +@@ -1451,7 +1451,7 @@ def rustc_compile_action( + }) + crate_info = rust_common.create_crate_info(**crate_info_dict) + - if crate_info.type in ["staticlib", "cdylib"]: + if crate_info.type in ["staticlib", "cdylib"] and not out_binary: # These rules are not supposed to be depended on by other rust targets, and From 07d5d7e236a4c96c77f0d4c89fd098416d1723bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:08:30 +0000 Subject: [PATCH 106/126] build(deps): bump the contrib-golang group in /contrib/golang/router/cluster_specifier/test/test_data/simple with 1 update (#31583) build(deps): bump the contrib-golang group Bumps the contrib-golang group in /contrib/golang/router/cluster_specifier/test/test_data/simple with 1 update: google.golang.org/protobuf. Updates `google.golang.org/protobuf` from 1.31.0 to 1.32.0 --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor dependency-group: contrib-golang ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../cluster_specifier/test/test_data/simple/go.mod | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/contrib/golang/router/cluster_specifier/test/test_data/simple/go.mod b/contrib/golang/router/cluster_specifier/test/test_data/simple/go.mod index f36b3e42a285..5ec718d9cfc0 100644 --- a/contrib/golang/router/cluster_specifier/test/test_data/simple/go.mod +++ b/contrib/golang/router/cluster_specifier/test/test_data/simple/go.mod @@ -3,17 +3,19 @@ module example.com/routeconfig go 1.18 require ( - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa github.com/envoyproxy/envoy v1.28.0 ) -require github.com/google/go-cmp v0.5.9 // indirect +require ( + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect +) require ( - github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 ) replace github.com/envoyproxy/envoy => ../../../../../../../ From 35ab7e521662e8046ab5c1a1d56128b6181af107 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:09:23 +0000 Subject: [PATCH 107/126] build(deps): bump the contrib-golang group in /contrib/golang/filters/http/test/test_data/action with 1 update (#31582) build(deps): bump the contrib-golang group Bumps the contrib-golang group in /contrib/golang/filters/http/test/test_data/action with 1 update: google.golang.org/protobuf. Updates `google.golang.org/protobuf` from 1.31.0 to 1.32.0 --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor dependency-group: contrib-golang ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../golang/filters/http/test/test_data/action/go.mod | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/contrib/golang/filters/http/test/test_data/action/go.mod b/contrib/golang/filters/http/test/test_data/action/go.mod index 9a07becf6234..bda83466971f 100644 --- a/contrib/golang/filters/http/test/test_data/action/go.mod +++ b/contrib/golang/filters/http/test/test_data/action/go.mod @@ -2,18 +2,10 @@ module example.com/action go 1.20 -require ( - github.com/cncf/xds/go v0.0.0-20230112175826-46e39c7b9b43 - github.com/envoyproxy/envoy v1.24.0 -) +require github.com/envoyproxy/envoy v1.24.0 require github.com/google/go-cmp v0.5.9 // indirect -require ( - github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/protobuf v1.31.0 -) +require google.golang.org/protobuf v1.32.0 // indirect replace github.com/envoyproxy/envoy => ../../../../../../../ From b28f89fc13797c4e3a794e96e15d56597c8c95af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:10:02 +0000 Subject: [PATCH 108/126] build(deps): bump the contrib-golang group in /contrib/golang/filters/http/test/test_data/routeconfig with 1 update (#31581) build(deps): bump the contrib-golang group Bumps the contrib-golang group in /contrib/golang/filters/http/test/test_data/routeconfig with 1 update: google.golang.org/protobuf. Updates `google.golang.org/protobuf` from 1.31.0 to 1.32.0 --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor dependency-group: contrib-golang ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../filters/http/test/test_data/routeconfig/go.mod | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/contrib/golang/filters/http/test/test_data/routeconfig/go.mod b/contrib/golang/filters/http/test/test_data/routeconfig/go.mod index b11b4ac5d871..9af0f126d93b 100644 --- a/contrib/golang/filters/http/test/test_data/routeconfig/go.mod +++ b/contrib/golang/filters/http/test/test_data/routeconfig/go.mod @@ -3,17 +3,19 @@ module example.com/routeconfig go 1.20 require ( - github.com/cncf/xds/go v0.0.0-20230112175826-46e39c7b9b43 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa github.com/envoyproxy/envoy v1.24.0 ) -require github.com/google/go-cmp v0.5.9 // indirect +require ( + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect +) require ( - github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/protobuf v1.31.0 + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + google.golang.org/protobuf v1.32.0 ) replace github.com/envoyproxy/envoy => ../../../../../../../ From fe8380756301a720fcd174902530f717a4b36243 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:10:19 +0000 Subject: [PATCH 109/126] build(deps): bump the contrib-golang group in /contrib/golang/filters/http/test/test_data/echo with 1 update (#31580) build(deps): bump the contrib-golang group Bumps the contrib-golang group in /contrib/golang/filters/http/test/test_data/echo with 1 update: google.golang.org/protobuf. Updates `google.golang.org/protobuf` from 1.31.0 to 1.32.0 --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor dependency-group: contrib-golang ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../golang/filters/http/test/test_data/echo/go.mod | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/contrib/golang/filters/http/test/test_data/echo/go.mod b/contrib/golang/filters/http/test/test_data/echo/go.mod index 7a258b6138a0..9079af021fca 100644 --- a/contrib/golang/filters/http/test/test_data/echo/go.mod +++ b/contrib/golang/filters/http/test/test_data/echo/go.mod @@ -3,17 +3,19 @@ module example.com/echo go 1.20 require ( - github.com/cncf/xds/go v0.0.0-20230112175826-46e39c7b9b43 + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa github.com/envoyproxy/envoy v1.24.0 ) -require github.com/google/go-cmp v0.5.9 // indirect +require ( + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect +) require ( - github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect - google.golang.org/protobuf v1.31.0 + github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + google.golang.org/protobuf v1.32.0 ) replace github.com/envoyproxy/envoy => ../../../../../../../ From 09ee5b1bfbee1c132f16b338f53823eec7233f7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:10:55 +0000 Subject: [PATCH 110/126] build(deps): bump openzipkin/zipkin from `197a969` to `f924731` in /examples/zipkin (#31368) build(deps): bump openzipkin/zipkin in /examples/zipkin Bumps openzipkin/zipkin from `197a969` to `f924731`. --- updated-dependencies: - dependency-name: openzipkin/zipkin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/zipkin/Dockerfile-zipkin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/zipkin/Dockerfile-zipkin b/examples/zipkin/Dockerfile-zipkin index ae7c849d0d59..fb6467dd4f71 100644 --- a/examples/zipkin/Dockerfile-zipkin +++ b/examples/zipkin/Dockerfile-zipkin @@ -1 +1 @@ -FROM openzipkin/zipkin:latest@sha256:197a9692f6a9416488c34741190a1cbc0d52733ed0c24c0303de065215a0a588 +FROM openzipkin/zipkin:latest@sha256:f924731cd0cdf4369ae3f0127bbf69270667c69da8d59232c568232ea7f30b49 From 493d8f87e06550025b693536451e0619c64312fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:11:40 +0000 Subject: [PATCH 111/126] build(deps): bump the examples-ext-authz group in /examples/ext_authz with 1 update (#31575) build(deps): bump the examples-ext-authz group Bumps the examples-ext-authz group in /examples/ext_authz with 1 update: openpolicyagent/opa. Updates `openpolicyagent/opa` from 0.59.0-istio to 0.60.0-istio --- updated-dependencies: - dependency-name: openpolicyagent/opa dependency-type: direct:production update-type: version-update:semver-minor dependency-group: examples-ext-authz ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/ext_authz/Dockerfile-opa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ext_authz/Dockerfile-opa b/examples/ext_authz/Dockerfile-opa index 9b69a5373a4c..53ddab6b56f5 100644 --- a/examples/ext_authz/Dockerfile-opa +++ b/examples/ext_authz/Dockerfile-opa @@ -1 +1 @@ -FROM openpolicyagent/opa:0.59.0-istio@sha256:559c15eeea98c78b4b88779afc17b1db4a09858b59af19594eccaefc96fb29e3 +FROM openpolicyagent/opa:0.60.0-istio@sha256:242a2dbe29b668b524daae8446fb00518ab95a46215bbc17d8b80b2d28370841 From 51d135071efe513c744540d4d096cb94ccf0e847 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:13:05 +0000 Subject: [PATCH 112/126] build(deps): bump the examples-grpc-bridge group in /examples/grpc-bridge/server with 1 update (#31578) build(deps): bump the examples-grpc-bridge group Bumps the examples-grpc-bridge group in /examples/grpc-bridge/server with 1 update: [google.golang.org/grpc](https://github.com/grpc/grpc-go). Updates `google.golang.org/grpc` from 1.60.0 to 1.60.1 - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.60.0...v1.60.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: examples-grpc-bridge ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/grpc-bridge/server/go.mod | 2 +- examples/grpc-bridge/server/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/grpc-bridge/server/go.mod b/examples/grpc-bridge/server/go.mod index 07334fa2cadd..9c041213ffca 100644 --- a/examples/grpc-bridge/server/go.mod +++ b/examples/grpc-bridge/server/go.mod @@ -5,5 +5,5 @@ go 1.13 require ( github.com/golang/protobuf v1.5.3 golang.org/x/net v0.19.0 - google.golang.org/grpc v1.60.0 + google.golang.org/grpc v1.60.1 ) diff --git a/examples/grpc-bridge/server/go.sum b/examples/grpc-bridge/server/go.sum index 6df09c7c39fc..c74c63afaa81 100644 --- a/examples/grpc-bridge/server/go.sum +++ b/examples/grpc-bridge/server/go.sum @@ -1753,8 +1753,8 @@ google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGO google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 55ecc2ff84acada2a57543d4930753ed1a5d3108 Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Thu, 4 Jan 2024 20:33:10 +0800 Subject: [PATCH 113/126] go/deps: regenerate go.mod by go mod vendor. (#31640) Signed-off-by: doujiang24 --- go.mod | 21 ++------------------- go.sum | 34 +--------------------------------- 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/go.mod b/go.mod index 424fa576908f..aa129ca09c2a 100644 --- a/go.mod +++ b/go.mod @@ -2,23 +2,6 @@ module github.com/envoyproxy/envoy go 1.20 -require ( - github.com/census-instrumentation/opencensus-proto v0.4.1 - github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa - github.com/envoyproxy/go-control-plane v0.12.0 - github.com/envoyproxy/protoc-gen-validate v1.0.2 - github.com/golang/protobuf v1.5.3 - github.com/prometheus/client_model v0.5.0 - go.opentelemetry.io/proto/otlp v1.0.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 - google.golang.org/grpc v1.60.1 - google.golang.org/protobuf v1.32.0 -) +require google.golang.org/protobuf v1.32.0 -require ( - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect -) +require github.com/google/go-cmp v0.5.9 // indirect diff --git a/go.sum b/go.sum index 2f7bac1bdc8c..e2499aef30e4 100644 --- a/go.sum +++ b/go.sum @@ -1,36 +1,4 @@ -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= -github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= -github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= -github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= From 839f249bb6890730eea7fabc31bc80bea1d8c6d8 Mon Sep 17 00:00:00 2001 From: Ali Beyad Date: Thu, 4 Jan 2024 09:08:15 -0500 Subject: [PATCH 114/126] quic: Remove unused function in QuicNetworkConnection (#31626) Signed-off-by: Ali Beyad --- source/common/quic/quic_network_connection.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/common/quic/quic_network_connection.h b/source/common/quic/quic_network_connection.h index 828f3eb1f761..39d543d6ecdb 100644 --- a/source/common/quic/quic_network_connection.h +++ b/source/common/quic/quic_network_connection.h @@ -45,8 +45,6 @@ class QuicNetworkConnection : protected Logger::Loggable protected: Network::Connection::ConnectionStats& connectionStats() const { return *connection_stats_; } - std::vector& connectionSockets() { return connection_sockets_; } - void setConnectionSocket(Network::ConnectionSocketPtr&& connection_socket) { connection_sockets_.push_back(std::move(connection_socket)); } From 7a1a883aed9dce124f449a82331228c055812356 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 4 Jan 2024 09:32:57 -0500 Subject: [PATCH 115/126] Resolver: switching to statusor (#31312) resolver: using statusor Signed-off-by: Alyssa Wilk --- envoy/network/resolver.h | 4 +-- .../common/listener_manager/listener_impl.cc | 12 +++++-- .../listener_manager/listener_manager_impl.cc | 4 ++- source/common/network/resolver_impl.cc | 15 ++++---- source/common/network/resolver_impl.h | 8 ++--- .../upstream/health_discovery_service.cc | 18 ++++++---- source/common/upstream/upstream_impl.cc | 30 +++++++++++----- .../network/dns_resolver/cares/dns_impl.cc | 4 ++- .../stat_sinks/dog_statsd/config.cc | 5 +-- .../stat_sinks/graphite_statsd/config.cc | 5 +-- source/extensions/stat_sinks/statsd/config.cc | 5 +-- source/server/api_listener_impl.cc | 20 ++++++++--- source/server/api_listener_impl.h | 13 ++++--- source/server/configuration_impl.cc | 4 ++- test/common/network/resolver_impl_test.cc | 34 +++++++++---------- test/fuzz/utility.h | 3 +- test/mocks/network/mocks.h | 2 +- test/server/api_listener_test.cc | 26 +++++++------- tools/code_format/config.yaml | 1 - 19 files changed, 132 insertions(+), 81 deletions(-) diff --git a/envoy/network/resolver.h b/envoy/network/resolver.h index dcdcfe8a8c92..64e66bff32f8 100644 --- a/envoy/network/resolver.h +++ b/envoy/network/resolver.h @@ -24,9 +24,9 @@ class Resolver : public Config::UntypedFactory { /** * Resolve a custom address string and port to an Address::Instance. * @param socket_address supplies the socket address to resolve. - * @return InstanceConstSharedPtr appropriate Address::Instance. + * @return InstanceConstSharedPtr appropriate Address::Instance or an error status. */ - virtual InstanceConstSharedPtr + virtual absl::StatusOr resolve(const envoy::config::core::v3::SocketAddress& socket_address) PURE; std::string category() const override { return "envoy.resolvers"; } diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 984ebca0a7b9..1c4034620a3f 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -223,7 +223,9 @@ std::string listenerStatsScope(const envoy::config::listener::v3::Listener& conf if (config.has_internal_listener()) { return absl::StrCat("envoy_internal_", config.name()); } - return Network::Address::resolveProtoAddress(config.address())->asString(); + auto address_or_error = Network::Address::resolveProtoAddress(config.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + return address_or_error.value()->asString(); } } // namespace @@ -308,7 +310,9 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, } else { // All the addresses should be same socket type, so get the first address's socket type is // enough. - auto address = Network::Address::resolveProtoAddress(config.address()); + auto address_or_error = Network::Address::resolveProtoAddress(config.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + auto address = std::move(address_or_error.value()); checkIpv4CompatAddress(address, config.address()); addresses_.emplace_back(address); address_opts_list.emplace_back(std::ref(config.socket_options())); @@ -321,8 +325,10 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, "support same socket type for all the addresses.", name_)); } - auto additional_address = + auto addresses_or_error = Network::Address::resolveProtoAddress(config.additional_addresses(i).address()); + THROW_IF_STATUS_NOT_OK(addresses_or_error, throw); + auto additional_address = std::move(addresses_or_error.value()); checkIpv4CompatAddress(address, config.additional_addresses(i).address()); addresses_.emplace_back(additional_address); if (config.additional_addresses(i).has_socket_options()) { diff --git a/source/common/listener_manager/listener_manager_impl.cc b/source/common/listener_manager/listener_manager_impl.cc index 3982b72eed00..853087d0b1bf 100644 --- a/source/common/listener_manager/listener_manager_impl.cc +++ b/source/common/listener_manager/listener_manager_impl.cc @@ -468,7 +468,9 @@ ListenerManagerImpl::addOrUpdateListener(const envoy::config::listener::v3::List name)); } if (!api_listener_ && !added_via_api) { - api_listener_ = std::make_unique(config, server_, config.name()); + auto listener_or_error = HttpApiListener::create(config, server_, config.name()); + THROW_IF_STATUS_NOT_OK(listener_or_error, throw); + api_listener_ = std::move(listener_or_error.value()); return true; } else { ENVOY_LOG(warn, "listener {} can not be added because currently only one ApiListener is " diff --git a/source/common/network/resolver_impl.cc b/source/common/network/resolver_impl.cc index bd51bcfd2272..63119deff8ae 100644 --- a/source/common/network/resolver_impl.cc +++ b/source/common/network/resolver_impl.cc @@ -20,7 +20,7 @@ namespace Address { class IpResolver : public Resolver { public: - InstanceConstSharedPtr + absl::StatusOr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { switch (socket_address.port_specifier_case()) { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kPortValue: @@ -31,8 +31,8 @@ class IpResolver : public Resolver { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort: break; } - throwEnvoyExceptionOrPanic(fmt::format("IP resolver can't handle port specifier type {}", - socket_address.port_specifier_case())); + return absl::InvalidArgumentError(fmt::format("IP resolver can't handle port specifier type {}", + socket_address.port_specifier_case())); } std::string name() const override { return Config::AddressResolverNames::get().IP; } @@ -43,7 +43,8 @@ class IpResolver : public Resolver { */ REGISTER_FACTORY(IpResolver, Resolver); -InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Address& address) { +absl::StatusOr +resolveProtoAddress(const envoy::config::core::v3::Address& address) { switch (address.address_case()) { case envoy::config::core::v3::Address::AddressCase::ADDRESS_NOT_SET: throwEnvoyExceptionOrPanic("Address must be set: " + address.DebugString()); @@ -66,7 +67,7 @@ InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Addres throwEnvoyExceptionOrPanic("Failed to resolve address:" + address.DebugString()); } -InstanceConstSharedPtr +absl::StatusOr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_address) { Resolver* resolver = nullptr; const std::string& resolver_name = socket_address.resolver_name(); @@ -79,7 +80,9 @@ resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_a if (resolver == nullptr) { throwEnvoyExceptionOrPanic(fmt::format("Unknown address resolver: {}", resolver_name)); } - return resolver->resolve(socket_address); + auto instance_or_error = resolver->resolve(socket_address); + THROW_IF_STATUS_NOT_OK(instance_or_error, throw); + return std::move(instance_or_error.value()); } } // namespace Address diff --git a/source/common/network/resolver_impl.h b/source/common/network/resolver_impl.h index fb26085eb00d..f36c0f03b203 100644 --- a/source/common/network/resolver_impl.h +++ b/source/common/network/resolver_impl.h @@ -14,17 +14,17 @@ namespace Address { /** * Create an Instance from a envoy::config::core::v3::Address. * @param address supplies the address proto to resolve. - * @return pointer to the Instance. + * @return pointer to the Instance or an error status */ -Address::InstanceConstSharedPtr +absl::StatusOr resolveProtoAddress(const envoy::config::core::v3::Address& address); /** * Create an Instance from a envoy::config::core::v3::SocketAddress. * @param address supplies the socket address proto to resolve. - * @return pointer to the Instance. + * @return pointer to the Instance or an error status. */ -Address::InstanceConstSharedPtr +absl::StatusOr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& address); DECLARE_FACTORY(IpResolver); diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index b1c659a5529f..4db99e3361d0 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -371,10 +371,11 @@ HdsCluster::HdsCluster(Server::Configuration::ServerFactoryContext& server_conte for (const auto& host : locality_endpoints.lb_endpoints()) { const LocalityEndpointTuple endpoint_key = {locality_endpoints.locality(), host}; // Initialize an endpoint host object. + auto address_or_error = Network::Address::resolveProtoAddress(host.endpoint().address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); HostSharedPtr endpoint = std::make_shared( - info_, "", Network::Address::resolveProtoAddress(host.endpoint().address()), nullptr, 1, - locality_endpoints.locality(), host.endpoint().health_check_config(), 0, - envoy::config::core::v3::UNKNOWN, time_source_); + info_, "", std::move(address_or_error.value()), nullptr, 1, locality_endpoints.locality(), + host.endpoint().health_check_config(), 0, envoy::config::core::v3::UNKNOWN, time_source_); // Add this host/endpoint pointer to our flat list of endpoints for health checking. hosts_->push_back(endpoint); // Add this host/endpoint pointer to our structured list by locality so results can be @@ -483,10 +484,13 @@ void HdsCluster::updateHosts( host = host_pair->second; } else { // We do not have this endpoint saved, so create a new one. - host = std::make_shared( - info_, "", Network::Address::resolveProtoAddress(endpoint.endpoint().address()), - nullptr, 1, endpoints.locality(), endpoint.endpoint().health_check_config(), 0, - envoy::config::core::v3::UNKNOWN, time_source_); + auto address_or_error = + Network::Address::resolveProtoAddress(endpoint.endpoint().address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + host = std::make_shared(info_, "", std::move(address_or_error.value()), nullptr, + 1, endpoints.locality(), + endpoint.endpoint().health_check_config(), 0, + envoy::config::core::v3::UNKNOWN, time_source_); // Set the initial health status as in HdsCluster::initialize. host->healthFlagSet(Host::HealthFlag::FAILED_ACTIVE_HC); diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index aa4e8fc849f9..5c781c9bd70a 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -227,10 +227,14 @@ parseBindConfig(::Envoy::OptRef bind_ std::vector<::Envoy::Upstream::UpstreamLocalAddress> upstream_local_addresses; if (bind_config.has_value()) { UpstreamLocalAddress upstream_local_address; - upstream_local_address.address_ = - bind_config->has_source_address() - ? ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()) - : nullptr; + upstream_local_address.address_ = nullptr; + if (bind_config->has_source_address()) { + + auto address_or_error = + ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + upstream_local_address.address_ = address_or_error.value(); + } upstream_local_address.socket_options_ = std::make_shared(); ::Envoy::Network::Socket::appendOptions(upstream_local_address.socket_options_, @@ -242,8 +246,10 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& extra_source_address : bind_config->extra_source_addresses()) { UpstreamLocalAddress extra_upstream_local_address; - extra_upstream_local_address.address_ = + auto address_or_error = ::Envoy::Network::Address::resolveProtoSocketAddress(extra_source_address.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + extra_upstream_local_address.address_ = address_or_error.value(); extra_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); @@ -264,8 +270,10 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& additional_source_address : bind_config->additional_source_addresses()) { UpstreamLocalAddress additional_upstream_local_address; - additional_upstream_local_address.address_ = + auto address_or_error = ::Envoy::Network::Address::resolveProtoSocketAddress(additional_source_address); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + additional_upstream_local_address.address_ = address_or_error.value(); additional_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); ::Envoy::Network::Socket::appendOptions(additional_upstream_local_address.socket_options_, @@ -1741,7 +1749,11 @@ void ClusterImplBase::reloadHealthyHostsHelper(const HostSharedPtr&) { const Network::Address::InstanceConstSharedPtr ClusterImplBase::resolveProtoAddress(const envoy::config::core::v3::Address& address) { - TRY_ASSERT_MAIN_THREAD { return Network::Address::resolveProtoAddress(address); } + TRY_ASSERT_MAIN_THREAD { + auto address_or_error = Network::Address::resolveProtoAddress(address); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + return address_or_error.value(); + } END_TRY CATCH(EnvoyException & e, { if (info_->type() == envoy::config::cluster::v3::Cluster::STATIC || @@ -2409,7 +2421,9 @@ Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress( Network::Address::InstanceConstSharedPtr health_check_address; const auto& port_value = health_check_config.port_value(); if (health_check_config.has_address()) { - auto address = Network::Address::resolveProtoAddress(health_check_config.address()); + auto address_or_error = Network::Address::resolveProtoAddress(health_check_config.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + auto address = address_or_error.value(); health_check_address = port_value == 0 ? address : Network::Utility::getAddressWithPort(*address, port_value); } else { diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc index f1fec3b6bcc8..64848d6a4331 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.cc +++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc @@ -555,7 +555,9 @@ class CaresDnsResolverFactory : public DnsResolverFactory, const auto& resolver_addrs = cares.resolvers(); resolvers.reserve(resolver_addrs.size()); for (const auto& resolver_addr : resolver_addrs) { - resolvers.push_back(Network::Address::resolveProtoAddress(resolver_addr)); + auto address_or_error = Network::Address::resolveProtoAddress(resolver_addr); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + resolvers.push_back(std::move(address_or_error.value())); } } return std::make_shared(cares, dispatcher, resolvers, diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index f3204bb322cb..78c39f20d914 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -22,8 +22,9 @@ DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, const auto& sink_config = MessageUtil::downcastAndValidate( config, server.messageValidationContext().staticValidationVisitor()); - Network::Address::InstanceConstSharedPtr address = - Network::Address::resolveProtoAddress(sink_config.address()); + auto address_or_error = Network::Address::resolveProtoAddress(sink_config.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (sink_config.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/graphite_statsd/config.cc b/source/extensions/stat_sinks/graphite_statsd/config.cc index 7320993e035e..93322442900d 100644 --- a/source/extensions/stat_sinks/graphite_statsd/config.cc +++ b/source/extensions/stat_sinks/graphite_statsd/config.cc @@ -25,8 +25,9 @@ GraphiteStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, switch (statsd_sink.statsd_specifier_case()) { case envoy::extensions::stat_sinks::graphite_statsd::v3::GraphiteStatsdSink::StatsdSpecifierCase:: kAddress: { - Network::Address::InstanceConstSharedPtr address = - Network::Address::resolveProtoAddress(statsd_sink.address()); + auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (statsd_sink.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/statsd/config.cc b/source/extensions/stat_sinks/statsd/config.cc index 84670fa1308b..ae76707892a0 100644 --- a/source/extensions/stat_sinks/statsd/config.cc +++ b/source/extensions/stat_sinks/statsd/config.cc @@ -23,8 +23,9 @@ StatsdSinkFactory::createStatsSink(const Protobuf::Message& config, config, server.messageValidationContext().staticValidationVisitor()); switch (statsd_sink.statsd_specifier_case()) { case envoy::config::metrics::v3::StatsdSink::StatsdSpecifierCase::kAddress: { - Network::Address::InstanceConstSharedPtr address = - Network::Address::resolveProtoAddress(statsd_sink.address()); + auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + Network::Address::InstanceConstSharedPtr address = address_or_error.value(); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), false, statsd_sink.prefix()); diff --git a/source/server/api_listener_impl.cc b/source/server/api_listener_impl.cc index d947a0549c7a..a9dfa065d89c 100644 --- a/source/server/api_listener_impl.cc +++ b/source/server/api_listener_impl.cc @@ -13,10 +13,10 @@ namespace Envoy { namespace Server { -ApiListenerImplBase::ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, +ApiListenerImplBase::ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, + const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : config_(config), name_(name), - address_(Network::Address::resolveProtoAddress(config.address())), + : config_(config), name_(name), address_(std::move(address)), factory_context_(server, *this, server.stats().createScope(""), server.stats().createScope(fmt::format("listener.api.{}.", name_)), std::make_shared(config)) {} @@ -41,9 +41,19 @@ HttpApiListener::ApiListenerWrapper::newStreamHandle(Http::ResponseEncoder& resp return http_connection_manager_->newStreamHandle(response_encoder, is_internally_created); } -HttpApiListener::HttpApiListener(const envoy::config::listener::v3::Listener& config, +absl::StatusOr> +HttpApiListener::create(const envoy::config::listener::v3::Listener& config, + Server::Instance& server, const std::string& name) { + auto address_or_error = Network::Address::resolveProtoAddress(config.address()); + RETURN_IF_STATUS_NOT_OK(address_or_error); + return std::unique_ptr( + new HttpApiListener(std::move(address_or_error.value()), config, server, name)); +} + +HttpApiListener::HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, + const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : ApiListenerImplBase(config, server, name) { + : ApiListenerImplBase(std::move(address), config, server, name) { if (config.api_listener().api_listener().type_url() == absl::StrCat( "type.googleapis.com/", diff --git a/source/server/api_listener_impl.h b/source/server/api_listener_impl.h index ccf1b2cbdcd3..5ac8a3b7c07b 100644 --- a/source/server/api_listener_impl.h +++ b/source/server/api_listener_impl.h @@ -49,7 +49,8 @@ class ApiListenerImplBase : public ApiListener, } protected: - ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, Server::Instance& server, + ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, + const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name); // Synthetic class that acts as a stub Network::ReadFilterCallbacks. @@ -221,14 +222,18 @@ class HttpApiListener : public ApiListenerImplBase { Http::ApiListenerPtr http_connection_manager_; }; - HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, - const std::string& name); - // ApiListener ApiListener::Type type() const override { return ApiListener::Type::HttpApiListener; } Http::ApiListenerPtr createHttpApiListener(Event::Dispatcher& dispatcher) override; + static absl::StatusOr> + create(const envoy::config::listener::v3::Listener& config, Server::Instance& server, + const std::string& name); private: + HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, + const envoy::config::listener::v3::Listener& config, Server::Instance& server, + const std::string& name); + // Need to store the factory due to the shared_ptrs that need to be kept alive: date provider, // route config manager, scoped route config manager. std::function diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 80818215be7b..6129c6182131 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -231,7 +231,9 @@ InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstra admin_.profile_path_ = admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); if (admin.has_address()) { - admin_.address_ = Network::Address::resolveProtoAddress(admin.address()); + auto address_or_error = Network::Address::resolveProtoAddress(admin.address()); + THROW_IF_STATUS_NOT_OK(address_or_error, throw); + admin_.address_ = std::move(address_or_error.value()); } admin_.socket_options_ = std::make_shared>(); if (!admin.socket_options().empty()) { diff --git a/test/common/network/resolver_impl_test.cc b/test/common/network/resolver_impl_test.cc index 22e752bd28ae..3574414e6298 100644 --- a/test/common/network/resolver_impl_test.cc +++ b/test/common/network/resolver_impl_test.cc @@ -32,7 +32,7 @@ TEST_F(IpResolverTest, Basic) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_port_value(443); - auto address = resolver_->resolve(socket_address); + auto address = resolver_->resolve(socket_address).value(); EXPECT_EQ(address->ip()->addressAsString(), "1.2.3.4"); EXPECT_EQ(address->ip()->port(), 443); } @@ -41,26 +41,25 @@ TEST_F(IpResolverTest, DisallowsNamedPort) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_named_port("http"); - EXPECT_THROW_WITH_MESSAGE( - resolver_->resolve(socket_address), EnvoyException, - fmt::format("IP resolver can't handle port specifier type {}", - envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); + EXPECT_EQ(resolver_->resolve(socket_address).status().message(), + fmt::format("IP resolver can't handle port specifier type {}", + envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); } TEST(ResolverTest, FromProtoAddress) { envoy::config::core::v3::Address ipv4_address; ipv4_address.mutable_socket_address()->set_address("1.2.3.4"); ipv4_address.mutable_socket_address()->set_port_value(5); - EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address)->asString()); + EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address).value()->asString()); envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address)->asString()); + EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address).value()->asString()); envoy::config::core::v3::Address pipe_address; pipe_address.mutable_pipe()->set_path("/foo/bar"); - EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address)->asString()); + EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address).value()->asString()); } TEST(ResolverTest, InternalListenerNameFromProtoAddress) { @@ -68,14 +67,14 @@ TEST(ResolverTest, InternalListenerNameFromProtoAddress) { internal_listener_address.mutable_envoy_internal_address()->set_server_listener_name( "internal_listener_foo"); EXPECT_EQ("envoy://internal_listener_foo/", - resolveProtoAddress(internal_listener_address)->asString()); + resolveProtoAddress(internal_listener_address).value()->asString()); } TEST(ResolverTest, UninitializedInternalAddressFromProtoAddress) { envoy::config::core::v3::Address internal_address; internal_address.mutable_envoy_internal_address(); EXPECT_THROW_WITH_MESSAGE( - resolveProtoAddress(internal_address), EnvoyException, + resolveProtoAddress(internal_address).IgnoreError(), EnvoyException, fmt::format("Failed to resolve address:{}", internal_address.DebugString())); } @@ -85,7 +84,7 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - auto resolved_addr = resolveProtoAddress(ipv6_address); + auto resolved_addr = resolveProtoAddress(ipv6_address).value(); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } { @@ -93,14 +92,14 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); ipv6_address.mutable_socket_address()->set_ipv4_compat(true); - auto resolved_addr = resolveProtoAddress(ipv6_address); + auto resolved_addr = resolveProtoAddress(ipv6_address).value(); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } } class TestResolver : public Resolver { public: - InstanceConstSharedPtr + absl::StatusOr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { const std::string& logical = socket_address.address(); const std::string physical = getPhysicalName(logical); @@ -154,7 +153,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address); + auto instance = resolveProtoAddress(address).value(); EXPECT_EQ("1.2.3.4:5", instance->asString()); EXPECT_EQ("foo:5", instance->logicalName()); } @@ -164,7 +163,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("bar"); socket->set_named_port("http"); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address); + auto instance = resolveProtoAddress(address).value(); EXPECT_EQ("4.3.2.1:http", instance->asString()); EXPECT_EQ("bar:http", instance->logicalName()); } @@ -172,7 +171,8 @@ TEST(ResolverTest, NonStandardResolver) { TEST(ResolverTest, UninitializedAddress) { envoy::config::core::v3::Address address; - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, "Address must be set: "); + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, + "Address must be set: "); } TEST(ResolverTest, NoSuchResolver) { @@ -181,7 +181,7 @@ TEST(ResolverTest, NoSuchResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, "Unknown address resolver: envoy.test.resolver"); } diff --git a/test/fuzz/utility.h b/test/fuzz/utility.h index 7ecd69d0942d..681674debc4e 100644 --- a/test/fuzz/utility.h +++ b/test/fuzz/utility.h @@ -170,7 +170,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn replaceInvalidHostCharacters( stream_info.address().envoy_internal_address().server_listener_name())); } else { - address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()); + address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()).value(); } } else { address = Network::Utility::resolveUrl("tcp://10.0.0.1:443"); @@ -178,6 +178,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn auto upstream_local_address = stream_info.has_upstream_local_address() ? Envoy::Network::Address::resolveProtoAddress(stream_info.upstream_local_address()) + .value() : Network::Utility::resolveUrl("tcp://10.0.0.1:10000"); test_stream_info->upstreamInfo()->setUpstreamLocalAddress(upstream_local_address); test_stream_info->downstream_connection_info_provider_ = diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 283bb4377df7..09417750b16b 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -88,7 +88,7 @@ class MockAddressResolver : public Address::Resolver { MockAddressResolver(); ~MockAddressResolver() override; - MOCK_METHOD(Address::InstanceConstSharedPtr, resolve, + MOCK_METHOD(absl::StatusOr, resolve, (const envoy::config::core::v3::SocketAddress&)); MOCK_METHOD(std::string, name, (), (const)); }; diff --git a/test/server/api_listener_test.cc b/test/server/api_listener_test.cc index 7183f80b8651..9d70fbd6e4e3 100644 --- a/test/server/api_listener_test.cc +++ b/test/server/api_listener_test.cc @@ -53,11 +53,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener(config, server_, config.name()); + auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); - ASSERT_EQ("test_api_listener", http_api_listener.name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener->name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); + ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, MobileApiListener) { @@ -88,11 +88,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener(config, server_, config.name()); + auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); - ASSERT_EQ("test_api_listener", http_api_listener.name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener->name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); + ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, HttpApiListenerThrowsWithBadConfig) { @@ -125,7 +125,7 @@ name: test_api_listener ->set_path("eds path"); expected_any_proto.PackFrom(expected_cluster_proto); EXPECT_THROW_WITH_MESSAGE( - HttpApiListener(config, server_, config.name()), EnvoyException, + HttpApiListener::create(config, server_, config.name()).IgnoreError(), EnvoyException, fmt::format("Unable to unpack as " "envoy.extensions.filters.network.http_connection_manager.v3." "HttpConnectionManager: {}", @@ -159,11 +159,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener(config, server_, config.name()); + auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); - ASSERT_EQ("test_api_listener", http_api_listener.name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); - auto api_listener = http_api_listener.createHttpApiListener(server_.dispatcher()); + ASSERT_EQ("test_api_listener", http_api_listener->name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); + auto api_listener = http_api_listener->createHttpApiListener(server_.dispatcher()); ASSERT_NE(api_listener, nullptr); Network::MockConnectionCallbacks network_connection_callbacks; diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index c7e1dc6bd7c9..1e1b071c2d19 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -109,7 +109,6 @@ paths: - source/common/network/address_impl.cc - source/common/network/utility.cc - source/common/network/dns_resolver/dns_factory_util.cc - - source/common/network/resolver_impl.cc - source/common/network/socket_impl.cc - source/common/ssl/tls_certificate_config_impl.cc - source/common/formatter/http_specific_formatter.cc From e99fd8e7fba15a4cb538f43c4961436bd57bbfa6 Mon Sep 17 00:00:00 2001 From: danzh Date: Thu, 4 Jan 2024 09:58:08 -0500 Subject: [PATCH 116/126] quic: support ALPN configuration from TLS context config (#31585) Commit Message: make QUIC server/client transport socket factories read ALPN config from TLS context config and expose configured ALPNs to QUIC sessions. Additional Description: The current QUIC implementation only supports HTTP/3 as application protocol indeed. So in most cases, there is no need to explicitly configure ALPNs for HTTP/3. It's by default derived from the negotiated QUIC version to be "h3" or "h3-draft29". The config plumbing is added so that some minor variations can override the default ALPNs and can be detected during handshake. Risk Level: medium, behind config alpn_protocols Testing: new unit tests and integration tests Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Part of #25418 Signed-off-by: Dan Zhang --- source/common/http/http3/conn_pool.cc | 2 +- .../quic/client_connection_factory_impl.cc | 5 +-- .../quic/client_connection_factory_impl.h | 3 +- .../common/quic/envoy_quic_client_session.cc | 22 ++++++++++-- .../common/quic/envoy_quic_client_session.h | 7 +++- .../common/quic/envoy_quic_server_session.cc | 23 +++++++++++++ .../common/quic/envoy_quic_server_session.h | 2 ++ .../quic_client_transport_socket_factory.cc | 7 ++++ .../quic_client_transport_socket_factory.h | 2 +- .../quic_server_transport_socket_factory.cc | 10 ++++++ .../quic_server_transport_socket_factory.h | 7 +--- .../quic/quic_transport_socket_factory.h | 5 +++ .../client_connection_factory_impl_test.cc | 8 ++--- .../quic/envoy_quic_client_session_test.cc | 12 +++---- .../quic/envoy_quic_proof_source_test.cc | 2 ++ .../quic_transport_socket_factory_test.cc | 9 ++++- test/common/quic/test_utils.h | 2 +- test/config/utility.cc | 24 +++++++++---- test/config/utility.h | 6 ++-- test/integration/http_integration.cc | 4 +-- test/integration/http_integration.h | 1 + .../integration/quic_http_integration_test.cc | 34 +++++++++++++++++-- test/integration/ssl_utility.cc | 2 +- .../tcp_tunneling_integration_test.cc | 2 +- test/integration/utility.cc | 2 +- 25 files changed, 159 insertions(+), 44 deletions(-) diff --git a/source/common/http/http3/conn_pool.cc b/source/common/http/http3/conn_pool.cc index 8a2e76aace40..ed6f4e812ea6 100644 --- a/source/common/http/http3/conn_pool.cc +++ b/source/common/http/http3/conn_pool.cc @@ -134,7 +134,7 @@ Http3ConnPoolImpl::createClientConnection(Quic::QuicStatNames& quic_stat_names, return Quic::createQuicNetworkConnection( quic_info_, std::move(crypto_config), server_id_, dispatcher(), host()->address(), source_address, quic_stat_names, rtt_cache, scope, upstream_local_address.socket_options_, - transportSocketOptions(), connection_id_generator_); + transportSocketOptions(), connection_id_generator_, host_->transportSocketFactory()); } std::unique_ptr diff --git a/source/common/quic/client_connection_factory_impl.cc b/source/common/quic/client_connection_factory_impl.cc index d3efeba84e51..3317e11463bc 100644 --- a/source/common/quic/client_connection_factory_impl.cc +++ b/source/common/quic/client_connection_factory_impl.cc @@ -34,7 +34,8 @@ std::unique_ptr createQuicNetworkConnection( OptRef rtt_cache, Stats::Scope& scope, const Network::ConnectionSocket::OptionsSharedPtr& options, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, - quic::ConnectionIdGeneratorInterface& generator) { + quic::ConnectionIdGeneratorInterface& generator, + Network::UpstreamTransportSocketFactory& transport_socket_factory) { // TODO: Quic should take into account the set_local_interface_name_on_upstream_connections config // and call maybeSetInterfaceName based on that upon acquiring a local socket. // Similar to what is done in ClientConnectionImpl::onConnected(). @@ -61,7 +62,7 @@ std::unique_ptr createQuicNetworkConnection( return std::make_unique( config, quic_versions, std::move(connection), server_id, std::move(crypto_config), dispatcher, info_impl->buffer_limit_, info_impl->crypto_stream_factory_, quic_stat_names, rtt_cache, - scope, transport_socket_options); + scope, transport_socket_options, transport_socket_factory); } } // namespace Quic diff --git a/source/common/quic/client_connection_factory_impl.h b/source/common/quic/client_connection_factory_impl.h index e2b8eede0e78..5a5aa9158a93 100644 --- a/source/common/quic/client_connection_factory_impl.h +++ b/source/common/quic/client_connection_factory_impl.h @@ -44,7 +44,8 @@ std::unique_ptr createQuicNetworkConnection( OptRef rtt_cache, Stats::Scope& scope, const Network::ConnectionSocket::OptionsSharedPtr& options, const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, - quic::ConnectionIdGeneratorInterface& generator); + quic::ConnectionIdGeneratorInterface& generator, + Network::UpstreamTransportSocketFactory& transport_socket_factory); } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_client_session.cc b/source/common/quic/envoy_quic_client_session.cc index d345a4fde0b9..14e7be0ddb3f 100644 --- a/source/common/quic/envoy_quic_client_session.cc +++ b/source/common/quic/envoy_quic_client_session.cc @@ -50,7 +50,8 @@ EnvoyQuicClientSession::EnvoyQuicClientSession( uint32_t send_buffer_limit, EnvoyQuicCryptoClientStreamFactoryInterface& crypto_stream_factory, QuicStatNames& quic_stat_names, OptRef rtt_cache, Stats::Scope& scope, - const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options) + const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, + OptRef transport_socket_factory) : QuicFilterManagerConnectionImpl( *connection, connection->connection_id(), dispatcher, send_buffer_limit, std::make_shared(*this), @@ -61,8 +62,19 @@ EnvoyQuicClientSession::EnvoyQuicClientSession( crypto_config.get()), crypto_config_(crypto_config), crypto_stream_factory_(crypto_stream_factory), quic_stat_names_(quic_stat_names), rtt_cache_(rtt_cache), scope_(scope), - transport_socket_options_(transport_socket_options) { + transport_socket_options_(transport_socket_options), + transport_socket_factory_(makeOptRefFromPtr( + dynamic_cast(transport_socket_factory.ptr()))) { streamInfo().setUpstreamInfo(std::make_shared()); + if (transport_socket_options_ != nullptr && + !transport_socket_options_->applicationProtocolListOverride().empty()) { + configured_alpns_ = transport_socket_options_->applicationProtocolListOverride(); + } else if (transport_socket_factory_.has_value() && + !transport_socket_factory_->supportedAlpnProtocols().empty()) { + configured_alpns_ = + std::vector(transport_socket_factory_->supportedAlpnProtocols().begin(), + transport_socket_factory_->supportedAlpnProtocols().end()); + } } EnvoyQuicClientSession::~EnvoyQuicClientSession() { @@ -195,7 +207,6 @@ void EnvoyQuicClientSession::OnTlsHandshakeComplete() { } std::unique_ptr EnvoyQuicClientSession::CreateQuicCryptoStream() { - // TODO(danzh) pass around transport_socket_options_ via context. return crypto_stream_factory_.createEnvoyQuicCryptoClientStream( server_id(), this, std::make_unique(dispatcher_, /*is_server=*/false, @@ -259,5 +270,10 @@ void EnvoyQuicClientSession::OnServerPreferredAddressAvailable( ->probeAndMigrateToServerPreferredAddress(server_preferred_address); } +std::vector EnvoyQuicClientSession::GetAlpnsToOffer() const { + return configured_alpns_.empty() ? quic::QuicSpdyClientSession::GetAlpnsToOffer() + : configured_alpns_; +} + } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_client_session.h b/source/common/quic/envoy_quic_client_session.h index 4e615fc5daf2..7128c43d8171 100644 --- a/source/common/quic/envoy_quic_client_session.h +++ b/source/common/quic/envoy_quic_client_session.h @@ -5,6 +5,7 @@ #include "source/common/quic/envoy_quic_client_connection.h" #include "source/common/quic/envoy_quic_client_crypto_stream_factory.h" #include "source/common/quic/envoy_quic_client_stream.h" +#include "source/common/quic/quic_client_transport_socket_factory.h" #include "source/common/quic/quic_filter_manager_connection_impl.h" #include "source/common/quic/quic_stat_names.h" @@ -31,7 +32,8 @@ class EnvoyQuicClientSession : public QuicFilterManagerConnectionImpl, EnvoyQuicCryptoClientStreamFactoryInterface& crypto_stream_factory, QuicStatNames& quic_stat_names, OptRef rtt_cache, Stats::Scope& scope, - const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options); + const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, + OptRef transport_socket_factory); ~EnvoyQuicClientSession() override; @@ -71,6 +73,7 @@ class EnvoyQuicClientSession : public QuicFilterManagerConnectionImpl, #endif return quic::HttpDatagramSupport::kNone; } + std::vector GetAlpnsToOffer() const override; // quic::QuicSpdyClientSessionBase bool ShouldKeepConnectionAlive() const override; @@ -127,6 +130,8 @@ class EnvoyQuicClientSession : public QuicFilterManagerConnectionImpl, Stats::Scope& scope_; bool disable_keepalive_{false}; Network::TransportSocketOptionsConstSharedPtr transport_socket_options_; + OptRef transport_socket_factory_; + std::vector configured_alpns_; }; } // namespace Quic diff --git a/source/common/quic/envoy_quic_server_session.cc b/source/common/quic/envoy_quic_server_session.cc index 66fdac04de41..00e1b56a9930 100644 --- a/source/common/quic/envoy_quic_server_session.cc +++ b/source/common/quic/envoy_quic_server_session.cc @@ -2,6 +2,7 @@ #include #include +#include #include "source/common/common/assert.h" #include "source/common/quic/envoy_quic_proof_source.h" @@ -210,5 +211,27 @@ void EnvoyQuicServerSession::ProcessUdpPacket(const quic::QuicSocketAddress& sel maybeApplyDelayedClose(); } +std::vector::const_iterator +EnvoyQuicServerSession::SelectAlpn(const std::vector& alpns) const { + if (!position_.has_value()) { + return quic::QuicServerSessionBase::SelectAlpn(alpns); + } + const std::vector& configured_alpns = + dynamic_cast( + position_->filter_chain_.transportSocketFactory()) + .supportedAlpnProtocols(); + if (configured_alpns.empty()) { + return quic::QuicServerSessionBase::SelectAlpn(alpns); + } + + for (absl::string_view configured_alpn : configured_alpns) { + auto it = absl::c_find(alpns, configured_alpn); + if (it != alpns.end()) { + return it; + } + } + return alpns.end(); +} + } // namespace Quic } // namespace Envoy diff --git a/source/common/quic/envoy_quic_server_session.h b/source/common/quic/envoy_quic_server_session.h index 94e4f145f47a..ed6296ca8832 100644 --- a/source/common/quic/envoy_quic_server_session.h +++ b/source/common/quic/envoy_quic_server_session.h @@ -86,6 +86,8 @@ class EnvoyQuicServerSession : public quic::QuicServerSessionBase, void ProcessUdpPacket(const quic::QuicSocketAddress& self_address, const quic::QuicSocketAddress& peer_address, const quic::QuicReceivedPacket& packet) override; + std::vector::const_iterator + SelectAlpn(const std::vector& alpns) const override; void setHeadersWithUnderscoreAction( envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction diff --git a/source/common/quic/quic_client_transport_socket_factory.cc b/source/common/quic/quic_client_transport_socket_factory.cc index 1e0f289c319e..7075c9867db6 100644 --- a/source/common/quic/quic_client_transport_socket_factory.cc +++ b/source/common/quic/quic_client_transport_socket_factory.cc @@ -35,6 +35,13 @@ QuicClientTransportSocketFactory::QuicClientTransportSocketFactory( fallback_factory_(std::make_unique( std::move(config), factory_context.sslContextManager(), factory_context.statsScope())) {} +void QuicClientTransportSocketFactory::initialize() { + if (!fallback_factory_->clientContextConfig()->alpnProtocols().empty()) { + supported_alpns_ = + absl::StrSplit(fallback_factory_->clientContextConfig()->alpnProtocols(), ','); + } +} + ProtobufTypes::MessagePtr QuicClientTransportSocketConfigFactory::createEmptyConfigProto() { return std::make_unique(); } diff --git a/source/common/quic/quic_client_transport_socket_factory.h b/source/common/quic/quic_client_transport_socket_factory.h index 3abc6e18be06..a9fa4c8b9c43 100644 --- a/source/common/quic/quic_client_transport_socket_factory.h +++ b/source/common/quic/quic_client_transport_socket_factory.h @@ -12,7 +12,7 @@ class QuicClientTransportSocketFactory : public Network::CommonUpstreamTransport Ssl::ClientContextConfigPtr config, Server::Configuration::TransportSocketFactoryContext& factory_context); - void initialize() override {} + void initialize() override; bool implementsSecureTransport() const override { return true; } bool supportsAlpn() const override { return true; } absl::string_view defaultServerNameIndication() const override { diff --git a/source/common/quic/quic_server_transport_socket_factory.cc b/source/common/quic/quic_server_transport_socket_factory.cc index eaa139a0555f..6be9342aa583 100644 --- a/source/common/quic/quic_server_transport_socket_factory.cc +++ b/source/common/quic/quic_server_transport_socket_factory.cc @@ -36,6 +36,16 @@ ProtobufTypes::MessagePtr QuicServerTransportSocketConfigFactory::createEmptyCon envoy::extensions::transport_sockets::quic::v3::QuicDownstreamTransport>(); } +void QuicServerTransportSocketFactory::initialize() { + config_->setSecretUpdateCallback([this]() { + // The callback also updates config_ with the new secret. + onSecretUpdated(); + }); + if (!config_->alpnProtocols().empty()) { + supported_alpns_ = absl::StrSplit(config_->alpnProtocols(), ','); + } +} + REGISTER_FACTORY(QuicServerTransportSocketConfigFactory, Server::Configuration::DownstreamTransportSocketConfigFactory); diff --git a/source/common/quic/quic_server_transport_socket_factory.h b/source/common/quic/quic_server_transport_socket_factory.h index 8e1439d526d6..bb64ec76e9af 100644 --- a/source/common/quic/quic_server_transport_socket_factory.h +++ b/source/common/quic/quic_server_transport_socket_factory.h @@ -29,12 +29,7 @@ class QuicServerTransportSocketFactory : public Network::DownstreamTransportSock } bool implementsSecureTransport() const override { return true; } - void initialize() override { - config_->setSecretUpdateCallback([this]() { - // The callback also updates config_ with the new secret. - onSecretUpdated(); - }); - } + void initialize() override; // Return TLS certificates if the context config is ready. std::vector> diff --git a/source/common/quic/quic_transport_socket_factory.h b/source/common/quic/quic_transport_socket_factory.h index ce6dbe312b48..d01bce40dc02 100644 --- a/source/common/quic/quic_transport_socket_factory.h +++ b/source/common/quic/quic_transport_socket_factory.h @@ -47,9 +47,14 @@ class QuicTransportSocketFactoryBase : protected Logger::Loggable& supportedAlpnProtocols() const { return supported_alpns_; } + protected: virtual void onSecretUpdated() PURE; QuicTransportSocketFactoryStats stats_; + // Populated during initialization. + std::vector supported_alpns_; }; // Base class to create above QuicTransportSocketFactory for server and client diff --git a/test/common/quic/client_connection_factory_impl_test.cc b/test/common/quic/client_connection_factory_impl_test.cc index 8958dcf1d901..6b8f77ae0691 100644 --- a/test/common/quic/client_connection_factory_impl_test.cc +++ b/test/common/quic/client_connection_factory_impl_test.cc @@ -92,13 +92,12 @@ class QuicNetworkConnectionTest : public Event::TestUsingSimulatedTime, TEST_P(QuicNetworkConnectionTest, BufferLimits) { initialize(); - const int port = 30; std::unique_ptr client_connection = createQuicNetworkConnection( *quic_info_, crypto_config_, quic::QuicServerId{factory_->clientContextConfig()->serverNameIndication(), port, false}, dispatcher_, test_address_, test_address_, quic_stat_names_, {}, *store_.rootScope(), nullptr, - nullptr, connection_id_generator_); + nullptr, connection_id_generator_, *factory_); EnvoyQuicClientSession* session = static_cast(client_connection.get()); session->Initialize(); client_connection->connect(); @@ -107,6 +106,7 @@ TEST_P(QuicNetworkConnectionTest, BufferLimits) { EXPECT_EQ(highWatermark(session), 45); EXPECT_EQ(absl::nullopt, session->unixSocketPeerCredentials()); EXPECT_NE(absl::nullopt, session->lastRoundTripTime()); + EXPECT_THAT(session->GetAlpnsToOffer(), testing::ElementsAre("h3")); client_connection->close(Network::ConnectionCloseType::NoFlush); } @@ -125,7 +125,7 @@ TEST_P(QuicNetworkConnectionTest, SocketOptions) { *quic_info_, crypto_config_, quic::QuicServerId{factory_->clientContextConfig()->serverNameIndication(), port, false}, dispatcher_, test_address_, test_address_, quic_stat_names_, {}, *store_.rootScope(), - socket_options, nullptr, connection_id_generator_); + socket_options, nullptr, connection_id_generator_, *factory_); EnvoyQuicClientSession* session = static_cast(client_connection.get()); session->Initialize(); client_connection->connect(); @@ -145,7 +145,7 @@ TEST_P(QuicNetworkConnectionTest, Srtt) { info, crypto_config_, quic::QuicServerId{factory_->clientContextConfig()->serverNameIndication(), port, false}, dispatcher_, test_address_, test_address_, quic_stat_names_, rtt_cache, *store_.rootScope(), - nullptr, nullptr, connection_id_generator_); + nullptr, nullptr, connection_id_generator_, *factory_); EnvoyQuicClientSession* session = static_cast(client_connection.get()); diff --git a/test/common/quic/envoy_quic_client_session_test.cc b/test/common/quic/envoy_quic_client_session_test.cc index 357519bef002..4ee4be66b293 100644 --- a/test/common/quic/envoy_quic_client_session_test.cc +++ b/test/common/quic/envoy_quic_client_session_test.cc @@ -76,12 +76,12 @@ class EnvoyQuicClientSessionTest : public testing::TestWithParam()), - envoy_quic_session_(quic_config_, quic_version_, - std::unique_ptr(quic_connection_), - quic::QuicServerId("example.com", 443, false), crypto_config_, - *dispatcher_, - /*send_buffer_limit*/ 1024 * 1024, crypto_stream_factory_, - quic_stat_names_, {}, *store_.rootScope(), transport_socket_options_), + envoy_quic_session_( + quic_config_, quic_version_, + std::unique_ptr(quic_connection_), + quic::QuicServerId("example.com", 443, false), crypto_config_, *dispatcher_, + /*send_buffer_limit*/ 1024 * 1024, crypto_stream_factory_, quic_stat_names_, {}, + *store_.rootScope(), transport_socket_options_, {}), stats_({ALL_HTTP3_CODEC_STATS(POOL_COUNTER_PREFIX(store_, "http3."), POOL_GAUGE_PREFIX(store_, "http3."))}), http_connection_(envoy_quic_session_, http_connection_callbacks_, stats_, http3_options_, diff --git a/test/common/quic/envoy_quic_proof_source_test.cc b/test/common/quic/envoy_quic_proof_source_test.cc index 7054488d6a5e..2c6bcc991cf8 100644 --- a/test/common/quic/envoy_quic_proof_source_test.cc +++ b/test/common/quic/envoy_quic_proof_source_test.cc @@ -149,6 +149,7 @@ class EnvoyQuicProofSourceTest : public ::testing::Test { POOL_HISTOGRAM(listener_config_.listenerScope()))}), proof_source_(listen_socket_, filter_chain_manager_, listener_stats_, time_system_) { EXPECT_CALL(*mock_context_config_, setSecretUpdateCallback(_)).Times(testing::AtLeast(1u)); + EXPECT_CALL(*mock_context_config_, alpnProtocols()).WillRepeatedly(ReturnRef(alpn_)); transport_socket_factory_ = std::make_unique( true, listener_config_.listenerScope(), std::unique_ptr(mock_context_config_)); @@ -201,6 +202,7 @@ class EnvoyQuicProofSourceTest : public ::testing::Test { Server::ListenerStats listener_stats_; Event::GlobalTimeSystem time_system_; EnvoyQuicProofSource proof_source_; + std::string alpn_{"h3"}; }; TEST_F(EnvoyQuicProofSourceTest, TestGetCerChainAndSignatureAndVerify) { diff --git a/test/common/quic/quic_transport_socket_factory_test.cc b/test/common/quic/quic_transport_socket_factory_test.cc index fe67629bcfb9..e2cc6998af3c 100644 --- a/test/common/quic/quic_transport_socket_factory_test.cc +++ b/test/common/quic/quic_transport_socket_factory_test.cc @@ -117,7 +117,6 @@ class QuicClientTransportSocketFactoryTest : public testing::Test { EXPECT_CALL(*context_config_, setSecretUpdateCallback(_)) .WillOnce(testing::SaveArg<0>(&update_callback_)); factory_.emplace(std::unique_ptr(context_config_), context_); - factory_->initialize(); } NiceMock context_; @@ -128,7 +127,15 @@ class QuicClientTransportSocketFactoryTest : public testing::Test { std::function update_callback_; }; +TEST_F(QuicClientTransportSocketFactoryTest, SupportedAlpns) { + context_config_->alpn_ = "h3,h3-draft29"; + factory_->initialize(); + EXPECT_THAT(factory_->supportedAlpnProtocols(), testing::ElementsAre("h3", "h3-draft29")); +} + TEST_F(QuicClientTransportSocketFactoryTest, GetCryptoConfig) { + factory_->initialize(); + EXPECT_TRUE(factory_->supportedAlpnProtocols().empty()); EXPECT_EQ(nullptr, factory_->getCryptoConfig()); Ssl::ClientContextSharedPtr ssl_context1{new Ssl::MockClientContext()}; diff --git a/test/common/quic/test_utils.h b/test/common/quic/test_utils.h index 8a5a46971f89..63a378bc3496 100644 --- a/test/common/quic/test_utils.h +++ b/test/common/quic/test_utils.h @@ -201,7 +201,7 @@ class MockEnvoyQuicClientSession : public IsolatedStoreProvider, public EnvoyQui std::make_shared( quic::test::crypto_test_utils::ProofVerifierForTesting()), dispatcher, send_buffer_limit, crypto_stream_factory, - quic_stat_names_, {}, *stats_store_.rootScope(), nullptr) {} + quic_stat_names_, {}, *stats_store_.rootScope(), nullptr, {}) {} void Initialize() override { EnvoyQuicClientSession::Initialize(); diff --git a/test/config/utility.cc b/test/config/utility.cc index 64c0e9cb91ea..aef14b5bfbd0 100644 --- a/test/config/utility.cc +++ b/test/config/utility.cc @@ -1310,7 +1310,7 @@ void ConfigHelper::addSslConfig(const ServerSslOptions& options) { auto* filter_chain = bootstrap_.mutable_static_resources()->mutable_listeners(0)->mutable_filter_chains(0); envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; - initializeTls(options, *tls_context.mutable_common_tls_context()); + initializeTls(options, *tls_context.mutable_common_tls_context(), false); if (options.ocsp_staple_required_) { tls_context.set_ocsp_staple_policy( envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext::MUST_STAPLE); @@ -1319,7 +1319,8 @@ void ConfigHelper::addSslConfig(const ServerSslOptions& options) { filter_chain->mutable_transport_socket()->mutable_typed_config()->PackFrom(tls_context); } -void ConfigHelper::addQuicDownstreamTransportSocketConfig(bool enable_early_data) { +void ConfigHelper::addQuicDownstreamTransportSocketConfig( + bool enable_early_data, std::vector custom_alpns) { for (auto& listener : *bootstrap_.mutable_static_resources()->mutable_listeners()) { if (listener.udp_listener_config().has_quic_options()) { // Disable SO_REUSEPORT, because it undesirably allows parallel test jobs to use the same @@ -1329,8 +1330,12 @@ void ConfigHelper::addQuicDownstreamTransportSocketConfig(bool enable_early_data } configDownstreamTransportSocketWithTls( bootstrap_, - [](envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context) { - initializeTls(ServerSslOptions().setRsaCert(true).setTlsV13(true), common_tls_context); + [&](envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context) { + initializeTls(ServerSslOptions().setRsaCert(true).setTlsV13(true), common_tls_context, + true); + for (absl::string_view alpn : custom_alpns) { + common_tls_context.add_alpn_protocols(alpn); + } }, enable_early_data); } @@ -1447,9 +1452,14 @@ void ConfigHelper::initializeTlsKeyLog( void ConfigHelper::initializeTls( const ServerSslOptions& options, - envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context) { - common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http2); - common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http11); + envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context, + bool http3) { + if (!http3) { + // If it's HTTP/3, leave it empty as QUIC will derive the supported ALPNs from QUIC version by + // default. + common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http2); + common_tls_context.add_alpn_protocols(Http::Utility::AlpnNames::get().Http11); + } auto* validation_context = common_tls_context.mutable_validation_context(); if (options.custom_validator_config_) { diff --git a/test/config/utility.h b/test/config/utility.h index f1914170610d..3f97515906bc 100644 --- a/test/config/utility.h +++ b/test/config/utility.h @@ -159,7 +159,8 @@ class ConfigHelper { static void initializeTls(const ServerSslOptions& options, - envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_context); + envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_context, + bool http3); static void initializeTlsKeyLog( envoy::extensions::transport_sockets::tls::v3::CommonTlsContext& common_tls_context, @@ -336,7 +337,8 @@ class ConfigHelper { void addSslConfig() { addSslConfig({}); } // Add the default SSL configuration for QUIC downstream. - void addQuicDownstreamTransportSocketConfig(bool enable_early_data); + void addQuicDownstreamTransportSocketConfig(bool enable_early_data, + std::vector custom_alpns); // Set the HTTP access log for the first HCM (if present) to a given file. The default is // the platform's null device. diff --git a/test/integration/http_integration.cc b/test/integration/http_integration.cc index 59e3c6bbac9e..7e5d8b735af7 100644 --- a/test/integration/http_integration.cc +++ b/test/integration/http_integration.cc @@ -253,7 +253,7 @@ Network::ClientConnectionPtr HttpIntegrationTest::makeClientConnectionWithOption quic_transport_socket_factory_ref.clientContextConfig()->serverNameIndication(), static_cast(port)), *dispatcher_, server_addr, local_addr, quic_stat_names_, {}, *stats_store_.rootScope(), - options, nullptr, connection_id_generator_); + options, nullptr, connection_id_generator_, quic_transport_socket_factory_ref); #else ASSERT(false, "running a QUIC integration test without compiling QUIC"); return nullptr; @@ -371,7 +371,7 @@ void HttpIntegrationTest::initialize() { // Needed to config QUIC transport socket factory, and needs to be added before base class calls // initialize(). - config_helper_.addQuicDownstreamTransportSocketConfig(enable_quic_early_data_); + config_helper_.addQuicDownstreamTransportSocketConfig(enable_quic_early_data_, custom_alpns_); BaseIntegrationTest::initialize(); registerTestServerPorts({"http"}, test_server_); diff --git a/test/integration/http_integration.h b/test/integration/http_integration.h index 3cb15cda441f..d8a6959f8dad 100644 --- a/test/integration/http_integration.h +++ b/test/integration/http_integration.h @@ -360,6 +360,7 @@ class HttpIntegrationTest : public BaseIntegrationTest { Quic::QuicStatNames quic_stat_names_; std::string san_to_match_{"spiffe://lyft.com/backend-team"}; bool enable_quic_early_data_{true}; + std::vector custom_alpns_; // Set this to true when sending malformed requests to avoid test client codec rejecting it. // This flag is only valid when UHV build flag is enabled. bool disable_client_header_validation_{false}; diff --git a/test/integration/quic_http_integration_test.cc b/test/integration/quic_http_integration_test.cc index 7d442edf53f7..526e2f47b10a 100644 --- a/test/integration/quic_http_integration_test.cc +++ b/test/integration/quic_http_integration_test.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include "envoy/config/bootstrap/v3/bootstrap.pb.h" @@ -225,7 +226,7 @@ class QuicHttpIntegrationTestBase : public HttpIntegrationTest { // exceeding high watermark. /*send_buffer_limit=*/2 * Http2::Utility::OptionsLimits::MIN_INITIAL_STREAM_WINDOW_SIZE, persistent_info.crypto_stream_factory_, quic_stat_names_, cache, *stats_store_.rootScope(), - nullptr); + nullptr, *transport_socket_factory_); return session; } @@ -294,7 +295,7 @@ class QuicHttpIntegrationTestBase : public HttpIntegrationTest { registerTestServerPorts({"http"}); // Initialize the transport socket factory using a customized ssl option. - ssl_client_option_.setAlpn(true).setSan(san_to_match_).setSni("lyft.com"); + ssl_client_option_.setSan(san_to_match_).setSni("lyft.com"); NiceMock context; ON_CALL(context.server_context_, api()).WillByDefault(testing::ReturnRef(*api_)); ON_CALL(context, statsScope()).WillByDefault(testing::ReturnRef(stats_scope_)); @@ -303,6 +304,7 @@ class QuicHttpIntegrationTestBase : public HttpIntegrationTest { quic_transport_socket_config; auto* tls_context = quic_transport_socket_config.mutable_upstream_tls_context(); initializeUpstreamTlsContextConfig(ssl_client_option_, *tls_context); + tls_context->mutable_common_tls_context()->add_alpn_protocols(client_alpn_); envoy::config::core::v3::TransportSocket message; message.mutable_typed_config()->PackFrom(quic_transport_socket_config); @@ -405,6 +407,7 @@ class QuicHttpIntegrationTestBase : public HttpIntegrationTest { bool validation_failure_on_path_response_{false}; quic::DeterministicConnectionIdGenerator connection_id_generator_{ quic::kQuicDefaultConnectionIdLength}; + std::string client_alpn_; }; class QuicHttpIntegrationTest : public QuicHttpIntegrationTestBase, @@ -1527,6 +1530,31 @@ TEST_P(QuicHttpIntegrationTest, InvalidTrailer) { EXPECT_FALSE(response->complete()); } +TEST_P(QuicHttpIntegrationTest, AlpnProtocolMismatch) { + client_alpn_ = "h3-special"; + initialize(); + codec_client_ = makeRawHttpConnection(makeClientConnection(lookupPort("http")), absl::nullopt); + EXPECT_TRUE(codec_client_->disconnected()); + EXPECT_EQ(quic::QUIC_HANDSHAKE_FAILED, + static_cast(codec_client_->connection())->error()); + EXPECT_THAT(codec_client_->connection()->transportFailureReason(), + testing::HasSubstr("no application protocol")); +} + +TEST_P(QuicHttpIntegrationTest, ConfigureAlpnProtocols) { + client_alpn_ = "h3-special"; + custom_alpns_ = {"h3", "h3-special"}; + initialize(); + codec_client_ = makeRawHttpConnection(makeClientConnection(lookupPort("http")), absl::nullopt); + EXPECT_EQ(transport_socket_factory_->clientContextConfig()->serverNameIndication(), + codec_client_->connection()->requestedServerName()); + auto response = codec_client_->makeHeaderOnlyRequest(default_request_headers_); + waitForNextUpstreamRequest(0); + upstream_request_->encodeHeaders(default_response_headers_, true); + ASSERT_TRUE(response->waitForEndStream()); + codec_client_->close(); +} + class QuicInplaceLdsIntegrationTest : public QuicHttpIntegrationTest { public: void inplaceInitialize(bool add_default_filter_chain = false) { @@ -1717,7 +1745,7 @@ TEST_P(QuicInplaceLdsIntegrationTest, EnableAndDisableEarlyData) { // Modify 1st transport socket factory to disable early data. ConfigHelper new_config_helper(version_, config_helper_.bootstrap()); - new_config_helper.addQuicDownstreamTransportSocketConfig(/*enable_early_data=*/false); + new_config_helper.addQuicDownstreamTransportSocketConfig(/*enable_early_data=*/false, {}); new_config_helper.setLds("1"); test_server_->waitForCounterGe("listener_manager.listener_in_place_updated", 1); diff --git a/test/integration/ssl_utility.cc b/test/integration/ssl_utility.cc index 1b226d79f9f7..0c4ae2e6dfd8 100644 --- a/test/integration/ssl_utility.cc +++ b/test/integration/ssl_utility.cc @@ -112,7 +112,7 @@ createClientSslTransportSocketFactory(const ClientSslTransportOptions& options, Network::DownstreamTransportSocketFactoryPtr createUpstreamSslContext(ContextManager& context_manager, Api::Api& api, bool use_http3) { envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; - ConfigHelper::initializeTls({}, *tls_context.mutable_common_tls_context()); + ConfigHelper::initializeTls({}, *tls_context.mutable_common_tls_context(), use_http3); NiceMock mock_factory_ctx; ON_CALL(mock_factory_ctx.server_context_, api()).WillByDefault(ReturnRef(api)); diff --git a/test/integration/tcp_tunneling_integration_test.cc b/test/integration/tcp_tunneling_integration_test.cc index d455fbd8ce4f..568dab2ad112 100644 --- a/test/integration/tcp_tunneling_integration_test.cc +++ b/test/integration/tcp_tunneling_integration_test.cc @@ -1333,7 +1333,7 @@ TEST_P(TcpTunnelingIntegrationTest, UpstreamConnectingDownstreamDisconnect) { // Use TLS because it will respond to a TCP half-close during handshake by closing the // connection. envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext tls_context; - ConfigHelper::initializeTls({}, *tls_context.mutable_common_tls_context()); + ConfigHelper::initializeTls({}, *tls_context.mutable_common_tls_context(), false); filter_chain->mutable_transport_socket()->set_name("envoy.transport_sockets.tls"); filter_chain->mutable_transport_socket()->mutable_typed_config()->PackFrom(tls_context); diff --git a/test/integration/utility.cc b/test/integration/utility.cc index 6ca68e0f333d..1f7e3b75f73d 100644 --- a/test/integration/utility.cc +++ b/test/integration/utility.cc @@ -258,7 +258,7 @@ IntegrationUtil::makeSingleRequest(const Network::Address::InstanceConstSharedPt quic_transport_socket_factory.clientContextConfig()->serverNameIndication(), static_cast(addr->ip()->port())), *dispatcher, addr, local_address, quic_stat_names, {}, *mock_stats_store.rootScope(), nullptr, - nullptr, generator); + nullptr, generator, quic_transport_socket_factory); connection->addConnectionCallbacks(connection_callbacks); Http::CodecClientProd client(type, std::move(connection), host_description, *dispatcher, random, options); From 2d99fcb243bf514381119883cf776fd6b46e0115 Mon Sep 17 00:00:00 2001 From: Jacob Bohanon Date: Thu, 4 Jan 2024 10:54:56 -0500 Subject: [PATCH 117/126] ext_proc: refactor per route config for immutability (#31431) * refactor per route config for immutability --------- Signed-off-by: Jacob Bohanon --- .../filters/http/ext_proc/ext_proc.cc | 67 ++++++++++++++----- .../filters/http/ext_proc/ext_proc.h | 29 ++++++-- .../filters/http/ext_proc/filter_test.cc | 40 +++++------ 3 files changed, 93 insertions(+), 43 deletions(-) diff --git a/source/extensions/filters/http/ext_proc/ext_proc.cc b/source/extensions/filters/http/ext_proc/ext_proc.cc index 21e57f4be82b..82b6848f9d3f 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.cc +++ b/source/extensions/filters/http/ext_proc/ext_proc.cc @@ -1,6 +1,8 @@ #include "source/extensions/filters/http/ext_proc/ext_proc.h" #include "envoy/config/common/mutation_rules/v3/mutation_rules.pb.h" +#include "envoy/config/core/v3/grpc_service.pb.h" +#include "envoy/extensions/filters/http/ext_proc/v3/processing_mode.pb.h" #include "source/common/http/utility.h" #include "source/common/runtime/runtime_features.h" @@ -113,24 +115,42 @@ ExtProcLoggingInfo::grpcCalls(envoy::config::core::v3::TrafficDirection traffic_ : encoding_processor_grpc_calls_; } -FilterConfigPerRoute::FilterConfigPerRoute(const ExtProcPerRoute& config) - : disabled_(config.disabled()) { - if (config.has_overrides()) { - processing_mode_ = config.overrides().processing_mode(); +absl::optional +FilterConfigPerRoute::initProcessingMode(const ExtProcPerRoute& config) { + if (!config.disabled() && config.has_overrides() && config.overrides().has_processing_mode()) { + return config.overrides().processing_mode(); } - if (config.overrides().has_grpc_service()) { - grpc_service_ = config.overrides().grpc_service(); + return absl::nullopt; +} +absl::optional +FilterConfigPerRoute::initGrpcService(const ExtProcPerRoute& config) { + if (config.has_overrides() && config.overrides().has_grpc_service()) { + return config.overrides().grpc_service(); } + return absl::nullopt; } -void FilterConfigPerRoute::merge(const FilterConfigPerRoute& src) { - disabled_ = src.disabled_; - processing_mode_ = src.processing_mode_; - if (src.grpcService().has_value()) { - grpc_service_ = src.grpcService(); +absl::optional +FilterConfigPerRoute::mergeProcessingMode(const FilterConfigPerRoute& less_specific, + const FilterConfigPerRoute& more_specific) { + if (more_specific.disabled()) { + return absl::nullopt; } + return more_specific.processingMode().has_value() ? more_specific.processingMode() + : less_specific.processingMode(); } +FilterConfigPerRoute::FilterConfigPerRoute(const ExtProcPerRoute& config) + : disabled_(config.disabled()), processing_mode_(initProcessingMode(config)), + grpc_service_(initGrpcService(config)) {} + +FilterConfigPerRoute::FilterConfigPerRoute(const FilterConfigPerRoute& less_specific, + const FilterConfigPerRoute& more_specific) + : disabled_(more_specific.disabled()), + processing_mode_(mergeProcessingMode(less_specific, more_specific)), + grpc_service_(more_specific.grpcService().has_value() ? more_specific.grpcService() + : less_specific.grpcService()) {} + void Filter::setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callbacks) { Http::PassThroughFilter::setDecoderFilterCallbacks(callbacks); decoding_state_.setDecoderFilterCallbacks(callbacks); @@ -850,14 +870,29 @@ void Filter::mergePerRouteConfig() { if (route_config_merged_) { return; } + route_config_merged_ = true; - auto merged_config = Http::Utility::getMergedPerFilterConfig( - decoder_callbacks_, - [](FilterConfigPerRoute& dst, const FilterConfigPerRoute& src) { dst.merge(src); }); + absl::optional merged_config; + + decoder_callbacks_->traversePerFilterConfig([&merged_config]( + const Router::RouteSpecificFilterConfig& cfg) { + const FilterConfigPerRoute* typed_cfg = dynamic_cast(&cfg); + if (typed_cfg == nullptr) { + ENVOY_LOG_MISC(debug, "Failed to retrieve the correct type of route specific filter config"); + return; + } + if (!merged_config) { + merged_config.emplace(*typed_cfg); + } else { + merged_config.emplace(FilterConfigPerRoute(merged_config.value(), *typed_cfg)); + } + }); + if (!merged_config.has_value()) { return; } + if (merged_config->disabled()) { // Rather than introduce yet another flag, use the processing mode // structure to disable all the callbacks. @@ -867,12 +902,12 @@ void Filter::mergePerRouteConfig() { encoding_state_.setProcessingMode(all_disabled); return; } - if (merged_config->processingMode()) { + if (merged_config->processingMode().has_value()) { ENVOY_LOG(trace, "Setting new processing mode from per-route configuration"); decoding_state_.setProcessingMode(*(merged_config->processingMode())); encoding_state_.setProcessingMode(*(merged_config->processingMode())); } - if (merged_config->grpcService()) { + if (merged_config->grpcService().has_value()) { ENVOY_LOG(trace, "Setting new GrpcService from per-route configuration"); grpc_service_ = *merged_config->grpcService(); config_with_hash_key_.setConfig(*merged_config->grpcService()); diff --git a/source/extensions/filters/http/ext_proc/ext_proc.h b/source/extensions/filters/http/ext_proc/ext_proc.h index 6338cc4e2aae..20a2e676719f 100644 --- a/source/extensions/filters/http/ext_proc/ext_proc.h +++ b/source/extensions/filters/http/ext_proc/ext_proc.h @@ -210,21 +210,36 @@ class FilterConfigPerRoute : public Router::RouteSpecificFilterConfig { explicit FilterConfigPerRoute( const envoy::extensions::filters::http::ext_proc::v3::ExtProcPerRoute& config); - void merge(const FilterConfigPerRoute& other); + // This constructor is used as a way to merge more-specific config into less-specific config in a + // clearly defined way (e.g. route config into vh config). All fields on this class must be const + // and thus must be initialized in the ctor initialization list. + FilterConfigPerRoute(const FilterConfigPerRoute& less_specific, + const FilterConfigPerRoute& more_specific); bool disabled() const { return disabled_; } - const absl::optional& + const absl::optional& processingMode() const { return processing_mode_; } - const absl::optional& grpcService() const { + const absl::optional& grpcService() const { return grpc_service_; } private: - bool disabled_; - absl::optional processing_mode_; - absl::optional grpc_service_; + absl::optional + initProcessingMode(const envoy::extensions::filters::http::ext_proc::v3::ExtProcPerRoute& config); + + absl::optional + initGrpcService(const envoy::extensions::filters::http::ext_proc::v3::ExtProcPerRoute& config); + + absl::optional + mergeProcessingMode(const FilterConfigPerRoute& less_specific, + const FilterConfigPerRoute& more_specific); + + const bool disabled_; + const absl::optional + processing_mode_; + const absl::optional grpc_service_; }; class Filter : public Logger::Loggable, @@ -330,7 +345,7 @@ class Filter : public Logger::Loggable, // know what response to return from certain failures. bool sent_immediate_response_ = false; - // Set to true then the mergePerRouteConfig() method has been called. + // Set to true when the mergePerRouteConfig() method has been called. bool route_config_merged_ = false; }; diff --git a/test/extensions/filters/http/ext_proc/filter_test.cc b/test/extensions/filters/http/ext_proc/filter_test.cc index 7e68bd4f1ac5..47865bdbf334 100644 --- a/test/extensions/filters/http/ext_proc/filter_test.cc +++ b/test/extensions/filters/http/ext_proc/filter_test.cc @@ -2899,11 +2899,11 @@ TEST(OverrideTest, OverrideProcessingMode) { ProcessingMode::BUFFERED); FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - EXPECT_FALSE(route1.disabled()); - EXPECT_EQ(route1.processingMode()->request_header_mode(), ProcessingMode::DEFAULT); - EXPECT_EQ(route1.processingMode()->request_body_mode(), ProcessingMode::STREAMED); - EXPECT_EQ(route1.processingMode()->response_body_mode(), ProcessingMode::BUFFERED); + FilterConfigPerRoute merged_route(route1, route2); + EXPECT_FALSE(merged_route.disabled()); + EXPECT_EQ(merged_route.processingMode()->request_header_mode(), ProcessingMode::DEFAULT); + EXPECT_EQ(merged_route.processingMode()->request_body_mode(), ProcessingMode::STREAMED); + EXPECT_EQ(merged_route.processingMode()->response_body_mode(), ProcessingMode::BUFFERED); } // When merging two configurations, if the first processing mode is set, and @@ -2916,9 +2916,9 @@ TEST(OverrideTest, DisableOverridesFirstMode) { cfg2.set_disabled(true); FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - EXPECT_TRUE(route1.disabled()); - EXPECT_FALSE(route1.processingMode()); + FilterConfigPerRoute merged_route(route1, route2); + EXPECT_TRUE(merged_route.disabled()); + EXPECT_FALSE(merged_route.processingMode()); } // When merging two configurations, if the first override is disabled, and @@ -2931,9 +2931,9 @@ TEST(OverrideTest, ModeOverridesFirstDisable) { ProcessingMode::SKIP); FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - EXPECT_FALSE(route1.disabled()); - EXPECT_EQ(route1.processingMode()->request_header_mode(), ProcessingMode::SKIP); + FilterConfigPerRoute merged_route(route1, route2); + EXPECT_FALSE(merged_route.disabled()); + EXPECT_EQ(merged_route.processingMode()->request_header_mode(), ProcessingMode::SKIP); } // When merging two configurations, if both are disabled, then it's still @@ -2945,9 +2945,9 @@ TEST(OverrideTest, DisabledThingsAreDisabled) { cfg2.set_disabled(true); FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - EXPECT_TRUE(route1.disabled()); - EXPECT_FALSE(route1.processingMode()); + FilterConfigPerRoute merged_route(route1, route2); + EXPECT_TRUE(merged_route.disabled()); + EXPECT_FALSE(merged_route.processingMode()); } // When merging two configurations, second grpc_service overrides the first. @@ -2960,9 +2960,9 @@ TEST(OverrideTest, GrpcServiceOverride) { "cluster_2"); FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - ASSERT_TRUE(route1.grpcService().has_value()); - EXPECT_THAT(*route1.grpcService(), ProtoEq(cfg2.overrides().grpc_service())); + FilterConfigPerRoute merged_route(route1, route2); + ASSERT_TRUE(merged_route.grpcService().has_value()); + EXPECT_THAT(*merged_route.grpcService(), ProtoEq(cfg2.overrides().grpc_service())); } // When merging two configurations, unset grpc_service is equivalent to no override. @@ -2974,9 +2974,9 @@ TEST(OverrideTest, GrpcServiceNonOverride) { // Leave cfg2.grpc_service unset. FilterConfigPerRoute route1(cfg1); FilterConfigPerRoute route2(cfg2); - route1.merge(route2); - ASSERT_TRUE(route1.grpcService().has_value()); - EXPECT_THAT(*route1.grpcService(), ProtoEq(cfg1.overrides().grpc_service())); + FilterConfigPerRoute merged_route(route1, route2); + ASSERT_TRUE(merged_route.grpcService().has_value()); + EXPECT_THAT(*merged_route.grpcService(), ProtoEq(cfg1.overrides().grpc_service())); } // Verify that attempts to change headers that are not allowed to be changed From b61026feb0cf160934225ad134c1eb1c74cd05ef Mon Sep 17 00:00:00 2001 From: IssaAbuKalbein <86603440+IssaAbuKalbein@users.noreply.github.com> Date: Thu, 4 Jan 2024 17:56:11 +0200 Subject: [PATCH 118/126] [UDP Proxy] Fix a bug in UDP session filter (#31316) Signed-off-by: Issa Abu Kalbein --- .../extensions/filters/udp/udp_proxy/session_filters/filter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/extensions/filters/udp/udp_proxy/session_filters/filter.h b/source/extensions/filters/udp/udp_proxy/session_filters/filter.h index b0daa46b27ba..f9d5af16215e 100644 --- a/source/extensions/filters/udp/udp_proxy/session_filters/filter.h +++ b/source/extensions/filters/udp/udp_proxy/session_filters/filter.h @@ -88,7 +88,7 @@ class FilterBase { /** * Session read filter interface. */ -class ReadFilter : public FilterBase { +class ReadFilter : public virtual FilterBase { public: virtual ~ReadFilter() = default; @@ -134,7 +134,7 @@ enum class WriteFilterStatus { /** * Session write filter interface. */ -class WriteFilter : public FilterBase { +class WriteFilter : public virtual FilterBase { public: virtual ~WriteFilter() = default; From 1cb0c626698e6872c8b8540a745f72a447d43dcc Mon Sep 17 00:00:00 2001 From: Alyssa Wilk Date: Thu, 4 Jan 2024 10:56:59 -0500 Subject: [PATCH 119/126] Revert "Resolver: switching to statusor (#31312)" This reverts commit 7a1a883aed9dce124f449a82331228c055812356. Signed-off-by: Alyssa Wilk --- envoy/network/resolver.h | 4 +-- .../common/listener_manager/listener_impl.cc | 12 ++----- .../listener_manager/listener_manager_impl.cc | 4 +-- source/common/network/resolver_impl.cc | 15 ++++---- source/common/network/resolver_impl.h | 8 ++--- .../upstream/health_discovery_service.cc | 18 ++++------ source/common/upstream/upstream_impl.cc | 30 +++++----------- .../network/dns_resolver/cares/dns_impl.cc | 4 +-- .../stat_sinks/dog_statsd/config.cc | 5 ++- .../stat_sinks/graphite_statsd/config.cc | 5 ++- source/extensions/stat_sinks/statsd/config.cc | 5 ++- source/server/api_listener_impl.cc | 20 +++-------- source/server/api_listener_impl.h | 13 +++---- source/server/configuration_impl.cc | 4 +-- test/common/network/resolver_impl_test.cc | 34 +++++++++---------- test/fuzz/utility.h | 3 +- test/mocks/network/mocks.h | 2 +- test/server/api_listener_test.cc | 26 +++++++------- tools/code_format/config.yaml | 1 + 19 files changed, 81 insertions(+), 132 deletions(-) diff --git a/envoy/network/resolver.h b/envoy/network/resolver.h index 64e66bff32f8..dcdcfe8a8c92 100644 --- a/envoy/network/resolver.h +++ b/envoy/network/resolver.h @@ -24,9 +24,9 @@ class Resolver : public Config::UntypedFactory { /** * Resolve a custom address string and port to an Address::Instance. * @param socket_address supplies the socket address to resolve. - * @return InstanceConstSharedPtr appropriate Address::Instance or an error status. + * @return InstanceConstSharedPtr appropriate Address::Instance. */ - virtual absl::StatusOr + virtual InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) PURE; std::string category() const override { return "envoy.resolvers"; } diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 1c4034620a3f..984ebca0a7b9 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -223,9 +223,7 @@ std::string listenerStatsScope(const envoy::config::listener::v3::Listener& conf if (config.has_internal_listener()) { return absl::StrCat("envoy_internal_", config.name()); } - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - return address_or_error.value()->asString(); + return Network::Address::resolveProtoAddress(config.address())->asString(); } } // namespace @@ -310,9 +308,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, } else { // All the addresses should be same socket type, so get the first address's socket type is // enough. - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - auto address = std::move(address_or_error.value()); + auto address = Network::Address::resolveProtoAddress(config.address()); checkIpv4CompatAddress(address, config.address()); addresses_.emplace_back(address); address_opts_list.emplace_back(std::ref(config.socket_options())); @@ -325,10 +321,8 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, "support same socket type for all the addresses.", name_)); } - auto addresses_or_error = + auto additional_address = Network::Address::resolveProtoAddress(config.additional_addresses(i).address()); - THROW_IF_STATUS_NOT_OK(addresses_or_error, throw); - auto additional_address = std::move(addresses_or_error.value()); checkIpv4CompatAddress(address, config.additional_addresses(i).address()); addresses_.emplace_back(additional_address); if (config.additional_addresses(i).has_socket_options()) { diff --git a/source/common/listener_manager/listener_manager_impl.cc b/source/common/listener_manager/listener_manager_impl.cc index 853087d0b1bf..3982b72eed00 100644 --- a/source/common/listener_manager/listener_manager_impl.cc +++ b/source/common/listener_manager/listener_manager_impl.cc @@ -468,9 +468,7 @@ ListenerManagerImpl::addOrUpdateListener(const envoy::config::listener::v3::List name)); } if (!api_listener_ && !added_via_api) { - auto listener_or_error = HttpApiListener::create(config, server_, config.name()); - THROW_IF_STATUS_NOT_OK(listener_or_error, throw); - api_listener_ = std::move(listener_or_error.value()); + api_listener_ = std::make_unique(config, server_, config.name()); return true; } else { ENVOY_LOG(warn, "listener {} can not be added because currently only one ApiListener is " diff --git a/source/common/network/resolver_impl.cc b/source/common/network/resolver_impl.cc index 63119deff8ae..bd51bcfd2272 100644 --- a/source/common/network/resolver_impl.cc +++ b/source/common/network/resolver_impl.cc @@ -20,7 +20,7 @@ namespace Address { class IpResolver : public Resolver { public: - absl::StatusOr + InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { switch (socket_address.port_specifier_case()) { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kPortValue: @@ -31,8 +31,8 @@ class IpResolver : public Resolver { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort: break; } - return absl::InvalidArgumentError(fmt::format("IP resolver can't handle port specifier type {}", - socket_address.port_specifier_case())); + throwEnvoyExceptionOrPanic(fmt::format("IP resolver can't handle port specifier type {}", + socket_address.port_specifier_case())); } std::string name() const override { return Config::AddressResolverNames::get().IP; } @@ -43,8 +43,7 @@ class IpResolver : public Resolver { */ REGISTER_FACTORY(IpResolver, Resolver); -absl::StatusOr -resolveProtoAddress(const envoy::config::core::v3::Address& address) { +InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Address& address) { switch (address.address_case()) { case envoy::config::core::v3::Address::AddressCase::ADDRESS_NOT_SET: throwEnvoyExceptionOrPanic("Address must be set: " + address.DebugString()); @@ -67,7 +66,7 @@ resolveProtoAddress(const envoy::config::core::v3::Address& address) { throwEnvoyExceptionOrPanic("Failed to resolve address:" + address.DebugString()); } -absl::StatusOr +InstanceConstSharedPtr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_address) { Resolver* resolver = nullptr; const std::string& resolver_name = socket_address.resolver_name(); @@ -80,9 +79,7 @@ resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_a if (resolver == nullptr) { throwEnvoyExceptionOrPanic(fmt::format("Unknown address resolver: {}", resolver_name)); } - auto instance_or_error = resolver->resolve(socket_address); - THROW_IF_STATUS_NOT_OK(instance_or_error, throw); - return std::move(instance_or_error.value()); + return resolver->resolve(socket_address); } } // namespace Address diff --git a/source/common/network/resolver_impl.h b/source/common/network/resolver_impl.h index f36c0f03b203..fb26085eb00d 100644 --- a/source/common/network/resolver_impl.h +++ b/source/common/network/resolver_impl.h @@ -14,17 +14,17 @@ namespace Address { /** * Create an Instance from a envoy::config::core::v3::Address. * @param address supplies the address proto to resolve. - * @return pointer to the Instance or an error status + * @return pointer to the Instance. */ -absl::StatusOr +Address::InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Address& address); /** * Create an Instance from a envoy::config::core::v3::SocketAddress. * @param address supplies the socket address proto to resolve. - * @return pointer to the Instance or an error status. + * @return pointer to the Instance. */ -absl::StatusOr +Address::InstanceConstSharedPtr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& address); DECLARE_FACTORY(IpResolver); diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index 4db99e3361d0..b1c659a5529f 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -371,11 +371,10 @@ HdsCluster::HdsCluster(Server::Configuration::ServerFactoryContext& server_conte for (const auto& host : locality_endpoints.lb_endpoints()) { const LocalityEndpointTuple endpoint_key = {locality_endpoints.locality(), host}; // Initialize an endpoint host object. - auto address_or_error = Network::Address::resolveProtoAddress(host.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); HostSharedPtr endpoint = std::make_shared( - info_, "", std::move(address_or_error.value()), nullptr, 1, locality_endpoints.locality(), - host.endpoint().health_check_config(), 0, envoy::config::core::v3::UNKNOWN, time_source_); + info_, "", Network::Address::resolveProtoAddress(host.endpoint().address()), nullptr, 1, + locality_endpoints.locality(), host.endpoint().health_check_config(), 0, + envoy::config::core::v3::UNKNOWN, time_source_); // Add this host/endpoint pointer to our flat list of endpoints for health checking. hosts_->push_back(endpoint); // Add this host/endpoint pointer to our structured list by locality so results can be @@ -484,13 +483,10 @@ void HdsCluster::updateHosts( host = host_pair->second; } else { // We do not have this endpoint saved, so create a new one. - auto address_or_error = - Network::Address::resolveProtoAddress(endpoint.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - host = std::make_shared(info_, "", std::move(address_or_error.value()), nullptr, - 1, endpoints.locality(), - endpoint.endpoint().health_check_config(), 0, - envoy::config::core::v3::UNKNOWN, time_source_); + host = std::make_shared( + info_, "", Network::Address::resolveProtoAddress(endpoint.endpoint().address()), + nullptr, 1, endpoints.locality(), endpoint.endpoint().health_check_config(), 0, + envoy::config::core::v3::UNKNOWN, time_source_); // Set the initial health status as in HdsCluster::initialize. host->healthFlagSet(Host::HealthFlag::FAILED_ACTIVE_HC); diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index 5c781c9bd70a..aa4e8fc849f9 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -227,14 +227,10 @@ parseBindConfig(::Envoy::OptRef bind_ std::vector<::Envoy::Upstream::UpstreamLocalAddress> upstream_local_addresses; if (bind_config.has_value()) { UpstreamLocalAddress upstream_local_address; - upstream_local_address.address_ = nullptr; - if (bind_config->has_source_address()) { - - auto address_or_error = - ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - upstream_local_address.address_ = address_or_error.value(); - } + upstream_local_address.address_ = + bind_config->has_source_address() + ? ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()) + : nullptr; upstream_local_address.socket_options_ = std::make_shared(); ::Envoy::Network::Socket::appendOptions(upstream_local_address.socket_options_, @@ -246,10 +242,8 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& extra_source_address : bind_config->extra_source_addresses()) { UpstreamLocalAddress extra_upstream_local_address; - auto address_or_error = + extra_upstream_local_address.address_ = ::Envoy::Network::Address::resolveProtoSocketAddress(extra_source_address.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - extra_upstream_local_address.address_ = address_or_error.value(); extra_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); @@ -270,10 +264,8 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& additional_source_address : bind_config->additional_source_addresses()) { UpstreamLocalAddress additional_upstream_local_address; - auto address_or_error = + additional_upstream_local_address.address_ = ::Envoy::Network::Address::resolveProtoSocketAddress(additional_source_address); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - additional_upstream_local_address.address_ = address_or_error.value(); additional_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); ::Envoy::Network::Socket::appendOptions(additional_upstream_local_address.socket_options_, @@ -1749,11 +1741,7 @@ void ClusterImplBase::reloadHealthyHostsHelper(const HostSharedPtr&) { const Network::Address::InstanceConstSharedPtr ClusterImplBase::resolveProtoAddress(const envoy::config::core::v3::Address& address) { - TRY_ASSERT_MAIN_THREAD { - auto address_or_error = Network::Address::resolveProtoAddress(address); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - return address_or_error.value(); - } + TRY_ASSERT_MAIN_THREAD { return Network::Address::resolveProtoAddress(address); } END_TRY CATCH(EnvoyException & e, { if (info_->type() == envoy::config::cluster::v3::Cluster::STATIC || @@ -2421,9 +2409,7 @@ Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress( Network::Address::InstanceConstSharedPtr health_check_address; const auto& port_value = health_check_config.port_value(); if (health_check_config.has_address()) { - auto address_or_error = Network::Address::resolveProtoAddress(health_check_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - auto address = address_or_error.value(); + auto address = Network::Address::resolveProtoAddress(health_check_config.address()); health_check_address = port_value == 0 ? address : Network::Utility::getAddressWithPort(*address, port_value); } else { diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc index 64848d6a4331..f1fec3b6bcc8 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.cc +++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc @@ -555,9 +555,7 @@ class CaresDnsResolverFactory : public DnsResolverFactory, const auto& resolver_addrs = cares.resolvers(); resolvers.reserve(resolver_addrs.size()); for (const auto& resolver_addr : resolver_addrs) { - auto address_or_error = Network::Address::resolveProtoAddress(resolver_addr); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - resolvers.push_back(std::move(address_or_error.value())); + resolvers.push_back(Network::Address::resolveProtoAddress(resolver_addr)); } } return std::make_shared(cares, dispatcher, resolvers, diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index 78c39f20d914..f3204bb322cb 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -22,9 +22,8 @@ DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, const auto& sink_config = MessageUtil::downcastAndValidate( config, server.messageValidationContext().staticValidationVisitor()); - auto address_or_error = Network::Address::resolveProtoAddress(sink_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(sink_config.address()); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (sink_config.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/graphite_statsd/config.cc b/source/extensions/stat_sinks/graphite_statsd/config.cc index 93322442900d..7320993e035e 100644 --- a/source/extensions/stat_sinks/graphite_statsd/config.cc +++ b/source/extensions/stat_sinks/graphite_statsd/config.cc @@ -25,9 +25,8 @@ GraphiteStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, switch (statsd_sink.statsd_specifier_case()) { case envoy::extensions::stat_sinks::graphite_statsd::v3::GraphiteStatsdSink::StatsdSpecifierCase:: kAddress: { - auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(statsd_sink.address()); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (statsd_sink.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/statsd/config.cc b/source/extensions/stat_sinks/statsd/config.cc index ae76707892a0..84670fa1308b 100644 --- a/source/extensions/stat_sinks/statsd/config.cc +++ b/source/extensions/stat_sinks/statsd/config.cc @@ -23,9 +23,8 @@ StatsdSinkFactory::createStatsSink(const Protobuf::Message& config, config, server.messageValidationContext().staticValidationVisitor()); switch (statsd_sink.statsd_specifier_case()) { case envoy::config::metrics::v3::StatsdSink::StatsdSpecifierCase::kAddress: { - auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(statsd_sink.address()); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), false, statsd_sink.prefix()); diff --git a/source/server/api_listener_impl.cc b/source/server/api_listener_impl.cc index a9dfa065d89c..d947a0549c7a 100644 --- a/source/server/api_listener_impl.cc +++ b/source/server/api_listener_impl.cc @@ -13,10 +13,10 @@ namespace Envoy { namespace Server { -ApiListenerImplBase::ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, +ApiListenerImplBase::ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : config_(config), name_(name), address_(std::move(address)), + : config_(config), name_(name), + address_(Network::Address::resolveProtoAddress(config.address())), factory_context_(server, *this, server.stats().createScope(""), server.stats().createScope(fmt::format("listener.api.{}.", name_)), std::make_shared(config)) {} @@ -41,19 +41,9 @@ HttpApiListener::ApiListenerWrapper::newStreamHandle(Http::ResponseEncoder& resp return http_connection_manager_->newStreamHandle(response_encoder, is_internally_created); } -absl::StatusOr> -HttpApiListener::create(const envoy::config::listener::v3::Listener& config, - Server::Instance& server, const std::string& name) { - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - RETURN_IF_STATUS_NOT_OK(address_or_error); - return std::unique_ptr( - new HttpApiListener(std::move(address_or_error.value()), config, server, name)); -} - -HttpApiListener::HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, +HttpApiListener::HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : ApiListenerImplBase(std::move(address), config, server, name) { + : ApiListenerImplBase(config, server, name) { if (config.api_listener().api_listener().type_url() == absl::StrCat( "type.googleapis.com/", diff --git a/source/server/api_listener_impl.h b/source/server/api_listener_impl.h index 5ac8a3b7c07b..ccf1b2cbdcd3 100644 --- a/source/server/api_listener_impl.h +++ b/source/server/api_listener_impl.h @@ -49,8 +49,7 @@ class ApiListenerImplBase : public ApiListener, } protected: - ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, Server::Instance& server, + ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name); // Synthetic class that acts as a stub Network::ReadFilterCallbacks. @@ -222,18 +221,14 @@ class HttpApiListener : public ApiListenerImplBase { Http::ApiListenerPtr http_connection_manager_; }; + HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, + const std::string& name); + // ApiListener ApiListener::Type type() const override { return ApiListener::Type::HttpApiListener; } Http::ApiListenerPtr createHttpApiListener(Event::Dispatcher& dispatcher) override; - static absl::StatusOr> - create(const envoy::config::listener::v3::Listener& config, Server::Instance& server, - const std::string& name); private: - HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, Server::Instance& server, - const std::string& name); - // Need to store the factory due to the shared_ptrs that need to be kept alive: date provider, // route config manager, scoped route config manager. std::function diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 6129c6182131..80818215be7b 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -231,9 +231,7 @@ InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstra admin_.profile_path_ = admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); if (admin.has_address()) { - auto address_or_error = Network::Address::resolveProtoAddress(admin.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - admin_.address_ = std::move(address_or_error.value()); + admin_.address_ = Network::Address::resolveProtoAddress(admin.address()); } admin_.socket_options_ = std::make_shared>(); if (!admin.socket_options().empty()) { diff --git a/test/common/network/resolver_impl_test.cc b/test/common/network/resolver_impl_test.cc index 3574414e6298..22e752bd28ae 100644 --- a/test/common/network/resolver_impl_test.cc +++ b/test/common/network/resolver_impl_test.cc @@ -32,7 +32,7 @@ TEST_F(IpResolverTest, Basic) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_port_value(443); - auto address = resolver_->resolve(socket_address).value(); + auto address = resolver_->resolve(socket_address); EXPECT_EQ(address->ip()->addressAsString(), "1.2.3.4"); EXPECT_EQ(address->ip()->port(), 443); } @@ -41,25 +41,26 @@ TEST_F(IpResolverTest, DisallowsNamedPort) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_named_port("http"); - EXPECT_EQ(resolver_->resolve(socket_address).status().message(), - fmt::format("IP resolver can't handle port specifier type {}", - envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); + EXPECT_THROW_WITH_MESSAGE( + resolver_->resolve(socket_address), EnvoyException, + fmt::format("IP resolver can't handle port specifier type {}", + envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); } TEST(ResolverTest, FromProtoAddress) { envoy::config::core::v3::Address ipv4_address; ipv4_address.mutable_socket_address()->set_address("1.2.3.4"); ipv4_address.mutable_socket_address()->set_port_value(5); - EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address).value()->asString()); + EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address)->asString()); envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address).value()->asString()); + EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address)->asString()); envoy::config::core::v3::Address pipe_address; pipe_address.mutable_pipe()->set_path("/foo/bar"); - EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address).value()->asString()); + EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address)->asString()); } TEST(ResolverTest, InternalListenerNameFromProtoAddress) { @@ -67,14 +68,14 @@ TEST(ResolverTest, InternalListenerNameFromProtoAddress) { internal_listener_address.mutable_envoy_internal_address()->set_server_listener_name( "internal_listener_foo"); EXPECT_EQ("envoy://internal_listener_foo/", - resolveProtoAddress(internal_listener_address).value()->asString()); + resolveProtoAddress(internal_listener_address)->asString()); } TEST(ResolverTest, UninitializedInternalAddressFromProtoAddress) { envoy::config::core::v3::Address internal_address; internal_address.mutable_envoy_internal_address(); EXPECT_THROW_WITH_MESSAGE( - resolveProtoAddress(internal_address).IgnoreError(), EnvoyException, + resolveProtoAddress(internal_address), EnvoyException, fmt::format("Failed to resolve address:{}", internal_address.DebugString())); } @@ -84,7 +85,7 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - auto resolved_addr = resolveProtoAddress(ipv6_address).value(); + auto resolved_addr = resolveProtoAddress(ipv6_address); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } { @@ -92,14 +93,14 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); ipv6_address.mutable_socket_address()->set_ipv4_compat(true); - auto resolved_addr = resolveProtoAddress(ipv6_address).value(); + auto resolved_addr = resolveProtoAddress(ipv6_address); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } } class TestResolver : public Resolver { public: - absl::StatusOr + InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { const std::string& logical = socket_address.address(); const std::string physical = getPhysicalName(logical); @@ -153,7 +154,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address).value(); + auto instance = resolveProtoAddress(address); EXPECT_EQ("1.2.3.4:5", instance->asString()); EXPECT_EQ("foo:5", instance->logicalName()); } @@ -163,7 +164,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("bar"); socket->set_named_port("http"); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address).value(); + auto instance = resolveProtoAddress(address); EXPECT_EQ("4.3.2.1:http", instance->asString()); EXPECT_EQ("bar:http", instance->logicalName()); } @@ -171,8 +172,7 @@ TEST(ResolverTest, NonStandardResolver) { TEST(ResolverTest, UninitializedAddress) { envoy::config::core::v3::Address address; - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, - "Address must be set: "); + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, "Address must be set: "); } TEST(ResolverTest, NoSuchResolver) { @@ -181,7 +181,7 @@ TEST(ResolverTest, NoSuchResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, "Unknown address resolver: envoy.test.resolver"); } diff --git a/test/fuzz/utility.h b/test/fuzz/utility.h index 681674debc4e..7ecd69d0942d 100644 --- a/test/fuzz/utility.h +++ b/test/fuzz/utility.h @@ -170,7 +170,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn replaceInvalidHostCharacters( stream_info.address().envoy_internal_address().server_listener_name())); } else { - address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()).value(); + address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()); } } else { address = Network::Utility::resolveUrl("tcp://10.0.0.1:443"); @@ -178,7 +178,6 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn auto upstream_local_address = stream_info.has_upstream_local_address() ? Envoy::Network::Address::resolveProtoAddress(stream_info.upstream_local_address()) - .value() : Network::Utility::resolveUrl("tcp://10.0.0.1:10000"); test_stream_info->upstreamInfo()->setUpstreamLocalAddress(upstream_local_address); test_stream_info->downstream_connection_info_provider_ = diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 09417750b16b..283bb4377df7 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -88,7 +88,7 @@ class MockAddressResolver : public Address::Resolver { MockAddressResolver(); ~MockAddressResolver() override; - MOCK_METHOD(absl::StatusOr, resolve, + MOCK_METHOD(Address::InstanceConstSharedPtr, resolve, (const envoy::config::core::v3::SocketAddress&)); MOCK_METHOD(std::string, name, (), (const)); }; diff --git a/test/server/api_listener_test.cc b/test/server/api_listener_test.cc index 9d70fbd6e4e3..7183f80b8651 100644 --- a/test/server/api_listener_test.cc +++ b/test/server/api_listener_test.cc @@ -53,11 +53,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, MobileApiListener) { @@ -88,11 +88,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, HttpApiListenerThrowsWithBadConfig) { @@ -125,7 +125,7 @@ name: test_api_listener ->set_path("eds path"); expected_any_proto.PackFrom(expected_cluster_proto); EXPECT_THROW_WITH_MESSAGE( - HttpApiListener::create(config, server_, config.name()).IgnoreError(), EnvoyException, + HttpApiListener(config, server_, config.name()), EnvoyException, fmt::format("Unable to unpack as " "envoy.extensions.filters.network.http_connection_manager.v3." "HttpConnectionManager: {}", @@ -159,11 +159,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - auto api_listener = http_api_listener->createHttpApiListener(server_.dispatcher()); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + auto api_listener = http_api_listener.createHttpApiListener(server_.dispatcher()); ASSERT_NE(api_listener, nullptr); Network::MockConnectionCallbacks network_connection_callbacks; diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 1e1b071c2d19..c7e1dc6bd7c9 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -109,6 +109,7 @@ paths: - source/common/network/address_impl.cc - source/common/network/utility.cc - source/common/network/dns_resolver/dns_factory_util.cc + - source/common/network/resolver_impl.cc - source/common/network/socket_impl.cc - source/common/ssl/tls_certificate_config_impl.cc - source/common/formatter/http_specific_formatter.cc From e82f672712b89df276ab0555082ef613c16a5eb7 Mon Sep 17 00:00:00 2001 From: Juan Manuel Olle Date: Thu, 4 Jan 2024 12:58:34 -0300 Subject: [PATCH 120/126] Add composite matched actions into filter_state (#31124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add mached action to filter state --------- Signed-off-by: Juan Manuel Ollé --- changelogs/current.yaml | 4 + .../http/http_filters/composite_filter.rst | 9 + .../extensions/filters/http/composite/BUILD | 1 + .../filters/http/composite/action.cc | 12 +- .../filters/http/composite/action.h | 6 +- .../filters/http/composite/filter.cc | 39 +++- .../filters/http/composite/filter.h | 30 +++ .../filters/http/composite/filter_test.cc | 195 +++++++++++++++++- 8 files changed, 279 insertions(+), 17 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 47a871a78008..9ef9d3b887f2 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -75,6 +75,10 @@ minor_behavior_changes: Added config name of filter sending a local reply in filter state with key ``envoy.filters.network.http_connection_manager.local_reply_owner``. See :ref:`the well-known filter state keys ` for more detail. +- area: composite filter + change: | + Added composite filter's matched action name to filter state with key + ``envoy.extensions.filters.http.composite.matched_actions``. - area: http2 change: | Flip the runtime guard ``envoy.reloadable_features.defer_processing_backedup_streams`` to be on by default. diff --git a/docs/root/configuration/http/http_filters/composite_filter.rst b/docs/root/configuration/http/http_filters/composite_filter.rst index af8efc2288ea..8515e51e1f71 100644 --- a/docs/root/configuration/http/http_filters/composite_filter.rst +++ b/docs/root/configuration/http/http_filters/composite_filter.rst @@ -18,6 +18,15 @@ Delegation can fail if the filter factory attempted to use a callback not suppor composite filter. In either case, the ``.composite.delegation_error`` stat will be incremented. +This filter adds a map of the delegated filter name (of the action that is matched )and the root config filter name to the filter state with key +``envoy.extensions.filters.http.composite.matched_actions`` + +Contains a map of pairs `FILTER_CONFIG_NAME:ACTION_NAME`: + + * ``FILTER_CONFIG_NAME``: root filter config name; + * ``ACTION_NAME``: delegated filter name of the action that is matched. + + Sample Envoy configuration -------------------------- diff --git a/source/extensions/filters/http/composite/BUILD b/source/extensions/filters/http/composite/BUILD index bf636545cf4b..ccc790873b21 100644 --- a/source/extensions/filters/http/composite/BUILD +++ b/source/extensions/filters/http/composite/BUILD @@ -38,6 +38,7 @@ envoy_cc_library( "//envoy/http:filter_interface", "//source/common/http:header_map_lib", "//source/common/http:headers_lib", + "//source/common/json:json_loader_lib", "//source/common/matcher:matcher_lib", "//source/extensions/filters/http/common:pass_through_filter_lib", ], diff --git a/source/extensions/filters/http/composite/action.cc b/source/extensions/filters/http/composite/action.cc index d7cb694e7452..d4cbf7f7fe1c 100644 --- a/source/extensions/filters/http/composite/action.cc +++ b/source/extensions/filters/http/composite/action.cc @@ -28,6 +28,7 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createActionFactoryCb( if (!context.factory_context_.has_value() || !context.server_factory_context_.has_value()) { throw EnvoyException(fmt::format("Failed to get factory context or server factory context.")); } + std::string name = composite_action.dynamic_config().name(); // Create a dynamic filter config provider and register it with the server factory context. auto config_discovery = composite_action.dynamic_config().config_discovery(); Server::Configuration::FactoryContext& factory_context = context.factory_context_.value(); @@ -40,15 +41,15 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createActionFactoryCb( provider_manager->createDynamicFilterConfigProvider( config_discovery, composite_action.dynamic_config().name(), server_factory_context, factory_context, server_factory_context.clusterManager(), false, "http", nullptr); - return [provider = std::move(provider)]() -> Matcher::ActionPtr { + return [provider = std::move(provider), n = std::move(name)]() -> Matcher::ActionPtr { auto config_value = provider->config(); if (config_value.has_value()) { auto factory_cb = config_value.value().get().factory_cb; - return std::make_unique(factory_cb); + return std::make_unique(factory_cb, n); } // There is no dynamic config available. Apply missing config filter. auto factory_cb = Envoy::Http::MissingConfigFilterFactory; - return std::make_unique(factory_cb); + return std::make_unique(factory_cb, n); }; } @@ -78,9 +79,10 @@ Matcher::ActionFactoryCb ExecuteFilterActionFactory::createActionFactoryCb( if (callback == nullptr) { throw EnvoyException("Failed to get filter factory creation function"); } + std::string name = composite_action.typed_config().name(); - return [cb = std::move(callback)]() -> Matcher::ActionPtr { - return std::make_unique(cb); + return [cb = std::move(callback), n = std::move(name)]() -> Matcher::ActionPtr { + return std::make_unique(cb, n); }; } diff --git a/source/extensions/filters/http/composite/action.h b/source/extensions/filters/http/composite/action.h index b78553d8ab77..af8241a03887 100644 --- a/source/extensions/filters/http/composite/action.h +++ b/source/extensions/filters/http/composite/action.h @@ -15,12 +15,16 @@ class ExecuteFilterAction : public Matcher::ActionBase< envoy::extensions::filters::http::composite::v3::ExecuteFilterAction> { public: - explicit ExecuteFilterAction(Http::FilterFactoryCb cb) : cb_(std::move(cb)) {} + explicit ExecuteFilterAction(Http::FilterFactoryCb cb, const std::string& name) + : cb_(std::move(cb)), name_(name) {} void createFilters(Http::FilterChainFactoryCallbacks& callbacks) const; + const std::string& actionName() const { return name_; } + private: Http::FilterFactoryCb cb_; + const std::string name_; }; class ExecuteFilterActionFactory diff --git a/source/extensions/filters/http/composite/filter.cc b/source/extensions/filters/http/composite/filter.cc index aace379d0f05..77475283214e 100644 --- a/source/extensions/filters/http/composite/filter.cc +++ b/source/extensions/filters/http/composite/filter.cc @@ -27,6 +27,16 @@ template struct Overloaded : Ts... { using Ts::operator()...; }; template Overloaded(Ts...) -> Overloaded; } // namespace + +std::unique_ptr MatchedActionInfo::buildProtoStruct() const { + auto message = std::make_unique(); + auto& fields = *message->mutable_fields(); + for (const auto& p : actions_) { + fields[p.first] = ValueUtil::stringValue(p.second); + } + return message; +} + Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, bool end_stream) { decoded_headers_ = true; @@ -95,18 +105,27 @@ void Filter::onMatchCallback(const Matcher::Action& action) { wrapper.errors_, [](const auto& status) { return status.ToString(); })); return; } + std::string actionName = composite_action.actionName(); if (wrapper.filter_to_inject_.has_value()) { stats_.filter_delegation_success_.inc(); auto createDelegatedFilterFn = Overloaded{ - [this](Http::StreamDecoderFilterSharedPtr filter) { + [this, actionName](Http::StreamDecoderFilterSharedPtr filter) { delegated_filter_ = std::make_shared(std::move(filter)); + updateFilterState(decoder_callbacks_, std::string(decoder_callbacks_->filterConfigName()), + actionName); }, - [this](Http::StreamEncoderFilterSharedPtr filter) { + [this, actionName](Http::StreamEncoderFilterSharedPtr filter) { delegated_filter_ = std::make_shared(std::move(filter)); + updateFilterState(encoder_callbacks_, std::string(encoder_callbacks_->filterConfigName()), + actionName); }, - [this](Http::StreamFilterSharedPtr filter) { delegated_filter_ = std::move(filter); }}; + [this, actionName](Http::StreamFilterSharedPtr filter) { + delegated_filter_ = std::move(filter); + updateFilterState(decoder_callbacks_, std::string(decoder_callbacks_->filterConfigName()), + actionName); + }}; absl::visit(createDelegatedFilterFn, std::move(wrapper.filter_to_inject_.value())); delegated_filter_->setDecoderFilterCallbacks(*decoder_callbacks_); @@ -121,6 +140,20 @@ void Filter::onMatchCallback(const Matcher::Action& action) { // either directly or via some return status. } +void Filter::updateFilterState(Http::StreamFilterCallbacks* callback, + const std::string& filter_name, const std::string& action_name) { + auto* info = callback->streamInfo().filterState()->getDataMutable( + MatchedActionsFilterStateKey); + if (info != nullptr) { + info->setFilterAction(filter_name, action_name); + } else { + callback->streamInfo().filterState()->setData( + MatchedActionsFilterStateKey, std::make_shared(filter_name, action_name), + StreamInfo::FilterState::StateType::Mutable, + StreamInfo::FilterState::LifeSpan::FilterChain); + } +} + Http::FilterHeadersStatus Filter::StreamFilterWrapper::decodeHeaders(Http::RequestHeaderMap& headers, bool end_stream) { return delegateFilterActionOr(decoder_filter_, &StreamDecoderFilter::decodeHeaders, diff --git a/source/extensions/filters/http/composite/filter.h b/source/extensions/filters/http/composite/filter.h index 9f73a566b034..76d2010430a5 100644 --- a/source/extensions/filters/http/composite/filter.h +++ b/source/extensions/filters/http/composite/filter.h @@ -4,10 +4,12 @@ #include "envoy/http/header_map.h" #include "envoy/server/filter_config.h" +#include "source/common/json/json_loader.h" #include "source/extensions/filters/http/common/pass_through_filter.h" #include "source/extensions/filters/http/composite/action.h" #include "source/extensions/filters/http/composite/factory_wrapper.h" +#include "absl/container/flat_hash_map.h" #include "absl/types/variant.h" namespace Envoy { @@ -15,6 +17,9 @@ namespace Extensions { namespace HttpFilters { namespace Composite { +constexpr absl::string_view MatchedActionsFilterStateKey = + "envoy.extensions.filters.http.composite.matched_actions"; + struct FactoryCallbacksWrapper; #define ALL_COMPOSITE_FILTER_STATS(COUNTER) \ @@ -25,6 +30,28 @@ struct FilterStats { ALL_COMPOSITE_FILTER_STATS(GENERATE_COUNTER_STRUCT) }; +class MatchedActionInfo : public StreamInfo::FilterState::Object { +public: + MatchedActionInfo(const std::string& filter, const std::string& action) { + actions_[filter] = action; + } + + ProtobufTypes::MessagePtr serializeAsProto() const override { return buildProtoStruct(); } + + absl::optional serializeAsString() const override { + return Json::Factory::loadFromProtobufStruct(*buildProtoStruct().get())->asJsonString(); + } + + void setFilterAction(const std::string& filter, const std::string& action) { + actions_[filter] = action; + } + +private: + std::unique_ptr buildProtoStruct() const; + + absl::flat_hash_map actions_; +}; + class Filter : public Http::StreamFilter, public AccessLog::Instance, Logger::Loggable { @@ -85,6 +112,9 @@ class Filter : public Http::StreamFilter, private: friend FactoryCallbacksWrapper; + void updateFilterState(Http::StreamFilterCallbacks* callback, const std::string& filter_name, + const std::string& action_name); + Event::Dispatcher& dispatcher_; // Use these to track whether we are allowed to insert a specific kind of filter. These mainly // serve to surface an easier to understand error, as attempting to insert a filter at a later diff --git a/test/extensions/filters/http/composite/filter_test.cc b/test/extensions/filters/http/composite/filter_test.cc index bbfc1407e94f..24ab95ac57d3 100644 --- a/test/extensions/filters/http/composite/filter_test.cc +++ b/test/extensions/filters/http/composite/filter_test.cc @@ -18,6 +18,8 @@ namespace HttpFilters { namespace Composite { namespace { +using Envoy::Protobuf::util::MessageDifferencer; + class FilterTest : public ::testing::Test { public: FilterTest() : filter_(stats_, decoder_callbacks_.dispatcher()) { @@ -74,8 +76,17 @@ class FilterTest : public ::testing::Test { filter_.encodeComplete(); } + void expectFilterStateInfo(std::shared_ptr filter_state) { + auto* info = filter_state->getDataMutable(MatchedActionsFilterStateKey); + EXPECT_NE(nullptr, info); + ProtobufWkt::Struct expected; + auto& fields = *expected.mutable_fields(); + fields["rootFilterName"] = ValueUtil::stringValue("actionName"); + EXPECT_TRUE(MessageDifferencer::Equals(expected, *(info->serializeAsProto()))); + } + testing::NiceMock decoder_callbacks_; - Http::MockStreamEncoderFilterCallbacks encoder_callbacks_; + testing::NiceMock encoder_callbacks_; Stats::MockCounter error_counter_; Stats::MockCounter success_counter_; FilterStats stats_{error_counter_, success_counter_}; @@ -91,19 +102,27 @@ class FilterTest : public ::testing::Test { TEST_F(FilterTest, StreamEncoderFilterDelegation) { auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(encoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(encoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamEncoderFilter(stream_filter); }; EXPECT_CALL(*stream_filter, setEncoderFilterCallbacks(_)); - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(success_counter_, inc()); filter_.onMatchCallback(action); + expectFilterStateInfo(filter_state); + doAllDecodingCallbacks(); expectDelegatedEncoding(*stream_filter); doAllEncodingCallbacks(); + EXPECT_CALL(*stream_filter, onStreamComplete()); EXPECT_CALL(*stream_filter, onDestroy()); filter_.onStreamComplete(); @@ -112,16 +131,23 @@ TEST_F(FilterTest, StreamEncoderFilterDelegation) { TEST_F(FilterTest, StreamDecoderFilterDelegation) { auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(decoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(decoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamDecoderFilter(stream_filter); }; EXPECT_CALL(*stream_filter, setDecoderFilterCallbacks(_)); - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(success_counter_, inc()); filter_.onMatchCallback(action); + expectFilterStateInfo(filter_state); + expectDelegatedDecoding(*stream_filter); doAllDecodingCallbacks(); doAllEncodingCallbacks(); @@ -133,6 +159,11 @@ TEST_F(FilterTest, StreamDecoderFilterDelegation) { TEST_F(FilterTest, StreamFilterDelegation) { auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(decoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(decoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamFilter(stream_filter); @@ -141,9 +172,11 @@ TEST_F(FilterTest, StreamFilterDelegation) { EXPECT_CALL(*stream_filter, setDecoderFilterCallbacks(_)); EXPECT_CALL(*stream_filter, setEncoderFilterCallbacks(_)); EXPECT_CALL(success_counter_, inc()); - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); filter_.onMatchCallback(action); + expectFilterStateInfo(filter_state); + expectDelegatedDecoding(*stream_filter); doAllDecodingCallbacks(); expectDelegatedEncoding(*stream_filter); @@ -155,16 +188,23 @@ TEST_F(FilterTest, StreamFilterDelegation) { // Adding multiple stream filters should cause delegation to be skipped. TEST_F(FilterTest, StreamFilterDelegationMultipleStreamFilters) { auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(decoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(decoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamFilter(stream_filter); cb.addStreamFilter(stream_filter); }; - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(error_counter_, inc()); filter_.onMatchCallback(action); + EXPECT_EQ(nullptr, filter_state->getDataMutable(MatchedActionsFilterStateKey)); + doAllDecodingCallbacks(); doAllEncodingCallbacks(); filter_.onDestroy(); @@ -173,16 +213,23 @@ TEST_F(FilterTest, StreamFilterDelegationMultipleStreamFilters) { // Adding multiple decoder filters should cause delegation to be skipped. TEST_F(FilterTest, StreamFilterDelegationMultipleStreamDecoderFilters) { auto decoder_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(decoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(decoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamDecoderFilter(decoder_filter); cb.addStreamDecoderFilter(decoder_filter); }; - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(error_counter_, inc()); filter_.onMatchCallback(action); + EXPECT_EQ(nullptr, filter_state->getDataMutable(MatchedActionsFilterStateKey)); + doAllDecodingCallbacks(); doAllEncodingCallbacks(); filter_.onDestroy(); @@ -191,16 +238,23 @@ TEST_F(FilterTest, StreamFilterDelegationMultipleStreamDecoderFilters) { // Adding multiple encoder filters should cause delegation to be skipped. TEST_F(FilterTest, StreamFilterDelegationMultipleStreamEncoderFilters) { auto encode_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(encoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(encoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamEncoderFilter(encode_filter); cb.addStreamEncoderFilter(encode_filter); }; - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(error_counter_, inc()); filter_.onMatchCallback(action); + EXPECT_EQ(nullptr, filter_state->getDataMutable(MatchedActionsFilterStateKey)); + doAllDecodingCallbacks(); doAllEncodingCallbacks(); filter_.onDestroy(); @@ -212,6 +266,11 @@ TEST_F(FilterTest, StreamFilterDelegationMultipleAccessLoggers) { auto encode_filter = std::make_shared(); auto access_log_1 = std::make_shared(); auto access_log_2 = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(encoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(encoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { cb.addStreamEncoderFilter(encode_filter); @@ -219,11 +278,13 @@ TEST_F(FilterTest, StreamFilterDelegationMultipleAccessLoggers) { cb.addAccessLogHandler(access_log_2); }; - ExecuteFilterAction action(factory_callback); + ExecuteFilterAction action(factory_callback, "actionName"); EXPECT_CALL(*encode_filter, setEncoderFilterCallbacks(_)); EXPECT_CALL(success_counter_, inc()); filter_.onMatchCallback(action); + expectFilterStateInfo(filter_state); + doAllDecodingCallbacks(); expectDelegatedEncoding(*encode_filter); doAllEncodingCallbacks(); @@ -273,6 +334,124 @@ TEST(ConfigTest, TestConfig) { EnvoyException, "Error: Only one of `dynamic_config` or `typed_config` can be set."); } +TEST_F(FilterTest, FilterStateShouldBeUpdatedWithTheMatchingActionForDynamicConfig) { + const std::string yaml_string = R"EOF( + dynamic_config: + name: actionName + config_discovery: + config_source: + resource_api_version: V3 + path_config_source: + path: "{{ test_tmpdir }}/set_response_code.yaml" + type_urls: + - type.googleapis.com/test.integration.filters.SetResponseCodeFilterConfig +)EOF"; + + testing::NiceMock server_factory_context; + testing::NiceMock factory_context; + envoy::extensions::filters::http::composite::v3::ExecuteFilterAction config; + TestUtility::loadFromYaml(yaml_string, config); + Envoy::Http::Matching::HttpFilterActionContext action_context{"test", factory_context, + server_factory_context}; + ExecuteFilterActionFactory factory; + auto action = factory.createActionFactoryCb(config, action_context, + ProtobufMessage::getStrictValidationVisitor())(); + + EXPECT_EQ("actionName", action->getTyped().actionName()); +} + +TEST_F(FilterTest, FilterStateShouldBeUpdatedWithTheMatchingActionForTypedConfig) { + const std::string yaml_string = R"EOF( + typed_config: + name: actionName + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault + abort: + http_status: 503 + percentage: + numerator: 0 + denominator: HUNDRED +)EOF"; + + testing::NiceMock server_factory_context; + testing::NiceMock factory_context; + envoy::extensions::filters::http::composite::v3::ExecuteFilterAction config; + TestUtility::loadFromYaml(yaml_string, config); + Envoy::Http::Matching::HttpFilterActionContext action_context{"test", factory_context, + server_factory_context}; + ExecuteFilterActionFactory factory; + auto action = factory.createActionFactoryCb(config, action_context, + ProtobufMessage::getStrictValidationVisitor())(); + + EXPECT_EQ("actionName", action->getTyped().actionName()); +} + +TEST_F(FilterTest, FilterStateShouldBeUpdatedWithTheMatchingAction) { + auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(encoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(encoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); + + filter_state->setData(MatchedActionsFilterStateKey, + std::make_shared("rootFilterName", "oldActionName"), + StreamInfo::FilterState::StateType::Mutable, + StreamInfo::FilterState::LifeSpan::FilterChain); + + auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { + cb.addStreamEncoderFilter(stream_filter); + }; + + EXPECT_CALL(*stream_filter, setEncoderFilterCallbacks(_)); + ExecuteFilterAction action(factory_callback, "actionName"); + EXPECT_CALL(success_counter_, inc()); + filter_.onMatchCallback(action); + + expectFilterStateInfo(filter_state); + + EXPECT_CALL(*stream_filter, onStreamComplete()); + EXPECT_CALL(*stream_filter, onDestroy()); + filter_.onStreamComplete(); + filter_.onDestroy(); +} + +TEST_F(FilterTest, MatchingActionShouldNotCollitionWithOtherRootFilter) { + auto stream_filter = std::make_shared(); + StreamInfo::FilterStateSharedPtr filter_state = + std::make_shared(StreamInfo::FilterState::LifeSpan::Connection); + ON_CALL(encoder_callbacks_, filterConfigName()).WillByDefault(testing::Return("rootFilterName")); + ON_CALL(encoder_callbacks_.stream_info_, filterState()) + .WillByDefault(testing::ReturnRef(filter_state)); + + filter_state->setData(MatchedActionsFilterStateKey, + std::make_shared("otherRootFilterName", "anyActionName"), + StreamInfo::FilterState::StateType::Mutable, + StreamInfo::FilterState::LifeSpan::FilterChain); + + auto factory_callback = [&](Http::FilterChainFactoryCallbacks& cb) { + cb.addStreamEncoderFilter(stream_filter); + }; + + EXPECT_CALL(*stream_filter, setEncoderFilterCallbacks(_)); + ExecuteFilterAction action(factory_callback, "actionName"); + EXPECT_CALL(success_counter_, inc()); + filter_.onMatchCallback(action); + + auto* info = filter_state->getDataMutable(MatchedActionsFilterStateKey); + EXPECT_NE(nullptr, info); + ProtobufWkt::Struct expected; + auto& fields = *expected.mutable_fields(); + fields["otherRootFilterName"] = ValueUtil::stringValue("anyActionName"); + fields["rootFilterName"] = ValueUtil::stringValue("actionName"); + EXPECT_TRUE(MessageDifferencer::Equals(expected, *(info->serializeAsProto()))); + + EXPECT_CALL(*stream_filter, onStreamComplete()); + EXPECT_CALL(*stream_filter, onDestroy()); + filter_.onStreamComplete(); + filter_.onDestroy(); +} + } // namespace } // namespace Composite } // namespace HttpFilters From 144bda79e16076bd85045304a31bfa28a75442de Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 4 Jan 2024 15:59:32 +0000 Subject: [PATCH 121/126] Revert "Resolver: switching to statusor (#31312)" (#31647) This reverts commit 7a1a883aed9dce124f449a82331228c055812356. Signed-off-by: Ryan Northey --- envoy/network/resolver.h | 4 +-- .../common/listener_manager/listener_impl.cc | 12 ++----- .../listener_manager/listener_manager_impl.cc | 4 +-- source/common/network/resolver_impl.cc | 15 ++++---- source/common/network/resolver_impl.h | 8 ++--- .../upstream/health_discovery_service.cc | 18 ++++------ source/common/upstream/upstream_impl.cc | 30 +++++----------- .../network/dns_resolver/cares/dns_impl.cc | 4 +-- .../stat_sinks/dog_statsd/config.cc | 5 ++- .../stat_sinks/graphite_statsd/config.cc | 5 ++- source/extensions/stat_sinks/statsd/config.cc | 5 ++- source/server/api_listener_impl.cc | 20 +++-------- source/server/api_listener_impl.h | 13 +++---- source/server/configuration_impl.cc | 4 +-- test/common/network/resolver_impl_test.cc | 34 +++++++++---------- test/fuzz/utility.h | 3 +- test/mocks/network/mocks.h | 2 +- test/server/api_listener_test.cc | 26 +++++++------- tools/code_format/config.yaml | 1 + 19 files changed, 81 insertions(+), 132 deletions(-) diff --git a/envoy/network/resolver.h b/envoy/network/resolver.h index 64e66bff32f8..dcdcfe8a8c92 100644 --- a/envoy/network/resolver.h +++ b/envoy/network/resolver.h @@ -24,9 +24,9 @@ class Resolver : public Config::UntypedFactory { /** * Resolve a custom address string and port to an Address::Instance. * @param socket_address supplies the socket address to resolve. - * @return InstanceConstSharedPtr appropriate Address::Instance or an error status. + * @return InstanceConstSharedPtr appropriate Address::Instance. */ - virtual absl::StatusOr + virtual InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) PURE; std::string category() const override { return "envoy.resolvers"; } diff --git a/source/common/listener_manager/listener_impl.cc b/source/common/listener_manager/listener_impl.cc index 1c4034620a3f..984ebca0a7b9 100644 --- a/source/common/listener_manager/listener_impl.cc +++ b/source/common/listener_manager/listener_impl.cc @@ -223,9 +223,7 @@ std::string listenerStatsScope(const envoy::config::listener::v3::Listener& conf if (config.has_internal_listener()) { return absl::StrCat("envoy_internal_", config.name()); } - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - return address_or_error.value()->asString(); + return Network::Address::resolveProtoAddress(config.address())->asString(); } } // namespace @@ -310,9 +308,7 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, } else { // All the addresses should be same socket type, so get the first address's socket type is // enough. - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - auto address = std::move(address_or_error.value()); + auto address = Network::Address::resolveProtoAddress(config.address()); checkIpv4CompatAddress(address, config.address()); addresses_.emplace_back(address); address_opts_list.emplace_back(std::ref(config.socket_options())); @@ -325,10 +321,8 @@ ListenerImpl::ListenerImpl(const envoy::config::listener::v3::Listener& config, "support same socket type for all the addresses.", name_)); } - auto addresses_or_error = + auto additional_address = Network::Address::resolveProtoAddress(config.additional_addresses(i).address()); - THROW_IF_STATUS_NOT_OK(addresses_or_error, throw); - auto additional_address = std::move(addresses_or_error.value()); checkIpv4CompatAddress(address, config.additional_addresses(i).address()); addresses_.emplace_back(additional_address); if (config.additional_addresses(i).has_socket_options()) { diff --git a/source/common/listener_manager/listener_manager_impl.cc b/source/common/listener_manager/listener_manager_impl.cc index 853087d0b1bf..3982b72eed00 100644 --- a/source/common/listener_manager/listener_manager_impl.cc +++ b/source/common/listener_manager/listener_manager_impl.cc @@ -468,9 +468,7 @@ ListenerManagerImpl::addOrUpdateListener(const envoy::config::listener::v3::List name)); } if (!api_listener_ && !added_via_api) { - auto listener_or_error = HttpApiListener::create(config, server_, config.name()); - THROW_IF_STATUS_NOT_OK(listener_or_error, throw); - api_listener_ = std::move(listener_or_error.value()); + api_listener_ = std::make_unique(config, server_, config.name()); return true; } else { ENVOY_LOG(warn, "listener {} can not be added because currently only one ApiListener is " diff --git a/source/common/network/resolver_impl.cc b/source/common/network/resolver_impl.cc index 63119deff8ae..bd51bcfd2272 100644 --- a/source/common/network/resolver_impl.cc +++ b/source/common/network/resolver_impl.cc @@ -20,7 +20,7 @@ namespace Address { class IpResolver : public Resolver { public: - absl::StatusOr + InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { switch (socket_address.port_specifier_case()) { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kPortValue: @@ -31,8 +31,8 @@ class IpResolver : public Resolver { case envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort: break; } - return absl::InvalidArgumentError(fmt::format("IP resolver can't handle port specifier type {}", - socket_address.port_specifier_case())); + throwEnvoyExceptionOrPanic(fmt::format("IP resolver can't handle port specifier type {}", + socket_address.port_specifier_case())); } std::string name() const override { return Config::AddressResolverNames::get().IP; } @@ -43,8 +43,7 @@ class IpResolver : public Resolver { */ REGISTER_FACTORY(IpResolver, Resolver); -absl::StatusOr -resolveProtoAddress(const envoy::config::core::v3::Address& address) { +InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Address& address) { switch (address.address_case()) { case envoy::config::core::v3::Address::AddressCase::ADDRESS_NOT_SET: throwEnvoyExceptionOrPanic("Address must be set: " + address.DebugString()); @@ -67,7 +66,7 @@ resolveProtoAddress(const envoy::config::core::v3::Address& address) { throwEnvoyExceptionOrPanic("Failed to resolve address:" + address.DebugString()); } -absl::StatusOr +InstanceConstSharedPtr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_address) { Resolver* resolver = nullptr; const std::string& resolver_name = socket_address.resolver_name(); @@ -80,9 +79,7 @@ resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& socket_a if (resolver == nullptr) { throwEnvoyExceptionOrPanic(fmt::format("Unknown address resolver: {}", resolver_name)); } - auto instance_or_error = resolver->resolve(socket_address); - THROW_IF_STATUS_NOT_OK(instance_or_error, throw); - return std::move(instance_or_error.value()); + return resolver->resolve(socket_address); } } // namespace Address diff --git a/source/common/network/resolver_impl.h b/source/common/network/resolver_impl.h index f36c0f03b203..fb26085eb00d 100644 --- a/source/common/network/resolver_impl.h +++ b/source/common/network/resolver_impl.h @@ -14,17 +14,17 @@ namespace Address { /** * Create an Instance from a envoy::config::core::v3::Address. * @param address supplies the address proto to resolve. - * @return pointer to the Instance or an error status + * @return pointer to the Instance. */ -absl::StatusOr +Address::InstanceConstSharedPtr resolveProtoAddress(const envoy::config::core::v3::Address& address); /** * Create an Instance from a envoy::config::core::v3::SocketAddress. * @param address supplies the socket address proto to resolve. - * @return pointer to the Instance or an error status. + * @return pointer to the Instance. */ -absl::StatusOr +Address::InstanceConstSharedPtr resolveProtoSocketAddress(const envoy::config::core::v3::SocketAddress& address); DECLARE_FACTORY(IpResolver); diff --git a/source/common/upstream/health_discovery_service.cc b/source/common/upstream/health_discovery_service.cc index 4db99e3361d0..b1c659a5529f 100644 --- a/source/common/upstream/health_discovery_service.cc +++ b/source/common/upstream/health_discovery_service.cc @@ -371,11 +371,10 @@ HdsCluster::HdsCluster(Server::Configuration::ServerFactoryContext& server_conte for (const auto& host : locality_endpoints.lb_endpoints()) { const LocalityEndpointTuple endpoint_key = {locality_endpoints.locality(), host}; // Initialize an endpoint host object. - auto address_or_error = Network::Address::resolveProtoAddress(host.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); HostSharedPtr endpoint = std::make_shared( - info_, "", std::move(address_or_error.value()), nullptr, 1, locality_endpoints.locality(), - host.endpoint().health_check_config(), 0, envoy::config::core::v3::UNKNOWN, time_source_); + info_, "", Network::Address::resolveProtoAddress(host.endpoint().address()), nullptr, 1, + locality_endpoints.locality(), host.endpoint().health_check_config(), 0, + envoy::config::core::v3::UNKNOWN, time_source_); // Add this host/endpoint pointer to our flat list of endpoints for health checking. hosts_->push_back(endpoint); // Add this host/endpoint pointer to our structured list by locality so results can be @@ -484,13 +483,10 @@ void HdsCluster::updateHosts( host = host_pair->second; } else { // We do not have this endpoint saved, so create a new one. - auto address_or_error = - Network::Address::resolveProtoAddress(endpoint.endpoint().address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - host = std::make_shared(info_, "", std::move(address_or_error.value()), nullptr, - 1, endpoints.locality(), - endpoint.endpoint().health_check_config(), 0, - envoy::config::core::v3::UNKNOWN, time_source_); + host = std::make_shared( + info_, "", Network::Address::resolveProtoAddress(endpoint.endpoint().address()), + nullptr, 1, endpoints.locality(), endpoint.endpoint().health_check_config(), 0, + envoy::config::core::v3::UNKNOWN, time_source_); // Set the initial health status as in HdsCluster::initialize. host->healthFlagSet(Host::HealthFlag::FAILED_ACTIVE_HC); diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index 5c781c9bd70a..aa4e8fc849f9 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -227,14 +227,10 @@ parseBindConfig(::Envoy::OptRef bind_ std::vector<::Envoy::Upstream::UpstreamLocalAddress> upstream_local_addresses; if (bind_config.has_value()) { UpstreamLocalAddress upstream_local_address; - upstream_local_address.address_ = nullptr; - if (bind_config->has_source_address()) { - - auto address_or_error = - ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - upstream_local_address.address_ = address_or_error.value(); - } + upstream_local_address.address_ = + bind_config->has_source_address() + ? ::Envoy::Network::Address::resolveProtoSocketAddress(bind_config->source_address()) + : nullptr; upstream_local_address.socket_options_ = std::make_shared(); ::Envoy::Network::Socket::appendOptions(upstream_local_address.socket_options_, @@ -246,10 +242,8 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& extra_source_address : bind_config->extra_source_addresses()) { UpstreamLocalAddress extra_upstream_local_address; - auto address_or_error = + extra_upstream_local_address.address_ = ::Envoy::Network::Address::resolveProtoSocketAddress(extra_source_address.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - extra_upstream_local_address.address_ = address_or_error.value(); extra_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); @@ -270,10 +264,8 @@ parseBindConfig(::Envoy::OptRef bind_ for (const auto& additional_source_address : bind_config->additional_source_addresses()) { UpstreamLocalAddress additional_upstream_local_address; - auto address_or_error = + additional_upstream_local_address.address_ = ::Envoy::Network::Address::resolveProtoSocketAddress(additional_source_address); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - additional_upstream_local_address.address_ = address_or_error.value(); additional_upstream_local_address.socket_options_ = std::make_shared<::Envoy::Network::ConnectionSocket::Options>(); ::Envoy::Network::Socket::appendOptions(additional_upstream_local_address.socket_options_, @@ -1749,11 +1741,7 @@ void ClusterImplBase::reloadHealthyHostsHelper(const HostSharedPtr&) { const Network::Address::InstanceConstSharedPtr ClusterImplBase::resolveProtoAddress(const envoy::config::core::v3::Address& address) { - TRY_ASSERT_MAIN_THREAD { - auto address_or_error = Network::Address::resolveProtoAddress(address); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - return address_or_error.value(); - } + TRY_ASSERT_MAIN_THREAD { return Network::Address::resolveProtoAddress(address); } END_TRY CATCH(EnvoyException & e, { if (info_->type() == envoy::config::cluster::v3::Cluster::STATIC || @@ -2421,9 +2409,7 @@ Network::Address::InstanceConstSharedPtr resolveHealthCheckAddress( Network::Address::InstanceConstSharedPtr health_check_address; const auto& port_value = health_check_config.port_value(); if (health_check_config.has_address()) { - auto address_or_error = Network::Address::resolveProtoAddress(health_check_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - auto address = address_or_error.value(); + auto address = Network::Address::resolveProtoAddress(health_check_config.address()); health_check_address = port_value == 0 ? address : Network::Utility::getAddressWithPort(*address, port_value); } else { diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc index 64848d6a4331..f1fec3b6bcc8 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.cc +++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc @@ -555,9 +555,7 @@ class CaresDnsResolverFactory : public DnsResolverFactory, const auto& resolver_addrs = cares.resolvers(); resolvers.reserve(resolver_addrs.size()); for (const auto& resolver_addr : resolver_addrs) { - auto address_or_error = Network::Address::resolveProtoAddress(resolver_addr); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - resolvers.push_back(std::move(address_or_error.value())); + resolvers.push_back(Network::Address::resolveProtoAddress(resolver_addr)); } } return std::make_shared(cares, dispatcher, resolvers, diff --git a/source/extensions/stat_sinks/dog_statsd/config.cc b/source/extensions/stat_sinks/dog_statsd/config.cc index 78c39f20d914..f3204bb322cb 100644 --- a/source/extensions/stat_sinks/dog_statsd/config.cc +++ b/source/extensions/stat_sinks/dog_statsd/config.cc @@ -22,9 +22,8 @@ DogStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, const auto& sink_config = MessageUtil::downcastAndValidate( config, server.messageValidationContext().staticValidationVisitor()); - auto address_or_error = Network::Address::resolveProtoAddress(sink_config.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(sink_config.address()); ENVOY_LOG(debug, "dog_statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (sink_config.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/graphite_statsd/config.cc b/source/extensions/stat_sinks/graphite_statsd/config.cc index 93322442900d..7320993e035e 100644 --- a/source/extensions/stat_sinks/graphite_statsd/config.cc +++ b/source/extensions/stat_sinks/graphite_statsd/config.cc @@ -25,9 +25,8 @@ GraphiteStatsdSinkFactory::createStatsSink(const Protobuf::Message& config, switch (statsd_sink.statsd_specifier_case()) { case envoy::extensions::stat_sinks::graphite_statsd::v3::GraphiteStatsdSink::StatsdSpecifierCase:: kAddress: { - auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(statsd_sink.address()); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); absl::optional max_bytes; if (statsd_sink.has_max_bytes_per_datagram()) { diff --git a/source/extensions/stat_sinks/statsd/config.cc b/source/extensions/stat_sinks/statsd/config.cc index ae76707892a0..84670fa1308b 100644 --- a/source/extensions/stat_sinks/statsd/config.cc +++ b/source/extensions/stat_sinks/statsd/config.cc @@ -23,9 +23,8 @@ StatsdSinkFactory::createStatsSink(const Protobuf::Message& config, config, server.messageValidationContext().staticValidationVisitor()); switch (statsd_sink.statsd_specifier_case()) { case envoy::config::metrics::v3::StatsdSink::StatsdSpecifierCase::kAddress: { - auto address_or_error = Network::Address::resolveProtoAddress(statsd_sink.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - Network::Address::InstanceConstSharedPtr address = address_or_error.value(); + Network::Address::InstanceConstSharedPtr address = + Network::Address::resolveProtoAddress(statsd_sink.address()); ENVOY_LOG(debug, "statsd UDP ip address: {}", address->asString()); return std::make_unique(server.threadLocal(), std::move(address), false, statsd_sink.prefix()); diff --git a/source/server/api_listener_impl.cc b/source/server/api_listener_impl.cc index a9dfa065d89c..d947a0549c7a 100644 --- a/source/server/api_listener_impl.cc +++ b/source/server/api_listener_impl.cc @@ -13,10 +13,10 @@ namespace Envoy { namespace Server { -ApiListenerImplBase::ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, +ApiListenerImplBase::ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : config_(config), name_(name), address_(std::move(address)), + : config_(config), name_(name), + address_(Network::Address::resolveProtoAddress(config.address())), factory_context_(server, *this, server.stats().createScope(""), server.stats().createScope(fmt::format("listener.api.{}.", name_)), std::make_shared(config)) {} @@ -41,19 +41,9 @@ HttpApiListener::ApiListenerWrapper::newStreamHandle(Http::ResponseEncoder& resp return http_connection_manager_->newStreamHandle(response_encoder, is_internally_created); } -absl::StatusOr> -HttpApiListener::create(const envoy::config::listener::v3::Listener& config, - Server::Instance& server, const std::string& name) { - auto address_or_error = Network::Address::resolveProtoAddress(config.address()); - RETURN_IF_STATUS_NOT_OK(address_or_error); - return std::unique_ptr( - new HttpApiListener(std::move(address_or_error.value()), config, server, name)); -} - -HttpApiListener::HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, +HttpApiListener::HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name) - : ApiListenerImplBase(std::move(address), config, server, name) { + : ApiListenerImplBase(config, server, name) { if (config.api_listener().api_listener().type_url() == absl::StrCat( "type.googleapis.com/", diff --git a/source/server/api_listener_impl.h b/source/server/api_listener_impl.h index 5ac8a3b7c07b..ccf1b2cbdcd3 100644 --- a/source/server/api_listener_impl.h +++ b/source/server/api_listener_impl.h @@ -49,8 +49,7 @@ class ApiListenerImplBase : public ApiListener, } protected: - ApiListenerImplBase(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, Server::Instance& server, + ApiListenerImplBase(const envoy::config::listener::v3::Listener& config, Server::Instance& server, const std::string& name); // Synthetic class that acts as a stub Network::ReadFilterCallbacks. @@ -222,18 +221,14 @@ class HttpApiListener : public ApiListenerImplBase { Http::ApiListenerPtr http_connection_manager_; }; + HttpApiListener(const envoy::config::listener::v3::Listener& config, Server::Instance& server, + const std::string& name); + // ApiListener ApiListener::Type type() const override { return ApiListener::Type::HttpApiListener; } Http::ApiListenerPtr createHttpApiListener(Event::Dispatcher& dispatcher) override; - static absl::StatusOr> - create(const envoy::config::listener::v3::Listener& config, Server::Instance& server, - const std::string& name); private: - HttpApiListener(Network::Address::InstanceConstSharedPtr&& address, - const envoy::config::listener::v3::Listener& config, Server::Instance& server, - const std::string& name); - // Need to store the factory due to the shared_ptrs that need to be kept alive: date provider, // route config manager, scoped route config manager. std::function diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 6129c6182131..80818215be7b 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -231,9 +231,7 @@ InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstra admin_.profile_path_ = admin.profile_path().empty() ? "/var/log/envoy/envoy.prof" : admin.profile_path(); if (admin.has_address()) { - auto address_or_error = Network::Address::resolveProtoAddress(admin.address()); - THROW_IF_STATUS_NOT_OK(address_or_error, throw); - admin_.address_ = std::move(address_or_error.value()); + admin_.address_ = Network::Address::resolveProtoAddress(admin.address()); } admin_.socket_options_ = std::make_shared>(); if (!admin.socket_options().empty()) { diff --git a/test/common/network/resolver_impl_test.cc b/test/common/network/resolver_impl_test.cc index 3574414e6298..22e752bd28ae 100644 --- a/test/common/network/resolver_impl_test.cc +++ b/test/common/network/resolver_impl_test.cc @@ -32,7 +32,7 @@ TEST_F(IpResolverTest, Basic) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_port_value(443); - auto address = resolver_->resolve(socket_address).value(); + auto address = resolver_->resolve(socket_address); EXPECT_EQ(address->ip()->addressAsString(), "1.2.3.4"); EXPECT_EQ(address->ip()->port(), 443); } @@ -41,25 +41,26 @@ TEST_F(IpResolverTest, DisallowsNamedPort) { envoy::config::core::v3::SocketAddress socket_address; socket_address.set_address("1.2.3.4"); socket_address.set_named_port("http"); - EXPECT_EQ(resolver_->resolve(socket_address).status().message(), - fmt::format("IP resolver can't handle port specifier type {}", - envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); + EXPECT_THROW_WITH_MESSAGE( + resolver_->resolve(socket_address), EnvoyException, + fmt::format("IP resolver can't handle port specifier type {}", + envoy::config::core::v3::SocketAddress::PortSpecifierCase::kNamedPort)); } TEST(ResolverTest, FromProtoAddress) { envoy::config::core::v3::Address ipv4_address; ipv4_address.mutable_socket_address()->set_address("1.2.3.4"); ipv4_address.mutable_socket_address()->set_port_value(5); - EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address).value()->asString()); + EXPECT_EQ("1.2.3.4:5", resolveProtoAddress(ipv4_address)->asString()); envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address).value()->asString()); + EXPECT_EQ("[1::1]:2", resolveProtoAddress(ipv6_address)->asString()); envoy::config::core::v3::Address pipe_address; pipe_address.mutable_pipe()->set_path("/foo/bar"); - EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address).value()->asString()); + EXPECT_EQ("/foo/bar", resolveProtoAddress(pipe_address)->asString()); } TEST(ResolverTest, InternalListenerNameFromProtoAddress) { @@ -67,14 +68,14 @@ TEST(ResolverTest, InternalListenerNameFromProtoAddress) { internal_listener_address.mutable_envoy_internal_address()->set_server_listener_name( "internal_listener_foo"); EXPECT_EQ("envoy://internal_listener_foo/", - resolveProtoAddress(internal_listener_address).value()->asString()); + resolveProtoAddress(internal_listener_address)->asString()); } TEST(ResolverTest, UninitializedInternalAddressFromProtoAddress) { envoy::config::core::v3::Address internal_address; internal_address.mutable_envoy_internal_address(); EXPECT_THROW_WITH_MESSAGE( - resolveProtoAddress(internal_address).IgnoreError(), EnvoyException, + resolveProtoAddress(internal_address), EnvoyException, fmt::format("Failed to resolve address:{}", internal_address.DebugString())); } @@ -84,7 +85,7 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { envoy::config::core::v3::Address ipv6_address; ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); - auto resolved_addr = resolveProtoAddress(ipv6_address).value(); + auto resolved_addr = resolveProtoAddress(ipv6_address); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } { @@ -92,14 +93,14 @@ TEST(ResolverTest, FromProtoAddressV4Compat) { ipv6_address.mutable_socket_address()->set_address("1::1"); ipv6_address.mutable_socket_address()->set_port_value(2); ipv6_address.mutable_socket_address()->set_ipv4_compat(true); - auto resolved_addr = resolveProtoAddress(ipv6_address).value(); + auto resolved_addr = resolveProtoAddress(ipv6_address); EXPECT_EQ("[1::1]:2", resolved_addr->asString()); } } class TestResolver : public Resolver { public: - absl::StatusOr + InstanceConstSharedPtr resolve(const envoy::config::core::v3::SocketAddress& socket_address) override { const std::string& logical = socket_address.address(); const std::string physical = getPhysicalName(logical); @@ -153,7 +154,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address).value(); + auto instance = resolveProtoAddress(address); EXPECT_EQ("1.2.3.4:5", instance->asString()); EXPECT_EQ("foo:5", instance->logicalName()); } @@ -163,7 +164,7 @@ TEST(ResolverTest, NonStandardResolver) { socket->set_address("bar"); socket->set_named_port("http"); socket->set_resolver_name("envoy.test.resolver"); - auto instance = resolveProtoAddress(address).value(); + auto instance = resolveProtoAddress(address); EXPECT_EQ("4.3.2.1:http", instance->asString()); EXPECT_EQ("bar:http", instance->logicalName()); } @@ -171,8 +172,7 @@ TEST(ResolverTest, NonStandardResolver) { TEST(ResolverTest, UninitializedAddress) { envoy::config::core::v3::Address address; - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, - "Address must be set: "); + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, "Address must be set: "); } TEST(ResolverTest, NoSuchResolver) { @@ -181,7 +181,7 @@ TEST(ResolverTest, NoSuchResolver) { socket->set_address("foo"); socket->set_port_value(5); socket->set_resolver_name("envoy.test.resolver"); - EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address).IgnoreError(), EnvoyException, + EXPECT_THROW_WITH_MESSAGE(resolveProtoAddress(address), EnvoyException, "Unknown address resolver: envoy.test.resolver"); } diff --git a/test/fuzz/utility.h b/test/fuzz/utility.h index 681674debc4e..7ecd69d0942d 100644 --- a/test/fuzz/utility.h +++ b/test/fuzz/utility.h @@ -170,7 +170,7 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn replaceInvalidHostCharacters( stream_info.address().envoy_internal_address().server_listener_name())); } else { - address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()).value(); + address = Envoy::Network::Address::resolveProtoAddress(stream_info.address()); } } else { address = Network::Utility::resolveUrl("tcp://10.0.0.1:443"); @@ -178,7 +178,6 @@ inline std::unique_ptr fromStreamInfo(const test::fuzz::StreamIn auto upstream_local_address = stream_info.has_upstream_local_address() ? Envoy::Network::Address::resolveProtoAddress(stream_info.upstream_local_address()) - .value() : Network::Utility::resolveUrl("tcp://10.0.0.1:10000"); test_stream_info->upstreamInfo()->setUpstreamLocalAddress(upstream_local_address); test_stream_info->downstream_connection_info_provider_ = diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 09417750b16b..283bb4377df7 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -88,7 +88,7 @@ class MockAddressResolver : public Address::Resolver { MockAddressResolver(); ~MockAddressResolver() override; - MOCK_METHOD(absl::StatusOr, resolve, + MOCK_METHOD(Address::InstanceConstSharedPtr, resolve, (const envoy::config::core::v3::SocketAddress&)); MOCK_METHOD(std::string, name, (), (const)); }; diff --git a/test/server/api_listener_test.cc b/test/server/api_listener_test.cc index 9d70fbd6e4e3..7183f80b8651 100644 --- a/test/server/api_listener_test.cc +++ b/test/server/api_listener_test.cc @@ -53,11 +53,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, MobileApiListener) { @@ -88,11 +88,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - ASSERT_NE(http_api_listener->createHttpApiListener(server_.dispatcher()), nullptr); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + ASSERT_NE(http_api_listener.createHttpApiListener(server_.dispatcher()), nullptr); } TEST_F(ApiListenerTest, HttpApiListenerThrowsWithBadConfig) { @@ -125,7 +125,7 @@ name: test_api_listener ->set_path("eds path"); expected_any_proto.PackFrom(expected_cluster_proto); EXPECT_THROW_WITH_MESSAGE( - HttpApiListener::create(config, server_, config.name()).IgnoreError(), EnvoyException, + HttpApiListener(config, server_, config.name()), EnvoyException, fmt::format("Unable to unpack as " "envoy.extensions.filters.network.http_connection_manager.v3." "HttpConnectionManager: {}", @@ -159,11 +159,11 @@ name: test_api_listener const envoy::config::listener::v3::Listener config = parseListenerFromV3Yaml(yaml); server_.server_factory_context_->cluster_manager_.initializeClusters( {"dynamic_forward_proxy_cluster"}, {}); - auto http_api_listener = HttpApiListener::create(config, server_, config.name()).value(); + auto http_api_listener = HttpApiListener(config, server_, config.name()); - ASSERT_EQ("test_api_listener", http_api_listener->name()); - ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener->type()); - auto api_listener = http_api_listener->createHttpApiListener(server_.dispatcher()); + ASSERT_EQ("test_api_listener", http_api_listener.name()); + ASSERT_EQ(ApiListener::Type::HttpApiListener, http_api_listener.type()); + auto api_listener = http_api_listener.createHttpApiListener(server_.dispatcher()); ASSERT_NE(api_listener, nullptr); Network::MockConnectionCallbacks network_connection_callbacks; diff --git a/tools/code_format/config.yaml b/tools/code_format/config.yaml index 1e1b071c2d19..c7e1dc6bd7c9 100644 --- a/tools/code_format/config.yaml +++ b/tools/code_format/config.yaml @@ -109,6 +109,7 @@ paths: - source/common/network/address_impl.cc - source/common/network/utility.cc - source/common/network/dns_resolver/dns_factory_util.cc + - source/common/network/resolver_impl.cc - source/common/network/socket_impl.cc - source/common/ssl/tls_certificate_config_impl.cc - source/common/formatter/http_specific_formatter.cc From c5aa29a2ac0fecf2610d05aad7c6feff261d0a93 Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 4 Jan 2024 16:15:33 +0000 Subject: [PATCH 122/126] deps: Bump python base tools (#31637) Signed-off-by: Ryan Northey --- tools/base/requirements.in | 2 +- tools/base/requirements.txt | 832 +++++++++++++++++------------------- 2 files changed, 404 insertions(+), 430 deletions(-) diff --git a/tools/base/requirements.in b/tools/base/requirements.in index 3adb4648a427..21a171d96306 100644 --- a/tools/base/requirements.in +++ b/tools/base/requirements.in @@ -37,7 +37,7 @@ pyreadline pyyaml setuptools slack_sdk -sphinx>=7 +sphinx>=7,<7.2 sphinxcontrib.googleanalytics thrift verboselogs diff --git a/tools/base/requirements.txt b/tools/base/requirements.txt index 9ec13dc5e4a6..a8da0cbfdff7 100644 --- a/tools/base/requirements.txt +++ b/tools/base/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# bazel run //tools/base:requirements.update +# pip-compile --allow-unsafe --generate-hashes requirements.in # abstracts==0.0.12 \ --hash=sha256:acc01ff56c8a05fb88150dff62e295f9071fc33388c42f1dfc2787a8d1c755ff @@ -206,31 +206,31 @@ alabaster==0.7.13 \ --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 # via sphinx -argcomplete==3.1.2 \ - --hash=sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b \ - --hash=sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99 +argcomplete==3.2.1 \ + --hash=sha256:30891d87f3c1abe091f2142613c9d33cac84a5e15404489f033b20399b691fec \ + --hash=sha256:437f67fb9b058da5a090df505ef9be0297c4883993f3f56cb186ff087778cfb4 # via gsutil -attrs==23.1.0 \ - --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ - --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 +attrs==23.2.0 \ + --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \ + --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1 # via # aiohttp # service-identity -babel==2.13.0 \ - --hash=sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210 \ - --hash=sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec +babel==2.14.0 \ + --hash=sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363 \ + --hash=sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287 # via sphinx boto==2.49.0 \ --hash=sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8 \ --hash=sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a # via gcs-oauth2-boto-plugin -cachetools==5.3.1 \ - --hash=sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590 \ - --hash=sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b +cachetools==5.3.2 \ + --hash=sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2 \ + --hash=sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1 # via google-auth -certifi==2023.7.22 \ - --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ - --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 +certifi==2023.11.17 \ + --hash=sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1 \ + --hash=sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474 # via # aioquic # requests @@ -291,97 +291,97 @@ cffi==1.16.0 \ # -r requirements.in # cryptography # pynacl -charset-normalizer==3.3.0 \ - --hash=sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843 \ - --hash=sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786 \ - --hash=sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e \ - --hash=sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8 \ - --hash=sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4 \ - --hash=sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa \ - --hash=sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d \ - --hash=sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82 \ - --hash=sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7 \ - --hash=sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895 \ - --hash=sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d \ - --hash=sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a \ - --hash=sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382 \ - --hash=sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678 \ - --hash=sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b \ - --hash=sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e \ - --hash=sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741 \ - --hash=sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4 \ - --hash=sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596 \ - --hash=sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9 \ - --hash=sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69 \ - --hash=sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c \ - --hash=sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77 \ - --hash=sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13 \ - --hash=sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459 \ - --hash=sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e \ - --hash=sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7 \ - --hash=sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908 \ - --hash=sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a \ - --hash=sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f \ - --hash=sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8 \ - --hash=sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482 \ - --hash=sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d \ - --hash=sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d \ - --hash=sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545 \ - --hash=sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34 \ - --hash=sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86 \ - --hash=sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6 \ - --hash=sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe \ - --hash=sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e \ - --hash=sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc \ - --hash=sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7 \ - --hash=sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd \ - --hash=sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c \ - --hash=sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557 \ - --hash=sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a \ - --hash=sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89 \ - --hash=sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078 \ - --hash=sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e \ - --hash=sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4 \ - --hash=sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403 \ - --hash=sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0 \ - --hash=sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89 \ - --hash=sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115 \ - --hash=sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9 \ - --hash=sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05 \ - --hash=sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a \ - --hash=sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec \ - --hash=sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56 \ - --hash=sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38 \ - --hash=sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479 \ - --hash=sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c \ - --hash=sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e \ - --hash=sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd \ - --hash=sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186 \ - --hash=sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455 \ - --hash=sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c \ - --hash=sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65 \ - --hash=sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78 \ - --hash=sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287 \ - --hash=sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df \ - --hash=sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43 \ - --hash=sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1 \ - --hash=sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7 \ - --hash=sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989 \ - --hash=sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a \ - --hash=sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63 \ - --hash=sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884 \ - --hash=sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649 \ - --hash=sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810 \ - --hash=sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828 \ - --hash=sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4 \ - --hash=sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2 \ - --hash=sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd \ - --hash=sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5 \ - --hash=sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe \ - --hash=sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293 \ - --hash=sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e \ - --hash=sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e \ - --hash=sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8 +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 # via requests clang-format==14.0.6 \ --hash=sha256:13f2d6d4a2af004a783c65f0921afa8f0384bffcdaf500b6c2cb542edeb0b4a5 \ @@ -583,68 +583,84 @@ frozendict==2.4.0 \ # -r requirements.in # aio-run-runner # envoy-base-utils -frozenlist==1.4.0 \ - --hash=sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6 \ - --hash=sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01 \ - --hash=sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251 \ - --hash=sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9 \ - --hash=sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b \ - --hash=sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87 \ - --hash=sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf \ - --hash=sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f \ - --hash=sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0 \ - --hash=sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2 \ - --hash=sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b \ - --hash=sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc \ - --hash=sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c \ - --hash=sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467 \ - --hash=sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9 \ - --hash=sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1 \ - --hash=sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a \ - --hash=sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79 \ - --hash=sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167 \ - --hash=sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300 \ - --hash=sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf \ - --hash=sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea \ - --hash=sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2 \ - --hash=sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab \ - --hash=sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3 \ - --hash=sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb \ - --hash=sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087 \ - --hash=sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc \ - --hash=sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8 \ - --hash=sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62 \ - --hash=sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f \ - --hash=sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326 \ - --hash=sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c \ - --hash=sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431 \ - --hash=sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963 \ - --hash=sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7 \ - --hash=sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef \ - --hash=sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3 \ - --hash=sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956 \ - --hash=sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781 \ - --hash=sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472 \ - --hash=sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc \ - --hash=sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839 \ - --hash=sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672 \ - --hash=sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3 \ - --hash=sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503 \ - --hash=sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d \ - --hash=sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8 \ - --hash=sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b \ - --hash=sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc \ - --hash=sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f \ - --hash=sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559 \ - --hash=sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b \ - --hash=sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95 \ - --hash=sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb \ - --hash=sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963 \ - --hash=sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919 \ - --hash=sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f \ - --hash=sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3 \ - --hash=sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1 \ - --hash=sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e +frozenlist==1.4.1 \ + --hash=sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7 \ + --hash=sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98 \ + --hash=sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad \ + --hash=sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5 \ + --hash=sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae \ + --hash=sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e \ + --hash=sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a \ + --hash=sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701 \ + --hash=sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d \ + --hash=sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6 \ + --hash=sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6 \ + --hash=sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106 \ + --hash=sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75 \ + --hash=sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868 \ + --hash=sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a \ + --hash=sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0 \ + --hash=sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1 \ + --hash=sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826 \ + --hash=sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec \ + --hash=sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6 \ + --hash=sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950 \ + --hash=sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19 \ + --hash=sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0 \ + --hash=sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8 \ + --hash=sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a \ + --hash=sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09 \ + --hash=sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86 \ + --hash=sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c \ + --hash=sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5 \ + --hash=sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b \ + --hash=sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b \ + --hash=sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d \ + --hash=sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0 \ + --hash=sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea \ + --hash=sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776 \ + --hash=sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a \ + --hash=sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897 \ + --hash=sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7 \ + --hash=sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09 \ + --hash=sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9 \ + --hash=sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe \ + --hash=sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd \ + --hash=sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742 \ + --hash=sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09 \ + --hash=sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0 \ + --hash=sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932 \ + --hash=sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1 \ + --hash=sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a \ + --hash=sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49 \ + --hash=sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d \ + --hash=sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7 \ + --hash=sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480 \ + --hash=sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89 \ + --hash=sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e \ + --hash=sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b \ + --hash=sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82 \ + --hash=sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb \ + --hash=sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068 \ + --hash=sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8 \ + --hash=sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b \ + --hash=sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb \ + --hash=sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2 \ + --hash=sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11 \ + --hash=sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b \ + --hash=sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc \ + --hash=sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0 \ + --hash=sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497 \ + --hash=sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17 \ + --hash=sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0 \ + --hash=sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2 \ + --hash=sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439 \ + --hash=sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5 \ + --hash=sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac \ + --hash=sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825 \ + --hash=sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887 \ + --hash=sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced \ + --hash=sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74 # via # aiohttp # aiosignal @@ -660,9 +676,9 @@ gidgethub==5.3.0 \ # envoy-distribution-release # envoy-github-abstract # envoy-github-release -gitdb==4.0.10 \ - --hash=sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a \ - --hash=sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7 +gitdb==4.0.11 \ + --hash=sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4 \ + --hash=sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b # via gitpython gitpython==3.1.40 \ --hash=sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4 \ @@ -672,12 +688,10 @@ google-apitools==0.5.32 \ --hash=sha256:b78f74116558e0476e19501b5b4b2ac7c93261a69c5449c861ea95cbc853c688 \ --hash=sha256:c3763e52289f61e21c41d5531e20fbda9cc8484a088b8686fd460770db8bad13 # via gsutil -google-auth[aiohttp]==2.23.3 \ - --hash=sha256:6864247895eea5d13b9c57c9e03abb49cb94ce2dc7c58e91cba3248c7477c9e3 \ - --hash=sha256:a8f4608e65c244ead9e0538f181a96c6e11199ec114d41f1d7b1bffa96937bda - # via - # google-auth - # gsutil +google-auth[aiohttp]==2.26.1 \ + --hash=sha256:2c8b55e3e564f298122a02ab7b97458ccfcc5617840beb5d0ac757ada92c9780 \ + --hash=sha256:54385acca5c0fbdda510cd8585ba6f3fcb06eeecf8a6ecca39d3ee148b092590 + # via gsutil google-reauth==0.1.1 \ --hash=sha256:cb39074488d74c8853074dde47368bbf8f739d4a4338b89aab696c895b6d8368 \ --hash=sha256:f9f6852a55c2c5453d581cd01f3d1278e86147c03d008409800390a834235892 @@ -703,9 +717,9 @@ icalendar==5.0.11 \ --hash=sha256:7a298bb864526589d0de81f4b736eeb6ff9e539fefb405f7977aa5c1e201ca00 \ --hash=sha256:81864971ac43a1b7d0a555dc1b667836ce59fc719a7f845a96f2f03205fb83b9 # via -r requirements.in -idna==3.4 \ - --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ - --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 +idna==3.6 \ + --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ + --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f # via # requests # yarl @@ -713,9 +727,9 @@ imagesize==1.4.1 \ --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a # via sphinx -importlib-metadata==6.8.0 \ - --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ - --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 +importlib-metadata==7.0.1 \ + --hash=sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e \ + --hash=sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc # via yapf jinja2==3.1.2 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ @@ -947,17 +961,17 @@ packaging==23.2 \ # envoy-github-abstract # envoy-github-release # sphinx -pathspec==0.11.2 \ - --hash=sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20 \ - --hash=sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3 +pathspec==0.12.1 \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 # via yamllint pep8-naming==0.13.3 \ --hash=sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971 \ --hash=sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80 # via -r requirements.in -platformdirs==3.11.0 \ - --hash=sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3 \ - --hash=sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e +platformdirs==4.1.0 \ + --hash=sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380 \ + --hash=sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420 # via yapf ply==3.11 \ --hash=sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3 \ @@ -979,9 +993,9 @@ protobuf==4.25.1 \ # -r requirements.in # envoy-base-utils # envoy-docs-sphinx-runner -pyasn1==0.5.0 \ - --hash=sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57 \ - --hash=sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde +pyasn1==0.5.1 \ + --hash=sha256:4439847c58d40b1d0a573d07e3856e95333f1976294494c325775aeca506eb58 \ + --hash=sha256:6d391a96e59b23130a5cfa74d6fd7f388dbbe26cc8f1edf39fdddf08d9d6676c # via # oauth2client # pyasn1-modules @@ -1010,9 +1024,9 @@ pygithub==2.1.1 \ --hash=sha256:4b528d5d6f35e991ea5fd3f942f58748f24938805cb7fcf24486546637917337 \ --hash=sha256:ecf12c2809c44147bce63b047b3d2e9dac8a41b63e90fcb263c703f64936b97c # via -r requirements.in -pygments==2.16.1 \ - --hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \ - --hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29 +pygments==2.17.2 \ + --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ + --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 # via # envoy-docs-sphinx-runner # sphinx @@ -1022,58 +1036,25 @@ pyjwt[crypto]==2.8.0 \ # via # gidgethub # pygithub - # pyjwt -pylsqpack==0.3.17 \ - --hash=sha256:016cfc9dc2dea9c0b06b7aba64da89315b4c96c309c69f5ea548f4e994429781 \ - --hash=sha256:0b1ed55872f8f984f655a4c853ad749b834a1fcd4c7e5a962c6f17d4d27687a2 \ - --hash=sha256:105e636a33cac3ad7bd62aab97d655b53486fab6eb33429e45e7963be814947c \ - --hash=sha256:14dd6f623afe7f4b2a45078ef6bf3cc4a686489abf487f6fe15deeede893a551 \ - --hash=sha256:1b5c86a9feb137d197fe9f3c4775f5308f91f00a720d212b205044c83d32ab2e \ - --hash=sha256:1f657966917239518dcbf508ca5311ded178d88b81fe4e8f5fc6f7d1d84153a4 \ - --hash=sha256:27922bb8bd2e6a32693ac0b4cf3e164695b33c3fe3d243648f2f6403f03636d9 \ - --hash=sha256:2b010cbd59416f1911e392f6ccfbedd51af1b9bb7c1da3ac40a844b103628d3a \ - --hash=sha256:2bd2848a8ee065e4632f38c36fa79e40159271872f1ac9c1fd68ab913523c8de \ - --hash=sha256:2f20778db956dc7e4b1a8a79722d57a4650c45997fb65c1352cbf85eb7aa3ce2 \ - --hash=sha256:346d804ca196c29d8eae69d943b272e22101bd7611268b2db726097bd74c9c11 \ - --hash=sha256:35159d4e2f8005162cb4d5d5f2b477e45e9a54850203ec67c00806addedfdcf0 \ - --hash=sha256:3563f7e563b0b9d48958e92b2262872d056325b19e12c7a9e0ea1eb297302ae4 \ - --hash=sha256:3a7256825ea88f3c64b80676f5aa0fc1b19cd0bc28dd4d6c37397bcbd6ed3b25 \ - --hash=sha256:41bf0f33cd2fe4c745a790adc0e3cf1bfcb5c156e2217b3ff9d0eaa7fab763be \ - --hash=sha256:4580bce6eb2c2dd3c60ac7eb13beae83bc899696e2446ee9499537f037083426 \ - --hash=sha256:46762cc6993ee64c24dcaf9ec8665dbd68633efc7198ceb65a27e5232b9760c6 \ - --hash=sha256:4e501e9b6422db8b6d8248ef7fe325713ffce59fc2ab99d7dcca026b7451ce7d \ - --hash=sha256:5d992ffa01bc03a8e705a64de68b91b6c1de1960afa777917e6a37cef394faed \ - --hash=sha256:64791cc8b45d63a0f7f447614b7d5d5fa9a3f6ce20c7c10d9ea94003aedeff4b \ - --hash=sha256:6b3e381cd3b72ae466c0f34e109071a006d9939bbdcdd4856f72f08579ed0e76 \ - --hash=sha256:6dbc15ed7438e0f7c3ce323cfb878a3ba7aa8fc961a1f57df7c0be87520dd63a \ - --hash=sha256:6fb77ceae0a88f481ebfe902dcb8a18c6026aaacc9fd3cb709e7fc8d70bad26b \ - --hash=sha256:73ce2604f6dbc0bf11cc8d0858c60a74f9aff227c98054ebd946b69c5adb34e0 \ - --hash=sha256:7c30e9b21d8575e3ec42cd0ffcabb87cd2f5cf6dbdd07a9b209fbffa085a5f33 \ - --hash=sha256:80f49846ab14c12189b4517fb56c493ca7dec840d878102af6918ac9a2018602 \ - --hash=sha256:8e0d8ff7f6267674b3989c58d9c9e7bf2387454f51488317062e7b5b81a88d00 \ - --hash=sha256:95561d3e77ba8a78565bbd7ee3d2c01ad19a240806e1f1fe3e9b2d5a455f9992 \ - --hash=sha256:9c3c3ad219c8525d70866cc8c3fc584b772d3bfdced6825bfe1e6f1f2c3a33fa \ - --hash=sha256:abcfe2630ccb3a671cae45700fcdfbae3419340d4ad15c85db0534d8ea7dc745 \ - --hash=sha256:ac16e1c01e1b1610598b1b530c698476581beca5dc13186efe248077c734e1de \ - --hash=sha256:add2ace26276b78b9e063b5439556cda6b36a36aed747d93ea06c43bc8176208 \ - --hash=sha256:bb74b8a730876626e63d83564af0f31d27a0e1dd9219e9e5bc0d4921e85da71e \ - --hash=sha256:bbbf789dc1273680430e3231144fc38214c7460e836cb7c6076365b16147a151 \ - --hash=sha256:bf5210736b79effe3fc0e6b0d8d6aa0afd4b50c0cdb21e49f3835c25642e1f6d \ - --hash=sha256:c245a2241ed295633d3c60f949a00e43bcf7d108eb6b062b51e2ebf735fb83ed \ - --hash=sha256:c760638dce05ac657c9452d02424e07e99b65f431f7e366e79f6e23ed7a1313f \ - --hash=sha256:c7b3da5f2d3a4ae87ec46e6b1acf7ee54beeea049a99bbd6973012f0309b85bb \ - --hash=sha256:c7efb558ab48e364dad500bd4a78536a802dae54a46176021d3889b4e77cb150 \ - --hash=sha256:c89bbbcf69afa77f422edd7cb4054b2a1a60d51b835024087bb407c6b27181f4 \ - --hash=sha256:d4232501a5554c1f05334dfe0cb35ec66cc16154e6f31ce3107b8a8cffc9420c \ - --hash=sha256:db6e72e2c1312a1d918f8fd3a6bb38de98473b8cbdf6a3ce0237bd7ba0f25ad2 \ - --hash=sha256:e3556432d8dbb8649bf38d87fa5c97280b16d5a5425d8f943c676ace3041f4b3 \ - --hash=sha256:e6ca0ecda0040afdce031c7b966b78d8ca2375416170410ac862689ed9a60e68 \ - --hash=sha256:ea41faaf98857fa94ff12b6f72bd39c23fcaaa26ecece65cb3db9fa2b28633e7 \ - --hash=sha256:f1e40bec882d6aac75e814a2b8ee92add31a82eddcb705530497ab25f0c09f9a \ - --hash=sha256:f5c46627262389a9151cb4a120aa5b3210ba2066ab8c3026f3263adf8336b0c1 \ - --hash=sha256:f864f3e6c9e0a42b89f3388723575e306f45e736e32f6c0317eefb53c6ff1a40 \ - --hash=sha256:fc93abbe5bee19ceb1cb76b90298d2f47923f2a6dd1398f99aa498de1da0e553 \ - --hash=sha256:fdbfb5df079a50a7a0eed87d51a12495c820d30277ddb58b52c4862b5d557fc4 +pylsqpack==0.3.18 \ + --hash=sha256:005ddce84bdcbf5c3cf99f764504208e1aa0a91a8331bf47108f2708f2a315e6 \ + --hash=sha256:06e1bbe47514b83cd03158e5558ef8cc44f578169c1820098be9f3cc4137f16a \ + --hash=sha256:1f415d2e03c779261ac7ed421a009a4c752eef6f1ef7b5a34c4a463a5e17fbad \ + --hash=sha256:3c4cccfd91afd589994f844fd1dbae0acdb58a8ab929d8edeadb25339deb6590 \ + --hash=sha256:3dd664354422d4cd51c189febb5f5d22bf3d8c453cc25517c04ce01a57478060 \ + --hash=sha256:40465d025b946bca195bdaed74b3b79fe3f7f419ab1d4bc4109dca34ba9881d7 \ + --hash=sha256:45ae55e721877505f4d5ccd49591d69353f2a548a8673dfafb251d385b3c097f \ + --hash=sha256:4a248be29d9ca1fa2ebd7ef4b8ac166d17df0d8d4631b4499c8c566e221d4e5b \ + --hash=sha256:711f3aa645f72a928e22606c1f026cde905de23efc07028fe1bc7429f73ec8ee \ + --hash=sha256:75042b442a0a7a283b5adc21045e6583f3c817d40ccec769837bf2f90b79c494 \ + --hash=sha256:8b5fd04bb27180286811f8e1659974e6e5e854a882de3f2aba8caefc1bb9ab81 \ + --hash=sha256:8ea75152e8cb8b8c7cfef11c3aa5ebe5b226bd850889f56ff70a688e9680acbf \ + --hash=sha256:a2798e1c08bd36875f77a1ebec0f130fdf9e27eebdb0499a764201d55ef78770 \ + --hash=sha256:ae628cd359ecb466dd85f151ea1ad53de3114e5a9ae0f0ac1408fb43a4318032 \ + --hash=sha256:bac5f2dc255ae70e5a14033e769769b38bd4c980b365dacd88665610f245e36f \ + --hash=sha256:c003eb882f41e4dbd093243c67b97c8634209b4d5ba7edd16163b1ff37306254 \ + --hash=sha256:c84e6d4dcb708d766a50bfd16579d8a0bff4eb4e5f5dff9f3df4018454d4013b \ + --hash=sha256:e1054b0b44f6141a99e84a9aa6a27c9df028e9223747b893e8e37cdc95b602f1 # via aioquic pynacl==1.5.0 \ --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ @@ -1087,9 +1068,9 @@ pynacl==1.5.0 \ --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 # via pygithub -pyopenssl==23.2.0 \ - --hash=sha256:24f0dc5227396b3e831f4c7f602b950a5e9833d292c8e4a2e06b709292806ae2 \ - --hash=sha256:276f931f55a452e7dea69c7173e984eb2a4407ce413c918aa34b55f82f9b8bac +pyopenssl==23.3.0 \ + --hash=sha256:6756834481d9ed5470f4a9393455154bc92fe7a64b7bc6ee2c804e78c52099b2 \ + --hash=sha256:6b2cba5cc46e822750ec3e5a81ee12819850b11303630d575e98108a079c2b12 # via # aioquic # gcs-oauth2-boto-plugin @@ -1107,9 +1088,9 @@ python-dateutil==2.8.2 \ # via # icalendar # pygithub -python-gnupg==0.5.1 \ - --hash=sha256:5674bad4e93876c0b0d3197e314d7f942d39018bf31e2b833f6788a6813c3fb8 \ - --hash=sha256:bf9b2d9032ef38139b7d64184176cd0b293eaeae6e4f93f50e304c7051174482 +python-gnupg==0.5.2 \ + --hash=sha256:01d8013931c9fa3f45824bbea7054c03d6e11f258a72e7e086e168dbcb91854c \ + --hash=sha256:72ce142af6da7f07e433fef148b445fb3e07854acd2f88739008838745c0e9f5 # via envoy-gpg-identity pytz==2023.3.post1 \ --hash=sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b \ @@ -1224,9 +1205,9 @@ snowballstemmer==2.2.0 \ --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a # via sphinx -sphinx==7.2.2 \ - --hash=sha256:1c0abe6d4de7a6b2c2b109a2e18387bf27b240742e1b34ea42ac3ed2ac99978c \ - --hash=sha256:ed33bc597dd8f05cd37118f64cbac0b8bf773389a628ddfe95ab9e915c9308dc +sphinx==7.1.2 \ + --hash=sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f \ + --hash=sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe # via # -r requirements.in # envoy-docs-sphinx-runner @@ -1240,9 +1221,9 @@ sphinx-copybutton==0.5.2 \ --hash=sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd \ --hash=sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e # via envoy-docs-sphinx-runner -sphinx-rtd-theme==2.0.0rc2 \ - --hash=sha256:d1270effe620df9164b1cd2d617909472a63531e21a716fd22d0fbcedf9d24ff \ - --hash=sha256:f04df9213acf421c3b42f4f39005c8bc68fc4696c5b4ed4ef13d1678369713f7 +sphinx-rtd-theme==2.0.0 \ + --hash=sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b \ + --hash=sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586 # via envoy-docs-sphinx-runner sphinxcontrib-applehelp==1.0.4 \ --hash=sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228 \ @@ -1304,15 +1285,15 @@ tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f # via yapf -trycast==1.0.0 \ - --hash=sha256:72dd9be7553337cfba04809646dc144ddd6e3a54f4213ab8b76a14b4a1882e04 \ - --hash=sha256:93fcbb922ef3a22c587f636ed8c128266bb2615171983dbf2f7edd3ae86afb10 +trycast==1.1.0 \ + --hash=sha256:09b194343bf07f0ffb2e228ff20d1cc63148fd9ab33b204acc5e03f1991d081c \ + --hash=sha256:218d3b9b9a6de0423aadb92a5c7059b25f2919c63914f30f96dd7c87726196bd # via # aio-core # envoy-base-utils -typing-extensions==4.8.0 \ - --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ - --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef +typing-extensions==4.9.0 \ + --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \ + --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd # via # aiodocker # pygithub @@ -1320,49 +1301,44 @@ uritemplate==4.1.1 \ --hash=sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0 \ --hash=sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e # via gidgethub -urllib3==2.0.7 \ - --hash=sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84 \ - --hash=sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e +urllib3==2.1.0 \ + --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \ + --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54 # via # pygithub # requests -uvloop==0.18.0 \ - --hash=sha256:1121087dfeb46e9e65920b20d1f46322ba299b8d93f7cb61d76c94b5a1adc20c \ - --hash=sha256:12af0d2e1b16780051d27c12de7e419b9daeb3516c503ab3e98d364cc55303bb \ - --hash=sha256:1f354d669586fca96a9a688c585b6257706d216177ac457c92e15709acaece10 \ - --hash=sha256:1f4a549cd747e6f4f8446f4b4c8cb79504a8372d5d3a9b4fc20e25daf8e76c05 \ - --hash=sha256:211ce38d84118ae282a91408f61b85cf28e2e65a0a8966b9a97e0e9d67c48722 \ - --hash=sha256:25b714f07c68dcdaad6994414f6ec0f2a3b9565524fba181dcbfd7d9598a3e73 \ - --hash=sha256:280904236a5b333a273292b3bcdcbfe173690f69901365b973fa35be302d7781 \ - --hash=sha256:2b8b7cf7806bdc745917f84d833f2144fabcc38e9cd854e6bc49755e3af2b53e \ - --hash=sha256:4d90858f32a852988d33987d608bcfba92a1874eb9f183995def59a34229f30d \ - --hash=sha256:53aca21735eee3859e8c11265445925911ffe410974f13304edb0447f9f58420 \ - --hash=sha256:54b211c46facb466726b227f350792770fc96593c4ecdfaafe20dc00f3209aef \ - --hash=sha256:56c1026a6b0d12b378425e16250acb7d453abaefe7a2f5977143898db6cfe5bd \ - --hash=sha256:585b7281f9ea25c4a5fa993b1acca4ad3d8bc3f3fe2e393f0ef51b6c1bcd2fe6 \ - --hash=sha256:58e44650cbc8607a218caeece5a689f0a2d10be084a69fc32f7db2e8f364927c \ - --hash=sha256:61151cc207cf5fc88863e50de3d04f64ee0fdbb979d0b97caf21cae29130ed78 \ - --hash=sha256:6132318e1ab84a626639b252137aa8d031a6c0550250460644c32ed997604088 \ - --hash=sha256:680da98f12a7587f76f6f639a8aa7708936a5d17c5e7db0bf9c9d9cbcb616593 \ - --hash=sha256:6e20bb765fcac07879cd6767b6dca58127ba5a456149717e0e3b1f00d8eab51c \ - --hash=sha256:74020ef8061678e01a40c49f1716b4f4d1cc71190d40633f08a5ef8a7448a5c6 \ - --hash=sha256:75baba0bfdd385c886804970ae03f0172e0d51e51ebd191e4df09b929771b71e \ - --hash=sha256:847f2ed0887047c63da9ad788d54755579fa23f0784db7e752c7cf14cf2e7506 \ - --hash=sha256:8849b8ef861431543c07112ad8436903e243cdfa783290cbee3df4ce86d8dd48 \ - --hash=sha256:895a1e3aca2504638a802d0bec2759acc2f43a0291a1dff886d69f8b7baff399 \ - --hash=sha256:99deae0504547d04990cc5acf631d9f490108c3709479d90c1dcd14d6e7af24d \ - --hash=sha256:ad79cd30c7e7484bdf6e315f3296f564b3ee2f453134a23ffc80d00e63b3b59e \ - --hash=sha256:b028776faf9b7a6d0a325664f899e4c670b2ae430265189eb8d76bd4a57d8a6e \ - --hash=sha256:b0a8f706b943c198dcedf1f2fb84899002c195c24745e47eeb8f2fb340f7dfc3 \ - --hash=sha256:c65585ae03571b73907b8089473419d8c0aff1e3826b3bce153776de56cbc687 \ - --hash=sha256:c6d341bc109fb8ea69025b3ec281fcb155d6824a8ebf5486c989ff7748351a37 \ - --hash=sha256:d5d1135beffe9cd95d0350f19e2716bc38be47d5df296d7cc46e3b7557c0d1ff \ - --hash=sha256:db1fcbad5deb9551e011ca589c5e7258b5afa78598174ac37a5f15ddcfb4ac7b \ - --hash=sha256:e14de8800765b9916d051707f62e18a304cde661fa2b98a58816ca38d2b94029 \ - --hash=sha256:e3d301e23984dcbc92d0e42253e0e0571915f0763f1eeaf68631348745f2dccc \ - --hash=sha256:ed3c28337d2fefc0bac5705b9c66b2702dc392f2e9a69badb1d606e7e7f773bb \ - --hash=sha256:edbb4de38535f42f020da1e3ae7c60f2f65402d027a08a8c60dc8569464873a6 \ - --hash=sha256:f3b18663efe0012bc4c315f1b64020e44596f5fabc281f5b0d9bc9465288559c +uvloop==0.19.0 \ + --hash=sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd \ + --hash=sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec \ + --hash=sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b \ + --hash=sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc \ + --hash=sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797 \ + --hash=sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5 \ + --hash=sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2 \ + --hash=sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d \ + --hash=sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be \ + --hash=sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd \ + --hash=sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12 \ + --hash=sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17 \ + --hash=sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef \ + --hash=sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24 \ + --hash=sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428 \ + --hash=sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1 \ + --hash=sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849 \ + --hash=sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593 \ + --hash=sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd \ + --hash=sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67 \ + --hash=sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6 \ + --hash=sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3 \ + --hash=sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd \ + --hash=sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8 \ + --hash=sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7 \ + --hash=sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533 \ + --hash=sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957 \ + --hash=sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650 \ + --hash=sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e \ + --hash=sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7 \ + --hash=sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256 # via aio-run-runner verboselogs==1.7 \ --hash=sha256:d63f23bf568295b95d3530c6864a0b580cec70e7ff974177dead1e4ffbc6ff49 \ @@ -1374,86 +1350,81 @@ verboselogs==1.7 \ # envoy-distribution-repo # envoy-github-abstract # envoy-github-release -wrapt==1.15.0 \ - --hash=sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0 \ - --hash=sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420 \ - --hash=sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a \ - --hash=sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c \ - --hash=sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079 \ - --hash=sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923 \ - --hash=sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f \ - --hash=sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1 \ - --hash=sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8 \ - --hash=sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86 \ - --hash=sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0 \ - --hash=sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364 \ - --hash=sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e \ - --hash=sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c \ - --hash=sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e \ - --hash=sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c \ - --hash=sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727 \ - --hash=sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff \ - --hash=sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e \ - --hash=sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29 \ - --hash=sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7 \ - --hash=sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72 \ - --hash=sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475 \ - --hash=sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a \ - --hash=sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317 \ - --hash=sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2 \ - --hash=sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd \ - --hash=sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640 \ - --hash=sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98 \ - --hash=sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248 \ - --hash=sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e \ - --hash=sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d \ - --hash=sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec \ - --hash=sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1 \ - --hash=sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e \ - --hash=sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9 \ - --hash=sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92 \ - --hash=sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb \ - --hash=sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094 \ - --hash=sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46 \ - --hash=sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29 \ - --hash=sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd \ - --hash=sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705 \ - --hash=sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8 \ - --hash=sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975 \ - --hash=sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb \ - --hash=sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e \ - --hash=sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b \ - --hash=sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418 \ - --hash=sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019 \ - --hash=sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1 \ - --hash=sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba \ - --hash=sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6 \ - --hash=sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2 \ - --hash=sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3 \ - --hash=sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7 \ - --hash=sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752 \ - --hash=sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416 \ - --hash=sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f \ - --hash=sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1 \ - --hash=sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc \ - --hash=sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145 \ - --hash=sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee \ - --hash=sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a \ - --hash=sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7 \ - --hash=sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b \ - --hash=sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653 \ - --hash=sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0 \ - --hash=sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90 \ - --hash=sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29 \ - --hash=sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6 \ - --hash=sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034 \ - --hash=sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09 \ - --hash=sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559 \ - --hash=sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639 +wrapt==1.16.0 \ + --hash=sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc \ + --hash=sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81 \ + --hash=sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 \ + --hash=sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e \ + --hash=sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca \ + --hash=sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0 \ + --hash=sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb \ + --hash=sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487 \ + --hash=sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40 \ + --hash=sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c \ + --hash=sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060 \ + --hash=sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202 \ + --hash=sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41 \ + --hash=sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9 \ + --hash=sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b \ + --hash=sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664 \ + --hash=sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d \ + --hash=sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362 \ + --hash=sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00 \ + --hash=sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc \ + --hash=sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1 \ + --hash=sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267 \ + --hash=sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956 \ + --hash=sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966 \ + --hash=sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 \ + --hash=sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228 \ + --hash=sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72 \ + --hash=sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d \ + --hash=sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292 \ + --hash=sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0 \ + --hash=sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0 \ + --hash=sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36 \ + --hash=sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c \ + --hash=sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5 \ + --hash=sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f \ + --hash=sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73 \ + --hash=sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b \ + --hash=sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2 \ + --hash=sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593 \ + --hash=sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39 \ + --hash=sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 \ + --hash=sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf \ + --hash=sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf \ + --hash=sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 \ + --hash=sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c \ + --hash=sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c \ + --hash=sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f \ + --hash=sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440 \ + --hash=sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465 \ + --hash=sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136 \ + --hash=sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b \ + --hash=sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8 \ + --hash=sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3 \ + --hash=sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8 \ + --hash=sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6 \ + --hash=sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e \ + --hash=sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f \ + --hash=sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c \ + --hash=sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e \ + --hash=sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8 \ + --hash=sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2 \ + --hash=sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020 \ + --hash=sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35 \ + --hash=sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d \ + --hash=sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3 \ + --hash=sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537 \ + --hash=sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809 \ + --hash=sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d \ + --hash=sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a \ + --hash=sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4 # via deprecated -yamllint==1.32.0 \ - --hash=sha256:d01dde008c65de5b235188ab3110bebc59d18e5c65fc8a58267cd211cd9df34a \ - --hash=sha256:d97a66e48da820829d96077d76b8dfbe6c6140f106e558dae87e81ac4e6b30b7 +yamllint==1.33.0 \ + --hash=sha256:28a19f5d68d28d8fec538a1db21bb2d84c7dc2e2ea36266da8d4d1c5a683814d \ + --hash=sha256:2dceab9ef2d99518a2fcf4ffc964d44250ac4459be1ba3ca315118e4a1a81f7d # via envoy-code-check yapf==0.40.2 \ --hash=sha256:4dab8a5ed7134e26d57c1647c7483afb3f136878b579062b786c9ba16b94637b \ @@ -1559,50 +1530,53 @@ zipp==3.17.0 \ --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 # via importlib-metadata -zstandard==0.21.0 \ - --hash=sha256:0aad6090ac164a9d237d096c8af241b8dcd015524ac6dbec1330092dba151657 \ - --hash=sha256:0bdbe350691dec3078b187b8304e6a9c4d9db3eb2d50ab5b1d748533e746d099 \ - --hash=sha256:0e1e94a9d9e35dc04bf90055e914077c80b1e0c15454cc5419e82529d3e70728 \ - --hash=sha256:1243b01fb7926a5a0417120c57d4c28b25a0200284af0525fddba812d575f605 \ - --hash=sha256:144a4fe4be2e747bf9c646deab212666e39048faa4372abb6a250dab0f347a29 \ - --hash=sha256:14e10ed461e4807471075d4b7a2af51f5234c8f1e2a0c1d37d5ca49aaaad49e8 \ - --hash=sha256:1545fb9cb93e043351d0cb2ee73fa0ab32e61298968667bb924aac166278c3fc \ - --hash=sha256:1e6e131a4df2eb6f64961cea6f979cdff22d6e0d5516feb0d09492c8fd36f3bc \ - --hash=sha256:25fbfef672ad798afab12e8fd204d122fca3bc8e2dcb0a2ba73bf0a0ac0f5f07 \ - --hash=sha256:2769730c13638e08b7a983b32cb67775650024632cd0476bf1ba0e6360f5ac7d \ - --hash=sha256:48b6233b5c4cacb7afb0ee6b4f91820afbb6c0e3ae0fa10abbc20000acdf4f11 \ - --hash=sha256:4af612c96599b17e4930fe58bffd6514e6c25509d120f4eae6031b7595912f85 \ - --hash=sha256:52b2b5e3e7670bd25835e0e0730a236f2b0df87672d99d3bf4bf87248aa659fb \ - --hash=sha256:57ac078ad7333c9db7a74804684099c4c77f98971c151cee18d17a12649bc25c \ - --hash=sha256:62957069a7c2626ae80023998757e27bd28d933b165c487ab6f83ad3337f773d \ - --hash=sha256:649a67643257e3b2cff1c0a73130609679a5673bf389564bc6d4b164d822a7ce \ - --hash=sha256:67829fdb82e7393ca68e543894cd0581a79243cc4ec74a836c305c70a5943f07 \ - --hash=sha256:7d3bc4de588b987f3934ca79140e226785d7b5e47e31756761e48644a45a6766 \ - --hash=sha256:7f2afab2c727b6a3d466faee6974a7dad0d9991241c498e7317e5ccf53dbc766 \ - --hash=sha256:8070c1cdb4587a8aa038638acda3bd97c43c59e1e31705f2766d5576b329e97c \ - --hash=sha256:8257752b97134477fb4e413529edaa04fc0457361d304c1319573de00ba796b1 \ - --hash=sha256:9980489f066a391c5572bc7dc471e903fb134e0b0001ea9b1d3eff85af0a6f1b \ - --hash=sha256:9cff89a036c639a6a9299bf19e16bfb9ac7def9a7634c52c257166db09d950e7 \ - --hash=sha256:a8d200617d5c876221304b0e3fe43307adde291b4a897e7b0617a61611dfff6a \ - --hash=sha256:a9fec02ce2b38e8b2e86079ff0b912445495e8ab0b137f9c0505f88ad0d61296 \ - --hash=sha256:b1367da0dde8ae5040ef0413fb57b5baeac39d8931c70536d5f013b11d3fc3a5 \ - --hash=sha256:b69cccd06a4a0a1d9fb3ec9a97600055cf03030ed7048d4bcb88c574f7895773 \ - --hash=sha256:b72060402524ab91e075881f6b6b3f37ab715663313030d0ce983da44960a86f \ - --hash=sha256:c053b7c4cbf71cc26808ed67ae955836232f7638444d709bfc302d3e499364fa \ - --hash=sha256:cff891e37b167bc477f35562cda1248acc115dbafbea4f3af54ec70821090965 \ - --hash=sha256:d12fa383e315b62630bd407477d750ec96a0f438447d0e6e496ab67b8b451d39 \ - --hash=sha256:d2d61675b2a73edcef5e327e38eb62bdfc89009960f0e3991eae5cc3d54718de \ - --hash=sha256:db62cbe7a965e68ad2217a056107cc43d41764c66c895be05cf9c8b19578ce9c \ - --hash=sha256:ddb086ea3b915e50f6604be93f4f64f168d3fc3cef3585bb9a375d5834392d4f \ - --hash=sha256:df28aa5c241f59a7ab524f8ad8bb75d9a23f7ed9d501b0fed6d40ec3064784e8 \ - --hash=sha256:e1e0c62a67ff425927898cf43da2cf6b852289ebcc2054514ea9bf121bec10a5 \ - --hash=sha256:e6048a287f8d2d6e8bc67f6b42a766c61923641dd4022b7fd3f7439e17ba5a4d \ - --hash=sha256:e7d560ce14fd209db6adacce8908244503a009c6c39eee0c10f138996cd66d3e \ - --hash=sha256:ea68b1ba4f9678ac3d3e370d96442a6332d431e5050223626bdce748692226ea \ - --hash=sha256:f08e3a10d01a247877e4cb61a82a319ea746c356a3786558bed2481e6c405546 \ - --hash=sha256:f1b9703fe2e6b6811886c44052647df7c37478af1b4a1a9078585806f42e5b15 \ - --hash=sha256:fe6c821eb6870f81d73bf10e5deed80edcac1e63fbc40610e61f340723fd5f7c \ - --hash=sha256:ff0852da2abe86326b20abae912d0367878dd0854b8931897d44cfeb18985472 +zstandard==0.22.0 \ + --hash=sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd \ + --hash=sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2 \ + --hash=sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356 \ + --hash=sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf \ + --hash=sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004 \ + --hash=sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69 \ + --hash=sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019 \ + --hash=sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a \ + --hash=sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440 \ + --hash=sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b \ + --hash=sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775 \ + --hash=sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e \ + --hash=sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc \ + --hash=sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d \ + --hash=sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09 \ + --hash=sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c \ + --hash=sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe \ + --hash=sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88 \ + --hash=sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94 \ + --hash=sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08 \ + --hash=sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0 \ + --hash=sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a \ + --hash=sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292 \ + --hash=sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93 \ + --hash=sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70 \ + --hash=sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8 \ + --hash=sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2 \ + --hash=sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45 \ + --hash=sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202 \ + --hash=sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3 \ + --hash=sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb \ + --hash=sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4 \ + --hash=sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d \ + --hash=sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c \ + --hash=sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f \ + --hash=sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26 \ + --hash=sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303 \ + --hash=sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df \ + --hash=sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e \ + --hash=sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73 \ + --hash=sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c \ + --hash=sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2 \ + --hash=sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0 \ + --hash=sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375 \ + --hash=sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912 \ + --hash=sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e # via envoy-base-utils # The following packages are considered to be unsafe in a requirements file: From 86f306da834c31a7e15badd85ff3d577dc1bb6a7 Mon Sep 17 00:00:00 2001 From: Jeongseok Son Date: Thu, 4 Jan 2024 08:18:26 -0800 Subject: [PATCH 123/126] http: fix HttpDatagramHandler object lifetime issue. (#31628) stream_decoder_ member variable must outlive the HttpDatagramHandler. Previously, stream_decoder_ became a dangling pointer when the stream is reset before OnHttp3Datagram is called. I made Envoy QUIC stream unregister the HTTP/3 Datagram visitor when the stream is reset to ensure the lifetime assumption. Additional Description: Risk Level: Low, this is a bug fix. Testing: Unit tests and integration tests. Docs Changes: N/A Release Notes: N/A Platform Specific Features: N/A Signed-off-by: Jeongseok Son --- source/common/quic/envoy_quic_client_stream.cc | 4 ++++ source/common/quic/envoy_quic_server_stream.cc | 5 +++++ source/common/quic/http_datagram_handler.cc | 6 +----- source/common/quic/http_datagram_handler.h | 1 - test/common/quic/envoy_quic_client_stream_test.cc | 8 ++++++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/source/common/quic/envoy_quic_client_stream.cc b/source/common/quic/envoy_quic_client_stream.cc index 1c0211e083d4..f8fde2fd0d84 100644 --- a/source/common/quic/envoy_quic_client_stream.cc +++ b/source/common/quic/envoy_quic_client_stream.cc @@ -215,6 +215,9 @@ void EnvoyQuicClientStream::encodeMetadata(const Http::MetadataMapVector& /*meta } void EnvoyQuicClientStream::resetStream(Http::StreamResetReason reason) { + if (http_datagram_handler_) { + UnregisterHttp3DatagramVisitor(); + } Reset(envoyResetReasonToQuicRstError(reason)); } @@ -527,6 +530,7 @@ bool EnvoyQuicClientStream::hasPendingData() { return BufferedDataBytes() > 0; } void EnvoyQuicClientStream::useCapsuleProtocol() { http_datagram_handler_ = std::make_unique(*this); http_datagram_handler_->setStreamDecoder(response_decoder_); + RegisterHttp3DatagramVisitor(http_datagram_handler_.get()); } #endif diff --git a/source/common/quic/envoy_quic_server_stream.cc b/source/common/quic/envoy_quic_server_stream.cc index 3ccc044d385b..4f9390bf7e5b 100644 --- a/source/common/quic/envoy_quic_server_stream.cc +++ b/source/common/quic/envoy_quic_server_stream.cc @@ -195,6 +195,10 @@ void EnvoyQuicServerStream::resetStream(Http::StreamResetReason reason) { buffer_memory_account_->clearDownstream(); } + if (http_datagram_handler_) { + UnregisterHttp3DatagramVisitor(); + } + if (local_end_stream_ && !reading_stopped()) { // This is after 200 early response. Reset with QUIC_STREAM_NO_ERROR instead // of propagating original reset reason. In QUICHE if a stream stops reading @@ -579,6 +583,7 @@ void EnvoyQuicServerStream::useCapsuleProtocol() { http_datagram_handler_ = std::make_unique(*this); ASSERT(request_decoder_ != nullptr); http_datagram_handler_->setStreamDecoder(request_decoder_); + RegisterHttp3DatagramVisitor(http_datagram_handler_.get()); } #endif diff --git a/source/common/quic/http_datagram_handler.cc b/source/common/quic/http_datagram_handler.cc index 3ff34d2e524b..929e848209dc 100644 --- a/source/common/quic/http_datagram_handler.cc +++ b/source/common/quic/http_datagram_handler.cc @@ -12,11 +12,7 @@ namespace Envoy { namespace Quic { -HttpDatagramHandler::HttpDatagramHandler(quic::QuicSpdyStream& stream) : stream_(stream) { - stream_.RegisterHttp3DatagramVisitor(this); -} - -HttpDatagramHandler::~HttpDatagramHandler() { stream_.UnregisterHttp3DatagramVisitor(); } +HttpDatagramHandler::HttpDatagramHandler(quic::QuicSpdyStream& stream) : stream_(stream) {} void HttpDatagramHandler::decodeCapsule(const quiche::Capsule& capsule) { quiche::QuicheBuffer serialized_capsule = SerializeCapsule(capsule, &capsule_buffer_allocator_); diff --git a/source/common/quic/http_datagram_handler.h b/source/common/quic/http_datagram_handler.h index 74a2ce8aa7f8..395c620fec11 100644 --- a/source/common/quic/http_datagram_handler.h +++ b/source/common/quic/http_datagram_handler.h @@ -23,7 +23,6 @@ class HttpDatagramHandler : public quic::QuicSpdyStream::Http3DatagramVisitor, // Does not take ownership of the QuicSpdyStream. "stream" must refer to a valid object // that outlives HttpDatagramHandler. explicit HttpDatagramHandler(quic::QuicSpdyStream& stream); - ~HttpDatagramHandler() override; // quic::QuicSpdyStream::Http3DatagramVisitor void OnHttp3Datagram(quic::QuicStreamId stream_id, absl::string_view payload) override; diff --git a/test/common/quic/envoy_quic_client_stream_test.cc b/test/common/quic/envoy_quic_client_stream_test.cc index 076216ae100e..7daf1fe0db1c 100644 --- a/test/common/quic/envoy_quic_client_stream_test.cc +++ b/test/common/quic/envoy_quic_client_stream_test.cc @@ -755,6 +755,14 @@ TEST_F(EnvoyQuicClientStreamTest, DecodeHttp3Datagram) { quic_session_.OnMessageReceived(datagram_fragment_); EXPECT_CALL(stream_callbacks_, onResetStream(_, _)); } + +TEST_F(EnvoyQuicClientStreamTest, ResetStreamWithHttpDatagramHandler) { + setUpCapsuleProtocol(true, false); + EXPECT_CALL(stream_callbacks_, onResetStream(_, _)); + quic_stream_->resetStream(Http::StreamResetReason::LocalReset); + EXPECT_TRUE(quic_stream_->rst_sent()); +} + #endif } // namespace Quic From be298f47abeb1ef1e1d085d19f4ea6c95dd7e7d3 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 4 Jan 2024 12:45:44 -0500 Subject: [PATCH 124/126] build: fix no-datagram build (#31650) Signed-off-by: Alyssa Wilk --- source/common/quic/envoy_quic_client_stream.cc | 2 ++ source/common/quic/envoy_quic_server_stream.cc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/source/common/quic/envoy_quic_client_stream.cc b/source/common/quic/envoy_quic_client_stream.cc index f8fde2fd0d84..b082eaec01f3 100644 --- a/source/common/quic/envoy_quic_client_stream.cc +++ b/source/common/quic/envoy_quic_client_stream.cc @@ -215,9 +215,11 @@ void EnvoyQuicClientStream::encodeMetadata(const Http::MetadataMapVector& /*meta } void EnvoyQuicClientStream::resetStream(Http::StreamResetReason reason) { +#ifdef ENVOY_ENABLE_HTTP_DATAGRAMS if (http_datagram_handler_) { UnregisterHttp3DatagramVisitor(); } +#endif Reset(envoyResetReasonToQuicRstError(reason)); } diff --git a/source/common/quic/envoy_quic_server_stream.cc b/source/common/quic/envoy_quic_server_stream.cc index 4f9390bf7e5b..662f4f123d8b 100644 --- a/source/common/quic/envoy_quic_server_stream.cc +++ b/source/common/quic/envoy_quic_server_stream.cc @@ -195,9 +195,11 @@ void EnvoyQuicServerStream::resetStream(Http::StreamResetReason reason) { buffer_memory_account_->clearDownstream(); } +#ifdef ENVOY_ENABLE_HTTP_DATAGRAMS if (http_datagram_handler_) { UnregisterHttp3DatagramVisitor(); } +#endif if (local_end_stream_ && !reading_stopped()) { // This is after 200 early response. Reset with QUIC_STREAM_NO_ERROR instead From 8c1e74acfa115c2f639b60461004344e4b66928d Mon Sep 17 00:00:00 2001 From: phlax Date: Thu, 4 Jan 2024 18:00:29 +0000 Subject: [PATCH 125/126] ci/codeql: Cleanup (#31639) Signed-off-by: Ryan Northey --- .github/workflows/codeql-push.yml | 55 ++++++++++++++++++-------- .github/workflows/get_build_targets.sh | 32 --------------- 2 files changed, 38 insertions(+), 49 deletions(-) delete mode 100755 .github/workflows/get_build_targets.sh diff --git a/.github/workflows/codeql-push.yml b/.github/workflows/codeql-push.yml index a3773944f4b2..2622f8b3ecf1 100644 --- a/.github/workflows/codeql-push.yml +++ b/.github/workflows/codeql-push.yml @@ -1,4 +1,4 @@ -name: CodeQL +name: CodeQL/push permissions: contents: read @@ -15,20 +15,18 @@ concurrency: group: ${{ github.head_ref-github.workflow || github.run_id }} cancel-in-progress: true +env: + SEARCH_FOLDER: //source/common/... + jobs: CodeQL-Build: - permissions: - security-events: write # for github/codeql-action/analyze to upload SARIF results + # for github/codeql-action/analyze to upload SARIF results + security-events: write pull-requests: read - strategy: - fail-fast: false - - # CodeQL runs on ubuntu-20.04 runs-on: ubuntu-20.04 if: github.repository == 'envoyproxy/envoy' - steps: - name: Pre-cleanup uses: envoyproxy/toolshed/gh-actions/diskspace@6b3ddd1e42c252d68fb98973760c0ee1943c9c21 # actions-v0.2.20 @@ -41,19 +39,33 @@ jobs: - name: Get build targets run: | - . .github/workflows/get_build_targets.sh - echo 'BUILD_TARGETS<> $GITHUB_ENV - echo $BUILD_TARGETS_LOCAL >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV + # TODO(phlax): Shift this to an action + compare_head () { + while IFS= read -r line; do + bazel query "rdeps($SEARCH_FOLDER, $line, 1)" 2> /dev/null + done < <(git diff --name-only HEAD FETCH_HEAD -- source/* include/*) + } + if [[ "$GIT_EVENT" == "pull_request" ]]; then + git fetch https://github.com/envoyproxy/envoy.git main 2> /dev/null + TO_OTHER=FETCH_HEAD + else + TO_OTHER=HEAD^1 + fi + BUILD_TARGETS="$(compare_head "$TO_OTHER" | grep -v '\.cc\|\.h' | sort -u | head -n 3)" + echo 'BUILD_TARGETS<> $GITHUB_ENV + echo "$BUILD_TARGETS" >> $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + env: + GIT_EVENT: ${{ github.event_name }} - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL + if: ${{ env.BUILD_TARGETS != '' }} uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 - # Override language selection by uncommenting this and choosing your languages with: languages: cpp - name: Install deps + if: ${{ env.BUILD_TARGETS != '' }} shell: bash run: | sudo apt-get update --error-on=any @@ -69,16 +81,25 @@ jobs: export PATH=bin/clang14/bin:$PATH - name: Build + if: ${{ env.BUILD_TARGETS != '' }} run: | bazel/setup_clang.sh bin/clang14 - bazelisk shutdown - bazelisk build -c fastbuild --spawn_strategy=local --discard_analysis_cache --nouse_action_cache --config clang --config libc++ $BUILD_TARGETS + bazel shutdown + bazel build \ + -c fastbuild \ + --spawn_strategy=local \ + --discard_analysis_cache \ + --nouse_action_cache \ + --config clang \ + --config libc++ \ + $BUILD_TARGETS echo -e "Built targets...\n$BUILD_TARGETS" - name: Clean Artifacts + if: ${{ env.BUILD_TARGETS != '' }} run: | git clean -xdf - name: Perform CodeQL Analysis - if: env.BUILD_TARGETS != '' + if: ${{ env.BUILD_TARGETS != '' }} uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # codeql-bundle-v2.13.4 diff --git a/.github/workflows/get_build_targets.sh b/.github/workflows/get_build_targets.sh deleted file mode 100755 index 8304ef77233a..000000000000 --- a/.github/workflows/get_build_targets.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# This limits the directory that bazel query is going to search under. -readonly SEARCH_FOLDER="//source/common/..." - -set -e -o pipefail - -function compare_head () { - # Comparing the PR HEAD with the upstream main HEAD. - git diff --name-only HEAD FETCH_HEAD | while IFS= read -r line; do - # Only targets under those folders. - case "$line" in - source/*|include/*) - bazel query "rdeps($SEARCH_FOLDER, $line, 1)" 2>/dev/null - ;; - esac - done -} - -get_targets () { - # This chain of commands from left to right are: - # 1. Excluding the redundant .cc/.h targets that bazel query emits. - # 2. Storing only the unique output. - # 3. Limiting to the first 3 targets. - compare_head | grep -v '\.cc\|\.h' | sort -u | head -n 3 -} - -# Fetching the upstream HEAD to compare with and stored in FETCH_HEAD. -git fetch https://github.com/envoyproxy/envoy.git main 2>/dev/null - -BUILD_TARGETS_LOCAL=$(get_targets || :) -export BUILD_TARGETS_LOCAL From a200898b71f6b071fb0fc68c770a81f7cecba986 Mon Sep 17 00:00:00 2001 From: alyssawilk Date: Thu, 4 Jan 2024 14:02:24 -0500 Subject: [PATCH 126/126] coverage: bumping (#31644) Signed-off-by: Alyssa Wilk --- test/per_file_coverage.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index ae83388bef9e..65de2f4fab36 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -6,7 +6,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common:96.2" "source/common/api:84.5" # flaky due to posix: be careful adjusting "source/common/api/posix:83.8" # flaky (accept failover non-deterministic): be careful adjusting -"source/common/config:95.3" +"source/common/config:95.4" "source/common/crypto:95.5" "source/common/event:95.0" # Emulated edge events guards don't report LCOV "source/common/filesystem/posix:96.2" # FileReadToEndNotReadable fails in some env; createPath can't test all failure branches. @@ -15,15 +15,13 @@ declare -a KNOWN_LOW_COVERAGE=( "source/common/matcher:94.6" "source/common/network:94.4" # Flaky, `activateFileEvents`, `startSecureTransport` and `ioctl`, listener_socket do not always report LCOV "source/common/network/dns_resolver:91.4" # A few lines of MacOS code not tested in linux scripts. Tested in MacOS scripts -"source/common/protobuf:96.4" "source/common/quic:93.4" "source/common/secret:95.1" "source/common/signal:87.2" # Death tests don't report LCOV -"source/common/tcp:94.5" +"source/common/tcp:94.6" "source/common/thread:0.0" # Death tests don't report LCOV "source/common/watchdog:58.6" # Death tests don't report LCOV -"source/exe:91.4" -"source/extensions/access_loggers/wasm:93.5" +"source/exe:91.5" "source/extensions/clusters/common:91.5" # This can be increased again once `#24903` lands "source/extensions/common:93.0" #flaky: be careful adjusting "source/extensions/common/tap:94.5" @@ -31,7 +29,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/common/wasm/ext:92.0" "source/extensions/filters/common/fault:94.5" "source/extensions/filters/common/rbac:90.5" -"source/extensions/filters/http/cache:94.0" +"source/extensions/filters/http/cache:94.9" "source/extensions/filters/http/grpc_json_transcoder:93.8" # TODO(#28232) "source/extensions/filters/http/ip_tagging:88.0" "source/extensions/filters/http/kill_request:91.7" # Death tests don't report LCOV @@ -47,9 +45,9 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/stat_sinks/graphite_statsd:78.6" # Death tests don't report LCOV "source/extensions/stat_sinks/statsd:80.8" # Death tests don't report LCOV "source/extensions/tracers:96.1" -"source/extensions/tracers/common:73.8" -"source/extensions/tracers/common/ot:71.8" -"source/extensions/tracers/opencensus:93.2" +"source/extensions/tracers/common:74.8" +"source/extensions/tracers/common/ot:72.9" +"source/extensions/tracers/opencensus:94.0" "source/extensions/tracers/zipkin:95.8" "source/extensions/transport_sockets:95.8" "source/extensions/transport_sockets/tls:95.0"