diff --git a/CODEOWNERS b/CODEOWNERS index 8b206bb0f1c74..3c6ccecfac91c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -80,6 +80,8 @@ extensions/filters/common/original_src @snowp @klarose /*/extensions/filters/common/expr @kyessenov @yangminzhu @lizan # webassembly common extension /*/extensions/common/wasm @jplevyak @PiotrSikora @lizan +# common matcher +/*/extensions/common/matcher @mattklein123 @yangminzhu # common crypto extension /*/extensions/common/crypto @lizan @PiotrSikora @bdecoste /*/extensions/common/proxy_protocol @alyssawilk @wez470 diff --git a/api/BUILD b/api/BUILD index 3ac2738ebc3e4..99bd1b119c62a 100644 --- a/api/BUILD +++ b/api/BUILD @@ -130,6 +130,7 @@ proto_library( "//envoy/config/accesslog/v3:pkg", "//envoy/config/bootstrap/v3:pkg", "//envoy/config/cluster/v3:pkg", + "//envoy/config/common/matcher/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/config/endpoint/v3:pkg", "//envoy/config/filter/thrift/router/v2alpha1:pkg", diff --git a/api/envoy/config/common/matcher/v3/BUILD b/api/envoy/config/common/matcher/v3/BUILD new file mode 100644 index 0000000000000..c312b8eb6a613 --- /dev/null +++ b/api/envoy/config/common/matcher/v3/BUILD @@ -0,0 +1,12 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/config/route/v3:pkg", + "@com_github_cncf_udpa//udpa/annotations:pkg", + ], +) diff --git a/api/envoy/config/common/matcher/v3/matcher.proto b/api/envoy/config/common/matcher/v3/matcher.proto new file mode 100644 index 0000000000000..d0955e7a1f8c1 --- /dev/null +++ b/api/envoy/config/common/matcher/v3/matcher.proto @@ -0,0 +1,100 @@ +syntax = "proto3"; + +package envoy.config.common.matcher.v3; + +import "envoy/config/route/v3/route_components.proto"; + +import "udpa/annotations/migrate.proto"; +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.config.common.matcher.v3"; +option java_outer_classname = "MatcherProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Unified Matcher API] + +// Match configuration. This is a recursive structure which allows complex nested match +// configurations to be built using various logical operators. +// [#next-free-field: 11] +message MatchPredicate { + // A set of match configurations used for logical operations. + message MatchSet { + // The list of rules that make up the set. + repeated MatchPredicate rules = 1 [(validate.rules).repeated = {min_items: 2}]; + } + + oneof rule { + option (validate.required) = true; + + // A set that describes a logical OR. If any member of the set matches, the match configuration + // matches. + MatchSet or_match = 1; + + // A set that describes a logical AND. If all members of the set match, the match configuration + // matches. + MatchSet and_match = 2; + + // A negation match. The match configuration will match if the negated match condition matches. + MatchPredicate not_match = 3; + + // The match configuration will always match. + bool any_match = 4 [(validate.rules).bool = {const: true}]; + + // HTTP request headers match configuration. + HttpHeadersMatch http_request_headers_match = 5; + + // HTTP request trailers match configuration. + HttpHeadersMatch http_request_trailers_match = 6; + + // HTTP response headers match configuration. + HttpHeadersMatch http_response_headers_match = 7; + + // HTTP response trailers match configuration. + HttpHeadersMatch http_response_trailers_match = 8; + + // HTTP request generic body match configuration. + HttpGenericBodyMatch http_request_generic_body_match = 9; + + // HTTP response generic body match configuration. + HttpGenericBodyMatch http_response_generic_body_match = 10; + } +} + +// HTTP headers match configuration. +message HttpHeadersMatch { + // HTTP headers to match. + repeated route.v3.HeaderMatcher headers = 1; +} + +// HTTP generic body match configuration. +// List of text strings and hex strings to be located in HTTP body. +// All specified strings must be found in the HTTP body for positive match. +// The search may be limited to specified number of bytes from the body start. +// +// .. attention:: +// +// Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. +// If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified +// to scan only part of the http body. +message HttpGenericBodyMatch { + message GenericTextMatch { + oneof rule { + option (validate.required) = true; + + // Text string to be located in HTTP body. + string string_match = 1; + + // Sequence of bytes to be located in HTTP body. + bytes binary_match = 2; + } + } + + // Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). + uint32 bytes_limit = 1; + + // List of patterns to match. + repeated GenericTextMatch patterns = 2 [(validate.rules).repeated = {min_items: 1}]; +} diff --git a/api/envoy/config/common/matcher/v4alpha/BUILD b/api/envoy/config/common/matcher/v4alpha/BUILD new file mode 100644 index 0000000000000..7028ce1a2aea3 --- /dev/null +++ b/api/envoy/config/common/matcher/v4alpha/BUILD @@ -0,0 +1,13 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/config/common/matcher/v3:pkg", + "//envoy/config/route/v4alpha:pkg", + "@com_github_cncf_udpa//udpa/annotations:pkg", + ], +) diff --git a/api/envoy/config/common/matcher/v4alpha/matcher.proto b/api/envoy/config/common/matcher/v4alpha/matcher.proto new file mode 100644 index 0000000000000..685ae03a1878f --- /dev/null +++ b/api/envoy/config/common/matcher/v4alpha/matcher.proto @@ -0,0 +1,114 @@ +syntax = "proto3"; + +package envoy.config.common.matcher.v4alpha; + +import "envoy/config/route/v4alpha/route_components.proto"; + +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.config.common.matcher.v4alpha"; +option java_outer_classname = "MatcherProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; + +// [#protodoc-title: Unified Matcher API] + +// Match configuration. This is a recursive structure which allows complex nested match +// configurations to be built using various logical operators. +// [#next-free-field: 11] +message MatchPredicate { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.MatchPredicate"; + + // A set of match configurations used for logical operations. + message MatchSet { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.MatchPredicate.MatchSet"; + + // The list of rules that make up the set. + repeated MatchPredicate rules = 1 [(validate.rules).repeated = {min_items: 2}]; + } + + oneof rule { + option (validate.required) = true; + + // A set that describes a logical OR. If any member of the set matches, the match configuration + // matches. + MatchSet or_match = 1; + + // A set that describes a logical AND. If all members of the set match, the match configuration + // matches. + MatchSet and_match = 2; + + // A negation match. The match configuration will match if the negated match condition matches. + MatchPredicate not_match = 3; + + // The match configuration will always match. + bool any_match = 4 [(validate.rules).bool = {const: true}]; + + // HTTP request headers match configuration. + HttpHeadersMatch http_request_headers_match = 5; + + // HTTP request trailers match configuration. + HttpHeadersMatch http_request_trailers_match = 6; + + // HTTP response headers match configuration. + HttpHeadersMatch http_response_headers_match = 7; + + // HTTP response trailers match configuration. + HttpHeadersMatch http_response_trailers_match = 8; + + // HTTP request generic body match configuration. + HttpGenericBodyMatch http_request_generic_body_match = 9; + + // HTTP response generic body match configuration. + HttpGenericBodyMatch http_response_generic_body_match = 10; + } +} + +// HTTP headers match configuration. +message HttpHeadersMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpHeadersMatch"; + + // HTTP headers to match. + repeated route.v4alpha.HeaderMatcher headers = 1; +} + +// HTTP generic body match configuration. +// List of text strings and hex strings to be located in HTTP body. +// All specified strings must be found in the HTTP body for positive match. +// The search may be limited to specified number of bytes from the body start. +// +// .. attention:: +// +// Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. +// If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified +// to scan only part of the http body. +message HttpGenericBodyMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpGenericBodyMatch"; + + message GenericTextMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpGenericBodyMatch.GenericTextMatch"; + + oneof rule { + option (validate.required) = true; + + // Text string to be located in HTTP body. + string string_match = 1; + + // Sequence of bytes to be located in HTTP body. + bytes binary_match = 2; + } + } + + // Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). + uint32 bytes_limit = 1; + + // List of patterns to match. + repeated GenericTextMatch patterns = 2 [(validate.rules).repeated = {min_items: 1}]; +} diff --git a/api/envoy/config/tap/v3/BUILD b/api/envoy/config/tap/v3/BUILD index f266efc592a2a..6fd3142264d9f 100644 --- a/api/envoy/config/tap/v3/BUILD +++ b/api/envoy/config/tap/v3/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/config/common/matcher/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/config/route/v3:pkg", "//envoy/service/tap/v2alpha:pkg", diff --git a/api/envoy/config/tap/v3/common.proto b/api/envoy/config/tap/v3/common.proto index 81de393e0581a..42783115f8719 100644 --- a/api/envoy/config/tap/v3/common.proto +++ b/api/envoy/config/tap/v3/common.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package envoy.config.tap.v3; +import "envoy/config/common/matcher/v3/matcher.proto"; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/grpc_service.proto"; import "envoy/config/route/v3/route_components.proto"; @@ -28,7 +29,17 @@ message TapConfig { // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. - MatchPredicate match_config = 1 [(validate.rules).message = {required: true}]; + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + MatchPredicate match_config = 1 [deprecated = true]; + + // The match configuration. If the configuration matches the data source being tapped, a tap will + // occur, with the result written to the configured output. + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + common.matcher.v3.MatchPredicate match = 4; // The tap output configuration. If a match configuration matches a data source being tapped, // a tap will occur and the data will be written to the configured output. diff --git a/api/envoy/config/tap/v4alpha/BUILD b/api/envoy/config/tap/v4alpha/BUILD index cb06389f01863..be8b1c3a17e31 100644 --- a/api/envoy/config/tap/v4alpha/BUILD +++ b/api/envoy/config/tap/v4alpha/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/config/common/matcher/v4alpha:pkg", "//envoy/config/core/v4alpha:pkg", "//envoy/config/route/v4alpha:pkg", "//envoy/config/tap/v3:pkg", diff --git a/api/envoy/config/tap/v4alpha/common.proto b/api/envoy/config/tap/v4alpha/common.proto index 5ce87d5b57707..8366187fd1bf2 100644 --- a/api/envoy/config/tap/v4alpha/common.proto +++ b/api/envoy/config/tap/v4alpha/common.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package envoy.config.tap.v4alpha; +import "envoy/config/common/matcher/v4alpha/matcher.proto"; import "envoy/config/core/v4alpha/base.proto"; import "envoy/config/core/v4alpha/grpc_service.proto"; import "envoy/config/route/v4alpha/route_components.proto"; @@ -25,9 +26,16 @@ message TapConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.tap.v3.TapConfig"; + reserved 1; + + reserved "match_config"; + // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. - MatchPredicate match_config = 1 [(validate.rules).message = {required: true}]; + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + common.matcher.v4alpha.MatchPredicate match = 4; // The tap output configuration. If a match configuration matches a data source being tapped, // a tap will occur and the data will be written to the configured output. diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 950594d7213e3..e0a67d2f3cb19 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -13,6 +13,7 @@ proto_library( "//envoy/config/accesslog/v3:pkg", "//envoy/config/bootstrap/v3:pkg", "//envoy/config/cluster/v3:pkg", + "//envoy/config/common/matcher/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/config/endpoint/v3:pkg", "//envoy/config/filter/thrift/router/v2alpha1:pkg", diff --git a/docs/root/api-v3/config/common/common.rst b/docs/root/api-v3/config/common/common.rst index 5739dffe3676e..bb6965a5f1497 100644 --- a/docs/root/api-v3/config/common/common.rst +++ b/docs/root/api-v3/config/common/common.rst @@ -5,5 +5,6 @@ Common :glob: :maxdepth: 2 + matcher/v3/* ../../extensions/common/dynamic_forward_proxy/v3/* ../../extensions/common/tap/v3/* diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index f06045af222ae..d71be4687145a 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -69,3 +69,5 @@ Deprecated ---------- * The :ref:`track_timeout_budgets ` field has been deprecated in favor of `timeout_budgets` part of an :ref:`Optional Configuration `. +* tap: the :ref:`match_config ` field has been deprecated in favor of + :ref:`match ` field. diff --git a/generated_api_shadow/envoy/config/common/matcher/v3/BUILD b/generated_api_shadow/envoy/config/common/matcher/v3/BUILD new file mode 100644 index 0000000000000..c312b8eb6a613 --- /dev/null +++ b/generated_api_shadow/envoy/config/common/matcher/v3/BUILD @@ -0,0 +1,12 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/config/route/v3:pkg", + "@com_github_cncf_udpa//udpa/annotations:pkg", + ], +) diff --git a/generated_api_shadow/envoy/config/common/matcher/v3/matcher.proto b/generated_api_shadow/envoy/config/common/matcher/v3/matcher.proto new file mode 100644 index 0000000000000..d0955e7a1f8c1 --- /dev/null +++ b/generated_api_shadow/envoy/config/common/matcher/v3/matcher.proto @@ -0,0 +1,100 @@ +syntax = "proto3"; + +package envoy.config.common.matcher.v3; + +import "envoy/config/route/v3/route_components.proto"; + +import "udpa/annotations/migrate.proto"; +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.config.common.matcher.v3"; +option java_outer_classname = "MatcherProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Unified Matcher API] + +// Match configuration. This is a recursive structure which allows complex nested match +// configurations to be built using various logical operators. +// [#next-free-field: 11] +message MatchPredicate { + // A set of match configurations used for logical operations. + message MatchSet { + // The list of rules that make up the set. + repeated MatchPredicate rules = 1 [(validate.rules).repeated = {min_items: 2}]; + } + + oneof rule { + option (validate.required) = true; + + // A set that describes a logical OR. If any member of the set matches, the match configuration + // matches. + MatchSet or_match = 1; + + // A set that describes a logical AND. If all members of the set match, the match configuration + // matches. + MatchSet and_match = 2; + + // A negation match. The match configuration will match if the negated match condition matches. + MatchPredicate not_match = 3; + + // The match configuration will always match. + bool any_match = 4 [(validate.rules).bool = {const: true}]; + + // HTTP request headers match configuration. + HttpHeadersMatch http_request_headers_match = 5; + + // HTTP request trailers match configuration. + HttpHeadersMatch http_request_trailers_match = 6; + + // HTTP response headers match configuration. + HttpHeadersMatch http_response_headers_match = 7; + + // HTTP response trailers match configuration. + HttpHeadersMatch http_response_trailers_match = 8; + + // HTTP request generic body match configuration. + HttpGenericBodyMatch http_request_generic_body_match = 9; + + // HTTP response generic body match configuration. + HttpGenericBodyMatch http_response_generic_body_match = 10; + } +} + +// HTTP headers match configuration. +message HttpHeadersMatch { + // HTTP headers to match. + repeated route.v3.HeaderMatcher headers = 1; +} + +// HTTP generic body match configuration. +// List of text strings and hex strings to be located in HTTP body. +// All specified strings must be found in the HTTP body for positive match. +// The search may be limited to specified number of bytes from the body start. +// +// .. attention:: +// +// Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. +// If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified +// to scan only part of the http body. +message HttpGenericBodyMatch { + message GenericTextMatch { + oneof rule { + option (validate.required) = true; + + // Text string to be located in HTTP body. + string string_match = 1; + + // Sequence of bytes to be located in HTTP body. + bytes binary_match = 2; + } + } + + // Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). + uint32 bytes_limit = 1; + + // List of patterns to match. + repeated GenericTextMatch patterns = 2 [(validate.rules).repeated = {min_items: 1}]; +} diff --git a/generated_api_shadow/envoy/config/common/matcher/v4alpha/BUILD b/generated_api_shadow/envoy/config/common/matcher/v4alpha/BUILD new file mode 100644 index 0000000000000..7028ce1a2aea3 --- /dev/null +++ b/generated_api_shadow/envoy/config/common/matcher/v4alpha/BUILD @@ -0,0 +1,13 @@ +# DO NOT EDIT. This file is generated by tools/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/config/common/matcher/v3:pkg", + "//envoy/config/route/v4alpha:pkg", + "@com_github_cncf_udpa//udpa/annotations:pkg", + ], +) diff --git a/generated_api_shadow/envoy/config/common/matcher/v4alpha/matcher.proto b/generated_api_shadow/envoy/config/common/matcher/v4alpha/matcher.proto new file mode 100644 index 0000000000000..685ae03a1878f --- /dev/null +++ b/generated_api_shadow/envoy/config/common/matcher/v4alpha/matcher.proto @@ -0,0 +1,114 @@ +syntax = "proto3"; + +package envoy.config.common.matcher.v4alpha; + +import "envoy/config/route/v4alpha/route_components.proto"; + +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.config.common.matcher.v4alpha"; +option java_outer_classname = "MatcherProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = NEXT_MAJOR_VERSION_CANDIDATE; + +// [#protodoc-title: Unified Matcher API] + +// Match configuration. This is a recursive structure which allows complex nested match +// configurations to be built using various logical operators. +// [#next-free-field: 11] +message MatchPredicate { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.MatchPredicate"; + + // A set of match configurations used for logical operations. + message MatchSet { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.MatchPredicate.MatchSet"; + + // The list of rules that make up the set. + repeated MatchPredicate rules = 1 [(validate.rules).repeated = {min_items: 2}]; + } + + oneof rule { + option (validate.required) = true; + + // A set that describes a logical OR. If any member of the set matches, the match configuration + // matches. + MatchSet or_match = 1; + + // A set that describes a logical AND. If all members of the set match, the match configuration + // matches. + MatchSet and_match = 2; + + // A negation match. The match configuration will match if the negated match condition matches. + MatchPredicate not_match = 3; + + // The match configuration will always match. + bool any_match = 4 [(validate.rules).bool = {const: true}]; + + // HTTP request headers match configuration. + HttpHeadersMatch http_request_headers_match = 5; + + // HTTP request trailers match configuration. + HttpHeadersMatch http_request_trailers_match = 6; + + // HTTP response headers match configuration. + HttpHeadersMatch http_response_headers_match = 7; + + // HTTP response trailers match configuration. + HttpHeadersMatch http_response_trailers_match = 8; + + // HTTP request generic body match configuration. + HttpGenericBodyMatch http_request_generic_body_match = 9; + + // HTTP response generic body match configuration. + HttpGenericBodyMatch http_response_generic_body_match = 10; + } +} + +// HTTP headers match configuration. +message HttpHeadersMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpHeadersMatch"; + + // HTTP headers to match. + repeated route.v4alpha.HeaderMatcher headers = 1; +} + +// HTTP generic body match configuration. +// List of text strings and hex strings to be located in HTTP body. +// All specified strings must be found in the HTTP body for positive match. +// The search may be limited to specified number of bytes from the body start. +// +// .. attention:: +// +// Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. +// If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified +// to scan only part of the http body. +message HttpGenericBodyMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpGenericBodyMatch"; + + message GenericTextMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.common.matcher.v3.HttpGenericBodyMatch.GenericTextMatch"; + + oneof rule { + option (validate.required) = true; + + // Text string to be located in HTTP body. + string string_match = 1; + + // Sequence of bytes to be located in HTTP body. + bytes binary_match = 2; + } + } + + // Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). + uint32 bytes_limit = 1; + + // List of patterns to match. + repeated GenericTextMatch patterns = 2 [(validate.rules).repeated = {min_items: 1}]; +} diff --git a/generated_api_shadow/envoy/config/tap/v3/BUILD b/generated_api_shadow/envoy/config/tap/v3/BUILD index f266efc592a2a..6fd3142264d9f 100644 --- a/generated_api_shadow/envoy/config/tap/v3/BUILD +++ b/generated_api_shadow/envoy/config/tap/v3/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/config/common/matcher/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/config/route/v3:pkg", "//envoy/service/tap/v2alpha:pkg", diff --git a/generated_api_shadow/envoy/config/tap/v3/common.proto b/generated_api_shadow/envoy/config/tap/v3/common.proto index 81de393e0581a..42783115f8719 100644 --- a/generated_api_shadow/envoy/config/tap/v3/common.proto +++ b/generated_api_shadow/envoy/config/tap/v3/common.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package envoy.config.tap.v3; +import "envoy/config/common/matcher/v3/matcher.proto"; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/grpc_service.proto"; import "envoy/config/route/v3/route_components.proto"; @@ -28,7 +29,17 @@ message TapConfig { // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. - MatchPredicate match_config = 1 [(validate.rules).message = {required: true}]; + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + MatchPredicate match_config = 1 [deprecated = true]; + + // The match configuration. If the configuration matches the data source being tapped, a tap will + // occur, with the result written to the configured output. + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + common.matcher.v3.MatchPredicate match = 4; // The tap output configuration. If a match configuration matches a data source being tapped, // a tap will occur and the data will be written to the configured output. diff --git a/generated_api_shadow/envoy/config/tap/v4alpha/BUILD b/generated_api_shadow/envoy/config/tap/v4alpha/BUILD index cb06389f01863..be8b1c3a17e31 100644 --- a/generated_api_shadow/envoy/config/tap/v4alpha/BUILD +++ b/generated_api_shadow/envoy/config/tap/v4alpha/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/config/common/matcher/v4alpha:pkg", "//envoy/config/core/v4alpha:pkg", "//envoy/config/route/v4alpha:pkg", "//envoy/config/tap/v3:pkg", diff --git a/generated_api_shadow/envoy/config/tap/v4alpha/common.proto b/generated_api_shadow/envoy/config/tap/v4alpha/common.proto index 5ce87d5b57707..d18ba1db94c1f 100644 --- a/generated_api_shadow/envoy/config/tap/v4alpha/common.proto +++ b/generated_api_shadow/envoy/config/tap/v4alpha/common.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package envoy.config.tap.v4alpha; +import "envoy/config/common/matcher/v4alpha/matcher.proto"; import "envoy/config/core/v4alpha/base.proto"; import "envoy/config/core/v4alpha/grpc_service.proto"; import "envoy/config/route/v4alpha/route_components.proto"; @@ -27,7 +28,17 @@ message TapConfig { // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. - MatchPredicate match_config = 1 [(validate.rules).message = {required: true}]; + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + MatchPredicate hidden_envoy_deprecated_match_config = 1 [deprecated = true]; + + // The match configuration. If the configuration matches the data source being tapped, a tap will + // occur, with the result written to the configured output. + // Exactly one of :ref:`match ` and + // :ref:`match_config ` must be set. If both + // are set, the :ref:`match ` will be used. + common.matcher.v4alpha.MatchPredicate match = 4; // The tap output configuration. If a match configuration matches a data source being tapped, // a tap will occur and the data will be written to the configured output. diff --git a/source/extensions/common/matcher/BUILD b/source/extensions/common/matcher/BUILD new file mode 100644 index 0000000000000..2ad3f963048af --- /dev/null +++ b/source/extensions/common/matcher/BUILD @@ -0,0 +1,21 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "matcher_lib", + srcs = ["matcher.cc"], + hdrs = ["matcher.h"], + deps = [ + "//source/common/buffer:buffer_lib", + "//source/common/common:minimal_logger_lib", + "//source/common/http:header_utility_lib", + "@envoy_api//envoy/config/common/matcher/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/common/tap/tap_matcher.cc b/source/extensions/common/matcher/matcher.cc similarity index 87% rename from source/extensions/common/tap/tap_matcher.cc rename to source/extensions/common/matcher/matcher.cc index 71c2704325632..8040b4650bca0 100644 --- a/source/extensions/common/tap/tap_matcher.cc +++ b/source/extensions/common/matcher/matcher.cc @@ -1,60 +1,58 @@ -#include "extensions/common/tap/tap_matcher.h" - -#include "envoy/config/tap/v3/common.pb.h" +#include "extensions/common/matcher/matcher.h" #include "common/common/assert.h" namespace Envoy { namespace Extensions { namespace Common { -namespace Tap { +namespace Matcher { -void buildMatcher(const envoy::config::tap::v3::MatchPredicate& match_config, +void buildMatcher(const envoy::config::common::matcher::v3::MatchPredicate& match_config, std::vector& matchers) { // In order to store indexes and build our matcher tree inline, we must reserve a slot where // the matcher we are about to create will go. This allows us to know its future index and still // construct more of the tree in each called constructor (e.g., multiple OR/AND conditions). - // Once fully constructed, we move the matcher into its position below. See the tap matcher - // overview in tap.h for more information. + // Once fully constructed, we move the matcher into its position below. See the matcher + // overview in matcher.h for more information. matchers.emplace_back(nullptr); MatcherPtr new_matcher; switch (match_config.rule_case()) { - case envoy::config::tap::v3::MatchPredicate::RuleCase::kOrMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kOrMatch: new_matcher = std::make_unique(match_config.or_match(), matchers, SetLogicMatcher::Type::Or); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kAndMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kAndMatch: new_matcher = std::make_unique(match_config.and_match(), matchers, SetLogicMatcher::Type::And); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kNotMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kNotMatch: new_matcher = std::make_unique(match_config.not_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kAnyMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kAnyMatch: new_matcher = std::make_unique(matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpRequestHeadersMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpRequestHeadersMatch: new_matcher = std::make_unique( match_config.http_request_headers_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpRequestTrailersMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpRequestTrailersMatch: new_matcher = std::make_unique( match_config.http_request_trailers_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpResponseHeadersMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpResponseHeadersMatch: new_matcher = std::make_unique( match_config.http_response_headers_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpResponseTrailersMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpResponseTrailersMatch: new_matcher = std::make_unique( match_config.http_response_trailers_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpRequestGenericBodyMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpRequestGenericBodyMatch: new_matcher = std::make_unique( match_config.http_request_generic_body_match(), matchers); break; - case envoy::config::tap::v3::MatchPredicate::RuleCase::kHttpResponseGenericBodyMatch: + case envoy::config::common::matcher::v3::MatchPredicate::RuleCase::kHttpResponseGenericBodyMatch: new_matcher = std::make_unique( match_config.http_response_generic_body_match(), matchers); break; @@ -66,8 +64,9 @@ void buildMatcher(const envoy::config::tap::v3::MatchPredicate& match_config, matchers[new_matcher->index()] = std::move(new_matcher); } -SetLogicMatcher::SetLogicMatcher(const envoy::config::tap::v3::MatchPredicate::MatchSet& configs, - std::vector& matchers, Type type) +SetLogicMatcher::SetLogicMatcher( + const envoy::config::common::matcher::v3::MatchPredicate::MatchSet& configs, + std::vector& matchers, Type type) : LogicMatcherBase(matchers), matchers_(matchers), type_(type) { for (const auto& config : configs.rules()) { indexes_.push_back(matchers_.size()); @@ -100,7 +99,7 @@ void SetLogicMatcher::updateLocalStatus(MatchStatusVector& statuses, [&statuses](size_t index) { return statuses[index].might_change_status_; }); } -NotMatcher::NotMatcher(const envoy::config::tap::v3::MatchPredicate& config, +NotMatcher::NotMatcher(const envoy::config::common::matcher::v3::MatchPredicate& config, std::vector& matchers) : LogicMatcherBase(matchers), matchers_(matchers), not_index_(matchers.size()) { buildMatcher(config, matchers); @@ -117,8 +116,9 @@ void NotMatcher::updateLocalStatus(MatchStatusVector& statuses, statuses[my_index_].might_change_status_ = statuses[not_index_].might_change_status_; } -HttpHeaderMatcherBase::HttpHeaderMatcherBase(const envoy::config::tap::v3::HttpHeadersMatch& config, - const std::vector& matchers) +HttpHeaderMatcherBase::HttpHeaderMatcherBase( + const envoy::config::common::matcher::v3::HttpHeadersMatch& config, + const std::vector& matchers) : SimpleMatcher(matchers), headers_to_match_(Http::HeaderUtility::buildHeaderDataVector(config.headers())) {} @@ -134,18 +134,18 @@ void HttpHeaderMatcherBase::matchHeaders(const Http::HeaderMap& headers, // HTTP body may be passed to the matcher in chunks. The search logic buffers // only as many bytes as is the length of the longest pattern to be found. HttpGenericBodyMatcher::HttpGenericBodyMatcher( - const envoy::config::tap::v3::HttpGenericBodyMatch& config, + const envoy::config::common::matcher::v3::HttpGenericBodyMatch& config, const std::vector& matchers) : HttpBodyMatcherBase(matchers) { patterns_ = std::make_shared>(); for (const auto& i : config.patterns()) { switch (i.rule_case()) { // For binary match 'i' contains sequence of bytes to locate in the body. - case envoy::config::tap::v3::HttpGenericBodyMatch::GenericTextMatch::kBinaryMatch: { + case envoy::config::common::matcher::v3::HttpGenericBodyMatch::GenericTextMatch::kBinaryMatch: { patterns_->push_back(i.binary_match()); } break; // For string match 'i' contains exact string to locate in the body. - case envoy::config::tap::v3::HttpGenericBodyMatch::GenericTextMatch::kStringMatch: + case envoy::config::common::matcher::v3::HttpGenericBodyMatch::GenericTextMatch::kStringMatch: patterns_->push_back(i.string_match()); break; default: @@ -329,7 +329,7 @@ void HttpGenericBodyMatcher::resizeOverlapBuffer(HttpGenericBodyMatcherCtx* ctx) } } -} // namespace Tap +} // namespace Matcher } // namespace Common } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/common/tap/tap_matcher.h b/source/extensions/common/matcher/matcher.h similarity index 94% rename from source/extensions/common/tap/tap_matcher.h rename to source/extensions/common/matcher/matcher.h index 79705e3fe9241..4eecd25d3786a 100644 --- a/source/extensions/common/tap/tap_matcher.h +++ b/source/extensions/common/matcher/matcher.h @@ -1,15 +1,14 @@ #pragma once -#include "envoy/config/tap/v3/common.pb.h" +#include "envoy/config/common/matcher/v3/matcher.pb.h" #include "common/buffer/buffer_impl.h" -#include "common/common/matchers.h" #include "common/http/header_utility.h" namespace Envoy { namespace Extensions { namespace Common { -namespace Tap { +namespace Matcher { class Matcher; using MatcherPtr = std::unique_ptr; @@ -27,9 +26,9 @@ class MatcherCtx { }; /** - * Base class for all tap matchers. + * Base class for all matchers. * - * A high level note on the design of tap matching which is different from other matching in Envoy + * A high level note on the design of matching which is different from other matching in Envoy * due to a requirement to support streaming matching (match as new data arrives versus * calculating the match given all available data at once). * - The matching system is composed of a constant matching configuration. This is essentially @@ -66,7 +65,7 @@ class Matcher { Matcher(const std::vector& matchers) // NOTE: This code assumes that the index for the matcher being constructed has already been // allocated, which is why my_index_ is set to size() - 1. See buildMatcher() in - // tap_matcher.cc. + // matcher.cc. : my_index_(matchers.size() - 1) {} virtual ~Matcher() = default; @@ -150,9 +149,9 @@ class Matcher { /** * Factory method to build a matcher given a match config. Calling this function may end * up recursively building many matchers, which will all be added to the passed in vector - * of matchers. See the comments in tap.h for the general structure of how tap matchers work. + * of matchers. See the comments in matcher.h for the general structure of how matchers work. */ -void buildMatcher(const envoy::config::tap::v3::MatchPredicate& match_config, +void buildMatcher(const envoy::config::common::matcher::v3::MatchPredicate& match_config, std::vector& matchers); /** @@ -162,7 +161,6 @@ class LogicMatcherBase : public Matcher { public: using Matcher::Matcher; - // Extensions::Common::Tap::Matcher void onNewStream(MatchStatusVector& statuses) const override { updateLocalStatus(statuses, [](Matcher& m, MatchStatusVector& statuses) { m.onNewStream(statuses); }); @@ -215,7 +213,7 @@ class SetLogicMatcher : public LogicMatcherBase { public: enum class Type { And, Or }; - SetLogicMatcher(const envoy::config::tap::v3::MatchPredicate::MatchSet& configs, + SetLogicMatcher(const envoy::config::common::matcher::v3::MatchPredicate::MatchSet& configs, std::vector& matchers, Type type); private: @@ -231,7 +229,7 @@ class SetLogicMatcher : public LogicMatcherBase { */ class NotMatcher : public LogicMatcherBase { public: - NotMatcher(const envoy::config::tap::v3::MatchPredicate& config, + NotMatcher(const envoy::config::common::matcher::v3::MatchPredicate& config, std::vector& matchers); private: @@ -249,7 +247,6 @@ class SimpleMatcher : public Matcher { public: using Matcher::Matcher; - // Extensions::Common::Tap::Matcher void onNewStream(MatchStatusVector&) const override {} void onHttpRequestHeaders(const Http::RequestHeaderMap&, MatchStatusVector&) const override {} void onHttpRequestTrailers(const Http::RequestTrailerMap&, MatchStatusVector&) const override {} @@ -266,7 +263,6 @@ class AnyMatcher : public SimpleMatcher { public: using SimpleMatcher::SimpleMatcher; - // Extensions::Common::Tap::Matcher void onNewStream(MatchStatusVector& statuses) const override { statuses[my_index_].matches_ = true; statuses[my_index_].might_change_status_ = false; @@ -278,7 +274,7 @@ class AnyMatcher : public SimpleMatcher { */ class HttpHeaderMatcherBase : public SimpleMatcher { public: - HttpHeaderMatcherBase(const envoy::config::tap::v3::HttpHeadersMatch& config, + HttpHeaderMatcherBase(const envoy::config::common::matcher::v3::HttpHeadersMatch& config, const std::vector& matchers); protected: @@ -294,7 +290,6 @@ class HttpRequestHeadersMatcher : public HttpHeaderMatcherBase { public: using HttpHeaderMatcherBase::HttpHeaderMatcherBase; - // Extensions::Common::Tap::Matcher void onHttpRequestHeaders(const Http::RequestHeaderMap& request_headers, MatchStatusVector& statuses) const override { matchHeaders(request_headers, statuses); @@ -308,7 +303,6 @@ class HttpRequestTrailersMatcher : public HttpHeaderMatcherBase { public: using HttpHeaderMatcherBase::HttpHeaderMatcherBase; - // Extensions::Common::Tap::Matcher void onHttpRequestTrailers(const Http::RequestTrailerMap& request_trailers, MatchStatusVector& statuses) const override { matchHeaders(request_trailers, statuses); @@ -322,7 +316,6 @@ class HttpResponseHeadersMatcher : public HttpHeaderMatcherBase { public: using HttpHeaderMatcherBase::HttpHeaderMatcherBase; - // Extensions::Common::Tap::Matcher void onHttpResponseHeaders(const Http::ResponseHeaderMap& response_headers, MatchStatusVector& statuses) const override { matchHeaders(response_headers, statuses); @@ -336,7 +329,6 @@ class HttpResponseTrailersMatcher : public HttpHeaderMatcherBase { public: using HttpHeaderMatcherBase::HttpHeaderMatcherBase; - // Extensions::Common::Tap::Matcher void onHttpResponseTrailers(const Http::ResponseTrailerMap& response_trailers, MatchStatusVector& statuses) const override { matchHeaders(response_trailers, statuses); @@ -404,7 +396,7 @@ class HttpGenericBodyMatcherCtx : public MatcherCtx { class HttpGenericBodyMatcher : public HttpBodyMatcherBase { public: - HttpGenericBodyMatcher(const envoy::config::tap::v3::HttpGenericBodyMatch& config, + HttpGenericBodyMatcher(const envoy::config::common::matcher::v3::HttpGenericBodyMatch& config, const std::vector& matchers); protected: @@ -425,7 +417,7 @@ class HttpGenericBodyMatcher : public HttpBodyMatcherBase { private: // The following fields are initialized based on matcher config and are used - // by all HTTP tappers. + // by all HTTP matchers. // List of strings which body must contain to get match. std::shared_ptr> patterns_; // Stores the length of the longest pattern. @@ -450,7 +442,7 @@ class HttpResponseGenericBodyMatcher : public HttpGenericBodyMatcher { } }; -} // namespace Tap +} // namespace Matcher } // namespace Common } // namespace Extensions } // namespace Envoy diff --git a/source/extensions/common/tap/BUILD b/source/extensions/common/tap/BUILD index 8cf381c67deec..e127bf3aaa192 100644 --- a/source/extensions/common/tap/BUILD +++ b/source/extensions/common/tap/BUILD @@ -12,8 +12,8 @@ envoy_cc_library( name = "tap_interface", hdrs = ["tap.h"], deps = [ - ":tap_matcher", "//include/envoy/http:header_map_interface", + "//source/extensions/common/matcher:matcher_lib", "@envoy_api//envoy/config/tap/v3:pkg_cc_proto", "@envoy_api//envoy/data/tap/v3:pkg_cc_proto", ], @@ -25,26 +25,14 @@ envoy_cc_library( hdrs = ["tap_config_base.h"], deps = [ ":tap_interface", - ":tap_matcher", "//source/common/common:assert_lib", "//source/common/common:hex_lib", + "//source/extensions/common/matcher:matcher_lib", "@envoy_api//envoy/config/tap/v3:pkg_cc_proto", "@envoy_api//envoy/data/tap/v3:pkg_cc_proto", ], ) -envoy_cc_library( - name = "tap_matcher", - srcs = ["tap_matcher.cc"], - hdrs = ["tap_matcher.h"], - deps = [ - "//source/common/buffer:buffer_lib", - "//source/common/common:matchers_lib", - "//source/common/http:header_utility_lib", - "@envoy_api//envoy/config/tap/v3:pkg_cc_proto", - ], -) - envoy_cc_library( name = "admin", srcs = ["admin.cc"], diff --git a/source/extensions/common/tap/admin.h b/source/extensions/common/tap/admin.h index bf80f6889b179..a3cbb7f6e815a 100644 --- a/source/extensions/common/tap/admin.h +++ b/source/extensions/common/tap/admin.h @@ -1,6 +1,5 @@ #pragma once -#include "envoy/config/tap/v3/common.pb.h" #include "envoy/server/admin.h" #include "envoy/singleton/manager.h" diff --git a/source/extensions/common/tap/tap.h b/source/extensions/common/tap/tap.h index 58ba4ba82d6d9..9abf88d6965b3 100644 --- a/source/extensions/common/tap/tap.h +++ b/source/extensions/common/tap/tap.h @@ -5,7 +5,7 @@ #include "envoy/data/tap/v3/wrapper.pb.h" #include "envoy/http/header_map.h" -#include "extensions/common/tap/tap_matcher.h" +#include "extensions/common/matcher/matcher.h" #include "absl/strings/string_view.h" @@ -14,6 +14,8 @@ namespace Extensions { namespace Common { namespace Tap { +using Matcher = Envoy::Extensions::Common::Matcher::Matcher; + using TraceWrapperPtr = std::unique_ptr; inline TraceWrapperPtr makeTraceWrapper() { return std::make_unique(); diff --git a/source/extensions/common/tap/tap_config_base.cc b/source/extensions/common/tap/tap_config_base.cc index b9debd1720e66..7eea4b7fe7beb 100644 --- a/source/extensions/common/tap/tap_config_base.cc +++ b/source/extensions/common/tap/tap_config_base.cc @@ -5,9 +5,11 @@ #include "envoy/data/tap/v3/wrapper.pb.h" #include "common/common/assert.h" +#include "common/common/fmt.h" +#include "common/config/version_converter.h" #include "common/protobuf/utility.h" -#include "extensions/common/tap/tap_matcher.h" +#include "extensions/common/matcher/matcher.h" #include "absl/container/fixed_array.h" @@ -16,6 +18,8 @@ namespace Extensions { namespace Common { namespace Tap { +using namespace Matcher; + bool Utility::addBufferToProtoBytes(envoy::data::tap::v3::Body& output_body, uint32_t max_buffered_bytes, const Buffer::Instance& data, uint32_t buffer_start_offset, uint32_t buffer_length_to_copy) { @@ -72,7 +76,20 @@ TapConfigBaseImpl::TapConfigBaseImpl(envoy::config::tap::v3::TapConfig&& proto_c NOT_REACHED_GCOVR_EXCL_LINE; } - buildMatcher(proto_config.match_config(), matchers_); + envoy::config::common::matcher::v3::MatchPredicate match; + if (proto_config.has_match()) { + // Use the match field whenever it is set. + match = proto_config.match(); + } else if (proto_config.has_match_config()) { + // Fallback to use the deprecated match_config field and upgrade (wire cast) it to the new + // MatchPredicate which is backward compatible with the old MatchPredicate originally + // introduced in the Tap filter. + Config::VersionConverter::upgrade(proto_config.match_config(), match); + } else { + throw EnvoyException(fmt::format("Neither match nor match_config is set in TapConfig: {}", + proto_config.DebugString())); + } + buildMatcher(match, matchers_); } const Matcher& TapConfigBaseImpl::rootMatcher() const { diff --git a/source/extensions/common/tap/tap_config_base.h b/source/extensions/common/tap/tap_config_base.h index 59b53da027f65..8a6014bc143c9 100644 --- a/source/extensions/common/tap/tap_config_base.h +++ b/source/extensions/common/tap/tap_config_base.h @@ -7,14 +7,17 @@ #include "envoy/data/tap/v3/common.pb.h" #include "envoy/data/tap/v3/wrapper.pb.h" +#include "extensions/common/matcher/matcher.h" #include "extensions/common/tap/tap.h" -#include "extensions/common/tap/tap_matcher.h" namespace Envoy { namespace Extensions { namespace Common { namespace Tap { +using Matcher = Envoy::Extensions::Common::Matcher::Matcher; +using MatcherPtr = Envoy::Extensions::Common::Matcher::MatcherPtr; + /** * Common utilities for tapping. */ diff --git a/test/extensions/common/matcher/BUILD b/test/extensions/common/matcher/BUILD new file mode 100644 index 0000000000000..a2723b48da781 --- /dev/null +++ b/test/extensions/common/matcher/BUILD @@ -0,0 +1,19 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_test", + "envoy_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_cc_test( + name = "matcher_test", + srcs = ["matcher_test.cc"], + deps = [ + "//source/extensions/common/matcher:matcher_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/config/common/matcher/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/common/tap/tap_matcher_test.cc b/test/extensions/common/matcher/matcher_test.cc similarity index 97% rename from test/extensions/common/tap/tap_matcher_test.cc rename to test/extensions/common/matcher/matcher_test.cc index 9898c7b4ee892..28f6752eb24a0 100644 --- a/test/extensions/common/tap/tap_matcher_test.cc +++ b/test/extensions/common/matcher/matcher_test.cc @@ -1,8 +1,8 @@ -#include "envoy/config/tap/v3/common.pb.h" +#include "envoy/config/common/matcher/v3/matcher.pb.h" #include "common/protobuf/utility.h" -#include "extensions/common/tap/tap_matcher.h" +#include "extensions/common/matcher/matcher.h" #include "test/test_common/utility.h" @@ -11,19 +11,19 @@ namespace Envoy { namespace Extensions { namespace Common { -namespace Tap { +namespace Matcher { namespace { -class TapMatcherTestBase { +class MatcherTestBase { public: std::vector matchers_; Matcher::MatchStatusVector statuses_; - envoy::config::tap::v3::MatchPredicate config_; + envoy::config::common::matcher::v3::MatchPredicate config_; enum class Direction { Request, Response }; }; -class TapMatcherTest : public TapMatcherTestBase, public testing::Test { +class TapMatcherTest : public MatcherTestBase, public testing::Test { public: Http::TestRequestHeaderMapImpl request_headers_; Http::TestRequestTrailerMapImpl request_trailers_; @@ -31,12 +31,12 @@ class TapMatcherTest : public TapMatcherTestBase, public testing::Test { Http::TestResponseTrailerMapImpl response_trailers_; }; -class TapMatcherGenericBodyConfigTest : public TapMatcherTestBase, public ::testing::Test {}; +class TapMatcherGenericBodyConfigTest : public MatcherTestBase, public ::testing::Test {}; class TapMatcherGenericBodyTest - : public TapMatcherTestBase, + : public MatcherTestBase, public ::testing::TestWithParam< - std::tuple, std::list>, std::pair>>> { public: @@ -242,8 +242,8 @@ TEST_P(TapMatcherGenericBodyTest, GenericBodyTest) { INSTANTIATE_TEST_SUITE_P( TapMatcherGenericBodyTestSuite, TapMatcherGenericBodyTest, ::testing::Combine( - ::testing::Values(TapMatcherTestBase::Direction::Request, - TapMatcherTestBase::Direction::Response), + ::testing::Values(MatcherTestBase::Direction::Request, + MatcherTestBase::Direction::Response), ::testing::Values( // SEARCHING FOR SINGLE PATTERN - no limit // Should match - there is a single body chunk and envoy is in the body @@ -500,7 +500,7 @@ TEST_F(TapMatcherGenericBodyTest, RandomLengthOverlappingPatterns) { } } } // namespace -} // namespace Tap +} // namespace Matcher } // namespace Common } // namespace Extensions } // namespace Envoy diff --git a/test/extensions/common/tap/BUILD b/test/extensions/common/tap/BUILD index 9775f2873b053..c5a459721fafc 100644 --- a/test/extensions/common/tap/BUILD +++ b/test/extensions/common/tap/BUILD @@ -31,16 +31,6 @@ envoy_cc_test( ], ) -envoy_cc_test( - name = "tap_matcher_test", - srcs = ["tap_matcher_test.cc"], - deps = [ - "//source/extensions/common/tap:tap_matcher", - "//test/test_common:utility_lib", - "@envoy_api//envoy/config/tap/v3:pkg_cc_proto", - ], -) - envoy_cc_test( name = "tap_config_base_test", srcs = ["tap_config_base_test.cc"], diff --git a/test/extensions/common/tap/admin_test.cc b/test/extensions/common/tap/admin_test.cc index 2e3d940eadc50..33dc0b2a342f4 100644 --- a/test/extensions/common/tap/admin_test.cc +++ b/test/extensions/common/tap/admin_test.cc @@ -49,7 +49,7 @@ class AdminHandlerTest : public testing::Test { R"EOF( config_id: test_config_id tap_config: - match_config: + match: any_match: true output_config: sinks: diff --git a/test/extensions/filters/http/tap/BUILD b/test/extensions/filters/http/tap/BUILD index a6b1a69672785..f134caaf53568 100644 --- a/test/extensions/filters/http/tap/BUILD +++ b/test/extensions/filters/http/tap/BUILD @@ -56,6 +56,7 @@ envoy_extension_cc_test( deps = [ "//source/extensions/filters/http/tap:config", "//test/integration:http_integration_lib", + "//test/test_common:utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/data/tap/v3:pkg_cc_proto", ], diff --git a/test/extensions/filters/http/tap/tap_filter_integration_test.cc b/test/extensions/filters/http/tap/tap_filter_integration_test.cc index a68b9d44ad195..fdfa591bc62e5 100644 --- a/test/extensions/filters/http/tap/tap_filter_integration_test.cc +++ b/test/extensions/filters/http/tap/tap_filter_integration_test.cc @@ -4,6 +4,7 @@ #include "envoy/data/tap/v3/wrapper.pb.h" #include "test/integration/http_integration.h" +#include "test/test_common/utility.h" #include "absl/strings/match.h" #include "gtest/gtest.h" @@ -127,6 +128,27 @@ class TapIntegrationTest : public testing::TestWithParamclose(); + test_server_->waitForCounterGe("http.config_test.downstream_cx_destroy", 1); + + // Find the written .pb file and verify it. + auto files = TestUtility::listFiles(path_prefix, false); + auto pb_file = std::find_if(files.begin(), files.end(), + [](const std::string& s) { return absl::EndsWith(s, ".pb"); }); + ASSERT_NE(pb_file, files.end()); + + envoy::data::tap::v3::TraceWrapper trace; + TestUtility::loadFromFile(*pb_file, trace, *api_); + EXPECT_TRUE(trace.has_http_buffered_trace()); + } + const Http::TestRequestHeaderMapImpl request_headers_tap_{{":method", "GET"}, {":path", "/"}, {":scheme", "http"}, @@ -168,10 +190,10 @@ TEST_P(TapIntegrationTest, StaticFilePerTap) { R"EOF( name: tap typed_config: - "@type": type.googleapis.com/envoy.config.filter.http.tap.v2alpha.Tap + "@type": type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap common_config: static_config: - match_config: + match: any_match: true output_config: sinks: @@ -180,24 +202,53 @@ name: tap path_prefix: {} )EOF"; - const std::string path_prefix = getTempPathPrefix(); - initializeFilter(fmt::format(filter_config, path_prefix)); + verifyStaticFilePerTap(filter_config); +} - // Initial request/response with tap. - codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); - makeRequest(request_headers_tap_, {}, nullptr, response_headers_no_tap_, {}, nullptr); - codec_client_->close(); - test_server_->waitForCounterGe("http.config_test.downstream_cx_destroy", 1); +// Verify the match field takes precedence over the deprecated match_config field. +TEST_P(TapIntegrationTest, DEPRECATED_FEATURE_TEST(StaticFilePerTapWithMatchConfigAndMatch)) { + const std::string filter_config = + R"EOF( +name: tap +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap + common_config: + static_config: + # match_config should be ignored by the match field. + match_config: + not_match: + any_match: true + match: + any_match: true + output_config: + sinks: + - format: PROTO_BINARY + file_per_tap: + path_prefix: {} +)EOF"; - // Find the written .pb file and verify it. - auto files = TestUtility::listFiles(path_prefix, false); - auto pb_file = std::find_if(files.begin(), files.end(), - [](const std::string& s) { return absl::EndsWith(s, ".pb"); }); - ASSERT_NE(pb_file, files.end()); + verifyStaticFilePerTap(filter_config); +} - envoy::data::tap::v3::TraceWrapper trace; - TestUtility::loadFromFile(*pb_file, trace, *api_); - EXPECT_TRUE(trace.has_http_buffered_trace()); +// Verify the deprecated match_config field. +TEST_P(TapIntegrationTest, DEPRECATED_FEATURE_TEST(StaticFilePerTapWithMatchConfig)) { + const std::string filter_config = + R"EOF( +name: tap +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap + common_config: + static_config: + match_config: + any_match: true + output_config: + sinks: + - format: PROTO_BINARY + file_per_tap: + path_prefix: {} +)EOF"; + + verifyStaticFilePerTap(filter_config); } // Verify a basic tap flow using the admin handler. @@ -212,7 +263,7 @@ TEST_P(TapIntegrationTest, AdminBasicFlow) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: or_match: rules: - http_request_headers_match: @@ -275,7 +326,7 @@ config_id: test_config_id R"EOF( config_id: test_config_id tap_config: - match_config: + match: and_match: rules: - http_request_headers_match: @@ -319,7 +370,7 @@ TEST_P(TapIntegrationTest, AdminTrailers) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: and_match: rules: - http_request_trailers_match: @@ -360,7 +411,7 @@ TEST_P(TapIntegrationTest, AdminBodyAsBytes) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: any_match: true output_config: sinks: @@ -391,7 +442,7 @@ TEST_P(TapIntegrationTest, AdminBodyAsString) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: any_match: true output_config: sinks: @@ -423,7 +474,7 @@ TEST_P(TapIntegrationTest, AdminBodyAsBytesTruncated) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: any_match: true output_config: max_buffered_rx_bytes: 3 @@ -546,7 +597,7 @@ TEST_P(TapIntegrationTest, AdminBodyMatching) { R"EOF( config_id: test_config_id tap_config: - match_config: + match: and_match: rules: - http_request_generic_body_match: diff --git a/test/extensions/filters/http/tap/tap_filter_test.cc b/test/extensions/filters/http/tap/tap_filter_test.cc index c4d229fd192d6..7ed0f1afb77fe 100644 --- a/test/extensions/filters/http/tap/tap_filter_test.cc +++ b/test/extensions/filters/http/tap/tap_filter_test.cc @@ -133,7 +133,7 @@ TEST(TapFilterConfigTest, InvalidProto) { R"EOF( common_config: static_config: - match_config: + match: any_match: true output_config: sinks: @@ -150,6 +150,29 @@ TEST(TapFilterConfigTest, InvalidProto) { "Error: Specifying admin streaming output without configuring admin."); } +TEST(TapFilterConfigTest, NeitherMatchNorMatchConfig) { + const std::string filter_config = + R"EOF( + common_config: + static_config: + output_config: + sinks: + - format: PROTO_BINARY + file_per_tap: + path_prefix: abc +)EOF"; + + envoy::extensions::filters::http::tap::v3::Tap config; + TestUtility::loadFromYaml(filter_config, config); + NiceMock context; + TapFilterFactory factory; + + EXPECT_THROW_WITH_MESSAGE(factory.createFilterFactoryFromProto(config, "stats", context), + EnvoyException, + fmt::format("Neither match nor match_config is set in TapConfig: {}", + config.common_config().static_config().DebugString())); +} + } // namespace } // namespace TapFilter } // namespace HttpFilters 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 9994f8ca314ba..db9b0afd9ec58 100644 --- a/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc +++ b/test/extensions/transport_sockets/tls/integration/ssl_integration_test.cc @@ -396,10 +396,8 @@ class SslTapIntegrationTest : public SslIntegrationTest { envoy::extensions::transport_sockets::tap::v3::Tap createTapConfig(const envoy::config::core::v3::TransportSocket& inner_transport) { envoy::extensions::transport_sockets::tap::v3::Tap tap_config; - tap_config.mutable_common_config() - ->mutable_static_config() - ->mutable_match_config() - ->set_any_match(true); + tap_config.mutable_common_config()->mutable_static_config()->mutable_match()->set_any_match( + true); auto* output_config = tap_config.mutable_common_config()->mutable_static_config()->mutable_output_config(); if (max_rx_bytes_.has_value()) {