From f5ab2e69b1ade185938ae0856f7aa263f1305045 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 26 Mar 2021 20:30:44 +0200 Subject: [PATCH 01/15] formatter: print request header without query string Signed-off-by: Tero Saarni --- CODEOWNERS | 2 + bazel/envoy_library.bzl | 1 + source/extensions/extensions_build_config.bzl | 6 + .../formatter/req_without_query/BUILD | 36 ++++++ .../formatter/req_without_query/config.cc | 24 ++++ .../formatter/req_without_query/config.h | 19 ++++ .../req_without_query/req_without_query.cc | 90 +++++++++++++++ .../req_without_query/req_without_query.h | 46 ++++++++ .../formatter/req_without_query/BUILD | 28 +++++ .../req_without_query_test.cc | 104 ++++++++++++++++++ 10 files changed, 356 insertions(+) create mode 100644 source/extensions/formatter/req_without_query/BUILD create mode 100644 source/extensions/formatter/req_without_query/config.cc create mode 100644 source/extensions/formatter/req_without_query/config.h create mode 100644 source/extensions/formatter/req_without_query/req_without_query.cc create mode 100644 source/extensions/formatter/req_without_query/req_without_query.h create mode 100644 test/extensions/formatter/req_without_query/BUILD create mode 100644 test/extensions/formatter/req_without_query/req_without_query_test.cc diff --git a/CODEOWNERS b/CODEOWNERS index a0c6e40bc469f..59205804a1f9c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -179,3 +179,5 @@ extensions/filters/http/oauth2 @rgs1 @derekargueta @snowp /*/extensions/filters/common/ext_authz @esmet @gsagula @dio /*/extensions/filters/http/ext_authz @esmet @gsagula @dio /*/extensions/filters/network/ext_authz @esmet @gsagula @dio +# Formatters +/*/extensions/formatter/req_without_query @dio @tsaarni diff --git a/bazel/envoy_library.bzl b/bazel/envoy_library.bzl index 75eb02258235d..3df96c77024e6 100644 --- a/bazel/envoy_library.bzl +++ b/bazel/envoy_library.bzl @@ -77,6 +77,7 @@ EXTENSION_CATEGORIES = [ "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", + "envoy.formatter", "envoy.grpc_credentials", "envoy.guarddog_actions", "envoy.health_checkers", diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index dcc15451a5abc..5f18c8cadc6fb 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -255,6 +255,12 @@ EXTENSIONS = { # "envoy.tls.cert_validator.spiffe": "//source/extensions/transport_sockets/tls/cert_validator/spiffe:config", + + # + # Formatter + # + + "envoy.formatter.req_without_query": "//source/extensions/formatter/req_without_query:config", } # These can be changed to ["//visibility:public"], for downstream builds which diff --git a/source/extensions/formatter/req_without_query/BUILD b/source/extensions/formatter/req_without_query/BUILD new file mode 100644 index 0000000000000..fa81745b76864 --- /dev/null +++ b/source/extensions/formatter/req_without_query/BUILD @@ -0,0 +1,36 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +# Access log formatter that strips query string from request path +# Public docs: docs/root/TODO(tsaarni) + +envoy_cc_library( + name = "req_without_query_lib", + srcs = ["req_without_query.cc"], + hdrs = ["req_without_query.h"], + deps = [ + "//source/common/formatter:substitution_formatter_lib", + "//source/common/protobuf:utility_lib", + ], +) + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + category = "envoy.formatter", + security_posture = "unknown", + status = "alpha", + deps = [ + "//include/envoy/registry", + "//source/extensions/formatter/req_without_query:req_without_query_lib", + ], +) diff --git a/source/extensions/formatter/req_without_query/config.cc b/source/extensions/formatter/req_without_query/config.cc new file mode 100644 index 0000000000000..2cc3a839417d8 --- /dev/null +++ b/source/extensions/formatter/req_without_query/config.cc @@ -0,0 +1,24 @@ +#include "extensions/formatter/req_without_query/config.h" + +#include "extensions/formatter/req_without_query/req_without_query.h" + +namespace Envoy { +namespace Extensions { +namespace Formatter { + +::Envoy::Formatter::CommandParserPtr +ReqWithoutQueryFactory::createCommandParserFromProto(const Protobuf::Message&) { + return std::make_unique(); +} + +ProtobufTypes::MessagePtr ReqWithoutQueryFactory::createEmptyConfigProto() { + return std::make_unique(); +} + +std::string ReqWithoutQueryFactory::name() const { return "envoy.formatter.req_without_query"; } + +REGISTER_FACTORY(ReqWithoutQueryFactory, ReqWithoutQueryFactory::CommandParserFactory); + +} // namespace Formatter +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/formatter/req_without_query/config.h b/source/extensions/formatter/req_without_query/config.h new file mode 100644 index 0000000000000..b15f0aec5b38a --- /dev/null +++ b/source/extensions/formatter/req_without_query/config.h @@ -0,0 +1,19 @@ +#pragma once + +#include "common/formatter/substitution_formatter.h" + +namespace Envoy { +namespace Extensions { +namespace Formatter { + +class ReqWithoutQueryFactory : public ::Envoy::Formatter::CommandParserFactory { +public: + ::Envoy::Formatter::CommandParserPtr + createCommandParserFromProto(const Protobuf::Message&) override; + ProtobufTypes::MessagePtr createEmptyConfigProto() override; + std::string name() const override; +}; + +} // namespace Formatter +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/formatter/req_without_query/req_without_query.cc b/source/extensions/formatter/req_without_query/req_without_query.cc new file mode 100644 index 0000000000000..43ce610277987 --- /dev/null +++ b/source/extensions/formatter/req_without_query/req_without_query.cc @@ -0,0 +1,90 @@ +#include "extensions/formatter/req_without_query/req_without_query.h" + +#include + +#include "common/protobuf/utility.h" + +namespace Envoy { +namespace Extensions { +namespace Formatter { + +void stripQueryString(std::string& path) { + const size_t query_pos = path.find('?'); + path = std::string(path.data(), query_pos != path.npos ? query_pos : path.size()); +} + +void truncate(std::string& str, absl::optional max_length) { + if (!max_length) { + return; + } + + str = str.substr(0, max_length.value()); +} + +ReqWithoutQuery::ReqWithoutQuery(const std::string& main_header, + const std::string& alternative_header, + absl::optional max_length) + : main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {} + +absl::optional ReqWithoutQuery::format(const Http::RequestHeaderMap& request, + const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&, + const StreamInfo::StreamInfo&, + absl::string_view) const { + const Http::HeaderEntry* header = findHeader(request); + if (!header) { + return absl::nullopt; + } + + std::string val = std::string(header->value().getStringView()); + stripQueryString(val); + truncate(val, max_length_); + + return val; +} + +ProtobufWkt::Value ReqWithoutQuery::formatValue(const Http::RequestHeaderMap& request, + const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&, + const StreamInfo::StreamInfo&, + absl::string_view) const { + const Http::HeaderEntry* header = findHeader(request); + if (!header) { + return ValueUtil::nullValue(); + } + + std::string val = std::string(header->value().getStringView()); + stripQueryString(val); + truncate(val, max_length_); + return ValueUtil::stringValue(val); +} + +const Http::HeaderEntry* ReqWithoutQuery::findHeader(const Http::HeaderMap& headers) const { + const auto header = headers.get(main_header_); + + if (header.empty() && !alternative_header_.get().empty()) { + const auto alternate_header = headers.get(alternative_header_); + // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially log all header values. + return alternate_header.empty() ? nullptr : alternate_header[0]; + } + + return header.empty() ? nullptr : header[0]; +} + +::Envoy::Formatter::FormatterProviderPtr +ReqWithoutQueryCommandParser::parse(const std::string& token, size_t, size_t) const { + if (absl::StartsWith(token, "REQ_WITHOUT_QUERY(")) { + std::string main_header, alternative_header; + absl::optional max_length; + + Envoy::Formatter::SubstitutionFormatParser::parseCommandHeader( + token, ReqWithoutQueryParamStart, main_header, alternative_header, max_length); + return std::make_unique(main_header, alternative_header, max_length); + } + + return nullptr; +} + +} // namespace Formatter +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/formatter/req_without_query/req_without_query.h b/source/extensions/formatter/req_without_query/req_without_query.h new file mode 100644 index 0000000000000..96a7b6c9ec3f2 --- /dev/null +++ b/source/extensions/formatter/req_without_query/req_without_query.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include "envoy/config/typed_config.h" +#include "envoy/registry/registry.h" + +#include "common/formatter/substitution_formatter.h" + +namespace Envoy { +namespace Extensions { +namespace Formatter { + +class ReqWithoutQuery : public ::Envoy::Formatter::FormatterProvider { +public: + ReqWithoutQuery(const std::string& main_header, const std::string& alternative_header, + absl::optional max_length); + + absl::optional format(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, + absl::string_view) const override; + ProtobufWkt::Value formatValue(const Http::RequestHeaderMap&, const Http::ResponseHeaderMap&, + const Http::ResponseTrailerMap&, const StreamInfo::StreamInfo&, + absl::string_view) const override; + +private: + const Http::HeaderEntry* findHeader(const Http::HeaderMap& headers) const; + + Http::LowerCaseString main_header_; + Http::LowerCaseString alternative_header_; + absl::optional max_length_; +}; + +class ReqWithoutQueryCommandParser : public ::Envoy::Formatter::CommandParser { +public: + ReqWithoutQueryCommandParser() = default; + ::Envoy::Formatter::FormatterProviderPtr parse(const std::string& token, size_t, + size_t) const override; + +private: + static const size_t ReqWithoutQueryParamStart{sizeof("REQ_WITHOUT_QUERY(") - 1}; +}; + +} // namespace Formatter +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/formatter/req_without_query/BUILD b/test/extensions/formatter/req_without_query/BUILD new file mode 100644 index 0000000000000..cc480a3703349 --- /dev/null +++ b/test/extensions/formatter/req_without_query/BUILD @@ -0,0 +1,28 @@ +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 = "req_without_query_test", + srcs = ["req_without_query_test.cc"], + extension_name = "envoy.formatter.req_without_query", + deps = [ + "//source/common/formatter:substitution_formatter_lib", + "//source/common/json:json_loader_lib", + "//source/extensions/formatter/req_without_query:config", + "//source/extensions/formatter/req_without_query:req_without_query_lib", + "//test/mocks/server:factory_context_mocks", + "//test/mocks/stream_info:stream_info_mocks", + "//test/test_common:test_runtime_lib", + "@envoy_api//envoy/config/core/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc new file mode 100644 index 0000000000000..819eed7b17b98 --- /dev/null +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -0,0 +1,104 @@ +#include "envoy/config/core/v3/substitution_format_string.pb.validate.h" + +#include "common/formatter/substitution_format_string.h" + +#include "test/mocks/server/factory_context.h" +#include "test/mocks/stream_info/mocks.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace Envoy { +namespace Extensions { +namespace Formatter { + +class ReqWithoutQueryTest : public ::testing::Test { +public: + Http::TestRequestHeaderMapImpl request_headers_{ + {":method", "GET"}, + {":path", "/request/path?secret=parameter"}, + {"x-envoy-original-path", "/original/path?secret=parameter"}}; + Http::TestResponseHeaderMapImpl response_headers_; + Http::TestResponseTrailerMapImpl response_trailers_; + StreamInfo::MockStreamInfo stream_info_; + std::string body_; + + envoy::config::core::v3::SubstitutionFormatString config_; + NiceMock context_; +}; + +TEST_F(ReqWithoutQueryTest, TestStripQueryString) { + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%REQ_WITHOUT_QUERY(:PATH)%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, + response_trailers_, stream_info_, body_)); +} + +TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { + + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%REQ_WITHOUT_QUERY(X-ENVOY-ORIGINAL-PATH?:PATH)%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + EXPECT_EQ("/original/path", formatter->format(request_headers_, response_headers_, + response_trailers_, stream_info_, body_)); +} + +TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { + + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%REQ_WITHOUT_QUERY(X-NON-EXISTING-HEADER?:PATH)%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, + response_trailers_, stream_info_, body_)); +} + +TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { + + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%REQ_WITHOUT_QUERY(:PATH):5%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/google.protobuf.StringValue +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + EXPECT_EQ("/requ", formatter->format(request_headers_, response_headers_, response_trailers_, + stream_info_, body_)); +} + +} // namespace Formatter +} // namespace Extensions +} // namespace Envoy From dd0d834776060d59a61415e182e29cf34716731b Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 16 Apr 2021 20:40:38 +0300 Subject: [PATCH 02/15] formatter: empty config proto for req_without_query Signed-off-by: Tero Saarni --- api/BUILD | 1 + api/envoy/config/accesslog/v3/accesslog.proto | 1 + .../config/accesslog/v4alpha/accesslog.proto | 1 + .../formatter/req_without_query/v3/BUILD | 9 +++++++++ .../v3/req_without_query.proto | 18 ++++++++++++++++++ api/versioning/BUILD | 1 + generated_api_shadow/BUILD | 1 + .../envoy/config/accesslog/v3/accesslog.proto | 1 + .../config/accesslog/v4alpha/accesslog.proto | 1 + .../formatter/req_without_query/v3/BUILD | 9 +++++++++ .../v3/req_without_query.proto | 18 ++++++++++++++++++ .../formatter/req_without_query/BUILD | 1 + .../formatter/req_without_query/config.cc | 4 +++- .../req_without_query_test.cc | 8 ++++---- 14 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 api/envoy/extensions/formatter/req_without_query/v3/BUILD create mode 100644 api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto create mode 100644 generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/BUILD create mode 100644 generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto diff --git a/api/BUILD b/api/BUILD index bc8c502662985..ffec247ea39cf 100644 --- a/api/BUILD +++ b/api/BUILD @@ -242,6 +242,7 @@ proto_library( "//envoy/extensions/filters/network/zookeeper_proxy/v3:pkg", "//envoy/extensions/filters/udp/dns_filter/v3alpha:pkg", "//envoy/extensions/filters/udp/udp_proxy/v3:pkg", + "//envoy/extensions/formatter/req_without_query/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/internal_redirect/allow_listed_routes/v3:pkg", "//envoy/extensions/internal_redirect/previous_routes/v3:pkg", diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 883f11274684b..538753e8a5a4f 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -321,6 +321,7 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { + // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index 8aed1a8d4f4a4..687c6dd0f4629 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -320,6 +320,7 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { + // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/api/envoy/extensions/formatter/req_without_query/v3/BUILD b/api/envoy/extensions/formatter/req_without_query/v3/BUILD new file mode 100644 index 0000000000000..ee92fb652582e --- /dev/null +++ b/api/envoy/extensions/formatter/req_without_query/v3/BUILD @@ -0,0 +1,9 @@ +# 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_udpa//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto new file mode 100644 index 0000000000000..02655840cd8bb --- /dev/null +++ b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package envoy.extensions.formatter.req_without_query.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.formatter.req_without_query.v3"; +option java_outer_classname = "ReqWithoutQueryProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Formatter extension for printing request without query string] +// [#extension: envoy.formatter.req_without_query] + +// [#not-implemented-hide:] +// Placeholder for future configuration for the ReqWithoutQuery formatter. +message ReqWithoutQuery { +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 83e85ed89d5af..a87ad2b0ea91b 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -125,6 +125,7 @@ proto_library( "//envoy/extensions/filters/network/zookeeper_proxy/v3:pkg", "//envoy/extensions/filters/udp/dns_filter/v3alpha:pkg", "//envoy/extensions/filters/udp/udp_proxy/v3:pkg", + "//envoy/extensions/formatter/req_without_query/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/internal_redirect/allow_listed_routes/v3:pkg", "//envoy/extensions/internal_redirect/previous_routes/v3:pkg", diff --git a/generated_api_shadow/BUILD b/generated_api_shadow/BUILD index bc8c502662985..ffec247ea39cf 100644 --- a/generated_api_shadow/BUILD +++ b/generated_api_shadow/BUILD @@ -242,6 +242,7 @@ proto_library( "//envoy/extensions/filters/network/zookeeper_proxy/v3:pkg", "//envoy/extensions/filters/udp/dns_filter/v3alpha:pkg", "//envoy/extensions/filters/udp/udp_proxy/v3:pkg", + "//envoy/extensions/formatter/req_without_query/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/internal_redirect/allow_listed_routes/v3:pkg", "//envoy/extensions/internal_redirect/previous_routes/v3:pkg", diff --git a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto index d331e6eb1b54e..0d971ba090b9d 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto @@ -316,6 +316,7 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { + // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; google.protobuf.Struct hidden_envoy_deprecated_config = 2 [deprecated = true]; diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto index 8aed1a8d4f4a4..687c6dd0f4629 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto @@ -320,6 +320,7 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { + // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/BUILD b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/BUILD new file mode 100644 index 0000000000000..ee92fb652582e --- /dev/null +++ b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/BUILD @@ -0,0 +1,9 @@ +# 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_udpa//udpa/annotations:pkg"], +) diff --git a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto new file mode 100644 index 0000000000000..02655840cd8bb --- /dev/null +++ b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package envoy.extensions.formatter.req_without_query.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.formatter.req_without_query.v3"; +option java_outer_classname = "ReqWithoutQueryProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Formatter extension for printing request without query string] +// [#extension: envoy.formatter.req_without_query] + +// [#not-implemented-hide:] +// Placeholder for future configuration for the ReqWithoutQuery formatter. +message ReqWithoutQuery { +} diff --git a/source/extensions/formatter/req_without_query/BUILD b/source/extensions/formatter/req_without_query/BUILD index fa81745b76864..46e231ae6716a 100644 --- a/source/extensions/formatter/req_without_query/BUILD +++ b/source/extensions/formatter/req_without_query/BUILD @@ -32,5 +32,6 @@ envoy_cc_extension( deps = [ "//include/envoy/registry", "//source/extensions/formatter/req_without_query:req_without_query_lib", + "@envoy_api//envoy/extensions/formatter/req_without_query/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/formatter/req_without_query/config.cc b/source/extensions/formatter/req_without_query/config.cc index 2cc3a839417d8..7d0a6d663df95 100644 --- a/source/extensions/formatter/req_without_query/config.cc +++ b/source/extensions/formatter/req_without_query/config.cc @@ -1,5 +1,7 @@ #include "extensions/formatter/req_without_query/config.h" +#include "envoy/extensions/formatter/req_without_query/v3/req_without_query.pb.h" + #include "extensions/formatter/req_without_query/req_without_query.h" namespace Envoy { @@ -12,7 +14,7 @@ ReqWithoutQueryFactory::createCommandParserFromProto(const Protobuf::Message&) { } ProtobufTypes::MessagePtr ReqWithoutQueryFactory::createEmptyConfigProto() { - return std::make_unique(); + return std::make_unique(); } std::string ReqWithoutQueryFactory::name() const { return "envoy.formatter.req_without_query"; } diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index 819eed7b17b98..3080937726b68 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -35,7 +35,7 @@ TEST_F(ReqWithoutQueryTest, TestStripQueryString) { formatters: - name: envoy.formatter.req_without_query typed_config: - "@type": type.googleapis.com/google.protobuf.StringValue + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery )EOF"; TestUtility::loadFromYaml(yaml, config_); @@ -53,7 +53,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { formatters: - name: envoy.formatter.req_without_query typed_config: - "@type": type.googleapis.com/google.protobuf.StringValue + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery )EOF"; TestUtility::loadFromYaml(yaml, config_); @@ -71,7 +71,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { formatters: - name: envoy.formatter.req_without_query typed_config: - "@type": type.googleapis.com/google.protobuf.StringValue + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery )EOF"; TestUtility::loadFromYaml(yaml, config_); @@ -89,7 +89,7 @@ TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { formatters: - name: envoy.formatter.req_without_query typed_config: - "@type": type.googleapis.com/google.protobuf.StringValue + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery )EOF"; TestUtility::loadFromYaml(yaml, config_); From ff3080cd0d138275522065ffe0d8e992fa1b9156 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Sun, 18 Apr 2021 18:48:13 +0300 Subject: [PATCH 03/15] formatter: documentation for req_without_query Signed-off-by: Tero Saarni --- api/envoy/config/accesslog/v3/accesslog.proto | 1 - api/envoy/config/accesslog/v4alpha/accesslog.proto | 1 - .../config/core/v3/substitution_format_string.proto | 1 + .../core/v4alpha/substitution_format_string.proto | 1 + .../req_without_query/v3/req_without_query.proto | 11 +++++++++++ .../configuration/observability/access_log/usage.rst | 2 ++ .../envoy/config/accesslog/v3/accesslog.proto | 1 - .../envoy/config/accesslog/v4alpha/accesslog.proto | 1 - .../config/core/v3/substitution_format_string.proto | 1 + .../core/v4alpha/substitution_format_string.proto | 1 + .../req_without_query/v3/req_without_query.proto | 11 +++++++++++ 11 files changed, 28 insertions(+), 4 deletions(-) diff --git a/api/envoy/config/accesslog/v3/accesslog.proto b/api/envoy/config/accesslog/v3/accesslog.proto index 538753e8a5a4f..883f11274684b 100644 --- a/api/envoy/config/accesslog/v3/accesslog.proto +++ b/api/envoy/config/accesslog/v3/accesslog.proto @@ -321,7 +321,6 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { - // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/api/envoy/config/accesslog/v4alpha/accesslog.proto b/api/envoy/config/accesslog/v4alpha/accesslog.proto index 687c6dd0f4629..8aed1a8d4f4a4 100644 --- a/api/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/api/envoy/config/accesslog/v4alpha/accesslog.proto @@ -320,7 +320,6 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { - // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/api/envoy/config/core/v3/substitution_format_string.proto b/api/envoy/config/core/v3/substitution_format_string.proto index 5d9c5b2ecd046..40b1a886202be 100644 --- a/api/envoy/config/core/v3/substitution_format_string.proto +++ b/api/envoy/config/core/v3/substitution_format_string.proto @@ -107,5 +107,6 @@ message SubstitutionFormatString { // Specifies a collection of Formatter plugins that can be called from the access log configuration. // See the formatters extensions documentation for details. + // [#extension-category: envoy.formatter] repeated TypedExtensionConfig formatters = 6; } diff --git a/api/envoy/config/core/v4alpha/substitution_format_string.proto b/api/envoy/config/core/v4alpha/substitution_format_string.proto index 36b25da75b8e4..6f5037f5f1770 100644 --- a/api/envoy/config/core/v4alpha/substitution_format_string.proto +++ b/api/envoy/config/core/v4alpha/substitution_format_string.proto @@ -96,5 +96,6 @@ message SubstitutionFormatString { // Specifies a collection of Formatter plugins that can be called from the access log configuration. // See the formatters extensions documentation for details. + // [#extension-category: envoy.formatter] repeated TypedExtensionConfig formatters = 6; } diff --git a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 02655840cd8bb..73a3ce67ac4a2 100644 --- a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -12,6 +12,17 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Formatter extension for printing request without query string] // [#extension: envoy.formatter.req_without_query] +// ReqWithoutQuery formatter extension implements REQ_WITHOUT_QUERY command operator that +// works the same way as :ref:`REQ ` except that it will +// remove the query string. It is used to avoid logging any sensitive information into +// the access log. + +// %REQ_WITHOUT_QUERY(X?Y):Z% +// An HTTP request header where X is the main HTTP header, Y is the alternative one, and Z is an +// optional parameter denoting string truncation up to Z characters long. The value is taken from +// the HTTP request header named X first and if it's not set, then request header Y is used. If +// none of the headers are present '-' symbol will be in the log. + // [#not-implemented-hide:] // Placeholder for future configuration for the ReqWithoutQuery formatter. message ReqWithoutQuery { diff --git a/docs/root/configuration/observability/access_log/usage.rst b/docs/root/configuration/observability/access_log/usage.rst index 4eb2b0b8e7b5a..5baf95a62c303 100644 --- a/docs/root/configuration/observability/access_log/usage.rst +++ b/docs/root/configuration/observability/access_log/usage.rst @@ -407,6 +407,8 @@ The following command operators are supported: %DOWNSTREAM_LOCAL_PORT% Similar to **%DOWNSTREAM_LOCAL_ADDRESS_WITHOUT_PORT%**, but only extracts the port portion of the **%DOWNSTREAM_LOCAL_ADDRESS%** +.. _config_access_log_format_req: + %REQ(X?Y):Z% HTTP An HTTP request header where X is the main HTTP header, Y is the alternative one, and Z is an diff --git a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto index 0d971ba090b9d..d331e6eb1b54e 100644 --- a/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v3/accesslog.proto @@ -316,7 +316,6 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { - // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; google.protobuf.Struct hidden_envoy_deprecated_config = 2 [deprecated = true]; diff --git a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto index 687c6dd0f4629..8aed1a8d4f4a4 100644 --- a/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto +++ b/generated_api_shadow/envoy/config/accesslog/v4alpha/accesslog.proto @@ -320,7 +320,6 @@ message ExtensionFilter { // Custom configuration that depends on the filter being instantiated. oneof config_type { - // [#extension-category: envoy.formatter] google.protobuf.Any typed_config = 3; } } diff --git a/generated_api_shadow/envoy/config/core/v3/substitution_format_string.proto b/generated_api_shadow/envoy/config/core/v3/substitution_format_string.proto index 5d9c5b2ecd046..40b1a886202be 100644 --- a/generated_api_shadow/envoy/config/core/v3/substitution_format_string.proto +++ b/generated_api_shadow/envoy/config/core/v3/substitution_format_string.proto @@ -107,5 +107,6 @@ message SubstitutionFormatString { // Specifies a collection of Formatter plugins that can be called from the access log configuration. // See the formatters extensions documentation for details. + // [#extension-category: envoy.formatter] repeated TypedExtensionConfig formatters = 6; } diff --git a/generated_api_shadow/envoy/config/core/v4alpha/substitution_format_string.proto b/generated_api_shadow/envoy/config/core/v4alpha/substitution_format_string.proto index c52202579212c..c97394a9a4e8e 100644 --- a/generated_api_shadow/envoy/config/core/v4alpha/substitution_format_string.proto +++ b/generated_api_shadow/envoy/config/core/v4alpha/substitution_format_string.proto @@ -111,5 +111,6 @@ message SubstitutionFormatString { // Specifies a collection of Formatter plugins that can be called from the access log configuration. // See the formatters extensions documentation for details. + // [#extension-category: envoy.formatter] repeated TypedExtensionConfig formatters = 6; } diff --git a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 02655840cd8bb..73a3ce67ac4a2 100644 --- a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -12,6 +12,17 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Formatter extension for printing request without query string] // [#extension: envoy.formatter.req_without_query] +// ReqWithoutQuery formatter extension implements REQ_WITHOUT_QUERY command operator that +// works the same way as :ref:`REQ ` except that it will +// remove the query string. It is used to avoid logging any sensitive information into +// the access log. + +// %REQ_WITHOUT_QUERY(X?Y):Z% +// An HTTP request header where X is the main HTTP header, Y is the alternative one, and Z is an +// optional parameter denoting string truncation up to Z characters long. The value is taken from +// the HTTP request header named X first and if it's not set, then request header Y is used. If +// none of the headers are present '-' symbol will be in the log. + // [#not-implemented-hide:] // Placeholder for future configuration for the ReqWithoutQuery formatter. message ReqWithoutQuery { From dfd49a53b92d0fe5b503fc8ba4ea41da94e9f8f1 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Thu, 22 Apr 2021 18:39:35 +0300 Subject: [PATCH 04/15] utility: helper for getting path without request string Signed-off-by: Tero Saarni --- source/common/http/utility.cc | 7 +++++++ source/common/http/utility.h | 7 +++++++ .../formatter/req_without_query/req_without_query.cc | 12 +++--------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/source/common/http/utility.cc b/source/common/http/utility.cc index e2a39c3aaf51a..1515224ac1dbc 100644 --- a/source/common/http/utility.cc +++ b/source/common/http/utility.cc @@ -379,6 +379,13 @@ absl::string_view Utility::findQueryStringStart(const HeaderString& path) { return path_str; } +std::string Utility::stripQueryString(const HeaderString& path) { + absl::string_view path_str = path.getStringView(); + size_t query_offset = path_str.find('?'); + return std::string(path_str.data(), + query_offset != path_str.npos ? query_offset : path_str.size()); +} + std::string Utility::parseCookieValue(const HeaderMap& headers, const std::string& key) { std::string ret; diff --git a/source/common/http/utility.h b/source/common/http/utility.h index 7d2a065bcb372..86db361706c5c 100644 --- a/source/common/http/utility.h +++ b/source/common/http/utility.h @@ -230,6 +230,13 @@ QueryParams parseParameters(absl::string_view data, size_t start, bool decode_pa */ absl::string_view findQueryStringStart(const HeaderString& path); +/** + * Returns the path without the query string. + * @param path supplies a HeaderString& possibly containing a query string. + * @return std::string the path without query string. + */ +std::string stripQueryString(const HeaderString& path); + /** * Parse a particular value out of a cookie * @param headers supplies the headers to get the cookie from. diff --git a/source/extensions/formatter/req_without_query/req_without_query.cc b/source/extensions/formatter/req_without_query/req_without_query.cc index 43ce610277987..17e4a6bf16609 100644 --- a/source/extensions/formatter/req_without_query/req_without_query.cc +++ b/source/extensions/formatter/req_without_query/req_without_query.cc @@ -2,17 +2,13 @@ #include +#include "common/http/utility.h" #include "common/protobuf/utility.h" namespace Envoy { namespace Extensions { namespace Formatter { -void stripQueryString(std::string& path) { - const size_t query_pos = path.find('?'); - path = std::string(path.data(), query_pos != path.npos ? query_pos : path.size()); -} - void truncate(std::string& str, absl::optional max_length) { if (!max_length) { return; @@ -36,8 +32,7 @@ absl::optional ReqWithoutQuery::format(const Http::RequestHeaderMap return absl::nullopt; } - std::string val = std::string(header->value().getStringView()); - stripQueryString(val); + std::string val = Http::Utility::stripQueryString(header->value()); truncate(val, max_length_); return val; @@ -53,8 +48,7 @@ ProtobufWkt::Value ReqWithoutQuery::formatValue(const Http::RequestHeaderMap& re return ValueUtil::nullValue(); } - std::string val = std::string(header->value().getStringView()); - stripQueryString(val); + std::string val = Http::Utility::stripQueryString(header->value()); truncate(val, max_length_); return ValueUtil::stringValue(val); } From d601684eb291aec2276298bbb10c446dd818701d Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Sat, 24 Apr 2021 14:51:23 +0300 Subject: [PATCH 05/15] formatter: improved test coverage for req_without_query Signed-off-by: Tero Saarni --- source/extensions/extensions_build_config.bzl | 7 +-- .../req_without_query_test.cc | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index f2082d824acf5..eedddeb8affa9 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -268,12 +268,13 @@ EXTENSIONS = { # # HTTP header formatters # - # Formatter - # + + "envoy.http.stateful_header_formatters.preserve_case": "//source/extensions/http/header_formatters/preserve_case:preserve_case_formatter", + # + # Formatter # - "envoy.http.stateful_header_formatters.preserve_case": "//source/extensions/http/header_formatters/preserve_case:preserve_case_formatter", "envoy.formatter.req_without_query": "//source/extensions/formatter/req_without_query:config", } diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index 3080937726b68..1619cb65467ed 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -1,6 +1,7 @@ #include "envoy/config/core/v3/substitution_format_string.pb.validate.h" #include "common/formatter/substitution_format_string.h" +#include "common/formatter/substitution_formatter.h" #include "test/mocks/server/factory_context.h" #include "test/mocks/stream_info/mocks.h" @@ -99,6 +100,53 @@ TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { stream_info_, body_)); } +TEST_F(ReqWithoutQueryTest, TestNonExistingHeader) { + + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%REQ_WITHOUT_QUERY(does-not-exist)%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + EXPECT_EQ("-", formatter->format(request_headers_, response_headers_, response_trailers_, + stream_info_, body_)); +} + +TEST_F(ReqWithoutQueryTest, TestFormatJson) { + const std::string yaml = R"EOF( + json_format: + no_query: "%REQ_WITHOUT_QUERY(:PATH)%" + select_main_header: "%REQ_WITHOUT_QUERY(X-ENVOY-ORIGINAL-PATH?:PATH)%" + select_alt_header: "%REQ_WITHOUT_QUERY(X-NON-EXISTING-HEADER?:PATH)%" + truncate: "%REQ_WITHOUT_QUERY(:PATH):5%" + does_not_exist: "%REQ_WITHOUT_QUERY(does-not-exist)%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery +)EOF"; + const std::string expected = R"EOF({ + "no_query": "/request/path", + "select_main_header": "/original/path", + "select_alt_header": "/request/path", + "truncate": "/requ", + "does_not_exist": null +})EOF"; + + TestUtility::loadFromYaml(yaml, config_); + auto formatter = + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + const std::string actual = formatter->format(request_headers_, response_headers_, + response_trailers_, stream_info_, body_); + EXPECT_TRUE(TestUtility::jsonStringEqual(actual, expected)); +} + } // namespace Formatter } // namespace Extensions } // namespace Envoy From c9218bdd5e8b6efd254525065464738eb59d0bdb Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Sat, 24 Apr 2021 21:24:33 +0300 Subject: [PATCH 06/15] formatter: 100% test coverage for req_without_query Signed-off-by: Tero Saarni --- .../req_without_query/req_without_query_test.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index 1619cb65467ed..7db45a6c91b2e 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -147,6 +147,23 @@ TEST_F(ReqWithoutQueryTest, TestFormatJson) { EXPECT_TRUE(TestUtility::jsonStringEqual(actual, expected)); } +TEST_F(ReqWithoutQueryTest, TestParserNotRecognizingCommand) { + + const std::string yaml = R"EOF( + text_format_source: + inline_string: "%COMMAND_THAT_DOES_NOT_EXIST()%" + formatters: + - name: envoy.formatter.req_without_query + typed_config: + "@type": type.googleapis.com/envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery +)EOF"; + TestUtility::loadFromYaml(yaml, config_); + + EXPECT_THROW( + ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()), + EnvoyException); +} + } // namespace Formatter } // namespace Extensions } // namespace Envoy From d17be60c604fcaba3b9aeba82fe65052a076f20c Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Tue, 25 May 2021 13:49:12 +0300 Subject: [PATCH 07/15] formatter: moved helper function to anoymous namespace Signed-off-by: Tero Saarni --- .../formatter/req_without_query/req_without_query.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/extensions/formatter/req_without_query/req_without_query.cc b/source/extensions/formatter/req_without_query/req_without_query.cc index 17e4a6bf16609..d84fe2492754a 100644 --- a/source/extensions/formatter/req_without_query/req_without_query.cc +++ b/source/extensions/formatter/req_without_query/req_without_query.cc @@ -9,6 +9,8 @@ namespace Envoy { namespace Extensions { namespace Formatter { +namespace { + void truncate(std::string& str, absl::optional max_length) { if (!max_length) { return; @@ -17,6 +19,8 @@ void truncate(std::string& str, absl::optional max_length) { str = str.substr(0, max_length.value()); } +} // namespace + ReqWithoutQuery::ReqWithoutQuery(const std::string& main_header, const std::string& alternative_header, absl::optional max_length) From bd7b0a2ef4f1ca73aa0bc76d42ac3728092f2dba Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Mon, 31 May 2021 18:22:27 +0300 Subject: [PATCH 08/15] formatter: updated after review Signed-off-by: Tero Saarni --- .../req_without_query/v3/req_without_query.proto | 1 - .../req_without_query/v3/req_without_query.proto | 1 - source/extensions/extensions_metadata.yaml | 5 +++++ .../extensions/formatter/req_without_query/BUILD | 3 --- .../req_without_query/req_without_query_test.cc | 14 +++++++------- tools/extensions/validate_extensions.py | 1 + 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 73a3ce67ac4a2..8a58b2a4cf6fc 100644 --- a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -23,7 +23,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // the HTTP request header named X first and if it's not set, then request header Y is used. If // none of the headers are present '-' symbol will be in the log. -// [#not-implemented-hide:] // Placeholder for future configuration for the ReqWithoutQuery formatter. message ReqWithoutQuery { } diff --git a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 73a3ce67ac4a2..8a58b2a4cf6fc 100644 --- a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -23,7 +23,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // the HTTP request header named X first and if it's not set, then request header Y is used. If // none of the headers are present '-' symbol will be in the log. -// [#not-implemented-hide:] // Placeholder for future configuration for the ReqWithoutQuery formatter. message ReqWithoutQuery { } diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 56570a9404282..295d10771b5a5 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -428,6 +428,11 @@ envoy.filters.udp_listener.udp_proxy: - envoy.filters.udp_listener security_posture: robust_to_untrusted_downstream status: stable +envoy.formatter.req_without_query: + categories: + - envoy.formatter + security_posture: unknown + status: alpha envoy.grpc_credentials.aws_iam: categories: - envoy.grpc_credentials diff --git a/source/extensions/formatter/req_without_query/BUILD b/source/extensions/formatter/req_without_query/BUILD index 46e231ae6716a..2b80cc63d51ce 100644 --- a/source/extensions/formatter/req_without_query/BUILD +++ b/source/extensions/formatter/req_without_query/BUILD @@ -26,9 +26,6 @@ envoy_cc_extension( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], - category = "envoy.formatter", - security_posture = "unknown", - status = "alpha", deps = [ "//include/envoy/registry", "//source/extensions/formatter/req_without_query:req_without_query_lib", diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index 7db45a6c91b2e..c891b94b1a29a 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -41,7 +41,7 @@ TEST_F(ReqWithoutQueryTest, TestStripQueryString) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -59,7 +59,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); EXPECT_EQ("/original/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -77,7 +77,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -95,7 +95,7 @@ TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); EXPECT_EQ("/requ", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -113,7 +113,7 @@ TEST_F(ReqWithoutQueryTest, TestNonExistingHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); EXPECT_EQ("-", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -141,7 +141,7 @@ TEST_F(ReqWithoutQueryTest, TestFormatJson) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); const std::string actual = formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_); EXPECT_TRUE(TestUtility::jsonStringEqual(actual, expected)); @@ -160,7 +160,7 @@ TEST_F(ReqWithoutQueryTest, TestParserNotRecognizingCommand) { TestUtility::loadFromYaml(yaml, config_); EXPECT_THROW( - ::Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()), + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()), EnvoyException); } diff --git a/tools/extensions/validate_extensions.py b/tools/extensions/validate_extensions.py index 8140c3e56f674..9715b4ce2d57a 100644 --- a/tools/extensions/validate_extensions.py +++ b/tools/extensions/validate_extensions.py @@ -51,6 +51,7 @@ "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", + "envoy.formatter", "envoy.grpc_credentials", "envoy.guarddog_actions", "envoy.health_checkers", From 190253ec1929e7d0b362ea49b7d8bddea1caab92 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Tue, 1 Jun 2021 17:27:01 +0300 Subject: [PATCH 09/15] formatter: fixed broken documentation Signed-off-by: Tero Saarni --- .../req_without_query/v3/req_without_query.proto | 3 ++- docs/root/api-v3/config/config.rst | 1 + docs/root/api-v3/config/formatter/formatter.rst | 10 ++++++++++ .../req_without_query/v3/req_without_query.proto | 3 ++- 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 docs/root/api-v3/config/formatter/formatter.rst diff --git a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 8a58b2a4cf6fc..e1b6c32a97e66 100644 --- a/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/api/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -16,6 +16,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // works the same way as :ref:`REQ ` except that it will // remove the query string. It is used to avoid logging any sensitive information into // the access log. +// See :ref:`here ` for more information on access log configuration. // %REQ_WITHOUT_QUERY(X?Y):Z% // An HTTP request header where X is the main HTTP header, Y is the alternative one, and Z is an @@ -23,6 +24,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // the HTTP request header named X first and if it's not set, then request header Y is used. If // none of the headers are present '-' symbol will be in the log. -// Placeholder for future configuration for the ReqWithoutQuery formatter. +// Configuration for the request without query formatter. message ReqWithoutQuery { } diff --git a/docs/root/api-v3/config/config.rst b/docs/root/api-v3/config/config.rst index 712ed03fa278d..03487e0f501e3 100644 --- a/docs/root/api-v3/config/config.rst +++ b/docs/root/api-v3/config/config.rst @@ -28,3 +28,4 @@ Extensions request_id/request_id http/header_formatters http/original_ip_detection + formatter/formatter diff --git a/docs/root/api-v3/config/formatter/formatter.rst b/docs/root/api-v3/config/formatter/formatter.rst new file mode 100644 index 0000000000000..b240b2c89f10d --- /dev/null +++ b/docs/root/api-v3/config/formatter/formatter.rst @@ -0,0 +1,10 @@ +.. _api-v3_config_accesslog_formatters: + +Access log formatters +===================== + +.. toctree:: + :glob: + :maxdepth: 2 + + ../../extensions/formatter/*/v3/* diff --git a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto index 8a58b2a4cf6fc..e1b6c32a97e66 100644 --- a/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto +++ b/generated_api_shadow/envoy/extensions/formatter/req_without_query/v3/req_without_query.proto @@ -16,6 +16,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // works the same way as :ref:`REQ ` except that it will // remove the query string. It is used to avoid logging any sensitive information into // the access log. +// See :ref:`here ` for more information on access log configuration. // %REQ_WITHOUT_QUERY(X?Y):Z% // An HTTP request header where X is the main HTTP header, Y is the alternative one, and Z is an @@ -23,6 +24,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // the HTTP request header named X first and if it's not set, then request header Y is used. If // none of the headers are present '-' symbol will be in the log. -// Placeholder for future configuration for the ReqWithoutQuery formatter. +// Configuration for the request without query formatter. message ReqWithoutQuery { } From dd2eb362b5984d98c6298cb17eb8f96f540371ed Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Tue, 8 Jun 2021 09:11:33 +0300 Subject: [PATCH 10/15] formatter: updated with the new include paths Signed-off-by: Tero Saarni --- source/extensions/formatter/req_without_query/BUILD | 2 +- source/extensions/formatter/req_without_query/config.cc | 4 ++-- source/extensions/formatter/req_without_query/config.h | 2 +- .../formatter/req_without_query/req_without_query.cc | 6 +++--- .../formatter/req_without_query/req_without_query.h | 2 +- .../formatter/req_without_query/req_without_query_test.cc | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/extensions/formatter/req_without_query/BUILD b/source/extensions/formatter/req_without_query/BUILD index 2b80cc63d51ce..45c8ee111559e 100644 --- a/source/extensions/formatter/req_without_query/BUILD +++ b/source/extensions/formatter/req_without_query/BUILD @@ -27,7 +27,7 @@ envoy_cc_extension( srcs = ["config.cc"], hdrs = ["config.h"], deps = [ - "//include/envoy/registry", + "//envoy/registry", "//source/extensions/formatter/req_without_query:req_without_query_lib", "@envoy_api//envoy/extensions/formatter/req_without_query/v3:pkg_cc_proto", ], diff --git a/source/extensions/formatter/req_without_query/config.cc b/source/extensions/formatter/req_without_query/config.cc index 7d0a6d663df95..76035de469515 100644 --- a/source/extensions/formatter/req_without_query/config.cc +++ b/source/extensions/formatter/req_without_query/config.cc @@ -1,8 +1,8 @@ -#include "extensions/formatter/req_without_query/config.h" +#include "source/extensions/formatter/req_without_query/config.h" #include "envoy/extensions/formatter/req_without_query/v3/req_without_query.pb.h" -#include "extensions/formatter/req_without_query/req_without_query.h" +#include "source/extensions/formatter/req_without_query/req_without_query.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/formatter/req_without_query/config.h b/source/extensions/formatter/req_without_query/config.h index b15f0aec5b38a..71b33f3904b06 100644 --- a/source/extensions/formatter/req_without_query/config.h +++ b/source/extensions/formatter/req_without_query/config.h @@ -1,6 +1,6 @@ #pragma once -#include "common/formatter/substitution_formatter.h" +#include "source/common/formatter/substitution_formatter.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/formatter/req_without_query/req_without_query.cc b/source/extensions/formatter/req_without_query/req_without_query.cc index d84fe2492754a..d0fb6580b4423 100644 --- a/source/extensions/formatter/req_without_query/req_without_query.cc +++ b/source/extensions/formatter/req_without_query/req_without_query.cc @@ -1,9 +1,9 @@ -#include "extensions/formatter/req_without_query/req_without_query.h" +#include "source/extensions/formatter/req_without_query/req_without_query.h" #include -#include "common/http/utility.h" -#include "common/protobuf/utility.h" +#include "source/common/http/utility.h" +#include "source/common/protobuf/utility.h" namespace Envoy { namespace Extensions { diff --git a/source/extensions/formatter/req_without_query/req_without_query.h b/source/extensions/formatter/req_without_query/req_without_query.h index 96a7b6c9ec3f2..4fd000351a64c 100644 --- a/source/extensions/formatter/req_without_query/req_without_query.h +++ b/source/extensions/formatter/req_without_query/req_without_query.h @@ -5,7 +5,7 @@ #include "envoy/config/typed_config.h" #include "envoy/registry/registry.h" -#include "common/formatter/substitution_formatter.h" +#include "source/common/formatter/substitution_formatter.h" namespace Envoy { namespace Extensions { diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index c891b94b1a29a..9712c1d7c54eb 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -1,7 +1,7 @@ #include "envoy/config/core/v3/substitution_format_string.pb.validate.h" -#include "common/formatter/substitution_format_string.h" -#include "common/formatter/substitution_formatter.h" +#include "source/common/formatter/substitution_format_string.h" +#include "source/common/formatter/substitution_formatter.h" #include "test/mocks/server/factory_context.h" #include "test/mocks/stream_info/mocks.h" From c4e28c7fd346226544421cf1973a89a925504896 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Tue, 8 Jun 2021 13:53:48 +0300 Subject: [PATCH 11/15] docs: updated version history with info about new formatter extension Signed-off-by: Tero Saarni --- docs/root/version_history/current.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 3e88b63f3c90b..766c6d3a27d53 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -92,6 +92,7 @@ New Features * metric service: added support for sending metric tags as labels. This can be enabled by setting the :ref:`emit_tags_as_labels ` field to true. * proxy protocol: added support for generating the header while using the :ref:`HTTP connection manager `. This is done using the using the :ref:`Proxy Protocol Transport Socket ` on upstream clusters. This feature is currently affected by a memory leak `issue `_. +* req_without_query: added access log formatter extension implementing command operator :ref:`REQ_WITHOUT_QUERY ` to log the request path, while excluding the query string. * tcp: added support for :ref:`preconnecting `. Preconnecting is off by default, but recommended for clusters serving latency-sensitive traffic. * thrift_proxy: added per upstream metrics within the :ref:`thrift router ` for request and response size histograms. * tls: allow dual ECDSA/RSA certs via SDS. Previously, SDS only supported a single certificate per context, and dual cert was only supported via non-SDS. From d49a6f51aa05170a6f8aefe0abf3cbdce823b19a Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Wed, 9 Jun 2021 09:52:50 +0300 Subject: [PATCH 12/15] formatter: changed the security posture of req_without_query Signed-off-by: Tero Saarni --- source/extensions/extensions_metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index be25859b3c6ea..560518fbbe12e 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -431,7 +431,7 @@ envoy.filters.udp_listener.udp_proxy: envoy.formatter.req_without_query: categories: - envoy.formatter - security_posture: unknown + security_posture: robust_to_untrusted_downstream_and_upstream status: alpha envoy.grpc_credentials.aws_iam: categories: From b16deb1700a522577d4afdd450194d4ce2efa6e9 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 11 Jun 2021 08:33:55 +0300 Subject: [PATCH 13/15] tools: add formatter extension category Signed-off-by: Tero Saarni --- tools/extensions/extensions_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/extensions/extensions_check.py b/tools/extensions/extensions_check.py index fde5752799b25..96f80dff2c0bd 100644 --- a/tools/extensions/extensions_check.py +++ b/tools/extensions/extensions_check.py @@ -45,7 +45,7 @@ EXTENSION_CATEGORIES = ( "envoy.access_loggers", "envoy.bootstrap", "envoy.clusters", "envoy.compression.compressor", "envoy.compression.decompressor", "envoy.filters.http", "envoy.filters.http.cache", - "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", + "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", "envoy.formatter", "envoy.grpc_credentials", "envoy.guarddog_actions", "envoy.health_checkers", "envoy.http.stateful_header_formatters", "envoy.internal_redirect_predicates", "envoy.io_socket", "envoy.http.original_ip_detection", "envoy.matching.common_inputs", From 708c3465ae6da8a4f59ae837cf0a96e089f50148 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 11 Jun 2021 09:53:41 +0300 Subject: [PATCH 14/15] formatter: updated req_without_query tests Signed-off-by: Tero Saarni --- .../req_without_query/req_without_query_test.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/extensions/formatter/req_without_query/req_without_query_test.cc b/test/extensions/formatter/req_without_query/req_without_query_test.cc index 9712c1d7c54eb..e4a1695625be8 100644 --- a/test/extensions/formatter/req_without_query/req_without_query_test.cc +++ b/test/extensions/formatter/req_without_query/req_without_query_test.cc @@ -41,7 +41,7 @@ TEST_F(ReqWithoutQueryTest, TestStripQueryString) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -59,7 +59,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectMainHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/original/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -77,7 +77,7 @@ TEST_F(ReqWithoutQueryTest, TestSelectAlternativeHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/request/path", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -95,7 +95,7 @@ TEST_F(ReqWithoutQueryTest, TestTruncateHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("/requ", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -113,7 +113,7 @@ TEST_F(ReqWithoutQueryTest, TestNonExistingHeader) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); EXPECT_EQ("-", formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_)); } @@ -141,7 +141,7 @@ TEST_F(ReqWithoutQueryTest, TestFormatJson) { TestUtility::loadFromYaml(yaml, config_); auto formatter = - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()); + Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_); const std::string actual = formatter->format(request_headers_, response_headers_, response_trailers_, stream_info_, body_); EXPECT_TRUE(TestUtility::jsonStringEqual(actual, expected)); @@ -159,9 +159,8 @@ TEST_F(ReqWithoutQueryTest, TestParserNotRecognizingCommand) { )EOF"; TestUtility::loadFromYaml(yaml, config_); - EXPECT_THROW( - Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_.api()), - EnvoyException); + EXPECT_THROW(Envoy::Formatter::SubstitutionFormatStringUtils::fromProtoConfig(config_, context_), + EnvoyException); } } // namespace Formatter From 91d717d266e88e03a2e54b48ca1775b0755e3776 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Fri, 11 Jun 2021 12:54:41 +0300 Subject: [PATCH 15/15] tools: fixed code formatting after adding new extension Signed-off-by: Tero Saarni --- tools/extensions/extensions_check.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/extensions/extensions_check.py b/tools/extensions/extensions_check.py index 96f80dff2c0bd..b3e0b6865c608 100644 --- a/tools/extensions/extensions_check.py +++ b/tools/extensions/extensions_check.py @@ -45,8 +45,8 @@ EXTENSION_CATEGORIES = ( "envoy.access_loggers", "envoy.bootstrap", "envoy.clusters", "envoy.compression.compressor", "envoy.compression.decompressor", "envoy.filters.http", "envoy.filters.http.cache", - "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", "envoy.formatter", - "envoy.grpc_credentials", "envoy.guarddog_actions", "envoy.health_checkers", + "envoy.filters.listener", "envoy.filters.network", "envoy.filters.udp_listener", + "envoy.formatter", "envoy.grpc_credentials", "envoy.guarddog_actions", "envoy.health_checkers", "envoy.http.stateful_header_formatters", "envoy.internal_redirect_predicates", "envoy.io_socket", "envoy.http.original_ip_detection", "envoy.matching.common_inputs", "envoy.matching.input_matchers", "envoy.quic.proof_source", "envoy.quic.server.crypto_stream",