diff --git a/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java b/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java index ad78a6967c5..2516ab17ca2 100644 --- a/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java +++ b/xds/src/main/java/io/grpc/xds/EnvoyProtoData.java @@ -226,6 +226,7 @@ static final class Builder { private Map metadata; @Nullable private Locality locality; + // TODO(sanjaypujare): eliminate usage of listening_addresses field. private final List
listeningAddresses = new ArrayList<>(); private String buildVersion = ""; private String userAgentName = ""; @@ -326,6 +327,7 @@ List
getListeningAddresses() { return listeningAddresses; } + @SuppressWarnings("deprecation") @VisibleForTesting public io.envoyproxy.envoy.config.core.v3.Node toEnvoyProtoNode() { io.envoyproxy.envoy.config.core.v3.Node.Builder builder = diff --git a/xds/src/main/java/io/grpc/xds/XdsClientImpl.java b/xds/src/main/java/io/grpc/xds/XdsClientImpl.java index 829e8711795..b427cdd7c90 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClientImpl.java +++ b/xds/src/main/java/io/grpc/xds/XdsClientImpl.java @@ -462,6 +462,7 @@ private void updateNodeMetadataForListenerRequest(int port) { newMetadata.putAll(node.getMetadata()); } newMetadata.put("TRAFFICDIRECTOR_PROXYLESS", "1"); + // TODO(sanjaypujare): eliminate usage of listening_addresses. EnvoyProtoData.Address listeningAddress = new EnvoyProtoData.Address("0.0.0.0", port); node = diff --git a/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java b/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java index 2e307d6c7eb..5ffabdf3642 100644 --- a/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java +++ b/xds/src/test/java/io/grpc/xds/EnvoyProtoDataTest.java @@ -96,6 +96,7 @@ public void locality_equal() { .testEquals(); } + @SuppressWarnings("deprecation") @Test public void convertNode() { Node node = Node.newBuilder() diff --git a/xds/third_party/envoy/import.sh b/xds/third_party/envoy/import.sh index 80352ca520a..593bec256c6 100755 --- a/xds/third_party/envoy/import.sh +++ b/xds/third_party/envoy/import.sh @@ -18,7 +18,7 @@ set -e BRANCH=master # import VERSION from one of the google internal CLs -VERSION=3dedf1693f45239c670c5ba7598db44ff2e32c2f +VERSION=fd28e42f31730f5ed6f13f52999692a4885dd312 GIT_REPO="https://github.com/envoyproxy/envoy.git" GIT_BASE_DIR=envoy SOURCE_PROTO_BASE_DIR=envoy/api @@ -130,8 +130,11 @@ envoy/type/matcher/metadata.proto envoy/type/matcher/path.proto envoy/type/matcher/value.proto envoy/type/matcher/number.proto +envoy/type/matcher/v3/metadata.proto +envoy/type/matcher/v3/number.proto envoy/type/matcher/v3/regex.proto envoy/type/matcher/v3/string.proto +envoy/type/matcher/v3/value.proto envoy/type/metadata/v2/metadata.proto envoy/type/metadata/v3/metadata.proto envoy/type/percent.proto diff --git a/xds/third_party/envoy/src/main/proto/envoy/api/v2/cluster.proto b/xds/third_party/envoy/src/main/proto/envoy/api/v2/cluster.proto index c95de62c128..d1a50fbdb91 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/api/v2/cluster.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/api/v2/cluster.proto @@ -448,7 +448,7 @@ message Cluster { // connections to upstream hosts whenever hosts are added or removed from the cluster. bool close_connections_on_host_set_change = 6; - //Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + // Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) ConsistentHashingLbConfig consistent_hashing_lb_config = 7; } diff --git a/xds/third_party/envoy/src/main/proto/envoy/api/v2/route/route_components.proto b/xds/third_party/envoy/src/main/proto/envoy/api/v2/route/route_components.proto index 007f71d57cb..339c7bcbc53 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/api/v2/route/route_components.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/api/v2/route/route_components.proto @@ -436,7 +436,7 @@ message RouteMatch { type.matcher.RegexMatcher safe_regex = 10 [(validate.rules).message = {required: true}]; } - // Indicates that prefix/path matching should be case insensitive. The default + // Indicates that prefix/path matching should be case sensitive. The default // is true. google.protobuf.BoolValue case_sensitive = 4; diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/accesslog/v3/accesslog.proto b/xds/third_party/envoy/src/main/proto/envoy/config/accesslog/v3/accesslog.proto index e1b5a2e58b9..e9d815aafce 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/accesslog/v3/accesslog.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/accesslog/v3/accesslog.proto @@ -4,10 +4,12 @@ package envoy.config.accesslog.v3; import "envoy/config/core/v3/base.proto"; import "envoy/config/route/v3/route_components.proto"; +import "envoy/type/matcher/v3/metadata.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/any.proto"; import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -39,8 +41,8 @@ message AccessLog { // Filter which is used to determine if the access log needs to be written. AccessLogFilter filter = 2; - // Custom configuration that depends on the access log being instantiated. Built-in - // configurations include: + // Custom configuration that depends on the access log being instantiated. + // Built-in configurations include: // // #. "envoy.access_loggers.file": :ref:`FileAccessLog // ` @@ -53,7 +55,7 @@ message AccessLog { } } -// [#next-free-field: 12] +// [#next-free-field: 13] message AccessLogFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.AccessLogFilter"; @@ -93,6 +95,9 @@ message AccessLogFilter { // Extension filter. ExtensionFilter extension_filter = 11; + + // Metadata Filter + MetadataFilter metadata_filter = 12; } } @@ -156,25 +161,30 @@ message RuntimeFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.RuntimeFilter"; - // Runtime key to get an optional overridden numerator for use in the *percent_sampled* field. - // If found in runtime, this value will replace the default numerator. + // Runtime key to get an optional overridden numerator for use in the + // *percent_sampled* field. If found in runtime, this value will replace the + // default numerator. string runtime_key = 1 [(validate.rules).string = {min_bytes: 1}]; - // The default sampling percentage. If not specified, defaults to 0% with denominator of 100. + // The default sampling percentage. If not specified, defaults to 0% with + // denominator of 100. type.v3.FractionalPercent percent_sampled = 2; // By default, sampling pivots on the header - // :ref:`x-request-id` being present. If - // :ref:`x-request-id` is present, the filter will - // consistently sample across multiple hosts based on the runtime key value and the value - // extracted from :ref:`x-request-id`. If it is - // missing, or *use_independent_randomness* is set to true, the filter will randomly sample based - // on the runtime key value alone. *use_independent_randomness* can be used for logging kill - // switches within complex nested :ref:`AndFilter + // :ref:`x-request-id` being + // present. If :ref:`x-request-id` + // is present, the filter will consistently sample across multiple hosts based + // on the runtime key value and the value extracted from + // :ref:`x-request-id`. If it is + // missing, or *use_independent_randomness* is set to true, the filter will + // randomly sample based on the runtime key value alone. + // *use_independent_randomness* can be used for logging kill switches within + // complex nested :ref:`AndFilter // ` and :ref:`OrFilter - // ` blocks that are easier to reason about - // from a probability perspective (i.e., setting to true will cause the filter to behave like - // an independent random variable when composed within logical operator filters). + // ` blocks that are easier to + // reason about from a probability perspective (i.e., setting to true will + // cause the filter to behave like an independent random variable when + // composed within logical operator filters). bool use_independent_randomness = 3; } @@ -203,21 +213,22 @@ message HeaderFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.HeaderFilter"; - // Only requests with a header which matches the specified HeaderMatcher will pass the filter - // check. + // Only requests with a header which matches the specified HeaderMatcher will + // pass the filter check. route.v3.HeaderMatcher header = 1 [(validate.rules).message = {required: true}]; } // Filters requests that received responses with an Envoy response flag set. // A list of the response flags can be found -// in the access log formatter :ref:`documentation`. +// in the access log formatter +// :ref:`documentation`. message ResponseFlagFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.ResponseFlagFilter"; - // Only responses with the any of the flags listed in this field will be logged. - // This field is optional. If it is not specified, then any response flag will pass - // the filter check. + // Only responses with the any of the flags listed in this field will be + // logged. This field is optional. If it is not specified, then any response + // flag will pass the filter check. repeated string flags = 1 [(validate.rules).repeated = { items { string { @@ -248,8 +259,8 @@ message ResponseFlagFilter { }]; } -// Filters gRPC requests based on their response status. If a gRPC status is not provided, the -// filter will infer the status from the HTTP status code. +// Filters gRPC requests based on their response status. If a gRPC status is not +// provided, the filter will infer the status from the HTTP status code. message GrpcStatusFilter { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.accesslog.v2.GrpcStatusFilter"; @@ -277,11 +288,32 @@ message GrpcStatusFilter { // Logs only responses that have any one of the gRPC statuses in this field. repeated Status statuses = 1 [(validate.rules).repeated = {items {enum {defined_only: true}}}]; - // If included and set to true, the filter will instead block all responses with a gRPC status or - // inferred gRPC status enumerated in statuses, and allow all other responses. + // If included and set to true, the filter will instead block all responses + // with a gRPC status or inferred gRPC status enumerated in statuses, and + // allow all other responses. bool exclude = 2; } +// Filters based on matching dynamic metadata. +// If the matcher path and key correspond to an existing key in dynamic +// metadata, the request is logged only if the matcher value is equal to the +// metadata value. If the matcher path and key *do not* correspond to an +// existing key in dynamic metadata, the request is logged only if +// match_if_key_not_found is "true" or unset. +message MetadataFilter { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.filter.accesslog.v2.MetadataFilter"; + + // Matcher to check metadata for specified value. For example, to match on the + // access_log_hint metadata, set the filter to "envoy.common" and the path to + // "access_log_hint", and the value to "true". + type.matcher.v3.MetadataMatcher matcher = 1; + + // Default result if the key does not exist in dynamic metadata: if unset or + // true, then log; if false, then don't log. + google.protobuf.BoolValue match_if_key_not_found = 2; +} + // Extension filter is statically registered at runtime. message ExtensionFilter { option (udpa.annotations.versioning).previous_message_type = diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/cluster/v3/cluster.proto b/xds/third_party/envoy/src/main/proto/envoy/config/cluster/v3/cluster.proto index b4ea53bb093..3571ccf9abb 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/cluster/v3/cluster.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/cluster/v3/cluster.proto @@ -43,7 +43,7 @@ message ClusterCollection { } // Configuration for a single upstream cluster. -// [#next-free-field: 50] +// [#next-free-field: 53] message Cluster { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Cluster"; @@ -246,6 +246,20 @@ message Cluster { // List of keys to match with the weighted cluster metadata. repeated string keys = 1; + // Selects a mode of operation in which each subset has only one host. This mode uses the same rules for + // choosing a host, but updating hosts is faster, especially for large numbers of hosts. + // + // If a match is found to a host, that host will be used regardless of priority levels, unless the host is unhealthy. + // + // Currently, this mode is only supported if `subset_selectors` has only one entry, and `keys` contains + // only one entry. + // + // When this mode is enabled, configurations that contain more than one host with the same metadata value for the single key in `keys` + // will use only one of the hosts with the given key; no requests will be routed to the others. The cluster gauge + // :ref:`lb_subsets_single_host_per_subset_duplicate` indicates how many duplicates are + // present in the current configuration. + bool single_host_per_subset = 4; + // The behavior used when no endpoint subset matches the selected route's // metadata. LbSubsetSelectorFallbackPolicy fallback_policy = 2 @@ -396,6 +410,16 @@ message Cluster { google.protobuf.UInt64Value maximum_ring_size = 4 [(validate.rules).uint64 = {lte: 8388608}]; } + // Specific configuration for the :ref:`Maglev` + // load balancing policy. + message MaglevLbConfig { + // The table size for Maglev hashing. The Maglev aims for ‘minimal disruption’ rather than an absolute guarantee. + // Minimal disruption means that when the set of upstreams changes, a connection will likely be sent to the same + // upstream as it was before. Increasing the table size reduces the amount of disruption. + // The table size must be prime number. If it is not specified, the default is 65537. + google.protobuf.UInt64Value table_size = 1; + } + // Specific configuration for the // :ref:`Original Destination ` // load balancing policy. @@ -462,6 +486,26 @@ message Cluster { // If set to `true`, the cluster will use hostname instead of the resolved // address as the key to consistently hash to an upstream host. Only valid for StrictDNS clusters with hostnames which resolve to a single IP address. bool use_hostname_for_hashing = 1; + + // Configures percentage of average cluster load to bound per upstream host. For example, with a value of 150 + // no upstream host will get a load more than 1.5 times the average load of all the hosts in the cluster. + // If not specified, the load is not bounded for any upstream host. Typical value for this parameter is between 120 and 200. + // Minimum is 100. + // + // Applies to both Ring Hash and Maglev load balancers. + // + // This is implemented based on the method described in the paper https://arxiv.org/abs/1608.01350. For the specified + // `hash_balance_factor`, requests to any upstream host are capped at `hash_balance_factor/100` times the average number of requests + // across the cluster. When a request arrives for an upstream host that is currently serving at its max capacity, linear probing + // is used to identify an eligible host. Further, the linear probe is implemented using a random jump in hosts ring/table to identify + // the eligible host (this technique is as described in the paper https://arxiv.org/abs/1908.08762 - the random jump avoids the + // cascading overflow effect when choosing the next host in the ring/table). + // + // If weights are specified on the hosts, they are respected. + // + // This is an O(N) algorithm, unlike other load balancers. Using a lower `hash_balance_factor` results in more hosts + // being probed, so use a higher value if you require better performance. + google.protobuf.UInt32Value hash_balance_factor = 2 [(validate.rules).uint32 = {gte: 100}]; } // Configures the :ref:`healthy panic threshold `. @@ -519,7 +563,7 @@ message Cluster { // connections to upstream hosts whenever hosts are added or removed from the cluster. bool close_connections_on_host_set_change = 6; - //Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) + // Common Configuration for all consistent hashing load balancers (MaglevLb, RingHashLb, etc.) ConsistentHashingLbConfig consistent_hashing_lb_config = 7; } @@ -541,6 +585,36 @@ message Cluster { google.protobuf.Duration max_interval = 2 [(validate.rules).duration = {gt {nanos: 1000000}}]; } + // [#not-implemented-hide:] + message PrefetchPolicy { + // Indicates how many streams (rounded up) can be anticipated per-upstream for each + // incoming stream. This is useful for high-QPS or latency-sensitive services. Prefetching + // will only be done if the upstream is healthy. + // + // For example if this is 2, for an incoming HTTP/1.1 stream, 2 connections will be + // established, one for the new incoming stream, and one for a presumed follow-up stream. For + // HTTP/2, only one connection would be established by default as one connection can + // serve both the original and presumed follow-up stream. + // + // In steady state for non-multiplexed connections a value of 1.5 would mean if there were 100 + // active streams, there would be 100 connections in use, and 50 connections prefetched. + // This might be a useful value for something like short lived single-use connections, + // for example proxying HTTP/1.1 if keep-alive were false and each stream resulted in connection + // termination. It would likely be overkill for long lived connections, such as TCP proxying SMTP + // or regular HTTP/1.1 with keep-alive. For long lived traffic, a value of 1.05 would be more + // reasonable, where for every 100 connections, 5 prefetched connections would be in the queue + // in case of unexpected disconnects where the connection could not be reused. + // + // If this value is not set, or set explicitly to one, Envoy will fetch as many connections + // as needed to serve streams in flight. This means in steady state if a connection is torn down, + // a subsequent streams will pay an upstream-rtt latency penalty waiting for streams to be + // prefetched. + // + // This is limited somewhat arbitrarily to 3 because prefetching connections too aggressively can + // harm latency more than the prefetching helps. + google.protobuf.DoubleValue prefetch_ratio = 1 [(validate.rules).double = {lte: 3.0 gte: 1.0}]; + } + reserved 12, 15, 7, 11, 35; reserved "hosts", "tls_context", "extension_protocol_options"; @@ -766,15 +840,19 @@ message Cluster { // Optional configuration for the load balancing algorithm selected by // LbPolicy. Currently only - // :ref:`RING_HASH` and + // :ref:`RING_HASH`, + // :ref:`MAGLEV` and // :ref:`LEAST_REQUEST` // has additional configuration options. - // Specifying ring_hash_lb_config or least_request_lb_config without setting the corresponding + // Specifying ring_hash_lb_config or maglev_lb_config or least_request_lb_config without setting the corresponding // LbPolicy will generate an error at runtime. oneof lb_config { // Optional configuration for the Ring Hash load balancing policy. RingHashLbConfig ring_hash_lb_config = 23; + // Optional configuration for the Maglev load balancing policy. + MaglevLbConfig maglev_lb_config = 52; + // Optional configuration for the Original Destination load balancing policy. OriginalDstLbConfig original_dst_lb_config = 34; @@ -884,6 +962,14 @@ message Cluster { // Configuration to track optional cluster stats. TrackClusterStats track_cluster_stats = 49; + + // [#not-implemented-hide:] + // Prefetch configuration for this cluster. + PrefetchPolicy prefetch_policy = 50; + + // If `connection_pool_per_downstream_connection` is true, the cluster will use a separate + // connection pool for every downstream connection + bool connection_pool_per_downstream_connection = 51; } // [#not-implemented-hide:] Extensible load balancing policy configuration. diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/address.proto b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/address.proto index 5102c2d5759..030b68e6948 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/address.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/address.proto @@ -30,6 +30,17 @@ message Pipe { uint32 mode = 2 [(validate.rules).uint32 = {lte: 511}]; } +// [#not-implemented-hide:] The address represents an envoy internal listener. +// TODO(lambdai): Make this address available for listener and endpoint. +message EnvoyInternalAddress { + oneof address_name_specifier { + option (validate.required) = true; + + // [#not-implemented-hide:] The :ref:`listener name ` of the destination internal listener. + string server_listener_name = 1; + } +} + // [#next-free-field: 7] message SocketAddress { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.SocketAddress"; @@ -129,6 +140,9 @@ message Address { SocketAddress socket_address = 1; Pipe pipe = 2; + + // [#not-implemented-hide:] + EnvoyInternalAddress envoy_internal_address = 3; } } diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/base.proto b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/base.proto index 4509c166256..15a17b49384 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/base.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/base.proto @@ -196,7 +196,7 @@ message Node { // for filtering :ref:`listeners ` to be returned. For example, // if there is a listener bound to port 80, the list can optionally contain the // SocketAddress `(0.0.0.0,80)`. The field is optional and just a hint. - repeated Address listening_addresses = 11; + repeated Address listening_addresses = 11 [deprecated = true]; } // Metadata provides additional inputs to filters based on matched listeners, @@ -293,7 +293,7 @@ message HeaderValueOption { HeaderValue header = 1 [(validate.rules).message = {required: true}]; // Should the value be appended? If true (default), the value is appended to - // existing values. + // existing values. Otherwise it replaces any existing values. google.protobuf.BoolValue append = 2; } diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/grpc_service.proto b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/grpc_service.proto index 3f62884df6e..967c694d2bc 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/grpc_service.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/grpc_service.proto @@ -36,6 +36,12 @@ message GrpcService { // in the :ref:`Cluster ` :ref:`transport_socket // `. string cluster_name = 1 [(validate.rules).string = {min_bytes: 1}]; + + // The `:authority` header in the grpc request. If this field is not set, the authority header value will be `cluster_name`. + // Note that this authority does not override the SNI. The SNI is provided by the transport socket of the cluster. + string authority = 2 + [(validate.rules).string = + {min_bytes: 0 max_bytes: 16384 well_known_regex: HTTP_HEADER_VALUE strict: false}]; } // [#next-free-field: 9] diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/protocol.proto b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/protocol.proto index 0ab6289e965..3e20f3b449a 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/protocol.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/protocol.proto @@ -100,7 +100,7 @@ message HttpProtocolOptions { HeadersWithUnderscoresAction headers_with_underscores_action = 5; } -// [#next-free-field: 6] +// [#next-free-field: 8] message Http1ProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.Http1ProtocolOptions"; @@ -157,6 +157,24 @@ message Http1ProtocolOptions { // - Not a response to a HEAD request. // - The content length header is not present. bool enable_trailers = 5; + + // Allows Envoy to process requests/responses with both `Content-Length` and `Transfer-Encoding` + // headers set. By default such messages are rejected, but if option is enabled - Envoy will + // remove Content-Length header and process message. + // See `RFC7230, sec. 3.3.3 ` for details. + // + // .. attention:: + // Enabling this option might lead to request smuggling vulnerability, especially if traffic + // is proxied via multiple layers of proxies. + bool allow_chunked_length = 6; + + // Allows invalid HTTP messaging. When this option is false, then Envoy will terminate + // HTTP/1.1 connections upon receiving an invalid HTTP message. However, + // when this option is true, then Envoy will leave the HTTP/1.1 connection + // open where possible. + // If set, this overrides any HCM :ref:`stream_error_on_invalid_http_messaging + // `. + google.protobuf.BoolValue override_stream_error_on_invalid_http_message = 7; } // [#next-free-field: 15] diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/substitution_format_string.proto b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/substitution_format_string.proto index 7537a1178b6..6c129707b2e 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/substitution_format_string.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/core/v3/substitution_format_string.proto @@ -58,4 +58,11 @@ message SubstitutionFormatString { // google.protobuf.Struct json_format = 2 [(validate.rules).message = {required: true}]; } + + // If set to true, when command operators are evaluated to null, + // + // * for ``text_format``, the output of the empty operator is changed from ``-`` to an + // empty string, so that empty values are omitted entirely. + // * for ``json_format`` the keys with null values are omitted in the output structure. + bool omit_empty_values = 3; } diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener.proto b/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener.proto index ab0b0ecac7c..dab0eb1ce68 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener.proto @@ -5,6 +5,7 @@ package envoy.config.listener.v3; import "envoy/config/accesslog/v3/accesslog.proto"; import "envoy/config/core/v3/address.proto"; import "envoy/config/core/v3/base.proto"; +import "envoy/config/core/v3/extension.proto"; import "envoy/config/core/v3/socket_option.proto"; import "envoy/config/listener/v3/api_listener.proto"; import "envoy/config/listener/v3/listener_components.proto"; @@ -32,10 +33,10 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Listener list collections. Entries are *Listener* resources or references. // [#not-implemented-hide:] message ListenerCollection { - udpa.core.v1.CollectionEntry entries = 1; + repeated udpa.core.v1.CollectionEntry entries = 1; } -// [#next-free-field: 23] +// [#next-free-field: 25] message Listener { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.Listener"; @@ -248,4 +249,18 @@ message Listener { // Configuration for :ref:`access logs ` // emitted by this listener. repeated accesslog.v3.AccessLog access_log = 22; + + // If the protocol in the listener socket address in :ref:`protocol + // ` is :ref:`UDP + // `, this field specifies the actual udp + // writer to create, i.e. :ref:`name ` + // = "udp_default_writer" for creating a udp writer with writing in passthrough mode, + // = "udp_gso_batch_writer" for creating a udp writer with writing in batch mode. + // If not present, treat it as "udp_default_writer". + // [#not-implemented-hide:] + core.v3.TypedExtensionConfig udp_writer_config = 23; + + // The maximum length a tcp listener's pending connections queue can grow to. If no value is + // provided net.core.somaxconn will be used on Linux and 128 otherwise. + google.protobuf.UInt32Value tcp_backlog_size = 24; } diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener_components.proto b/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener_components.proto index 88e75e65b52..8a22fbc97f5 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener_components.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/listener/v3/listener_components.proto @@ -7,6 +7,7 @@ import "envoy/config/core/v3/base.proto"; import "envoy/type/v3/range.proto"; import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/wrappers.proto"; @@ -167,10 +168,25 @@ message FilterChainMatch { // A filter chain wraps a set of match criteria, an option TLS context, a set of filters, and // various other parameters. -// [#next-free-field: 8] +// [#next-free-field: 9] message FilterChain { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.listener.FilterChain"; + // The configuration for on-demand filter chain. If this field is not empty in FilterChain message, + // a filter chain will be built on-demand. + // On-demand filter chains help speedup the warming up of listeners since the building and initialization of + // an on-demand filter chain will be postponed to the arrival of new connection requests that require this filter chain. + // Filter chains that are not often used can be set as on-demand. + message OnDemandConfiguration { + // The timeout to wait for filter chain placeholders to complete rebuilding. + // 1. If this field is set to 0, timeout is disabled. + // 2. If not specified, a default timeout of 15s is used. + // Rebuilding will wait until dependencies are ready, have failed, or this timeout is reached. + // Upon failure or timeout, all connections related to this filter chain will be closed. + // Rebuilding will start again on the next new connection. + google.protobuf.Duration rebuild_timeout = 1; + } + reserved 2; reserved "tls_context"; @@ -206,6 +222,11 @@ message FilterChain { // name is provided, Envoy will allocate an internal UUID for the filter chain. If the filter // chain is to be dynamically updated or removed via FCDS a unique name must be provided. string name = 7; + + // [#not-implemented-hide:] The configuration to specify whether the filter chain will be built on-demand. + // If this field is not empty, the filter chain will be built on-demand. + // Otherwise, the filter chain will be built normally and block listener warming. + OnDemandConfiguration on_demand_configuration = 8; } // Listener filter chain match configuration. This is a recursive structure which allows complex diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/route_components.proto b/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/route_components.proto index c35e210691c..0d1d7cf4c43 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/route_components.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/route_components.proto @@ -338,7 +338,9 @@ message WeightedCluster { // Specifies a list of HTTP headers that should be removed from each request when // this cluster is selected through the enclosing :ref:`envoy_api_msg_config.route.v3.RouteAction`. - repeated string request_headers_to_remove = 9; + repeated string request_headers_to_remove = 9 [(validate.rules).repeated = { + items {string {well_known_regex: HTTP_HEADER_NAME strict: false}} + }]; // Specifies a list of headers to be added to responses when this cluster is selected // through the enclosing :ref:`envoy_api_msg_config.route.v3.RouteAction`. @@ -352,7 +354,9 @@ message WeightedCluster { // Specifies a list of headers to be removed from responses when this cluster is selected // through the enclosing :ref:`envoy_api_msg_config.route.v3.RouteAction`. - repeated string response_headers_to_remove = 6; + repeated string response_headers_to_remove = 6 [(validate.rules).repeated = { + items {string {well_known_regex: HTTP_HEADER_NAME strict: false}} + }]; // The per_filter_config field can be used to provide weighted cluster-specific // configurations for filters. The key should match the filter name, such as @@ -440,14 +444,14 @@ message RouteMatch { // (WebSocket and the like) as they are normalized in Envoy as HTTP/1.1 style // upgrades. // This is the only way to match CONNECT requests for HTTP/1.1. For HTTP/2, - // where CONNECT requests may have a path, the path matchers will work if + // where Extended CONNECT requests may have a path, the path matchers will work if // there is a path present. // Note that CONNECT support is currently considered alpha in Envoy. // [#comment:TODO(htuch): Replace the above comment with an alpha tag. ConnectMatcher connect_matcher = 12; } - // Indicates that prefix/path matching should be case insensitive. The default + // Indicates that prefix/path matching should be case sensitive. The default // is true. google.protobuf.BoolValue case_sensitive = 4; @@ -545,7 +549,7 @@ message CorsPolicy { core.v3.RuntimeFractionalPercent shadow_enabled = 10; } -// [#next-free-field: 35] +// [#next-free-field: 37] message RouteAction { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RouteAction"; @@ -760,6 +764,31 @@ message RouteAction { ConnectConfig connect_config = 3; } + // [#not-implemented-hide:] + message MaxStreamDuration { + // Specifies the maximum duration allowed for streams on the route. If not specified, the value + // from the :ref:`max_stream_duration + // ` field in + // :ref:`HttpConnectionManager.common_http_protocol_options + // ` + // is used. + google.protobuf.Duration max_stream_duration = 1; + + // If present, and the request contains a `grpc-timeout header + // `_, use that value as the + // *max_stream_duration*, but limit the applied timeout to the maximum value specified here. + // If set to 0, the `grpc-timeout` header is used without modification. + google.protobuf.Duration grpc_max_timeout = 2; + + // If present, Envoy will adjust the timeout provided by the `grpc-timeout` header by + // subtracting the provided duration from the header. This is useful for allowing Envoy to set + // its global timeout to be less than that of the deadline imposed by the calling client, which + // makes it more likely that Envoy will handle the timeout instead of having the call canceled + // by the client. If, after applying the offset, the resulting timeout is zero or negative, + // the stream will timeout immediately. + google.protobuf.Duration grpc_timeout_offset = 3; + } + reserved 12, 18, 19, 16, 22, 21, 10; reserved "request_mirror_policy"; @@ -890,6 +919,23 @@ message RouteAction { // must come from trusted source. string host_rewrite_header = 29 [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false}]; + + // Indicates that during forwarding, the host header will be swapped with + // the result of the regex substitution executed on path value with query and fragment removed. + // This is useful for transitioning variable content between path segment and subdomain. + // + // For example with the following config: + // + // .. code-block:: yaml + // + // host_rewrite_path_regex: + // pattern: + // google_re2: {} + // regex: "^/(.+)/.+$" + // substitution: \1 + // + // Would rewrite the host header to `envoyproxy.io` given the path `/envoyproxy.io/some/path`. + type.matcher.v3.RegexMatchAndSubstitute host_rewrite_path_regex = 35; } // Specifies the upstream timeout for the route. If not specified, the default is 15s. This @@ -951,7 +997,9 @@ message RouteAction { // limits. By default, if the route configured rate limits, the virtual host // :ref:`rate_limits ` are not applied to the // request. - google.protobuf.BoolValue include_vh_rate_limits = 14; + // + // This field is deprecated. Please use :ref:`vh_rate_limits ` + google.protobuf.BoolValue include_vh_rate_limits = 14 [deprecated = true]; // Specifies a list of hash policies to use for ring hash load balancing. Each // hash policy is evaluated individually and the combined result is used to @@ -1030,13 +1078,22 @@ message RouteAction { // it'll take precedence over the virtual host level hedge policy entirely // (e.g.: policies are not merged, most internal one becomes the enforced policy). HedgePolicy hedge_policy = 27; + + // Specifies the maximum stream duration for this route. + // [#not-implemented-hide:] + MaxStreamDuration max_stream_duration = 36; } // HTTP retry :ref:`architecture overview `. -// [#next-free-field: 11] +// [#next-free-field: 12] message RetryPolicy { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RetryPolicy"; + enum ResetHeaderFormat { + SECONDS = 0; + UNIX_TIMESTAMP = 1; + } + message RetryPriority { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RetryPolicy.RetryPriority"; @@ -1087,6 +1144,69 @@ message RetryPolicy { google.protobuf.Duration max_interval = 2 [(validate.rules).duration = {gt {}}]; } + message ResetHeader { + string name = 1 + [(validate.rules).string = {min_bytes: 1 well_known_regex: HTTP_HEADER_NAME strict: false}]; + + ResetHeaderFormat format = 2 [(validate.rules).enum = {defined_only: true}]; + } + + // A retry back-off strategy that applies when the upstream server rate limits + // the request. + // + // Given this configuration: + // + // .. code-block:: yaml + // + // rate_limited_retry_back_off: + // reset_headers: + // - name: Retry-After + // format: SECONDS + // - name: X-RateLimit-Reset + // format: UNIX_TIMESTAMP + // max_interval: "300s" + // + // The following algorithm will apply: + // + // 1. If the response contains the header ``Retry-After`` its value must be on + // the form ``120`` (an integer that represents the number of seconds to + // wait before retrying). If so, this value is used as the back-off interval. + // 2. Otherwise, if the response contains the header ``X-RateLimit-Reset`` its + // value must be on the form ``1595320702`` (an integer that represents the + // point in time at which to retry, as a Unix timestamp in seconds). If so, + // the current time is subtracted from this value and the result is used as + // the back-off interval. + // 3. Otherwise, Envoy will use the default + // :ref:`exponential back-off ` + // strategy. + // + // No matter which format is used, if the resulting back-off interval exceeds + // ``max_interval`` it is discarded and the next header in ``reset_headers`` + // is tried. If a request timeout is configured for the route it will further + // limit how long the request will be allowed to run. + // + // To prevent many clients retrying at the same point in time jitter is added + // to the back-off interval, so the resulting interval is decided by taking: + // ``random(interval, interval * 1.5)``. + // + // .. attention:: + // + // Configuring ``rate_limited_retry_back_off`` will not by itself cause a request + // to be retried. You will still need to configure the right retry policy to match + // the responses from the upstream server. + message RateLimitedRetryBackOff { + // Specifies the reset headers (like ``Retry-After`` or ``X-RateLimit-Reset``) + // to match against the response. Headers are tried in order, and matched case + // insensitive. The first header to be parsed successfully is used. If no headers + // match the default exponential back-off is used instead. + repeated ResetHeader reset_headers = 1 [(validate.rules).repeated = {min_items: 1}]; + + // Specifies the maximum back off interval that Envoy will allow. If a reset + // header contains an interval longer than this then it will be discarded and + // the next header will be tried. Defaults to 300 seconds. + google.protobuf.Duration max_interval = 2 [(validate.rules).duration = {gt {}}]; + } + // Specifies the conditions under which retry takes place. These are the same // conditions documented for :ref:`config_http_filters_router_x-envoy-retry-on` and // :ref:`config_http_filters_router_x-envoy-retry-grpc-on`. @@ -1130,13 +1250,22 @@ message RetryPolicy { // HTTP status codes that should trigger a retry in addition to those specified by retry_on. repeated uint32 retriable_status_codes = 7; - // Specifies parameters that control retry back off. This parameter is optional, in which case the + // Specifies parameters that control exponential retry back off. This parameter is optional, in which case the // default base interval is 25 milliseconds or, if set, the current value of the // `upstream.base_retry_backoff_ms` runtime parameter. The default maximum interval is 10 times // the base interval. The documentation for :ref:`config_http_filters_router_x-envoy-max-retries` // describes Envoy's back-off algorithm. RetryBackOff retry_back_off = 8; + // Specifies parameters that control a retry back-off strategy that is used + // when the request is rate limited by the upstream server. The server may + // return a response header like ``Retry-After`` or ``X-RateLimit-Reset`` to + // provide feedback to the client on how long to wait before retrying. If + // configured, this back-off strategy will be used instead of the + // default exponential back off strategy (configured using `retry_back_off`) + // whenever a response includes the matching headers. + RateLimitedRetryBackOff rate_limited_retry_back_off = 11; + // HTTP response headers that trigger a retry if present in the response. A retry will be // triggered if any of the header matches match the upstream response headers. // The field is only consulted if 'retriable-headers' retry policy is active. @@ -1452,6 +1581,10 @@ message RateLimit { // The value to use in the descriptor entry. string descriptor_value = 1 [(validate.rules).string = {min_bytes: 1}]; + + // An optional key to use in the descriptor entry. If not set it defaults + // to 'generic_key' as the descriptor key. + string descriptor_key = 2; } // The following descriptor entry is appended to the descriptor: @@ -1593,7 +1726,7 @@ message RateLimit { // value. // // [#next-major-version: HeaderMatcher should be refactored to use StringMatcher.] -// [#next-free-field: 12] +// [#next-free-field: 13] message HeaderMatcher { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.HeaderMatcher"; @@ -1647,6 +1780,15 @@ message HeaderMatcher { // // * The suffix *abcd* matches the value *xyzabcd*, but not for *xyzbcd*. string suffix_match = 10 [(validate.rules).string = {min_bytes: 1}]; + + // If specified, header match will be performed based on whether the header value contains + // the given value or not. + // Note: empty contains match is not allowed, please use present_match instead. + // + // Examples: + // + // * The value *abcd* matches the value *xyzabcdpqr*, but not for *xyzbcdpqr*. + string contains_match = 12 [(validate.rules).string = {min_bytes: 1}]; } // If specified, the match result will be inverted before checking. Defaults to false. diff --git a/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/scoped_route.proto b/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/scoped_route.proto index f2b28ed974c..d6611b0b1d0 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/scoped_route.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/config/route/v3/scoped_route.proto @@ -104,6 +104,9 @@ message ScopedRouteConfiguration { repeated Fragment fragments = 1 [(validate.rules).repeated = {min_items: 1}]; } + // Whether the RouteConfiguration should be loaded on demand. + bool on_demand = 4; + // The name assigned to the routing scope. string name = 1 [(validate.rules).string = {min_bytes: 1}]; diff --git a/xds/third_party/envoy/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto b/xds/third_party/envoy/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto index 04a132ad267..68c5c8cad2a 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto @@ -298,7 +298,8 @@ message HttpConnectionManager { // An optional override that the connection manager will write to the server // header in responses. If not set, the default is *envoy*. - string server_name = 10; + string server_name = 10 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}]; // Defines the action to be applied to the Server header on the response path. // By default, Envoy will overwrite the header with the value specified in @@ -552,7 +553,8 @@ message HttpConnectionManager { // company-internal mesh) and false when receiving untrusted traffic (edge deployments). // // If different behaviors for invalid_http_message for HTTP/1 and HTTP/2 are - // desired, one *must* use the new HTTP/2 option + // desired, one should use the new HTTP/1 option :ref:`override_stream_error_on_invalid_http_message + // ` or the new HTTP/2 option // :ref:`override_stream_error_on_invalid_http_message // ` // *not* the deprecated but similarly named :ref:`stream_error_on_invalid_http_messaging diff --git a/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto b/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto index 115ecad72f9..5eab3c1060b 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto @@ -224,7 +224,10 @@ message CertificateValidationContext { // specified. // // It can optionally contain certificate revocation lists, in which case Envoy will verify - // that the presented peer certificate has not been revoked by one of the included CRLs. + // that the presented peer certificate has not been revoked by one of the included CRLs. Note + // that if a CRL is provided for any certificate authority in a trust chain, a CRL must be + // provided for all certificate authorities in that chain. Failure to do so will result in + // verification failure for both revoked and unrevoked certificates from that chain. // // See :ref:`the TLS overview ` for a list of common // system CA locations. @@ -322,7 +325,11 @@ message CertificateValidationContext { // `_ // (in PEM format). If specified, Envoy will verify that the presented peer // certificate has not been revoked by this CRL. If this DataSource contains - // multiple CRLs, all of them will be used. + // multiple CRLs, all of them will be used. Note that if a CRL is provided + // for any certificate authority in a trust chain, a CRL must be provided + // for all certificate authorities in that chain. Failure to do so will + // result in verification failure for both revoked and unrevoked certificates + // from that chain. config.core.v3.DataSource crl = 7; // If specified, Envoy will not reject expired certificates. diff --git a/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto b/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto index 7ee7920c724..f746f3d2f1c 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto @@ -99,7 +99,7 @@ message DownstreamTlsContext { } // TLS context shared by both client and server TLS contexts. -// [#next-free-field: 13] +// [#next-free-field: 14] message CommonTlsContext { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.auth.CommonTlsContext"; @@ -238,4 +238,8 @@ message CommonTlsContext { // // There is no default for this parameter. If empty, Envoy will not expose ALPN. repeated string alpn_protocols = 4; + + // Custom TLS handshaker. If empty, defaults to native TLS handshaking + // behavior. + config.core.v3.TypedExtensionConfig custom_handshaker = 13; } diff --git a/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/metadata.proto b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/metadata.proto new file mode 100644 index 00000000000..65ec4f47fff --- /dev/null +++ b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/metadata.proto @@ -0,0 +1,104 @@ +syntax = "proto3"; + +package envoy.type.matcher.v3; + +import "envoy/type/matcher/v3/value.proto"; + +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.type.matcher.v3"; +option java_outer_classname = "MetadataProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Metadata matcher] + +// MetadataMatcher provides a general interface to check if a given value is matched in +// :ref:`Metadata `. It uses `filter` and `path` to retrieve the value +// from the Metadata and then check if it's matched to the specified value. +// +// For example, for the following Metadata: +// +// .. code-block:: yaml +// +// filter_metadata: +// envoy.filters.http.rbac: +// fields: +// a: +// struct_value: +// fields: +// b: +// struct_value: +// fields: +// c: +// string_value: pro +// t: +// list_value: +// values: +// - string_value: m +// - string_value: n +// +// The following MetadataMatcher is matched as the path [a, b, c] will retrieve a string value "pro" +// from the Metadata which is matched to the specified prefix match. +// +// .. code-block:: yaml +// +// filter: envoy.filters.http.rbac +// path: +// - key: a +// - key: b +// - key: c +// value: +// string_match: +// prefix: pr +// +// The following MetadataMatcher is matched as the code will match one of the string values in the +// list at the path [a, t]. +// +// .. code-block:: yaml +// +// filter: envoy.filters.http.rbac +// path: +// - key: a +// - key: t +// value: +// list_match: +// one_of: +// string_match: +// exact: m +// +// An example use of MetadataMatcher is specifying additional metadata in envoy.filters.http.rbac to +// enforce access control based on dynamic metadata in a request. See :ref:`Permission +// ` and :ref:`Principal +// `. + +// [#next-major-version: MetadataMatcher should use StructMatcher] +message MetadataMatcher { + option (udpa.annotations.versioning).previous_message_type = "envoy.type.matcher.MetadataMatcher"; + + // Specifies the segment in a path to retrieve value from Metadata. + // Note: Currently it's not supported to retrieve a value from a list in Metadata. This means that + // if the segment key refers to a list, it has to be the last segment in a path. + message PathSegment { + option (udpa.annotations.versioning).previous_message_type = + "envoy.type.matcher.MetadataMatcher.PathSegment"; + + oneof segment { + option (validate.required) = true; + + // If specified, use the key to retrieve the value in a Struct. + string key = 1 [(validate.rules).string = {min_bytes: 1}]; + } + } + + // The filter name to retrieve the Struct from the Metadata. + string filter = 1 [(validate.rules).string = {min_bytes: 1}]; + + // The path to retrieve the Value from the Struct. + repeated PathSegment path = 2 [(validate.rules).repeated = {min_items: 1}]; + + // The MetadataMatcher is matched if the value retrieved by path is matched to this value. + ValueMatcher value = 3 [(validate.rules).message = {required: true}]; +} diff --git a/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/number.proto b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/number.proto new file mode 100644 index 00000000000..2379efdcbd2 --- /dev/null +++ b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/number.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package envoy.type.matcher.v3; + +import "envoy/type/v3/range.proto"; + +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.type.matcher.v3"; +option java_outer_classname = "NumberProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Number matcher] + +// Specifies the way to match a double value. +message DoubleMatcher { + option (udpa.annotations.versioning).previous_message_type = "envoy.type.matcher.DoubleMatcher"; + + oneof match_pattern { + option (validate.required) = true; + + // If specified, the input double value must be in the range specified here. + // Note: The range is using half-open interval semantics [start, end). + type.v3.DoubleRange range = 1; + + // If specified, the input double value must be equal to the value specified here. + double exact = 2; + } +} diff --git a/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/string.proto b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/string.proto index 77fe48ac74c..d453d43d3f8 100644 --- a/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/string.proto +++ b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/string.proto @@ -17,7 +17,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: String matcher] // Specifies the way to match a string. -// [#next-free-field: 7] +// [#next-free-field: 8] message StringMatcher { option (udpa.annotations.versioning).previous_message_type = "envoy.type.matcher.StringMatcher"; @@ -53,6 +53,14 @@ message StringMatcher { // The input string must match the regular expression specified here. RegexMatcher safe_regex = 5 [(validate.rules).message = {required: true}]; + + // The input string must have the substring specified here. + // Note: empty contains match is not allowed, please use regex instead. + // + // Examples: + // + // * *abc* matches the value *xyz.abc.def* + string contains = 7 [(validate.rules).string = {min_bytes: 1}]; } // If true, indicates the exact/prefix/suffix matching should be case insensitive. This has no diff --git a/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/value.proto b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/value.proto new file mode 100644 index 00000000000..040332273ba --- /dev/null +++ b/xds/third_party/envoy/src/main/proto/envoy/type/matcher/v3/value.proto @@ -0,0 +1,71 @@ +syntax = "proto3"; + +package envoy.type.matcher.v3; + +import "envoy/type/matcher/v3/number.proto"; +import "envoy/type/matcher/v3/string.proto"; + +import "udpa/annotations/status.proto"; +import "udpa/annotations/versioning.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.type.matcher.v3"; +option java_outer_classname = "ValueProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Value matcher] + +// Specifies the way to match a ProtobufWkt::Value. Primitive values and ListValue are supported. +// StructValue is not supported and is always not matched. +// [#next-free-field: 7] +message ValueMatcher { + option (udpa.annotations.versioning).previous_message_type = "envoy.type.matcher.ValueMatcher"; + + // NullMatch is an empty message to specify a null value. + message NullMatch { + option (udpa.annotations.versioning).previous_message_type = + "envoy.type.matcher.ValueMatcher.NullMatch"; + } + + // Specifies how to match a value. + oneof match_pattern { + option (validate.required) = true; + + // If specified, a match occurs if and only if the target value is a NullValue. + NullMatch null_match = 1; + + // If specified, a match occurs if and only if the target value is a double value and is + // matched to this field. + DoubleMatcher double_match = 2; + + // If specified, a match occurs if and only if the target value is a string value and is + // matched to this field. + StringMatcher string_match = 3; + + // If specified, a match occurs if and only if the target value is a bool value and is equal + // to this field. + bool bool_match = 4; + + // If specified, value match will be performed based on whether the path is referring to a + // valid primitive value in the metadata. If the path is referring to a non-primitive value, + // the result is always not matched. + bool present_match = 5; + + // If specified, a match occurs if and only if the target value is a list value and + // is matched to this field. + ListMatcher list_match = 6; + } +} + +// Specifies the way to match a list value. +message ListMatcher { + option (udpa.annotations.versioning).previous_message_type = "envoy.type.matcher.ListMatcher"; + + oneof match_pattern { + option (validate.required) = true; + + // If specified, at least one of the values in the list must match the value specified. + ValueMatcher one_of = 1; + } +}