From 804a5c5faf3edaa8819294debcbbcb29578eff28 Mon Sep 17 00:00:00 2001 From: envoy-bot Date: Wed, 15 Jul 2026 10:38:42 +0000 Subject: [PATCH] [protobuf] Update protobuf definitions to v1.39.0 Signed-off-by: envoy-bot --- .../proto/envoy/admin/v3/server_info.proto | 5 +- .../envoy/config/bootstrap/v3/bootstrap.proto | 41 ++++- .../config/cluster/v3/circuit_breaker.proto | 20 +++ .../proto/envoy/config/core/v3/base.proto | 17 ++ .../proto/envoy/config/core/v3/protocol.proto | 46 +++++- .../endpoint/v3/endpoint_components.proto | 17 +- .../envoy/config/listener/v3/listener.proto | 47 +++--- .../proto/envoy/config/metrics/v3/stats.proto | 14 ++ .../config/route/v3/route_components.proto | 54 ++++++- .../proto/envoy/config/tap/v3/common.proto | 18 ++- .../envoy/config/trace/v3/opentelemetry.proto | 16 +- .../data/core/v3/health_check_event.proto | 13 ++ .../proto/envoy/data/tap/v3/wrapper.proto | 21 +++ .../access_loggers/stats/v3/stats.proto | 12 +- ..._reverse_connection_socket_interface.proto | 30 ++++ ..._reverse_connection_socket_interface.proto | 7 +- .../clusters/dns/v3/dns_cluster.proto | 10 +- .../dynamic_forward_proxy/v3/cluster.proto | 14 +- .../original_dst/v3/original_dst.proto | 50 ++++++ .../dynamic_forward_proxy/v3/dns_cache.proto | 11 +- .../common/set_filter_state/v3/value.proto | 6 +- .../v3/ai_protocol_manager.proto | 23 +++ .../http/aws_lambda/v3/aws_lambda.proto | 38 ++++- .../bandwidth_share/v3/bandwidth_share.proto | 153 ++++++++++++++++++ .../http/basic_auth/v3/basic_auth.proto | 24 +++ .../filters/http/composite/v3/composite.proto | 18 ++- .../custom_response/v3/custom_response.proto | 35 +++- .../filters/http/ext_authz/v3/ext_authz.proto | 11 ++ .../filters/http/ext_proc/v3/ext_proc.proto | 11 ++ .../http/filter_chain/v3/filter_chain.proto | 85 ++++++++++ .../filters/http/gcp_authn/v3/gcp_authn.proto | 26 ++- .../http/ip_tagging/v3/ip_tagging.proto | 22 ++- .../filters/http/jwt_authn/v3/config.proto | 84 +++++++--- .../extensions/filters/http/mcp/v3/mcp.proto | 16 +- .../v3/mcp_json_rest_bridge.proto | 144 +++++++++++++++-- .../http/mcp_router/v3/mcp_router.proto | 7 + .../filters/http/oauth2/v3/oauth.proto | 144 ++++++++++++++++- .../http/ratelimit/v3/rate_limit.proto | 6 +- .../proxy_protocol/v3/proxy_protocol.proto | 27 ++++ .../network/ext_proc/v3/ext_proc.proto | 9 ++ .../v3/http_connection_manager.proto | 14 +- .../network/mongo_proxy/v3/mongo_proxy.proto | 7 +- .../reverse_tunnel/v3/drain_aware_hcm.proto | 6 + .../reverse_tunnel/v3/reverse_tunnel.proto | 14 +- .../network/tcp_proxy/v3/tcp_proxy.proto | 18 ++- .../session/ext_authz/v3/ext_authz.proto | 57 +++++++ .../dynamic_modules/v3/dynamic_modules.proto | 70 ++++++++ .../dynamic_modules/v3/dynamic_modules.proto | 72 +++++++++ .../v3/client_side_weighted_round_robin.proto | 7 +- .../common/v3/common.proto | 27 ++++ .../v3/load_aware_locality.proto | 95 +++++++++++ .../cares/v3/cares_dns_resolver.proto | 12 +- .../socket_interface/sockmap/v3/sockmap.proto | 64 ++++++++ .../v3/default_socket_interface.proto | 81 ++++++++-- .../uri_template/v3/uri_template_match.proto | 7 + .../fixed_heap/v3/fixed_heap.proto | 14 +- .../dynamic_modules/v3/dynamic_modules.proto | 63 ++++++++ .../open_telemetry/v3/open_telemetry.proto | 6 +- .../dynamic_modules/v3/dynamic_modules.proto | 55 +++++++ .../quic/v3/quic_transport.proto | 4 + .../transport_sockets/tls/v3/common.proto | 63 +++++++- .../transport_sockets/tls/v3/tls.proto | 11 +- .../v3/reverse_tunnel_codec.proto | 26 +++ .../v3/network_external_processor.proto | 19 ++- .../envoy/service/ratelimit/v3/rls.proto | 4 +- api/src/main/proto/envoy/type/v3/scope.proto | 45 ++++++ .../proto/envoy/type/v3/token_bucket.proto | 5 +- .../controlplane/server/EnvoyContainer.java | 2 +- tools/API_SHAS | 4 +- tools/envoy_release | 2 +- 70 files changed, 2082 insertions(+), 144 deletions(-) create mode 100644 api/src/main/proto/envoy/extensions/clusters/original_dst/v3/original_dst.proto create mode 100644 api/src/main/proto/envoy/extensions/filters/http/ai_protocol_manager/v3/ai_protocol_manager.proto create mode 100644 api/src/main/proto/envoy/extensions/filters/http/bandwidth_share/v3/bandwidth_share.proto create mode 100644 api/src/main/proto/envoy/extensions/filters/http/filter_chain/v3/filter_chain.proto create mode 100644 api/src/main/proto/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.proto create mode 100644 api/src/main/proto/envoy/extensions/formatter/dynamic_modules/v3/dynamic_modules.proto create mode 100644 api/src/main/proto/envoy/extensions/health_checkers/dynamic_modules/v3/dynamic_modules.proto create mode 100644 api/src/main/proto/envoy/extensions/load_balancing_policies/load_aware_locality/v3/load_aware_locality.proto create mode 100644 api/src/main/proto/envoy/extensions/network/socket_interface/sockmap/v3/sockmap.proto create mode 100644 api/src/main/proto/envoy/extensions/stat_sinks/dynamic_modules/v3/dynamic_modules.proto create mode 100644 api/src/main/proto/envoy/extensions/transport_sockets/dynamic_modules/v3/dynamic_modules.proto create mode 100644 api/src/main/proto/envoy/extensions/upstreams/http/reverse_tunnel/v3/reverse_tunnel_codec.proto create mode 100644 api/src/main/proto/envoy/type/v3/scope.proto diff --git a/api/src/main/proto/envoy/admin/v3/server_info.proto b/api/src/main/proto/envoy/admin/v3/server_info.proto index 3e6d32f8a..dfd3e7a20 100644 --- a/api/src/main/proto/envoy/admin/v3/server_info.proto +++ b/api/src/main/proto/envoy/admin/v3/server_info.proto @@ -62,7 +62,7 @@ message ServerInfo { bool hot_restart_initializing = 8; } -// [#next-free-field: 43] +// [#next-free-field: 44] message CommandLineOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.admin.v2alpha.CommandLineOptions"; @@ -197,6 +197,9 @@ message CommandLineOptions { // See :option:`--enable-fine-grain-logging` for details. bool enable_fine_grain_logging = 34; + // See :option:`--log-stacktrace-single-entry` for details. + bool log_stacktrace_single_entry = 43; + // See :option:`--socket-path` for details. string socket_path = 35; diff --git a/api/src/main/proto/envoy/config/bootstrap/v3/bootstrap.proto b/api/src/main/proto/envoy/config/bootstrap/v3/bootstrap.proto index 2e7458525..90c2b62d5 100644 --- a/api/src/main/proto/envoy/config/bootstrap/v3/bootstrap.proto +++ b/api/src/main/proto/envoy/config/bootstrap/v3/bootstrap.proto @@ -42,7 +42,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // ` for more detail. // Bootstrap :ref:`configuration overview `. -// [#next-free-field: 43] +// [#next-free-field: 44] message Bootstrap { option (udpa.annotations.versioning).previous_message_type = "envoy.config.bootstrap.v2.Bootstrap"; @@ -433,6 +433,17 @@ message Bootstrap { // Optional configuration for memory allocation manager. // Memory releasing is only supported for `tcmalloc allocator `_. MemoryAllocatorManager memory_allocator_manager = 41; + + // When enabled, Envoy pins each worker thread to a distinct CPU from the process affinity mask, + // worker ``i`` to the ``i-th`` CPU in ascending order. This improves CPU cache and ``NUMA`` + // locality for high concurrency deployments on bare metal. It is available on Linux only and is + // ignored on other platforms. Pinning requires a worker count no greater than the number of CPUs + // in the process affinity mask. When the worker count exceeds the available CPUs no worker is + // pinned. Pinning is applied once when the workers start, so a later change to the process + // affinity mask does not re-pin. + // + // Defaults to ``false``. + bool enable_worker_cpu_affinity = 43; } // Administration interface :ref:`operations documentation @@ -813,3 +824,31 @@ message MemoryAllocatorManager { // Defaults to ``104857600`` (100 MB). uint64 max_unfreed_memory_bytes = 5; } + +// A placeholder proto so that users can explicitly configure the standard +// Listener Manager via the bootstrap's :ref:`listener_manager `. +// [#not-implemented-hide:] +message ListenerManager { +} + +// A placeholder proto so that users can explicitly configure the standard +// Validation Listener Manager via the bootstrap's :ref:`listener_manager `. +// [#not-implemented-hide:] +message ValidationListenerManager { +} + +// A placeholder proto so that users can explicitly configure the API +// Listener Manager via the bootstrap's :ref:`listener_manager `. +// [#not-implemented-hide:] +message ApiListenerManager { + enum ThreadingModel { + // Handle HTTP requests on the main Envoy thread which also processes platform-raised events and runs xDS clients. + MAIN_THREAD_ONLY = 0; + + // Handle HTTP requests on a standalone worker thread. + STANDALONE_WORKER_THREAD = 1; + } + + // Default to MainThreadOnly. + ThreadingModel threading_model = 1; +} diff --git a/api/src/main/proto/envoy/config/cluster/v3/circuit_breaker.proto b/api/src/main/proto/envoy/config/cluster/v3/circuit_breaker.proto index fe798ceb0..fdc0af546 100644 --- a/api/src/main/proto/envoy/config/cluster/v3/circuit_breaker.proto +++ b/api/src/main/proto/envoy/config/cluster/v3/circuit_breaker.proto @@ -5,6 +5,7 @@ package envoy.config.cluster.v3; import "envoy/config/core/v3/base.proto"; import "envoy/type/v3/percent.proto"; +import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; @@ -43,6 +44,25 @@ message CircuitBreakers { // This parameter is optional. Defaults to 20%. type.v3.Percent budget_percent = 1; + // An optional duration in which requests will be considered when calculating + // the budget for retries. This parameter alters the way in which the retry budget + // is calculated, overriding the default behavior when specified. + // + // By default, when budget_interval is set to 0ms, only presently active + // and pending requests are considered when calculating the retry budget. + // + // When a non-zero budget_interval is specified, new requests are + // considered for the duration of budget_interval when calculating + // the retry budget. + // + // For example, if 10 requests start at the same time, with a specified budget_interval + // of 100ms, all 10 requests will be considered when calculating the retry + // budget for the next 100ms, regardless of if they have completed. + // All 10 requests will expire after the budget_interval duration. + // + // This parameter is optional. Defaults to 0ms. + google.protobuf.Duration budget_interval = 3; + // Specifies the minimum retry concurrency allowed for the retry budget. The limit on the // number of active retries may never go below this number. // diff --git a/api/src/main/proto/envoy/config/core/v3/base.proto b/api/src/main/proto/envoy/config/core/v3/base.proto index 978f365d5..8d2ede9e6 100644 --- a/api/src/main/proto/envoy/config/core/v3/base.proto +++ b/api/src/main/proto/envoy/config/core/v3/base.proto @@ -269,6 +269,15 @@ message RuntimeUInt32 { string runtime_key = 3; } +// Runtime derived uint64 with a default when not specified. +message RuntimeUInt64 { + // Default value if runtime value is not available. + uint64 default_value = 2; + + // Runtime key to get value for comparison. This value is used if defined. + string runtime_key = 3; +} + // Runtime derived percentage with a default when not specified. message RuntimePercent { // Default value if runtime value is not available. @@ -493,6 +502,14 @@ message HeaderMap { message WatchedDirectory { // Directory path to watch. string path = 1 [(validate.rules).string = {min_len: 1}]; + + // If set to true, the watcher will also subscribe to file modification events + // (``IN_MODIFY`` on Linux) in addition to move events (``IN_MOVED_TO``). This allows + // in-place file writes to trigger reload callbacks. Use this when the writing process + // cannot use atomic rename (e.g. certain secret managers that write certificate files + // directly). By default, only move/rename events are watched, which is the safe choice + // for atomic updates (e.g. Kubernetes ConfigMap symlink swaps). + bool watch_modify = 2; } // Data source consisting of a file, an inline value, or an environment variable. diff --git a/api/src/main/proto/envoy/config/core/v3/protocol.proto b/api/src/main/proto/envoy/config/core/v3/protocol.proto index d5d66be23..a2cfc6d4f 100644 --- a/api/src/main/proto/envoy/config/core/v3/protocol.proto +++ b/api/src/main/proto/envoy/config/core/v3/protocol.proto @@ -284,7 +284,7 @@ message AlternateProtocolsCacheOptions { repeated string canonical_suffixes = 5; } -// [#next-free-field: 8] +// [#next-free-field: 9] message HttpProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.HttpProtocolOptions"; @@ -338,6 +338,22 @@ message HttpProtocolOptions { // `. google.protobuf.Duration max_connection_duration = 3; + // Percentage-based jitter for ``max_connection_duration``. If set, the actual connection duration + // limit is extended by a random duration up to ``max_connection_duration * jitter / 100``. + // This staggers connection teardowns across time and prevents a thundering-herd of reconnects + // when many connections are established at roughly the same time. + // This field is ignored if ``max_connection_duration`` is not set. If not set, no jitter is added. + // + // .. note:: + // This field is currently only honored for downstream connections by the HTTP connection + // manager. It is not yet supported for upstream cluster connections. + // + // This is analogous to + // :ref:`max_downstream_connection_duration_jitter_percentage + // ` + // in the TCP proxy filter. + type.v3.Percent max_connection_duration_jitter = 8; + // The maximum number of headers (request headers if configured on HttpConnectionManager, // response headers when configured on a cluster). // If unconfigured, the default maximum number of headers allowed is ``100``. @@ -445,8 +461,8 @@ message Http1ProtocolOptions { // This is a no-op if ``accept_http_10`` is not true. string default_host_for_http_10 = 3; - // Describes how the keys for response headers should be formatted. By default, all header keys - // are lower cased. + // Describes how the keys for headers encoded by the HTTP/1 codec should be formatted. By + // default, all header keys are lower cased. HeaderKeyFormat header_key_format = 4; // Enables trailers for HTTP/1. By default the HTTP/1 codec drops proxied trailers. @@ -552,7 +568,7 @@ message KeepaliveSettings { [(validate.rules).duration = {gte {nanos: 1000000}}]; } -// [#next-free-field: 21] +// [#next-free-field: 23] message Http2ProtocolOptions { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.Http2ProtocolOptions"; @@ -669,7 +685,7 @@ message Http2ProtocolOptions { // the connection is terminated. For downstream connections the ``opened_streams`` is incremented when // Envoy receives complete response headers from the upstream server. For upstream connections the // ``opened_streams`` is incremented when Envoy sends the ``HEADERS`` frame for a new stream. The - // ``http2.inbound_priority_frames_flood`` stat tracks the number of connections terminated due to + // ``http2.inbound_window_update_frames_flood`` stat tracks the number of connections terminated due to // flood mitigation. The default ``max_inbound_window_update_frames_per_data_frame_sent`` value is ``10``. // Setting this to ``1`` should be enough to support HTTP/2 implementations with basic flow control, // but more complex implementations that try to estimate available bandwidth require at least ``2``. @@ -791,6 +807,26 @@ message Http2ProtocolOptions { // From RFC 9110, https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5: // obs-text = %x80-FF google.protobuf.BoolValue disallow_obs_text = 20; + + // Configures the initial token count for the RST_STREAM rate limiter used by the ``nghttp2`` + // server-side connection. This uses a token-bucket algorithm where each received RST_STREAM + // frame consumes one token, and tokens are replenished at :ref:`stream_reset_rate + // ` per second. + // When no tokens remain, ``nghttp2`` sends GOAWAY with ``INTERNAL_ERROR`` to close the + // connection, protecting against CVE-2023-44487 (HTTP/2 Rapid Reset). Defaults to ``1000``. + // + // This option only applies when using ``nghttp2`` as a server. It has no effect on ``oghttp2`` + // or on client-side connections. + google.protobuf.UInt64Value stream_reset_burst = 21; + + // Configures the token replenishment rate (tokens per second) for the RST_STREAM rate limiter + // used by the ``nghttp2`` server-side connection. See :ref:`stream_reset_burst + // ` for details. + // Defaults to ``33``. + // + // This option only applies when using ``nghttp2`` as a server. It has no effect on ``oghttp2`` + // or on client-side connections. + google.protobuf.UInt64Value stream_reset_rate = 22; } // [#not-implemented-hide:] diff --git a/api/src/main/proto/envoy/config/endpoint/v3/endpoint_components.proto b/api/src/main/proto/envoy/config/endpoint/v3/endpoint_components.proto index eacc555df..16e795d0e 100644 --- a/api/src/main/proto/envoy/config/endpoint/v3/endpoint_components.proto +++ b/api/src/main/proto/envoy/config/endpoint/v3/endpoint_components.proto @@ -25,6 +25,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Endpoints] // Upstream host identifier. +// [#next-free-field: 6] message Endpoint { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.endpoint.Endpoint"; @@ -97,6 +98,20 @@ message Endpoint { // sorted by preference order of the addresses. This will only be supported // for STATIC and EDS clusters. repeated AdditionalAddress additional_addresses = 4; + + // Optional alternative stat name for this endpoint. If not specified, the main address will be used + // as the stat name and be extracted as ``envoy.endpoint_address`` tag value in generated stats. + // If specified, the ``observability_name`` here will be used to replace the main address. + // + // .. note:: + // + // This field is ignored for logical DNS host implementation.. + // + // This is useful when there are duplicate addresses in the cluster, for example when multiple + // endpoints share the same address but have different hostnames or metadata. + // In this case, the observability name can be used to differentiate between these endpoints in + // stats and logs. + string observability_name = 5; } // An Endpoint that Envoy can route traffic to. @@ -139,7 +154,7 @@ message LbEndpoint { // LbEndpoint list collection. Entries are `LbEndpoint` resources or references. // [#not-implemented-hide:] message LbEndpointCollection { - xds.core.v3.CollectionEntry entries = 1; + repeated xds.core.v3.CollectionEntry entries = 1; } // A configuration for an LEDS collection. diff --git a/api/src/main/proto/envoy/config/listener/v3/listener.proto b/api/src/main/proto/envoy/config/listener/v3/listener.proto index e7dff2e19..0668ae3f8 100644 --- a/api/src/main/proto/envoy/config/listener/v3/listener.proto +++ b/api/src/main/proto/envoy/config/listener/v3/listener.proto @@ -106,6 +106,29 @@ message Listener { "envoy.api.v2.Listener.ConnectionBalanceConfig.ExactBalance"; } + // A connection balancer that steers each new TCP connection to the worker thread pinned to the + // CPU that received the connection, using a kernel ``SO_REUSEPORT`` BPF program. This removes + // the lock that the :ref:`exact balancer + // ` takes on + // every accept and keeps each connection on a single worker for cache and ``NUMA`` locality. To + // realize locality the operator should align ``NIC`` receive steering so connections arrive on + // the worker CPUs, for example with receive side scaling or ``IRQ`` affinity. + // + // It is available on Linux only and requires :ref:`enable_worker_cpu_affinity + // ` so worker ``i`` + // is pinned to the CPU the program steers to it, :ref:`enable_reuse_port + // `, a kernel that supports + // reuse port BPF steering, and a worker count no greater than the number of CPUs in the process + // affinity mask. When any of these is not met, or if the kernel rejects the steering program at + // runtime, the listener keeps serving with the kernel default reuse port hashing and without CPU + // locality. + // + // Worker affinity is fixed when the worker threads start, so a listener added dynamically via LDS + // steers with the same mapping. During a hot restart new connections may be steered to the + // draining parent process until it exits. + message CpuLocalityBalance { + } + oneof balance_type { option (validate.required) = true; @@ -118,6 +141,12 @@ message Listener { // because the only registered member (``envoy.network.connection_balance.dlb``) // is disabled. See https://github.com/envoyproxy/envoy/issues/45491. core.v3.TypedExtensionConfig extend_balance = 2; + + // If specified, the listener will steer new connections to worker threads using a kernel + // ``SO_REUSEPORT`` BPF program. See :ref:`CpuLocalityBalance + // ` + // for the requirements and fallback behavior. + CpuLocalityBalance cpu_locality_balance = 3; } } @@ -450,21 +479,3 @@ message Listener { // to explicitly configure TCP keepalive settings for individual additional addresses. core.v3.TcpKeepalive tcp_keepalive = 37; } - -// A placeholder proto so that users can explicitly configure the standard -// Listener Manager via the bootstrap's :ref:`listener_manager `. -// [#not-implemented-hide:] -message ListenerManager { -} - -// A placeholder proto so that users can explicitly configure the standard -// Validation Listener Manager via the bootstrap's :ref:`listener_manager `. -// [#not-implemented-hide:] -message ValidationListenerManager { -} - -// A placeholder proto so that users can explicitly configure the API -// Listener Manager via the bootstrap's :ref:`listener_manager `. -// [#not-implemented-hide:] -message ApiListenerManager { -} diff --git a/api/src/main/proto/envoy/config/metrics/v3/stats.proto b/api/src/main/proto/envoy/config/metrics/v3/stats.proto index 0fcf36c1c..46331c1ab 100644 --- a/api/src/main/proto/envoy/config/metrics/v3/stats.proto +++ b/api/src/main/proto/envoy/config/metrics/v3/stats.proto @@ -44,6 +44,7 @@ message StatsSink { } // Statistics configuration such as tagging. +// [#next-free-field: 6] message StatsConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.metrics.v2.StatsConfig"; @@ -104,6 +105,19 @@ message StatsConfig { // 3600000 // ] repeated HistogramBucketSettings histogram_bucket_settings = 4; + + // When set to ``true``, tag extractors specified in :ref:`stats_tags + // ` take precedence over the built-in + // default tag extractors that share the same ``tag_name``, instead of the default taking + // precedence. This allows overriding individual default Envoy tags (for example + // ``envoy.cluster_name``) while keeping :ref:`use_all_default_tags + // ` enabled, so it is not + // necessary to disable all defaults and re-declare every extractor. + // + // Has no effect when ``use_all_default_tags`` is ``false`` (no default extractors are added in + // that case). If not provided, the value is assumed to be false, preserving existing behavior + // where the default extractor takes precedence over custom extractors with the same ``tag_name``. + google.protobuf.BoolValue allow_default_tag_overrides = 5; } // Configuration for disabling stat instantiation. diff --git a/api/src/main/proto/envoy/config/route/v3/route_components.proto b/api/src/main/proto/envoy/config/route/v3/route_components.proto index f58349caa..bc3f57483 100644 --- a/api/src/main/proto/envoy/config/route/v3/route_components.proto +++ b/api/src/main/proto/envoy/config/route/v3/route_components.proto @@ -16,6 +16,7 @@ import "envoy/type/metadata/v3/metadata.proto"; import "envoy/type/tracing/v3/custom_tag.proto"; import "envoy/type/v3/percent.proto"; import "envoy/type/v3/range.proto"; +import "envoy/type/v3/ratelimit_unit.proto"; import "google/protobuf/any.proto"; import "google/protobuf/duration.proto"; @@ -1564,7 +1565,7 @@ message RouteAction { } // HTTP retry :ref:`architecture overview `. -// [#next-free-field: 14] +// [#next-free-field: 15] message RetryPolicy { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RetryPolicy"; @@ -1788,6 +1789,18 @@ message RetryPolicy { // HTTP headers which must be present in the request for retries to be attempted. repeated HeaderMatcher retriable_request_headers = 10; + + // By default, the target upstream cluster of a retry request is the same as the original request, + // and Envoy will not try to refresh it when retrying. + // If this field is set to true, Envoy will try to refresh the target upstream cluster when + // retrying a request. This is useful when users want to try different upstream cluster for + // each retry attempt. + // + // .. note:: + // This currently works when the route cluster specifier support the dynamic refresh, + // e.g. :ref:`matcher cluster specifier + // `. + bool refresh_cluster_on_retry = 14; } // HTTP request hedging :ref:`architecture overview `. @@ -1826,7 +1839,7 @@ message HedgePolicy { bool hedge_on_per_try_timeout = 3; } -// [#next-free-field: 10] +// [#next-free-field: 11] message RedirectAction { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RedirectAction"; @@ -1922,6 +1935,21 @@ message RedirectAction { // would do a case-insensitive match and transform path ``/aaa/XxX/bbb`` to // ``/aaa/yyy/bbb``. type.matcher.v3.RegexMatchAndSubstitute regex_rewrite = 9; + + // The path portion of the URL will be set to this value and supports + // :ref:`substitution format specifiers ` and CEL + // expressions. + // + // For example, with the following config: + // + // .. code-block:: yaml + // + // path_rewrite: "/new/%REQ(x-version)%" + // + // Would redirect to ``/new/v2`` given a request header ``x-version: v2``. + // If the substitution produces an empty string the path redirect is ignored + // and the original path is preserved. + string path_rewrite = 10; } // The HTTP status code to use in the redirect response. The default response @@ -2612,11 +2640,23 @@ message RateLimit { type.metadata.v3.MetadataKey metadata_key = 1 [(validate.rules).message = {required: true}]; } + // Rate limit to apply to this descriptor. + message RateLimitOverride { + // The number of requests per unit of time. + uint32 requests_per_unit = 1; + + // The unit of time. + type.v3.RateLimitUnit unit = 2; + } + oneof override_specifier { option (validate.required) = true; // Limit override from dynamic metadata. DynamicMetadata dynamic_metadata = 1; + + // Static limit override. + RateLimitOverride rate_limit = 2; } } @@ -2688,9 +2728,13 @@ message RateLimit { // ` for more information. // // .. note:: - // This is not supported if the rate limit action is configured in the ``typed_per_filter_config`` like - // :ref:`VirtualHost.typed_per_filter_config` or - // :ref:`Route.typed_per_filter_config`, etc. + // For the global HTTP :ref:`rate limit filter + // `, this is supported both at the route/virtual host + // level and when the rate limit configuration is supplied via the filter's + // ``rate_limits`` field or the ``typed_per_filter_config`` + // (:ref:`RateLimitPerRoute `). + // This is not supported by the :ref:`local rate limit filter + // `. Override limit = 4; // An optional hits addend to be appended to the descriptor produced by this rate limit diff --git a/api/src/main/proto/envoy/config/tap/v3/common.proto b/api/src/main/proto/envoy/config/tap/v3/common.proto index ecdb5faaa..ea28e3382 100644 --- a/api/src/main/proto/envoy/config/tap/v3/common.proto +++ b/api/src/main/proto/envoy/config/tap/v3/common.proto @@ -50,14 +50,16 @@ message TapConfig { // a tap will occur and the data will be written to the configured output. OutputConfig output_config = 2 [(validate.rules).message = {required: true}]; - // [#not-implemented-hide:] Specify if Tap matching is enabled. The % of requests\connections for - // which the tap matching is enabled. When not enabled, the request\connection will not be - // recorded. - // - // .. note:: - // - // This field defaults to 100/:ref:`HUNDRED - // `. + // Specifies the fraction of requests (HTTP tap filter) or connections (transport + // socket tap) for which the tap match predicate is evaluated. When unset, every + // request/connection proceeds to match evaluation (equivalent to sampling at 100%), + // the runtime layer is not consulted, and ``configured_sample_rate`` is not set on + // emitted traces. When set, only the configured fraction is matched; the remainder + // is not tapped. The value can be overridden at runtime via :ref:`runtime_key + // `. The + // configured sampling rate is recorded on the :ref:`configured_sample_rate + // ` of the + // first segment of each emitted trace. core.v3.RuntimeFractionalPercent tap_enabled = 3; } diff --git a/api/src/main/proto/envoy/config/trace/v3/opentelemetry.proto b/api/src/main/proto/envoy/config/trace/v3/opentelemetry.proto index 5a295d6f4..928d5a5d9 100644 --- a/api/src/main/proto/envoy/config/trace/v3/opentelemetry.proto +++ b/api/src/main/proto/envoy/config/trace/v3/opentelemetry.proto @@ -21,7 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Configuration for the OpenTelemetry tracer. // [#extension: envoy.tracers.opentelemetry] -// [#next-free-field: 7] +// [#next-free-field: 9] message OpenTelemetryConfig { // The upstream gRPC cluster that will receive OTLP traces. // Note that the tracer drops traces if the server does not read data fast enough. @@ -62,4 +62,18 @@ message OpenTelemetryConfig { // This field specifies the maximum number of spans that can be cached. If not specified, the // default is 1024. google.protobuf.UInt32Value max_cache_size = 6; + + // Specifies whether to set the telemetry SDK resource attributes. + // The following attributes will be set: + // + // - telemetry.sdk.language + // - telemetry.sdk.name + // - telemetry.sdk.version + // + // If not specified, the default is to set these attributes. + google.protobuf.BoolValue set_telemetry_sdk_resource_attributes = 7; + + // Specifies whether to set the ``service.name`` resource attribute. + // If not specified, the default is to set this attribute. + google.protobuf.BoolValue set_service_name_resource_attribute = 8; } diff --git a/api/src/main/proto/envoy/data/core/v3/health_check_event.proto b/api/src/main/proto/envoy/data/core/v3/health_check_event.proto index 2f8c32d92..dc2e17445 100644 --- a/api/src/main/proto/envoy/data/core/v3/health_check_event.proto +++ b/api/src/main/proto/envoy/data/core/v3/health_check_event.proto @@ -33,6 +33,7 @@ enum HealthCheckerType { GRPC = 2; REDIS = 3; THRIFT = 4; + DYNAMIC_MODULE = 5; } // [#next-free-field: 13] @@ -87,6 +88,12 @@ message HealthCheckEjectUnhealthy { // The type of failure that caused this ejection. HealthCheckFailureType failure_type = 1 [(validate.rules).enum = {defined_only: true}]; + + // HTTP status code observed on the response associated with the failure. + // Only set when the health checker type is HTTP and the failure type is ``ACTIVE``. + // A value of ``0`` indicates that no HTTP status code was recorded (e.g., network-level failures + // or non-HTTP health checkers). + uint32 http_status_code = 2; } message HealthCheckAddHealthy { @@ -111,6 +118,12 @@ message HealthCheckFailure { // Whether this event is the result of the first ever health check on a host. bool first_check = 2; + + // HTTP status code observed on the response associated with the failure. + // Only set when the health checker type is HTTP and the failure type is ``ACTIVE``. + // A value of ``0`` indicates that no HTTP status code was recorded (e.g., network-level failures + // or non-HTTP health checkers). + uint32 http_status_code = 3; } message DegradedHealthyHost { diff --git a/api/src/main/proto/envoy/data/tap/v3/wrapper.proto b/api/src/main/proto/envoy/data/tap/v3/wrapper.proto index 983b350b0..3bf15e51f 100644 --- a/api/src/main/proto/envoy/data/tap/v3/wrapper.proto +++ b/api/src/main/proto/envoy/data/tap/v3/wrapper.proto @@ -4,6 +4,7 @@ package envoy.data.tap.v3; import "envoy/data/tap/v3/http.proto"; import "envoy/data/tap/v3/transport.proto"; +import "envoy/type/v3/percent.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -19,6 +20,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Wrapper for all fully buffered and streamed tap traces that Envoy emits. This is required for // sending traces over gRPC APIs or more easily persisting binary messages to files. +// [#next-free-field: 6] message TraceWrapper { option (udpa.annotations.versioning).previous_message_type = "envoy.data.tap.v2alpha.TraceWrapper"; @@ -38,4 +40,23 @@ message TraceWrapper { // A socket streamed tap trace segment. SocketStreamedTraceSegment socket_streamed_trace_segment = 4; } + + // The configured sample rate at the time this trace was admitted, sourced from the + // :ref:`default_value + // ` of + // :ref:`tap_enabled `. For + // buffered output (where each ``TraceWrapper`` carries a complete trace) the rate is + // always present when sampling is configured. For streamed output (where a trace is + // split across multiple ``TraceWrapper`` segments) the rate is set on the first + // emitted segment only; subsequent segments belonging to the same trace can be + // joined to it via the ``trace_id`` carried on each inner segment message. Absent + // when sampling is unconfigured. + // + // .. note:: + // + // When :ref:`runtime_key + // ` is + // configured and an active runtime override is in effect, the effective sampling + // rate that admitted the trace may differ from the recorded configured value. + type.v3.FractionalPercent configured_sample_rate = 5; } diff --git a/api/src/main/proto/envoy/extensions/access_loggers/stats/v3/stats.proto b/api/src/main/proto/envoy/extensions/access_loggers/stats/v3/stats.proto index a797cf449..6a554882d 100644 --- a/api/src/main/proto/envoy/extensions/access_loggers/stats/v3/stats.proto +++ b/api/src/main/proto/envoy/extensions/access_loggers/stats/v3/stats.proto @@ -3,11 +3,13 @@ syntax = "proto3"; package envoy.extensions.access_loggers.stats.v3; import "envoy/data/accesslog/v3/accesslog.proto"; +import "envoy/type/v3/scope.proto"; import "google/protobuf/wrappers.proto"; import "xds/type/matcher/v3/matcher.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "validate/validate.proto"; @@ -29,7 +31,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // leading to a denial of service in Envoy, or can overwhelm any configured // stat sinks by sending too many unique metrics. -// [#next-free-field: 6] +// [#next-free-field: 7] message Config { // Defines a tag on a stat. message Tag { @@ -153,7 +155,13 @@ message Config { } // The stat prefix for the generated stats. - string stat_prefix = 1 [(validate.rules).string = {min_len: 1}]; + // Deprecated: please use ``stats_scope.prefix`` instead. + // It will override ``stats_scope.prefix`` if non-empty. + string stat_prefix = 1 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; + + // Configuration for stats scope limits and sharing. + type.v3.Scope stats_scope = 6; // The histograms this logger will emit. repeated Histogram histograms = 3; diff --git a/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/downstream_socket_interface/v3/downstream_reverse_connection_socket_interface.proto b/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/downstream_socket_interface/v3/downstream_reverse_connection_socket_interface.proto index cb3ccb4c1..9c6c3090d 100644 --- a/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/downstream_socket_interface/v3/downstream_reverse_connection_socket_interface.proto +++ b/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/downstream_socket_interface/v3/downstream_reverse_connection_socket_interface.proto @@ -2,9 +2,14 @@ syntax = "proto3"; package envoy.extensions.bootstrap.reverse_tunnel.downstream_socket_interface.v3; +import "envoy/config/accesslog/v3/accesslog.proto"; import "envoy/config/core/v3/base.proto"; +import "envoy/config/core/v3/extension.proto"; + +import "google/protobuf/duration.proto"; import "udpa/annotations/status.proto"; +import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.extensions.bootstrap.reverse_tunnel.downstream_socket_interface.v3"; option java_outer_classname = "DownstreamReverseConnectionSocketInterfaceProto"; @@ -18,6 +23,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Configuration for the downstream reverse connection socket interface. // This interface initiates reverse connections to upstream Envoys and provides // them as socket connections for downstream requests. +// [#next-free-field: 6] message DownstreamReverseConnectionSocketInterface { // HTTP handshake settings for initiator envoy initiated reverse tunnels. message HttpHandshakeConfig { @@ -27,6 +33,18 @@ message DownstreamReverseConnectionSocketInterface { // Additional headers to include in the HTTP handshake request. repeated config.core.v3.HeaderValueOption additional_headers = 2; + + // Perform the handshake as an HTTP/1.1 ``Upgrade`` exchange (``Upgrade: reverse-tunnel``, + // success on ``101``) so HTTP proxies can route the handshake and splice the tunnel + // afterward. The responder must set this flag to the same value. + // Defaults to ``false``. + bool use_http_upgrade = 3; + + // Formatter extensions usable in ``additional_headers`` substitution. See the formatter + // extensions documentation for details. When set, ``additional_headers`` values are evaluated + // as substitution format strings; when empty, the values are sent literally. + // [#extension-category: envoy.formatter] + repeated config.core.v3.TypedExtensionConfig formatters = 4; } // Stat prefix to be used for downstream reverse connection socket interface stats. @@ -40,4 +58,16 @@ message DownstreamReverseConnectionSocketInterface { // Optional HTTP handshake configuration. When unset, the initiator envoy uses the defaults // provided by ``HttpHandshakeConfig``. HttpHandshakeConfig http_handshake = 3; + + // Access log configuration for reverse tunnel initiator lifecycle events. + // Logs are emitted on handshake success, handshake failure, and connection close. + // Reverse tunnel metadata (``node_id``, ``cluster_id``, ``tenant_id``, upstream cluster, etc.) + // is available via ``%DYNAMIC_METADATA(envoy.reverse_tunnel.initiator:*)%`` substitutions. + repeated config.accesslog.v3.AccessLog access_log = 4; + + // Upper bound on the per-host reconnect backoff. The initiator retries a failed handshake on a + // deterministic exponential schedule (1s, 2s, 4s, ...) with small upward jitter; this value caps + // that schedule. + google.protobuf.Duration max_reconnect_backoff = 5 + [(validate.rules).duration = {gte {seconds: 1}}]; } diff --git a/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/upstream_socket_interface/v3/upstream_reverse_connection_socket_interface.proto b/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/upstream_socket_interface/v3/upstream_reverse_connection_socket_interface.proto index 0338c3027..1591290b6 100644 --- a/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/upstream_socket_interface/v3/upstream_reverse_connection_socket_interface.proto +++ b/api/src/main/proto/envoy/extensions/bootstrap/reverse_tunnel/upstream_socket_interface/v3/upstream_reverse_connection_socket_interface.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package envoy.extensions.bootstrap.reverse_tunnel.upstream_socket_interface.v3; +import "envoy/config/accesslog/v3/accesslog.proto"; import "envoy/config/core/v3/extension.proto"; import "google/protobuf/wrappers.proto"; @@ -19,7 +20,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#extension: envoy.bootstrap.reverse_tunnel.upstream_socket_interface] // Configuration for the upstream reverse connection socket interface. -// [#next-free-field: 6] +// [#next-free-field: 7] message UpstreamReverseConnectionSocketInterface { // Stat prefix for upstream reverse connection socket interface stats. string stat_prefix = 1; @@ -44,4 +45,8 @@ message UpstreamReverseConnectionSocketInterface { // containing the ``:`` delimiter are rejected to avoid ambiguity. // Defaults to ``false`` for backwards compatibility. google.protobuf.BoolValue enable_tenant_isolation = 5; + + // Access logs emitted for reverse tunnel lifecycle events. Entries are generated for tunnel setup, + // socket handoff, tunnel close, and post-handoff HTTP/2 keepalive timeout observations. + repeated config.accesslog.v3.AccessLog access_log = 6; } diff --git a/api/src/main/proto/envoy/extensions/clusters/dns/v3/dns_cluster.proto b/api/src/main/proto/envoy/extensions/clusters/dns/v3/dns_cluster.proto index 4266541e6..5c5865fde 100644 --- a/api/src/main/proto/envoy/extensions/clusters/dns/v3/dns_cluster.proto +++ b/api/src/main/proto/envoy/extensions/clusters/dns/v3/dns_cluster.proto @@ -21,7 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Configuration for DNS discovery clusters. // [#extension: envoy.clusters.dns] -// [#next-free-field: 10] +// [#next-free-field: 11] message DnsCluster { message RefreshRate { // Specifies the base interval between refreshes. This parameter is required and must be greater @@ -89,4 +89,12 @@ message DnsCluster { // semantics. Otherwise, each address is considered to be a separate endpoint, which maps to // :ref:`strict DNS discovery ` semantics. bool all_addresses_in_single_endpoint = 9; + + // When :ref:`respect_dns_ttl ` + // is enabled, this field specifies a minimum value for the TTL-derived DNS refresh rate. + // DNS records with TTLs shorter than this value will be refreshed at this rate instead. If not + // set, the TTL from the DNS response is used directly with no minimum floor. + // The value must be at least 1 second. + google.protobuf.Duration dns_min_refresh_rate = 10 + [(validate.rules).duration = {gte {seconds: 1}}]; } diff --git a/api/src/main/proto/envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.proto b/api/src/main/proto/envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.proto index 6ad6b9eb0..519723edc 100644 --- a/api/src/main/proto/envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.proto +++ b/api/src/main/proto/envoy/extensions/clusters/dynamic_forward_proxy/v3/cluster.proto @@ -4,6 +4,7 @@ package envoy.extensions.clusters.dynamic_forward_proxy.v3; import "envoy/config/cluster/v3/cluster.proto"; import "envoy/config/core/v3/address.proto"; +import "envoy/extensions/clusters/dns/v3/dns_cluster.proto"; import "envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto"; import "google/protobuf/duration.proto"; @@ -76,7 +77,9 @@ message ClusterConfig { bool allow_coalesced_connections = 3; } -// Configuration for sub clusters. Hard code STRICT_DNS cluster type now. +// Configuration for sub clusters. Sub clusters default to the ``STRICT_DNS`` discovery type, or +// use the ``DnsCluster`` extension when ``dns_cluster_config`` is set. +// [#next-free-field: 6] message SubClustersConfig { // The :ref:`load balancer type ` to use // when picking a host in a sub cluster. Note that CLUSTER_PROVIDED is not allowed here. @@ -93,4 +96,13 @@ message SubClustersConfig { // performance improvement, in the form of cache hits, for sub clusters that are going to be // warmed during steady state and are known at config load time. repeated config.core.v3.SocketAddress preresolve_clusters = 4; + + // Optional DNS configuration for dynamically created sub clusters. When set, sub clusters + // are created using the :ref:`DnsCluster ` + // extension (``envoy.cluster.dns``) rather than the legacy ``STRICT_DNS`` discovery type, + // enabling full DNS configuration including refresh rates, failure backoff, TTL respect, + // lookup family, and resolver selection. + // + // When not set, sub clusters inherit DNS settings from the parent cluster configuration. + dns.v3.DnsCluster dns_cluster_config = 5; } diff --git a/api/src/main/proto/envoy/extensions/clusters/original_dst/v3/original_dst.proto b/api/src/main/proto/envoy/extensions/clusters/original_dst/v3/original_dst.proto new file mode 100644 index 000000000..03ffd9fa8 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/clusters/original_dst/v3/original_dst.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; + +package envoy.extensions.clusters.original_dst.v3; + +import "envoy/type/metadata/v3/metadata.proto"; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.clusters.original_dst.v3"; +option java_outer_classname = "OriginalDstProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/original_dst/v3;original_dstv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Original Destination Cluster Configuration] +// [#extension: envoy.clusters.original_dst] + +// Configuration for the Original Destination cluster. +message OriginalDstCluster { + // When true, an HTTP header can be used to override the original dst address. The default header is + // :ref:`x-envoy-original-dst-host `. + // + // .. attention:: + // + // This header isn't sanitized by default, so enabling this feature allows HTTP clients to + // route traffic to arbitrary hosts and/or ports, which may have serious security + // consequences. + // + // .. note:: + // + // If the header appears multiple times only the first value is used. + bool use_http_header = 1; + + // The http header to override destination address if :ref:`use_http_header + // ` + // is set to true. If the value is empty, + // :ref:`x-envoy-original-dst-host ` will be used. + string http_header_name = 2; + + // The port to override for the original dst address. This port + // will take precedence over filter state and header override ports. + google.protobuf.UInt32Value upstream_port_override = 3 [(validate.rules).uint32 = {lte: 65535}]; + + // The dynamic metadata key to override destination address. + // First the request metadata is considered, then the connection one. + type.metadata.v3.MetadataKey metadata_key = 4; +} diff --git a/api/src/main/proto/envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto b/api/src/main/proto/envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto index cbd23095c..627a0b8c3 100644 --- a/api/src/main/proto/envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto +++ b/api/src/main/proto/envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.proto @@ -7,6 +7,7 @@ import "envoy/config/common/key_value/v3/config.proto"; import "envoy/config/core/v3/address.proto"; import "envoy/config/core/v3/extension.proto"; import "envoy/config/core/v3/resolver.proto"; +import "envoy/type/matcher/v3/address.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; @@ -33,7 +34,7 @@ message DnsCacheCircuitBreakers { // Configuration for the dynamic forward proxy DNS cache. See the :ref:`architecture overview // ` for more information. -// [#next-free-field: 16] +// [#next-free-field: 17] message DnsCacheConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.common.dynamic_forward_proxy.v2alpha.DnsCacheConfig"; @@ -148,4 +149,12 @@ message DnsCacheConfig { // Configuration to flush the DNS cache to long term storage. config.common.key_value.v3.KeyValueStoreConfig key_value_config = 13; + + // Optional matcher to filter out DNS resolution results that match specific IP address ranges. + // If a DNS response contains addresses matching this matcher, those addresses will be + // removed from the response. If all addresses are removed, the resolution is treated + // as a failure and the host will retain any previously resolved address. + // This can be used as an SSRF protection mechanism to prevent DNS rebinding attacks + // that resolve to internal/private IP addresses. + type.matcher.v3.AddressMatcher resolved_address_filter = 16; } diff --git a/api/src/main/proto/envoy/extensions/filters/common/set_filter_state/v3/value.proto b/api/src/main/proto/envoy/extensions/filters/common/set_filter_state/v3/value.proto index 054529c54..7f2578e87 100644 --- a/api/src/main/proto/envoy/extensions/filters/common/set_filter_state/v3/value.proto +++ b/api/src/main/proto/envoy/extensions/filters/common/set_filter_state/v3/value.proto @@ -4,6 +4,7 @@ package envoy.extensions.filters.common.set_filter_state.v3; import "envoy/config/core/v3/substitution_format_string.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "validate/validate.proto"; @@ -91,9 +92,8 @@ message FilterStateValue { config.core.v3.SubstitutionFormatString format_string = 2; } - // If marked as read-only, the filter state key value is locked, and cannot - // be overridden by any filter, including this filter. - bool read_only = 3; + // This field is deprecated and its value has no effect. + bool read_only = 3 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // Configures the object to be shared with the upstream internal connections. See :ref:`internal upstream // transport ` for more details on the filter state sharing with diff --git a/api/src/main/proto/envoy/extensions/filters/http/ai_protocol_manager/v3/ai_protocol_manager.proto b/api/src/main/proto/envoy/extensions/filters/http/ai_protocol_manager/v3/ai_protocol_manager.proto new file mode 100644 index 000000000..d7950a423 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/filters/http/ai_protocol_manager/v3/ai_protocol_manager.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +package envoy.extensions.filters.http.ai_protocol_manager.v3; + +import "xds/annotations/v3/status.proto"; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.http.ai_protocol_manager.v3"; +option java_outer_classname = "AiProtocolManagerProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ai_protocol_manager/v3;ai_protocol_managerv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; +option (xds.annotations.v3.file_status).work_in_progress = true; + +// [#protodoc-title: AI Protocol Manager] +// AI Protocol Manager filter +// :ref:`configuration overview `. +// [#extension: envoy.filters.http.ai_protocol_manager] + +// Configuration for the AI Protocol Manager filter. +message AiProtocolManager { +} diff --git a/api/src/main/proto/envoy/extensions/filters/http/aws_lambda/v3/aws_lambda.proto b/api/src/main/proto/envoy/extensions/filters/http/aws_lambda/v3/aws_lambda.proto index 9200ae943..7c9f93734 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/aws_lambda/v3/aws_lambda.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/aws_lambda/v3/aws_lambda.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package envoy.extensions.filters.http.aws_lambda.v3; +import "envoy/type/matcher/v3/string.proto"; + import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; @@ -17,7 +19,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#extension: envoy.filters.http.aws_lambda] // AWS Lambda filter config -// [#next-free-field: 7] +// [#next-free-field: 9] message Config { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.http.aws_lambda.v2alpha.Config"; @@ -76,6 +78,40 @@ message Config { // .. warning:: // Distributing the AWS credentials via this configuration should not be done in production. Credentials credentials = 6; + + // A list of request header string matchers that will be excluded from signing. The excluded header can be matched by + // any patterns defined in the StringMatcher proto (e.g. exact string, prefix, regex, etc). + // Headers such as ``x-amzn-cipher-suite``, ``x-amzn-tls-version``, ``x-amzn-vpc-id``, ``x-amzn-vpce-config`` and ``x-amzn-vpce-id``, + // when included in the request and signed, can cause errors to be generated by the Lambda endpoint. + // + // Example: + // + // .. code-block:: yaml + // + // match_excluded_headers: + // - prefix: x-amzn + // - exact: foo + // - exact: bar + // + // When applied, all headers that start with ``x-amzn`` and headers ``foo`` and ``bar`` will not be signed. + repeated type.matcher.v3.StringMatcher match_excluded_headers = 7; + + // A list of request header string matchers that will be included during signing. The included header can be matched by + // any patterns defined in the StringMatcher proto (e.g. exact string, prefix, regex, etc). + // match_included_headers takes precedence over match_excluded_headers - if match_included_headers is set, only those headers will be signed and match_excluded_headers will be ignored. + // Required headers for signing such as ``host`` will always be signed regardless of this setting. The required headers are determined via ``CanonicalHeaders`` section in the AWS documentation `here `_. + // + // Example: + // + // .. code-block:: yaml + // + // match_included_headers: + // - prefix: x-amzn + // - exact: foo + // - exact: bar + // + // When applied, all headers that start with ``x-amzn`` and headers ``foo`` and ``bar`` will be signed and all other headers will be excluded from signing except required headers. + repeated type.matcher.v3.StringMatcher match_included_headers = 8; } // AWS Lambda Credentials config. diff --git a/api/src/main/proto/envoy/extensions/filters/http/bandwidth_share/v3/bandwidth_share.proto b/api/src/main/proto/envoy/extensions/filters/http/bandwidth_share/v3/bandwidth_share.proto new file mode 100644 index 000000000..24bbcae05 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/filters/http/bandwidth_share/v3/bandwidth_share.proto @@ -0,0 +1,153 @@ +syntax = "proto3"; + +package envoy.extensions.filters.http.bandwidth_share.v3; + +import "envoy/config/core/v3/base.proto"; + +import "google/protobuf/duration.proto"; + +import "xds/type/matcher/v3/matcher.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.http.bandwidth_share.v3"; +option java_outer_classname = "BandwidthShareProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/bandwidth_share/v3;bandwidth_sharev3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Bandwidth share] +// Bandwidth share :ref:`configuration overview `. +// [#extension: envoy.filters.http.bandwidth_share] + +// [#next-free-field: 9] +message BandwidthShare { + message TenantConfig { + // Weight of the tenant. For example, if two tenants are competing for + // limited bandwidth, one has weight=3 and the other has weight=1, the + // contested bandwidth will be distributed 3/4 to the weight=3 tenant + // and 1/4 to the weight=1 tenant. + // + // If unset or 0, the default weight of 1 will be used. + uint32 weight = 1; + + // True to record stats with ``tenant`` tag set to the tenant name. + // If false or unset, the stats tag will be empty. It is recommended not + // to set this to default true if tenant names are dynamically generated + // from untrusted sources (or otherwise with unlimited scope), to + // avoid creating unlimited stats cardinality. + bool include_stats_tag = 2; + } + + message Limit { + // The unique id of the limiter. Should be set if you want to apply distinct + // limits on different listeners, or distinct limits for requests and responses. + // With matching ``bucket_id`` values, multiple listeners can share a single limit + // (e.g. for https and http listener that share a network bandwidth constraint). + // + // Also used for the ``bucket_id`` stats tag. + // + // The empty string is a valid ``bucket_id``. + string bucket_id = 1; + + // The limit supplied in KiB/s. + // + // .. note:: + // The limit is associated with the ``bucket_id``. If the same ``bucket_id`` + // is used in multiple listeners/routes, it is a config error for the + // configurations to not be identical. If the configuration is updated + // dynamically via xds, changing the runtime key, the ``bucket_id`` must + // also be changed or it is a config error. + // + // The limit can be updated dynamically via runtime. Setting the limit + // to zero, or unset, disables the filter. + config.core.v3.RuntimeUInt32 kbps = 2 [(validate.rules).message = {required: true}]; + } + + // Configuration for request limiting. If unset, requests are not limited. + // If ``kbps`` is zero, requests are not limited. + Limit request_limit = 1; + + // Configuration for response limiting. If unset, responses are not limited. + // If ``kbps`` is zero, responses are not limited. + Limit response_limit = 2; + + // Optional fill interval in milliseconds for the token refills. Defaults to 50ms. + // It must be at least 20ms to avoid too aggressive refills. + // + // Lower values will use more CPU and provide smoother bandwidth distribution + // when the limit is being enforced. + google.protobuf.Duration fill_interval = 3 [(validate.rules).duration = { + lte {seconds: 1} + gte {nanos: 20000000} + }]; + + // Enable response trailers. + // + // .. note:: + // + // If set true, the following 4 trailers will be added, prefixed by ``response_trailer_prefix``: + // * bandwidth-request-delay-ms: delay time in milliseconds added by the limiter. + // * bandwidth-response-delay-ms: delay time in milliseconds added by the limiter. + // * bandwidth-request-duration-ms: total duration of receiving and processing the request. + // * bandwidth-response-duration-ms: total duration of receiving and processing the response. + // + // If ``response_limit`` is unset or has ``kbps`` of 0, the trailers will not be set. + // + // If both the request and response delay time is 0, the trailers will not be set. + // + // Note that the delay time may overlap with other factors such that it may not actually + // increase the duration by the stated amount - for example, the source data may still be + // arriving into a buffer during the artificial delay, such that it's possible to fully + // "catch up" the lost time by reading from that buffer at a later, less-constrained time. + bool enable_response_trailers = 4; + + // The prefix for the response trailers. Empty string is a valid prefix. + // + // If set, ``enable_response_trailers`` must be true. + // + // For example, if this value is ``x-banana-`` then the trailer keys will be + // ``x-banana-bandwidth-request-delay-ms``, ``x-banana-bandwidth-response-duration-ms``, + // etc. + string response_trailer_prefix = 5 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false}]; + + // An optional matcher which returns a string to use as a tenant name. + // + // If unset, the tenant name will always be the empty string, and all requests will + // have equal weight when limiting is being enforced. + // + // If tenant names are set when limiting is being enforced, traffic may be + // distributed unevenly - for example, assuming all requests want all possible + // bandwidth, if there are five streams with tenant ``foo`` and two streams with + // tenant ``bar``, and no custom weights, ``foo`` and ``bar`` will get an equal + // share of the bandwidth (half), then the requests within each tenant will get + // an equal share of that tenant's share, i.e. the ``foo`` requests will each + // get a fifth of the ``foo`` half, a tenth of the total, and the ``bar`` requests + // will each get half of the ``bar`` half, a quarter of the total. + // + // An example way this might be used is to have ``tenant_name_selector`` make + // each source IP address a tenant. Then if one source IP is trying to make 100 + // requests in parallel, and 99 other IPs are making one request each, the + // total bandwidth distribution (assuming the limit is being exceeded) would + // be equal per IP, versus with no tenants it would be equal per request and + // the greedy IP address would be getting 100x more bandwidth than the others. + // + // Note that if the limit is not consistently exceeded, all available bandwidth + // is still distributed - so in this case if the 99 other IPs were only using + // half the available bandwidth total between them, the greedy IP would still + // be able to get 50x more bandwidth than the rest. In this example the value is + // clearer - the less greedy tenants get all the bandwidth they want, and + // only the greedy tenant gets throttled, vs. without tenants all the requests + // would be throttled equally. + xds.type.matcher.v3.Matcher tenant_name_selector = 6; + + // A map from tenant names to configurations. If a tenant name is not present + // in the map, ``default_tenant_config`` is used. + map tenant_configs = 7; + + // Optional configuration override for the default tenant. If unset, the + // default values are used. + TenantConfig default_tenant_config = 8; +} diff --git a/api/src/main/proto/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto b/api/src/main/proto/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto index af3c442c0..af163642a 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/basic_auth/v3/basic_auth.proto @@ -29,6 +29,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // user1:{SHA}hashed_user1_password // user2:{SHA}hashed_user2_password // +// [#next-free-field: 6] message BasicAuth { // Username-password pairs used to verify user credentials in the "Authorization" header. // The value needs to be the htpasswd format. @@ -47,6 +48,29 @@ message BasicAuth { // If it is not specified, the filter loads the credential from the "Authorization" header. string authentication_header = 3 [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME strict: false}]; + + // If set to true, requests without Basic credentials (missing ``Authorization`` header, or + // ``Authorization`` header with a non-``Basic`` scheme such as ``Bearer``) are allowed to pass through + // without authentication. Requests that present ``Basic`` credentials are still fully validated. + // + // This is useful when combining BasicAuth with other authentication methods (e.g. JWT) to + // achieve OR semantics: a request is accepted if any one configured auth method succeeds. + // When ``allow_missing`` is ``true`` on all auth filters, pair it with an RBAC filter that checks + // the dynamic metadata emitted by this filter (see ``emit_dynamic_metadata``) to ensure at + // least one method authenticated the request. Requires ``emit_dynamic_metadata`` to be set to + // ``true``. + bool allow_missing = 4; + + // If set to ``true``, the filter emits dynamic metadata on successful authentication with key + // ``username`` set to the authenticated username. The metadata is emitted under the namespace + // corresponding to the name of this basic_auth filter as configured in the ``http_filters`` + // chain (e.g. if the filter is configured with name ``envoy.filters.http.basic_auth``, that is + // the namespace that will be used). + // + // This is typically enabled together with ``allow_missing`` when combining BasicAuth with + // other authentication methods (e.g. JWT) and using a downstream RBAC filter to enforce + // OR semantics. + bool emit_dynamic_metadata = 5; } // Extra settings that may be added to per-route configuration for diff --git a/api/src/main/proto/envoy/extensions/filters/http/composite/v3/composite.proto b/api/src/main/proto/envoy/extensions/filters/http/composite/v3/composite.proto index 1835240d9..00ee5cd8b 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/composite/v3/composite.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/composite/v3/composite.proto @@ -41,17 +41,31 @@ message Composite { // as it avoids duplicating the filter chain configuration. map named_filter_chains = 1; - // [#not-implemented-hide:] // The match tree that will be used to select an action to execute. The action type should be // :ref:`ExecuteFilterAction // `. + // + // .. warning:: + // This should only be set when using the Composite filter as in the :ref:`http_filters + // `. + // Never set this field when using the Composite filter with the :ref:`ExtensionWithMatcher + // ` which will result in + // undefined behavior. + // xds.type.matcher.v3.Matcher matcher = 2; } // Per-route configuration for the Composite filter. -// [#not-implemented-hide:] message CompositePerRoute { // Override of the match tree for this route. + // + // .. warning:: + // This should only be set when using the Composite filter as in the :ref:`http_filters + // `. + // Never set this field when using the Composite filter with the :ref:`ExtensionWithMatcher + // ` which will result in + // undefined behavior. + // xds.type.matcher.v3.Matcher matcher = 1 [(validate.rules).message = {required: true}]; } diff --git a/api/src/main/proto/envoy/extensions/filters/http/custom_response/v3/custom_response.proto b/api/src/main/proto/envoy/extensions/filters/http/custom_response/v3/custom_response.proto index cd28640fe..ad22bd57e 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/custom_response/v3/custom_response.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/custom_response/v3/custom_response.proto @@ -27,7 +27,11 @@ message CustomResponse { // Matcher to match against the original response to select a // :ref:`Custom Response Policy ` // that will override the original response. The matching is done by matching - // against :ref:`response header values` + // against the response status code, response header values, and/or + // :ref:`request header values`. + // Request inputs (for example ``HttpRequestHeaderMatchInput``) match against + // the original downstream request, which allows selecting a custom response + // based on, e.g., the ``Accept`` request header. // Example: // // .. validated-code-block:: yaml @@ -96,6 +100,35 @@ message CustomResponse { // - header: // key: "foo2" // value: "x-bar2" + // # Apply a JSON custom response to 5xx responses when the request asks for JSON. + // - predicate: + // and_matcher: + // predicate: + // - single_predicate: + // input: + // name: 5xx_response + // typed_config: + // "@type": type.googleapis.com/envoy.type.matcher.v3.HttpResponseStatusCodeClassMatchInput + // value_match: + // exact: "5xx" + // - single_predicate: + // input: + // name: accept_request_header + // typed_config: + // "@type": type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput + // header_name: accept + // value_match: + // exact: "application/json" + // on_match: + // action: + // name: action + // typed_config: + // "@type": type.googleapis.com/envoy.extensions.http.custom_response.local_response_policy.v3.LocalResponsePolicy + // status_code: 500 + // body_format: + // json_format: + // status: "%RESPONSE_CODE%" + // message: "%LOCAL_REPLY_BODY%" // // -- attention:: // The first matched policy wins. Once the response is matched, matcher diff --git a/api/src/main/proto/envoy/extensions/filters/http/ext_authz/v3/ext_authz.proto b/api/src/main/proto/envoy/extensions/filters/http/ext_authz/v3/ext_authz.proto index 2cc6e689b..2b565dea3 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/ext_authz/v3/ext_authz.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/ext_authz/v3/ext_authz.proto @@ -88,6 +88,17 @@ message ExtAuthz { // alter another client request header. // // Defaults to ``false``. + // + // .. attention:: + // + // Enabling this option can cause Envoy to recompute route matching after earlier HTTP filters + // have already processed the request. This can be security-sensitive when route-dependent + // authorization filters, such as the RBAC filter, run before ext_authz. + // + // Operators should avoid enabling this option for authorization services that are not fully + // trusted to influence routing. When possible, filters that mutate route-matching inputs and + // clear the route cache should run before route-dependent authorization filters. Operators can + // also use decoder_header_mutation_rules to restrict sensitive request header mutations. bool clear_route_cache = 6; // Sets the HTTP status that is returned to the client when the authorization server returns an error diff --git a/api/src/main/proto/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/src/main/proto/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 9bd1b6f76..ec0c901a9 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -299,6 +299,17 @@ message ExternalProcessor { // received in response to request headers. It is recommended to set this field rather than set // :ref:`disable_clear_route_cache `. // Only one of ``disable_clear_route_cache`` or ``route_cache_action`` can be set. + // + // .. attention:: + // + // Clearing the route cache can cause Envoy to recompute route matching after earlier HTTP + // filters have already processed the request. This can be security-sensitive when filters + // that make route-dependent authorization decisions, such as the RBAC filter, run before + // ext_proc and ext_proc mutates route-matching inputs. + // + // Operators should only enable route cache clearing for trusted external processors, should + // carefully order route-dependent authorization filters, and should use mutation_rules to + // restrict sensitive mutations when appropriate. RouteCacheAction route_cache_action = 18 [(udpa.annotations.field_migrate).oneof_promotion = "clear_route_cache_type"]; diff --git a/api/src/main/proto/envoy/extensions/filters/http/filter_chain/v3/filter_chain.proto b/api/src/main/proto/envoy/extensions/filters/http/filter_chain/v3/filter_chain.proto new file mode 100644 index 000000000..85e19c47f --- /dev/null +++ b/api/src/main/proto/envoy/extensions/filters/http/filter_chain/v3/filter_chain.proto @@ -0,0 +1,85 @@ +syntax = "proto3"; + +package envoy.extensions.filters.http.filter_chain.v3; + +import "envoy/config/core/v3/extension.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.http.filter_chain.v3"; +option java_outer_classname = "FilterChainProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/filter_chain/v3;filter_chainv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Filter Chain] +// Filter Chain :ref:`configuration overview `. +// +// .. attention:: +// This filter is specific to Envoy and is not supported in other xDS implementations. +// +// [#extension: envoy.filters.http.filter_chain] + +// Filter-level configuration for the filter chain filter. This filter acts as a wrapper +// that applies a configurable chain of HTTP filters to incoming requests. +// +// When a request arrives the filter collects all active filter chains in order from least +// to most specific: ``default_filter_chain`` first, then any per-route chains ordered from +// the outermost scope (e.g. route configuration level) to the innermost scope (route level). +// Each filter in a less-specific chain is applied **unless** a more-specific chain contains +// a filter with the same ``name``. +// +// The final set of filters is applied in order from least to most specific, so that the +// least-specific filter runs first and the most-specific filter runs last. This allows +// more specific filters to override the behavior of less specific ones. +// +// If no chains are found at all the filter passes through without modifying the request. +message FilterChainConfig { + // Default filter chain to apply when processing every request. + // + // This field is optional. When omitted the filter still participates in per-route + // override resolution. + FilterChain default_filter_chain = 1; +} + +// Per-route configuration for the filter chain filter. This allows different filter chains +// to be applied on different routes. +// +// .. note:: +// Only the initial route match is considered for filter chain selection. Subsequent +// internal route refreshes do not affect the filter chain applied to the request. +// +// When multiple per-route configs exist along the route hierarchy (e.g. one at virtual-host +// level and one at route level) the same merge rules apply iteratively from least specific +// to most specific, so the most specific definition of any named filter always wins. +message FilterChainConfigPerRoute { + // Filter chain to apply on this route. Must contain at least one filter. + // + // .. note:: + // Not all HTTP filters are compatible to be used within this route level filter chain + // for now. + // + FilterChain filter_chain = 1 [(validate.rules).message = {required: true}]; +} + +// A filter chain is a list of HTTP filters that are applied in order. +// This message is used to define a reusable chain of filters. +message FilterChain { + // A list of HTTP filter configurations to be applied in order. + // Each filter in the chain will process the request/response in sequence. + // At least one filter must be specified. + // + // .. warning:: + // Please do not configure the ``filter_chain`` filter itself or ``composite`` filter + // within this list recursively to avoid undefined behavior. + // + // .. note:: + // It is possible to configure ``terminal`` filters (filters that do not expect next filter + // in the chain, e.g., ``envoy.filters.http.router``) in the middle of the chain. However, + // use it with caution to avoid unexpected behavior. + // + // [#extension-category: envoy.filters.http] + repeated config.core.v3.TypedExtensionConfig filters = 1 + [(validate.rules).repeated = {min_items: 1}]; +} diff --git a/api/src/main/proto/envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.proto b/api/src/main/proto/envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.proto index f4646389f..b741120c1 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/gcp_authn/v3/gcp_authn.proto @@ -64,7 +64,31 @@ message GcpAuthnFilterConfig { // Audience is the URL of the receiving service that performs token authentication. // It will be provided to the filter through cluster's typed_filter_metadata. message Audience { - string url = 1 [(validate.rules).string = {min_len: 1}]; + message AccessToken { + } + + message BoundJwt { + // The audience URL, used for fetching bound JWT token. + string url = 1 [(validate.rules).string = {min_len: 1}]; + } + + message BoundAccessToken { + } + + // The audience URL, used for fetching unbound JWT token. + string url = 1; + + // If defined, the filter will fetch unbound Access Token instead of JWT. + // It takes precedence over ``url``. + AccessToken access_token = 2; + + // If defined, the filter will fetch bound JWT token instead of unbound. + // It takes precedence over ``access_token`` and ``url``. + BoundJwt bound_jwt = 3; + + // If defined, the filter will fetch bound Access Token instead of unbound. + // It takes precedence over ``bound_jwt``, ``access_token`` and ``url``. + BoundAccessToken bound_access_token = 4; } // Token Cache configuration. diff --git a/api/src/main/proto/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto b/api/src/main/proto/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto index 87f725e1c..228cc72f7 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/ip_tagging/v3/ip_tagging.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package envoy.extensions.filters.http.ip_tagging.v3; import "envoy/config/core/v3/address.proto"; +import "envoy/config/core/v3/base.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; @@ -18,7 +19,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // IP tagging :ref:`configuration overview `. // [#extension: envoy.filters.http.ip_tagging] -// [#next-free-field: 6] +// [#next-free-field: 7] message IPTagging { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.http.ip_tagging.v2.IPTagging"; @@ -53,6 +54,12 @@ message IPTagging { repeated config.core.v3.CidrRange ip_list = 2; } + // Specifies the content of the IP tag file. + // Allow the file to be created with no IP tags. + message IPTags { + repeated IPTag ip_tags = 1; + } + // Specify to which header the tags will be written. message IpTagHeader { // Describes how to apply the tags to the headers. @@ -88,13 +95,20 @@ message IPTagging { // The type of request the filter should apply to. RequestType request_type = 1 [(validate.rules).enum = {defined_only: true}]; - // [#comment:TODO(ccaraman): Extend functionality to load IP tags from file system. - // Tracked by issue https://github.com/envoyproxy/envoy/issues/2695] // The set of IP tags for the filter. - repeated IPTag ip_tags = 4 [(validate.rules).repeated = {min_items: 1}]; + // Only one of :ref:`ip_tags ` + // or :ref:`ip_tags_datasource ` + // can be set for the IP Tagging filter. + repeated IPTag ip_tags = 4; // Specify to which header the tags will be written. // // If left unspecified, the tags will be appended to the ``x-envoy-ip-tags`` header. IpTagHeader ip_tag_header = 5; + + // Data source from which to retrieve ip tags. + // Only filename based data source is currently supported for IP tags. + // When using this data source, if a ``watched_directory`` is provided, the IP tags file will be re-read when a file move is detected. + // See :ref:`watched_directory ` for more information about the ``watched_directory`` field. + config.core.v3.DataSource ip_tags_datasource = 6; } diff --git a/api/src/main/proto/envoy/extensions/filters/http/jwt_authn/v3/config.proto b/api/src/main/proto/envoy/extensions/filters/http/jwt_authn/v3/config.proto index 9a955bdd8..20baa3183 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/jwt_authn/v3/config.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/jwt_authn/v3/config.proto @@ -78,6 +78,7 @@ message JwtProvider { // otherwise the JWT ``iss`` field is not checked. // // .. note:: + // // ``JwtRequirement`` :ref:`allow_missing ` // and :ref:`allow_missing_or_failed ` // are implemented differently than other ``JwtRequirements``. Hence the usage of this field @@ -324,10 +325,11 @@ message JwtProvider { // alg: PS256 // // .. warning:: - // Using the same key name for :ref:`header_in_metadata ` - // and :ref:`payload_in_metadata ` - // is not suggested due to potential override of existing entry, while it is not enforced during - // config validation. + // + // Using the same key name for :ref:`header_in_metadata ` + // and :ref:`payload_in_metadata ` + // is not suggested due to potential override of existing entry, while it is not enforced during + // config validation. // string header_in_metadata = 14; @@ -593,38 +595,70 @@ message JwtRequirement { // different is this mode will reject requests with invalid tokens. google.protobuf.Empty allow_missing = 6; - // Extract JWT claims without performing signature validation. - // This mode will decode the JWT, extract claims, and forward them as - // configured (via claim_to_headers, forward_payload_header, etc.) but - // will NOT verify the JWT signature against JWKS. + // [#next-major-version: consider removing or gating behind explicit opt-in] // // .. warning:: // - // This mode does not verify JWT authenticity. Use only in scenarios where: - // - // - JWTs come from a trusted source (e.g., internal service mesh) - // - Signature verification is performed elsewhere in the request path - // - You are in a testing period and the token issuer doesn't support JWKS yet + // SECURITY WARNING: This mode does NOT verify JWT signatures. Any party + // can forge a JWT with arbitrary claims, and those claims will be extracted + // and forwarded as HTTP headers. Headers set by this mode are + // INDISTINGUISHABLE from headers set by fully validated JWTs unless the + // ``verification_status_header`` is checked by downstream filters + // (set to ``false`` by default on all extract-only requests). // - // This mode will: + // DO NOT use this mode if: + // - RBAC policies match on JWT-derived headers + // - ext_authz services trust JWT-derived headers + // - Backend services use JWT-derived headers for authorization + // - The JWT source is not cryptographically authenticated by other means // - // * Decode the JWT header and payload - // * Extract claims and forward them as headers - // * Always return success (Status::Ok) regardless of JWT validity - // * Log when extraction occurs + // Use only when signature verification is PROVABLY performed elsewhere + // in the request path (e.g., by an upstream mTLS-authenticated service). // - // This mode will NOT: - // - // * Verify the JWT signature - // * Validate the (issuer) claim - // * Validate the (audience) claim - // * Check not-before time (nbf claim) ExtractOnlyWithoutValidation extract_only_without_validation = 7; } } +// Configuration for extract-only mode without JWT signature validation. +// +// When this mode is active and a JWT is present in the request but fails +// signature verification, a verification status header is set on the request +// to signal to downstream filters (RBAC, ext_authz) that the JWT claims were +// NOT cryptographically verified. The header is not set when the JWT is valid +// or when no JWT is present. +// message ExtractOnlyWithoutValidation { - // Reserved for future extensions (e.g., claim filtering, logging options) + // Name of the HTTP header set to "false" when a JWT is present but fails + // signature verification. The header is NOT set when: + // + // - The JWT is valid (verification succeeded), or + // - No JWT is present in the request. + // + // This means the header's presence is a meaningful signal to downstream + // filters: if set, the JWT was present but could not be verified, and any + // extracted claim headers should not be trusted for authorization. + // + // Downstream filters (RBAC, ext_authz) SHOULD check for the absence of this + // header (or its non-"false" value) before trusting JWT-derived claim headers + // for authorization decisions. + // + // Default (unset or empty): ``x-jwt-signature-verified``. + // + // Custom value: uses the specified header name. + // + // The header-setting behavior is guarded by the + // ``envoy.reloadable_features.jwt_authn_add_verification_status_header`` + // runtime flag (default on). If removal is needed downstream, use header + // mutation in a subsequent filter. + // + // Example: when a JWT is present in the request but fails signature + // verification, the request will carry: + // + // .. code-block:: yaml + // + // x-jwt-signature-verified: false + // + string verification_status_header = 1; } // This message specifies a list of RequiredProvider. diff --git a/api/src/main/proto/envoy/extensions/filters/http/mcp/v3/mcp.proto b/api/src/main/proto/envoy/extensions/filters/http/mcp/v3/mcp.proto index d0548c35f..fe87574ac 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/mcp/v3/mcp.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/mcp/v3/mcp.proto @@ -21,7 +21,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#extension: envoy.filters.http.mcp] // This filter will inspect and get attributes from MCP traffic. -// [#next-free-field: 8] +// [#next-free-field: 9] message Mcp { // Traffic handling mode for non-MCP traffic. enum TrafficMode { @@ -69,9 +69,12 @@ message Mcp { // Defaults to false. bool clear_route_cache = 2; - // Maximum size of the request body to buffer for JSON-RPC validation. - // If the request body exceeds this size, the request is rejected with ``413 Payload Too Large``. - // This limit applies to both ``REJECT_NO_MCP`` and ``PASS_THROUGH`` modes to prevent unbounded buffering. + // Maximum size of the request body to buffer for JSON-RPC parsing. + // Only the first ``max_request_body_size`` bytes are parsed for MCP attribute extraction. + // + // When the body exceeds this limit: + // - In ``PASS_THROUGH`` mode: the request is allowed through with an ``is_exceeding_limit`` marker in the dynamic metadata, indicating that the MCP payload was only partially parsed. + // - In ``REJECT_NO_MCP`` mode: the request is rejected with ``400 Bad Request`` because the complete root JSON object must fit within the size limit. // // It defaults to 8KB (8192 bytes) and the maximum allowed value is 10MB (10485760 bytes). // @@ -107,6 +110,11 @@ message Mcp { // // If unset (default), do not extract or inject baggage. BaggagePropagationConfig propagate_baggage = 7; + + // When true, reject requests that contain duplicate JSON keys at any + // nesting level. RFC 8259 Section 4 states that names within an object SHOULD be + // unique. Defaults to false (last-key-wins / last-win). + google.protobuf.BoolValue reject_duplicate_keys = 8; } // Parser configuration with method-specific rules. diff --git a/api/src/main/proto/envoy/extensions/filters/http/mcp_json_rest_bridge/v3/mcp_json_rest_bridge.proto b/api/src/main/proto/envoy/extensions/filters/http/mcp_json_rest_bridge/v3/mcp_json_rest_bridge.proto index 11df0c8b6..4eb8a794d 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/mcp_json_rest_bridge/v3/mcp_json_rest_bridge.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/mcp_json_rest_bridge/v3/mcp_json_rest_bridge.proto @@ -90,12 +90,66 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // - Body: {"data": "updated value"} // (Only the "payload" field from arguments is used as the body. Other arguments not in the // path, like 'resource_id', become query parameters.) +// [#next-free-field: 8] message McpJsonRestBridge { + // Where to store parsed MCP request attributes. + enum RequestStorageMode { + // Unspecified. Uses default behavior (nothing is stored). + MODE_UNSPECIFIED = 0; + + // Store request attributes in dynamic metadata. The metadata namespace + // is the filter's config name as specified by the ``name`` field in the + // ``http_filters`` list (e.g. ``envoy.filters.http.mcp_json_rest_bridge`` + // if using the canonical filter name). + DYNAMIC_METADATA = 1; + } + // General server information. ServerInfo server_info = 1; // Configuration for the MCP tools. ServerToolConfig tool_config = 2; + + // Maximum size of the request body to buffer for transcoding and validation. + // If the request body exceeds this size, the request is rejected with ``413 Payload Too Large``. + // This limit applies to prevent unbounded buffering. + // + // It defaults to 64KB (65536 bytes) as the MCP calls (tools, resources, or prompts) + // only pass small arguments or identifiers. + // + // Setting it to 0 would disable the limit. It is not recommended to do so in production. + google.protobuf.UInt32Value max_request_body_size = 3; + + // Maximum size of the response body to buffer for transcoding. + // If the response body exceeds this size, the response is rejected with an appropriate error. + // This limit applies to prevent unbounded buffering. + // + // It defaults to 1MB (1048576 bytes) to prevent transcoding failures on large payloads like + // file reads, while aligning with Envoy's standard default connection buffer limit. + // + // Setting it to 0 would disable the limit. It is not recommended to do so in production. + google.protobuf.UInt32Value max_response_body_size = 4; + + // Where to store parsed MCP request attributes. + // Default is not storing anything. + // When set to ``DYNAMIC_METADATA``, attributes are stored in dynamic metadata + // using the filter's config name (i.e. the ``name`` field of this filter's entry + // in the ``http_filters`` list) as the metadata namespace. + RequestStorageMode request_storage_mode = 5 [(validate.rules).enum = {defined_only: true}]; + + // If set, extract OpenTelemetry (OTel) trace context from MCP requests and propagate it to + // request headers. The keys ``traceparent``, ``tracestate``, and ``baggage`` + // will be extracted from ``_meta``. + // Ref: `Request Meta SEP `_ + TraceContextExtractionOptions trace_context_extraction = 6; + + // When set to true, the filter will not clear the route cache after transcoding. + // This allows the route to be re-selected based on the updated request path or method. + bool disable_clear_route_cache = 7; +} + +// Options for trace context extraction. +message TraceContextExtractionOptions { } // Configuration for the server metadata. @@ -127,7 +181,12 @@ message ServerInfo { google.protobuf.StringValue fallback_protocol_version = 3; } +// Configuration for sending locally-generated responses to tools/list requests. +message ToolsListLocal { +} + // Configuration for the MCP tool capability of the server. +// [#next-free-field: 6] message ServerToolConfig { // List of MCP tools configurations. repeated ToolConfig tools = 1; @@ -137,26 +196,80 @@ message ServerToolConfig { // Whether this server supports notifications for changes to the tool list. bool list_changed = 2; - // Optional configuration to transcode the tools/list requests to a standard HTTP request. - // - // Note: tools/list should be mapped to a GET request with an empty body. - // - // - If provided: The extension transcodes the request and forwards it down the filter chain. - // The response (whether from an upstream backend, a configured ``direct_response``, or another - // extension) MUST be a JSON body strictly matching the MCP ``ListToolsResult`` schema. - // Ref: https://modelcontextprotocol.io/specification/2025-11-25/schema#listtoolsresult - // - If not provided: The ``tools/list`` request is passed through. This allows subsequent - // extension or the backend itself to handle the tools/list request if they support it. - HttpRule tool_list_http_rule = 3; + // Optional configuration for tools/list requests. If not set: The ``tools/list`` request is + // passed through. This allows subsequent extension or the backend itself to handle the tools/list + // request if they support it. + oneof tool_list_config { + // Configuration to transcode the tools/list requests to a standard HTTP request. If provided: + // The extension transcodes the request and forwards it down the filter chain. The response + // (whether from an upstream backend, a configured ``direct_response``, or another extension) + // MUST be a JSON body strictly matching the MCP ``ListToolsResult`` schema. Ref: + // https://modelcontextprotocol.io/specification/2025-11-25/schema#listtoolsresult + HttpRule tool_list_http_rule = 3; + + // If provided: The extension sends a local response, according to each tool's + // ToolsListSpecificConfig. + ToolsListLocal tool_list_local = 4; + } + + // [#not-implemented-hide:] + // Default server info for tools without specific ones. + McpServerInfo default_server_info = 5; +} + +// Configuration for a tool's entry in tools/list responses. +message ToolsListSpecificConfig { + // Optional, human-readable name of the tool for display purposes. + string title = 1; + + // Human-readable description of functionality. + string description = 2 [(validate.rules).string = {min_len: 1}]; + + // A JSON Schema describing expected parameters, as a serialized JSON string, in the JSON Schema + // 2020-12 dialect. This should be raw JSON, including the "properties" and "required" keys, but + // not "type". Tools with no parameters may omit this to signify a tool with no constraints on the + // parameters object, or set to '"additionalProperties": false' to require empty parameters. + string input_schema = 3; } -// Configuration for a specific MCP tool. +message McpServerInfo { + // The path to the endpoint hosting this tool. + string path = 1; + + // The host hosting this tool. + string host = 2; +} + +// [#next-free-field: 6] message ToolConfig { - // Name of the tool. + // Unique identifier of the tool. Used both for tools/list and tools/call transcoding. string name = 1 [(validate.rules).string = {min_len: 1}]; // The HTTP configuration rules that apply to the normal backend. HttpRule http_rule = 2; + + // Config for this tool's entry in a local tools/list response. Used when tool_list_local is set + // in the ServerToolConfig. + ToolsListSpecificConfig tool_list_config = 3; + + // Enables streaming transcoding for unstructured text responses (``content`` field of a result). + // + // When enabled, the response body is streamed directly to the client without buffering. Each + // chunk is JSON escaped as it arrives and wrapped with a pre-built JSON-RPC prefix and suffix. + // + // Streaming flow: + // + // .. code-block:: text + // + // input: [chunk1] → [chunk2] → [chunk3] + // output: [prefix+escaped_chunk1] → [escaped_chunk2] → [escaped_chunk3+suffix] + // + // Disabled by default. + bool text_content_streaming_enabled = 4; + + // [#not-implemented-hide:] + // Path and host of the MCP server that hosts this tool. + repeated McpServerInfo server_info = 5; } // Defines the schema of the JSON-RPC to REST mapping. It specifies how the "arguments" @@ -207,3 +320,8 @@ message HttpRule { // - If omitted: There is no HTTP request body; fields not in the path become query parameters. string body = 6; } + +// Per-route override configuration for the MCP JSON REST Bridge filter. +message McpJsonRestBridgePerRoute { + repeated ServerToolConfig tool_config = 1; +} diff --git a/api/src/main/proto/envoy/extensions/filters/http/mcp_router/v3/mcp_router.proto b/api/src/main/proto/envoy/extensions/filters/http/mcp_router/v3/mcp_router.proto index 1d3244993..185a61e01 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/mcp_router/v3/mcp_router.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/mcp_router/v3/mcp_router.proto @@ -125,4 +125,11 @@ message McpRouter { // If set, extracts a request "subject" and binds it into the MCP session. // If not set, sessions are created without identity binding. SessionIdentity session_identity = 2; + + // If true, backend initialization is deferred until the first request that targets each backend. + // The ``initialize`` response is returned immediately with gateway capabilities and an empty + // backend session map. Each backend is initialized on-demand when a request first routes to it. + // This avoids blocking the client ``initialize`` on slow or misbehaving backends. + // Default is false (eager initialization of all backends during ``initialize``). + bool lazy_initialization = 3; } diff --git a/api/src/main/proto/envoy/extensions/filters/http/oauth2/v3/oauth.proto b/api/src/main/proto/envoy/extensions/filters/http/oauth2/v3/oauth.proto index 28766ca51..fbe20a537 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/oauth2/v3/oauth.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/oauth2/v3/oauth.proto @@ -129,6 +129,8 @@ message OAuth2Credentials { // The secret used to retrieve the access token. This value will be URL encoded when sent to the OAuth server. // This field is required unless :ref:`auth_type ` // is set to ``TLS_CLIENT_AUTH``, in which case authentication is done via the client certificate. + // When ``auth_type`` is ``PRIVATE_KEY_JWT``, this field must contain the PEM-encoded private key + // used to sign the JWT client assertion. transport_sockets.tls.v3.SdsSecretConfig token_secret = 2; // Configures how the secret token should be created. @@ -149,9 +151,71 @@ message OAuth2Credentials { [(validate.rules).string = {pattern: "^$|^[^\\x00-\\x1f\\x7f \",;<>\\\\]+$"}]; } +// Configuration for ``PRIVATE_KEY_JWT`` client authentication (RFC 7523). +message PrivateKeyJwtConfig { + // Supported JWT signing algorithms for the client assertion. + enum SigningAlgorithm { + // ``RSASSA-PKCS1-v1_5`` using SHA-256. + RS256 = 0; + + // ``RSASSA-PKCS1-v1_5`` using SHA-384. + RS384 = 1; + + // ``RSASSA-PKCS1-v1_5`` using SHA-512. + RS512 = 2; + + // ECDSA using P-256 and SHA-256. + ES256 = 3; + + // ECDSA using P-384 and SHA-384. + ES384 = 4; + + // ECDSA using P-521 and SHA-512. + ES512 = 5; + } + + // The signing algorithm to use for the JWT assertion. + // The private key provided in ``token_secret`` must match the algorithm family: an RSA key for + // the ``RS*`` algorithms, or an EC key for the ``ES*`` algorithms. + // Default: ``RS256``. + SigningAlgorithm signing_algorithm = 1 [(validate.rules).enum = {defined_only: true}]; + + // The lifetime of the JWT assertion. After this duration, the assertion expires. + // The value is truncated to whole seconds, so it must be at least ``1s`` when set. + // Default: ``60s``. + google.protobuf.Duration assertion_lifetime = 2 [(validate.rules).duration = {gte {seconds: 1}}]; +} + +// Defines how an OAuth token is forwarded upstream. +message OAuth2TokenForwarding { + // The upstream request header that will carry the token. + // Pseudo-headers (names starting with ``:``) and the ``Host`` header are not allowed. + string header = 1 + [(validate.rules).string = {min_len: 1 well_known_regex: HTTP_HEADER_NAME strict: false}]; +} + +// Configuration for the ``post_logout_redirect_uri`` parameter used in OpenID Connect +// `RP-Initiated Logout requests `_. +// This configuration is ignored if ``end_session_endpoint`` is not set. +message PostLogoutRedirectUri { + oneof config { + option (validate.required) = true; + + // Do not include the ``post_logout_redirect_uri`` parameter in requests to the + // configured ``end_session_endpoint``. + bool disabled = 1 [(validate.rules).bool = {const: true}]; + + // URI to send as the ``post_logout_redirect_uri`` parameter. Supports header formatting + // tokens, and will be percent-encoded automatically when building the logout URL. + // + // The URI should be registered with the authorization server. + string uri = 2 [(validate.rules).string = {min_len: 1}]; + } +} + // OAuth config // -// [#next-free-field: 28] +// [#next-free-field: 34] message OAuth2Config { enum AuthType { // The ``client_id`` and ``client_secret`` will be sent in the URL encoded request body. @@ -168,6 +232,12 @@ message OAuth2Config { // transport socket configuration. // This implements OAuth 2.0 Mutual-TLS Client Authentication as defined in RFC 8705. TLS_CLIENT_AUTH = 2; + + // The client authenticates using a signed JWT assertion (RFC 7523). + // The ``token_secret`` in credentials must contain the PEM-encoded private key used to sign the assertion. + // The JWT assertion is sent as ``client_assertion`` in the token request body along with + // ``client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer``. + PRIVATE_KEY_JWT = 3; } // Endpoint on the authorization server to retrieve the access token from. @@ -187,6 +257,15 @@ message OAuth2Config { // If configured, the OAuth2 filter will redirect users to this endpoint when they access the signout_path. string end_session_endpoint = 23; + // Optional control for the ``post_logout_redirect_uri`` parameter sent to the ``end_session_endpoint`` when a user + // accesses the ``signout_path``. + // This field should be set only if ``openid`` is in the ``auth_scopes``, the ``end_session_endpoint`` is configured, + // and the authorization server supports the OpenID Connect RP-Initiated Logout specification. + // + // If unset, Envoy preserves the historical behavior and sends ``:///``, constructed from the inbound + // request, as ``post_logout_redirect_uri``. + PostLogoutRedirectUri post_logout_redirect_uri = 33; + // Credentials used for OAuth. OAuth2Credentials credentials = 3 [(validate.rules).message = {required: true}]; @@ -207,6 +286,19 @@ message OAuth2Config { // Forward the OAuth token as a Bearer to upstream web service. bool forward_bearer_token = 7; + // Forward the OIDC ID token to the upstream. + // + // If the configured header is ``Authorization``, Envoy forwards the ID token using the + // ``Bearer`` prefix. For any other header, Envoy forwards the raw token value. + // If not specified, the ID token will not be forwarded. + // + // This can not be configured with :ref:`forward_bearer_token + // ` + // or :ref:`preserve_authorization_header + // ` + // when the header is ``Authorization``. + OAuth2TokenForwarding forward_id_token = 31; + // If set to true, preserve the existing authorization header. // By default the client strips the existing authorization header before forwarding upstream. // Can not be set to true if forward_bearer_token is already set to true. @@ -304,6 +396,56 @@ message OAuth2Config { // Note: If a request matches pass_through_matcher, it bypasses OAuth validation and this matcher won't be evaluated. // This matcher takes precedence over deny_redirect_matcher. repeated config.route.v3.HeaderMatcher allow_failed_matcher = 27; + + // Optional base URI (scheme + host, e.g. ``https://app.example.com``) used to build the + // original request URI that is encoded into the OAuth2 ``state`` parameter. + // This URI will be used later to redirect users on a successful OAuth. + // + // This is useful when Envoy sits behind a gateway or load balancer that terminates the + // user-facing hostname: In that case, the post-authentication redirect derived from ``state`` would + // send the user to an internal host they didn't request. + // + // Supports request header formatting tokens. + // + // Example: + // + // original_request_uri: "%REQ(x-forwarded-proto?:scheme)%://%REQ(x-forwarded-host?:authority)%" + // + // If not set, defaults to ``<:scheme>://<:authority>`` of the incoming request. + string original_request_uri = 28; + + // Optional list of domains that are allowed as + // 1. redirect_uri: which is what the IdP calls after OAuth + // 2. original_request_uri: the one extracted from the state of an OAuth callback (where should the request go after OAuth) + // + // This mitigates: + // - injecting a malicious x-forwarded-host or any header that is used to template the redirect urls + // - open redirect attacks where an attacker crafts a ``state`` value pointing to an untrusted host. + // + // Each entry is matched against the host (with any port stripped) extracted from the + // formatted ``redirect_uri``, the formatted ``original_request_uri``, and the URL decoded from + // the ``state`` parameter on callback. Matching is case-insensitive and supports two forms: + // + // * Exact match, e.g. ``example.com`` matches only ``example.com``. + // * Wildcard subdomain match using a leading ``*.``, e.g. ``*.example.com`` matches + // ``foo.example.com`` and ``bar.baz.example.com`` but not ``example.com`` itself. + // + // IPv6 literals must be configured without surrounding brackets (e.g. ``::1``, not ``[::1]``). + // + // If this list is empty (the default), all hosts are allowed and no validation is performed. + repeated string allowed_redirect_domains = 29; + + // If set to true, the expiration time for the ID token cookie will always be derived from the + // ``expires_in`` field of the access token response rather than from the ``exp`` claim in the + // ID token JWT. This is useful when the access token response advertises a longer lifetime than + // the ID token and you want the ID token cookie to remain valid for that full duration. + // Default is false (use the ID token's own ``exp`` claim when available). + bool use_access_token_expiry_for_id_token_cookie = 30; + + // Configuration for ``PRIVATE_KEY_JWT`` client authentication. + // Only used when :ref:`auth_type ` + // is set to ``PRIVATE_KEY_JWT``. + PrivateKeyJwtConfig private_key_jwt_config = 32; } // Per-route OAuth2 config. diff --git a/api/src/main/proto/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto b/api/src/main/proto/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto index cd8152eb1..0286617ee 100644 --- a/api/src/main/proto/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto +++ b/api/src/main/proto/envoy/extensions/filters/http/ratelimit/v3/rate_limit.proto @@ -23,7 +23,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Rate limit :ref:`configuration overview `. // [#extension: envoy.filters.http.ratelimit] -// [#next-free-field: 18] +// [#next-free-field: 19] message RateLimit { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.http.rate_limit.v2.RateLimit"; @@ -186,6 +186,10 @@ message RateLimit { // 3. :ref:`disable_key `. // 4. :ref:`override limit `. repeated config.route.v3.RateLimit rate_limits = 17; + + // The namespace where dynamic metadata from rate limit response is saved. + // If not set, the default is "envoy.filters.http.ratelimit". + string metadata_namespace = 18; } message RateLimitPerRoute { diff --git a/api/src/main/proto/envoy/extensions/filters/listener/proxy_protocol/v3/proxy_protocol.proto b/api/src/main/proto/envoy/extensions/filters/listener/proxy_protocol/v3/proxy_protocol.proto index b90d08dc0..560403772 100644 --- a/api/src/main/proto/envoy/extensions/filters/listener/proxy_protocol/v3/proxy_protocol.proto +++ b/api/src/main/proto/envoy/extensions/filters/listener/proxy_protocol/v3/proxy_protocol.proto @@ -33,11 +33,38 @@ message ProxyProtocol { } message KeyValuePair { + // Specifies the encoding scheme that is used to encode the TLV value before it is + // stored in dynamic metadata or filter state. + enum ValueStringEncoding { + // Unspecified encoding scheme. Defaults to ``SANITIZED_UTF8``. + UNSPECIFIED = 0; + + // The TLV value will be sanitized to a valid UTF-8 string before being stored: + // any invalid UTF-8 sequences will be replaced with the ``!`` character. + SANITIZED_UTF8 = 1; + + // The raw TLV value will be encoded as a `Base64 `_ + // string (with padding) before being stored. This is useful for binary TLV values that + // are not valid UTF-8 strings. + BASE64 = 2; + } + // The namespace — if this is empty, the filter's namespace will be used. string metadata_namespace = 1; // The key to use within the namespace. string key = 2 [(validate.rules).string = {min_len: 1}]; + + // The value encoding scheme that is used to encode the TLV value before it is stored in + // dynamic metadata or filter state. If not set, defaults to ``SANITIZED_UTF8``, which + // sanitizes the TLV value to a valid UTF-8 string. + // + // .. note:: + // + // This option only applies to the legacy untyped dynamic metadata and filter state. + // For the new typed dynamic metadata, the raw TLV value bytes are stored as is and + // no encoding is applied. + ValueStringEncoding value_string_encoding = 3; } // A Rule defines what metadata to apply when a header is present or missing. diff --git a/api/src/main/proto/envoy/extensions/filters/network/ext_proc/v3/ext_proc.proto b/api/src/main/proto/envoy/extensions/filters/network/ext_proc/v3/ext_proc.proto index f37feaa94..a72773323 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/ext_proc/v3/ext_proc.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/ext_proc/v3/ext_proc.proto @@ -105,4 +105,13 @@ message MetadataOptions { // Describes which typed or untyped dynamic metadata namespaces to forward to // the external processing server. MetadataNamespaces forwarding_namespaces = 1; + + // Describes which typed or untyped dynamic metadata namespaces to receive + // from the external processing server. + // Since the server returns untyped dynamic metadata, this configuration acts + // as a allowlist. Only metadata namespaces explicitly listed here will be + // ingested by Envoy from the server's response. + // Receiving of typed metadata is not supported. + // Set to empty or leave unset to disallow writing any received dynamic metadata. + MetadataNamespaces receiving_namespaces = 2; } diff --git a/api/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto b/api/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto index 78ddd1a97..53b118f02 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto @@ -39,7 +39,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // HTTP connection manager :ref:`configuration overview `. // [#extension: envoy.filters.network.http_connection_manager] -// [#next-free-field: 62] +// [#next-free-field: 63] message HttpConnectionManager { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"; @@ -664,6 +664,18 @@ message HttpConnectionManager { // 5000 milliseconds (5 seconds) if this option is not specified. google.protobuf.Duration drain_timeout = 12; + // Percentage-based jitter for ``drain_timeout``. If set, the actual drain grace period + // is extended by a random duration up to ``drain_timeout * jitter / 100`` per connection. + // This staggers the final GOAWAY (and connection close) across time so that connections + // entering the drain state simultaneously do not all complete draining at the same instant, + // mitigating thundering-herd reconnects. If not set, no jitter is added. + // + // This is analogous to + // :ref:`max_connection_duration_jitter + // `, + // but applied to the drain grace timer rather than the connection duration timer. + type.v3.Percent drain_timeout_jitter = 62; + // The delayed close timeout is for downstream connections managed by the HTTP connection manager. // It is defined as a grace period after connection close processing has been locally initiated // during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy diff --git a/api/src/main/proto/envoy/extensions/filters/network/mongo_proxy/v3/mongo_proxy.proto b/api/src/main/proto/envoy/extensions/filters/network/mongo_proxy/v3/mongo_proxy.proto index 721f722ef..d370b92b6 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/mongo_proxy/v3/mongo_proxy.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/mongo_proxy/v3/mongo_proxy.proto @@ -4,6 +4,8 @@ package envoy.extensions.filters.network.mongo_proxy.v3; import "envoy/extensions/filters/common/fault/v3/fault.proto"; +import "google/protobuf/wrappers.proto"; + import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; @@ -18,7 +20,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // MongoDB :ref:`configuration overview `. // [#extension: envoy.filters.network.mongo_proxy] -// [#next-free-field: 6] +// [#next-free-field: 7] message MongoProxy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.network.mongo_proxy.v2.MongoProxy"; @@ -46,4 +48,7 @@ message MongoProxy { // Note that metrics will not be emitted for "find" commands, since those are considered // queries, and metrics for those are emitted under a dedicated "query" namespace. repeated string commands = 5; + + // The maximum depth of a BSON document that Envoy will parse. Defaults to 100. + google.protobuf.UInt32Value max_bson_depth = 6 [(validate.rules).uint32 = {gt: 0}]; } diff --git a/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/drain_aware_hcm.proto b/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/drain_aware_hcm.proto index 0c65b5049..116e1972a 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/drain_aware_hcm.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/drain_aware_hcm.proto @@ -26,4 +26,10 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; message DrainAwareHttpConnectionManager { // The underlying HCM configuration to apply. http_connection_manager.v3.HttpConnectionManager hcm_config = 1; + + // When true, a peer-initiated GOAWAY on a reverse tunnel makes the initiator drop the draining + // tunnel and dial a replacement, so capacity is restored before the old tunnel closes while its + // in-flight streams finish. Default false, so the behavior is opt-in and unconfigured listeners + // are unaffected. + bool enable_drain_with_goaway = 2; } diff --git a/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/reverse_tunnel.proto b/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/reverse_tunnel.proto index ac9bf4717..77e155216 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/reverse_tunnel.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/reverse_tunnel/v3/reverse_tunnel.proto @@ -96,7 +96,7 @@ message Validation { // Configuration for the reverse tunnel network filter. // This filter handles reverse tunnel connection acceptance and rejection by processing // HTTP requests where required identification values are provided via HTTP headers. -// [#next-free-field: 7] +// [#next-free-field: 9] message ReverseTunnel { // Ping interval for health checks on established reverse tunnel connections. // If not specified, defaults to ``2 seconds``. @@ -133,4 +133,16 @@ message ReverseTunnel { // via ``x-envoy-reverse-tunnel-upstream-cluster-name`` header. Connections with mismatched or missing // cluster names are rejected with HTTP ``400 Bad Request``. When empty, no cluster name validation is performed. string required_cluster_name = 6 [(validate.rules).string = {max_len: 255 ignore_empty: true}]; + + // Accept the handshake as an HTTP/1.1 ``Upgrade`` exchange (``Upgrade: reverse-tunnel``, + // reply ``101``) so HTTP proxies can route the handshake and splice the tunnel + // afterward. Non-upgrade requests are rejected with ``426``. The initiator must set this + // flag to the same value. + // Defaults to ``false``. + bool use_http_upgrade = 7; + + // When true, skip worker-thread rebalancing for accepted reverse tunnel connections. + // This avoids the cross-worker lock in pickLeastLoadedSocketManager. + // Default: false (rebalancing enabled). + bool skip_rebalancing = 8; } diff --git a/api/src/main/proto/envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.proto b/api/src/main/proto/envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.proto index 280baff90..e6d073782 100644 --- a/api/src/main/proto/envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.proto +++ b/api/src/main/proto/envoy/extensions/filters/network/tcp_proxy/v3/tcp_proxy.proto @@ -6,6 +6,7 @@ import "envoy/config/accesslog/v3/accesslog.proto"; import "envoy/config/core/v3/backoff.proto"; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/config_source.proto"; +import "envoy/config/core/v3/extension.proto"; import "envoy/config/core/v3/proxy_protocol.proto"; import "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto"; import "envoy/type/v3/hash_policy.proto"; @@ -80,7 +81,7 @@ enum ProxyProtocolTlvMergePolicy { APPEND_IF_EXISTS_OR_ADD = 2; } -// [#next-free-field: 24] +// [#next-free-field: 25] message TcpProxy { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.network.tcp_proxy.v2.TcpProxy"; @@ -119,7 +120,7 @@ message TcpProxy { // Configuration for tunneling TCP over other transports or application layers. // Tunneling is supported over HTTP/1.1 and HTTP/2. The upstream protocol is // determined by the cluster configuration. - // [#next-free-field: 10] + // [#next-free-field: 11] message TunnelingConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.filter.network.tcp_proxy.v2.TcpProxy.TunnelingConfig"; @@ -200,6 +201,12 @@ message TcpProxy { // This enables customizing the key used by access log formatters such as // ``%DYNAMIC_METADATA(envoy.filters.network.tcp_proxy:)%``. string request_id_metadata_key = 9; + + // Specifies a collection of Formatter plugins that can be used in substitution formatters + // in ``headers_to_add``. + // See the formatters extensions documentation for details. + // [#extension-category: envoy.formatter] + repeated config.core.v3.TypedExtensionConfig formatters = 10; } message OnDemand { @@ -390,4 +397,11 @@ message TcpProxy { // Use this carefully with server-first protocols. The upstream may send data before // receiving anything from downstream, which could fill the early data buffer. google.protobuf.UInt32Value max_early_data_bytes = 22 [(validate.rules).uint32 = {lte: 1048576}]; + + // If set to ``true``, the TCP proxy checks if the downstream connection was marked as drained + // after each read or write. When drain close is requested for the listener's traffic direction, + // the downstream connection is closed with ``FlushWrite``. + // + // This is disabled by default for backward compatibility. + google.protobuf.BoolValue check_drain_close = 24; } diff --git a/api/src/main/proto/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.proto b/api/src/main/proto/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.proto new file mode 100644 index 000000000..5d7e11f59 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3/ext_authz.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; + +package envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3; + +import "envoy/config/core/v3/grpc_service.proto"; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.filters.udp.udp_proxy.session.ext_authz.v3"; +option java_outer_classname = "ExtAuthzProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/udp/udp_proxy/session/ext_authz/v3;ext_authzv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: UDP session external authorization] +// UDP proxy session external authorization +// :ref:`configuration overview `. +// [#extension: envoy.filters.udp.session.ext_authz] + +// External authorization for UDP proxy sessions over the gRPC +// :ref:`CheckRequest ` API. +message FilterConfig { + // Configuration for UDP datagrams buffering while the authorization call is in flight. + message BufferOptions { + // If set, the filter will only buffer datagrams up to the requested limit, and will drop + // new UDP datagrams if the buffer contains the max_buffered_datagrams value at the time + // of a new datagram arrival. If not set, the default value is 1024 datagrams. + google.protobuf.UInt32Value max_buffered_datagrams = 1; + + // If set, the filter will only buffer datagrams up to the requested total buffered bytes limit, + // and will drop new UDP datagrams if the buffer contains the max_buffered_bytes value + // at the time of a new datagram arrival. If not set, the default value is 16,384 (16KB). + google.protobuf.UInt64Value max_buffered_bytes = 2; + } + + // The prefix to use when emitting :ref:`statistics + // `. + string stat_prefix = 1 [(validate.rules).string = {min_len: 1}]; + + // The external authorization gRPC service configuration (default timeout: 200ms). + config.core.v3.GrpcService grpc_service = 2 [(validate.rules).message = {required: true}]; + + // The filter's behaviour in case the external authorization service does not respond back, or + // when it returns an error. When set to true, the new session is established and traffic is + // forwarded to the upstream. When set to false, the session is dropped. Defaults to false. + bool failure_mode_allow = 3; + + // If configured, the filter will buffer datagrams while it is waiting for the authorization + // response. If this field is not configured, there will be no buffering and downstream datagrams + // that arrive while the authorization call is in progress will be dropped. In case this field is + // set but the options are not configured, the default values will be applied as described in the + // ``BufferOptions``. + BufferOptions buffer_options = 4; +} diff --git a/api/src/main/proto/envoy/extensions/formatter/dynamic_modules/v3/dynamic_modules.proto b/api/src/main/proto/envoy/extensions/formatter/dynamic_modules/v3/dynamic_modules.proto new file mode 100644 index 000000000..4ba383458 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/formatter/dynamic_modules/v3/dynamic_modules.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; + +package envoy.extensions.formatter.dynamic_modules.v3; + +import "envoy/extensions/dynamic_modules/v3/dynamic_modules.proto"; + +import "google/protobuf/any.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.formatter.dynamic_modules.v3"; +option java_outer_classname = "DynamicModulesProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/dynamic_modules/v3;dynamic_modulesv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Dynamic Modules Formatter] +// [#extension: envoy.formatter.dynamic_modules] + +// Configuration for the Dynamic Modules Formatter. This formatter allows loading shared object +// files via ``dlopen`` to implement custom ``%COMMAND%`` operators for access logs and header +// formatting. +// +// A module can be loaded by multiple formatters; the module is loaded only once and shared across +// multiple command parser instances. Each parsed command produces a provider that is invoked on the +// worker threads to compute the substitution value, with access to request and response headers, +// stream info attributes, dynamic metadata, and the local reply body. +message DynamicModuleFormatter { + // Specifies the shared-object level configuration. This field is required. + envoy.extensions.dynamic_modules.v3.DynamicModuleConfig dynamic_module_config = 1 + [(validate.rules).message = {required: true}]; + + // The name for this formatter configuration. If not specified, defaults to an empty string. + // + // This can be used to distinguish between different formatter implementations inside a dynamic + // module. When Envoy receives this configuration, it passes the ``formatter_name`` to the dynamic + // module's formatter config init function together with the ``formatter_config``. That way a + // module can decide which in-module command parser implementation to use based on the name at + // load time. + string formatter_name = 2; + + // The configuration for the formatter chosen by ``formatter_name``. If not specified, an empty + // configuration is passed to the module. + // + // This is passed to the module's formatter initialization function. Together with the + // ``formatter_name``, the module can decide which in-module command parser implementation to use + // and fine-tune which commands it recognizes. + // + // ``google.protobuf.Struct`` is serialized as JSON before passing it to the module. + // ``google.protobuf.BytesValue`` and ``google.protobuf.StringValue`` are passed directly + // without the wrapper. + // + // .. code-block:: yaml + // + // # Passing a JSON struct configuration + // formatter_config: + // "@type": "type.googleapis.com/google.protobuf.Struct" + // value: + // redact_headers: + // - authorization + // - cookie + // + // # Passing a simple string configuration + // formatter_config: + // "@type": "type.googleapis.com/google.protobuf.StringValue" + // value: "x-request-id" + // + google.protobuf.Any formatter_config = 3; +} diff --git a/api/src/main/proto/envoy/extensions/health_checkers/dynamic_modules/v3/dynamic_modules.proto b/api/src/main/proto/envoy/extensions/health_checkers/dynamic_modules/v3/dynamic_modules.proto new file mode 100644 index 000000000..d881af7cc --- /dev/null +++ b/api/src/main/proto/envoy/extensions/health_checkers/dynamic_modules/v3/dynamic_modules.proto @@ -0,0 +1,72 @@ +syntax = "proto3"; + +package envoy.extensions.health_checkers.dynamic_modules.v3; + +import "envoy/extensions/dynamic_modules/v3/dynamic_modules.proto"; + +import "google/protobuf/any.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.health_checkers.dynamic_modules.v3"; +option java_outer_classname = "DynamicModulesProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/health_checkers/dynamic_modules/v3;dynamic_modulesv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Dynamic Modules Health Checker] +// [#extension: envoy.health_checkers.dynamic_modules] + +// Configuration for the Dynamic Modules Health Checker. This health checker allows loading shared +// object files via ``dlopen`` to implement custom active health checking behavior. +// +// A module can be loaded by multiple health checkers; the module is loaded only once and shared +// across multiple health checker instances. +// +// Envoy drives the standard per-host interval and timeout timers and applies the common +// ``interval``, ``timeout``, ``healthy_threshold`` and ``unhealthy_threshold`` settings. On each +// interval the module is asked to check the host; it may perform the work on its own thread and +// reports the host's health status back to Envoy. +message DynamicModuleHealthCheck { + // Specifies the shared-object level configuration. This field is required. + envoy.extensions.dynamic_modules.v3.DynamicModuleConfig dynamic_module_config = 1 + [(validate.rules).message = {required: true}]; + + // The name for this health checker configuration. + // + // This can be used to distinguish between different health checker implementations inside a + // dynamic module. For example, a module can have completely different health checker + // implementations (e.g., a ping checker, an external-service checker). When Envoy receives this + // configuration, it passes the ``health_checker_name`` to the dynamic module's health checker + // config init function together with the ``health_checker_config``. That way a module can decide + // which in-module health checker implementation to use based on the name at load time. + string health_checker_name = 2 [(validate.rules).string = {min_len: 1}]; + + // The configuration for the health checker chosen by ``health_checker_name``. If not specified, + // an empty configuration is passed to the module. + // + // This is passed to the module's health checker initialization function. Together with the + // ``health_checker_name``, the module can decide which in-module health checker implementation to + // use and fine-tune the behavior of the health checker. + // + // ``google.protobuf.Struct`` is serialized as JSON before passing it to the module. + // ``google.protobuf.BytesValue`` and ``google.protobuf.StringValue`` are passed directly + // without the wrapper. + // + // .. code-block:: yaml + // + // # Passing a JSON struct configuration + // health_checker_config: + // "@type": "type.googleapis.com/google.protobuf.Struct" + // value: + // path: "/healthz" + // degraded_on_slow_response: true + // + // # Passing a simple string configuration + // health_checker_config: + // "@type": "type.googleapis.com/google.protobuf.StringValue" + // value: "/healthz" + // + google.protobuf.Any health_checker_config = 3; +} diff --git a/api/src/main/proto/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto b/api/src/main/proto/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto index c55d30b89..7c47e6d15 100644 --- a/api/src/main/proto/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto +++ b/api/src/main/proto/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto @@ -44,7 +44,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // See the :ref:`load balancing architecture // overview` for more information. // -// [#next-free-field: 9] +// [#next-free-field: 10] message ClientSideWeightedRoundRobin { // Whether to enable out-of-band utilization reporting collection from // the endpoints. By default, per-request utilization reporting is used. @@ -88,4 +88,9 @@ message ClientSideWeightedRoundRobin { // Configuration for slow start mode. // If this configuration is not set, slow start will not be not enabled. common.v3.SlowStartConfig slow_start_config = 8; + + // Optional overrides for the OOB reporting connection (alternative port, + // ``:authority``, transport socket selection). Honored only when + // ``enable_oob_load_report`` is true. + common.v3.OrcaOobReportingConfig oob_reporting_config = 9; } diff --git a/api/src/main/proto/envoy/extensions/load_balancing_policies/common/v3/common.proto b/api/src/main/proto/envoy/extensions/load_balancing_policies/common/v3/common.proto index 22faf11b9..5064b1aa2 100644 --- a/api/src/main/proto/envoy/extensions/load_balancing_policies/common/v3/common.proto +++ b/api/src/main/proto/envoy/extensions/load_balancing_policies/common/v3/common.proto @@ -7,6 +7,7 @@ import "envoy/config/route/v3/route_components.proto"; import "envoy/type/v3/percent.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; import "google/protobuf/wrappers.proto"; import "envoy/annotations/deprecation.proto"; @@ -159,3 +160,29 @@ message ConsistentHashingLbConfig { // will be ignored. repeated config.route.v3.RouteAction.HashPolicy hash_policy = 3; } + +// Connection overrides for the ORCA out-of-band (OOB) reporting stream, used by +// load balancing policies that consume ORCA load reports (e.g. +// :ref:`client_side_weighted_round_robin +// `). +// Whether and when OOB reporting runs is controlled by the embedding policy. +message OrcaOobReportingConfig { + // Optional alternative port for the OOB reporting connection, for example an + // ORCA reporting sidecar listening on a dedicated port. If 0 or unset, the + // port of the host's ORCA reporting address is used. Ignored for non-IP + // (pipe/UDS) host addresses. + uint32 port_value = 1 [(validate.rules).uint32 = {lte: 65535}]; + + // Value of the ``:authority`` header on the OOB gRPC stream. If empty, the + // endpoint hostname is used, then the dialed address, then the cluster name. + string authority = 2 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}]; + + // Optional key/value pairs used to select a transport socket from the + // cluster's :ref:`transport_socket_matches + // ` + // for the OOB connection. If unset, or if no match is found, the cluster's + // default transport socket is used. ALPN ``h2`` is always forced on the OOB + // connection regardless of this setting. + google.protobuf.Struct transport_socket_match_criteria = 3; +} diff --git a/api/src/main/proto/envoy/extensions/load_balancing_policies/load_aware_locality/v3/load_aware_locality.proto b/api/src/main/proto/envoy/extensions/load_balancing_policies/load_aware_locality/v3/load_aware_locality.proto new file mode 100644 index 000000000..ec573dc86 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/load_balancing_policies/load_aware_locality/v3/load_aware_locality.proto @@ -0,0 +1,95 @@ +syntax = "proto3"; + +package envoy.extensions.load_balancing_policies.load_aware_locality.v3; + +import "envoy/config/cluster/v3/cluster.proto"; + +import "google/protobuf/duration.proto"; +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.load_balancing_policies.load_aware_locality.v3"; +option java_outer_classname = "LoadAwareLocalityProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/load_aware_locality/v3;load_aware_localityv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Load-Aware Locality-Picking Load Balancing Policy] +// [#extension: envoy.load_balancing_policies.load_aware_locality] + +// Configuration for the load_aware_locality LB policy which uses ORCA utilization data +// to route traffic between localities based on available headroom. +// [#next-free-field: 10] +message LoadAwareLocality { + // The child LB policy to create for endpoint-picking within each locality. + config.cluster.v3.LoadBalancingPolicy endpoint_picking_policy = 1 + [(validate.rules).message = {required: true}]; + + // How frequently ORCA weights and locality utilization are recomputed on the + // main thread. Must be at least 100ms. Defaults to 1s. + google.protobuf.Duration weight_update_period = 2 + [(validate.rules).duration = {gte {nanos: 100000000}}]; + + // By default, endpoint utilization is computed based on the + // :ref:`application_utilization ` + // field reported by the endpoint. If that field is not set, then utilization + // will instead be computed by taking the max of the values of the metrics + // specified here. For map fields in the ORCA proto, the string will be of + // the form ``.``. For example, the string + // ``named_metrics.foo`` will mean to look for the key ``foo`` in the ORCA + // :ref:`named_metrics ` + // field. If none of the specified metrics are present in the load report, + // then :ref:`cpu_utilization ` + // is used instead. + repeated string metric_names_for_computing_utilization = 3; + + // When the local locality's utilization is at most this threshold above the + // remote average, route 100% of traffic to the local locality. This avoids + // unnecessary cross-zone routing when utilization is roughly balanced. + // One-sided: if the local zone is less loaded than remote, all-local routing + // always applies. Must be in [0, 1]. Defaults to 0.1. + google.protobuf.DoubleValue utilization_variance_threshold = 4 + [(validate.rules).double = {lte: 1.0 gte: 0.0}]; + + // EWMA time constant for per-locality utilization smoothing. The per-tick + // smoothing factor alpha is derived as ``1 - exp(-weight_update_period / + // smoothing_time_constant)``, so settling time is consistent regardless of + // the configured tick rate. Larger values produce more stable weights; + // smaller values react faster. Must be greater than 0s. Defaults to 5s + // (~95% settling within ~15s). + google.protobuf.Duration smoothing_time_constant = 5 [(validate.rules).duration = {gt {}}]; + + // Minimum fraction of traffic sent to non-local localities to keep ORCA + // data fresh when the local-preference check would otherwise route 100% of + // traffic to the local locality. The deficit is redistributed across remote + // localities proportionally to their host count. Must be in [0, 1). Set to + // 0 to disable (safe only when ORCA reports arrive out-of-band, or when + // cross-zone traffic must be strictly avoided). Defaults to 0.03 (3%). + // + // Probe fraction is a global value split across all remote localities. + // At very high remote-locality counts combined with low aggregate request + // rates, per-host sample intervals can exceed ``weight_expiration_period``. + // See the architecture overview for the scaling matrix. + google.protobuf.DoubleValue remote_probe_fraction = 6 + [(validate.rules).double = {lt: 1.0 gte: 0.0}]; + + // Per-host ORCA sample validity window. Hosts that have not reported load + // metrics within this duration are excluded from their locality's + // utilization aggregation. The locality's EWMA state continues normally + // over the remaining reporting hosts. If every host in a locality is + // stale, the locality falls back to host-count-proportional weighting + // (the same path used when all localities are overloaded). Set to 0s to + // disable expiration. Defaults to 3 minutes. + google.protobuf.Duration weight_expiration_period = 7 [(validate.rules).duration = {gte {}}]; + + // Whether to enable out-of-band utilization reporting collection from + // the endpoints. By default, per-request utilization reporting is used. + google.protobuf.BoolValue enable_oob_load_report = 8; + + // Load reporting interval to request from the server. Note that the + // server may not provide reports as frequently as the client requests. + // Used only when enable_oob_load_report is true. Default is 10 seconds. + google.protobuf.Duration oob_reporting_period = 9; +} diff --git a/api/src/main/proto/envoy/extensions/network/dns_resolver/cares/v3/cares_dns_resolver.proto b/api/src/main/proto/envoy/extensions/network/dns_resolver/cares/v3/cares_dns_resolver.proto index d05d073da..077ba1e9e 100644 --- a/api/src/main/proto/envoy/extensions/network/dns_resolver/cares/v3/cares_dns_resolver.proto +++ b/api/src/main/proto/envoy/extensions/network/dns_resolver/cares/v3/cares_dns_resolver.proto @@ -21,7 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#extension: envoy.network.dns_resolver.cares] // Configuration for c-ares DNS resolver. -// [#next-free-field: 12] +// [#next-free-field: 13] message CaresDnsResolverConfig { // A list of DNS resolver addresses. // :ref:`use_resolvers_as_fallback ` @@ -113,4 +113,14 @@ message CaresDnsResolverConfig { // // Default is false. bool reinit_channel_on_timeout = 11; + + // The maximum duration (in seconds) for which DNS responses will be cached by c-ares. + // + // If set to a non-zero value, the query cache is enabled and will respect the + // TTL provided in the DNS response, up to this maximum limit. + // + // .. note:: + // While the underlying c-ares library defaults to 1 hour, Envoy's default + // for this field is 0, which disables the query cache entirely. + google.protobuf.UInt32Value qcache_max_ttl = 12 [(validate.rules).uint32 = {gte: 0}]; } diff --git a/api/src/main/proto/envoy/extensions/network/socket_interface/sockmap/v3/sockmap.proto b/api/src/main/proto/envoy/extensions/network/socket_interface/sockmap/v3/sockmap.proto new file mode 100644 index 000000000..3d9323bb6 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/network/socket_interface/sockmap/v3/sockmap.proto @@ -0,0 +1,64 @@ +syntax = "proto3"; + +package envoy.extensions.network.socket_interface.sockmap.v3; + +import "envoy/type/v3/range.proto"; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.network.socket_interface.sockmap.v3"; +option java_outer_classname = "SockmapProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/network/socket_interface/sockmap/v3;sockmapv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Sockmap socket interface configuration] +// Sockmap socket interface :ref:`configuration overview `. +// [#extension: envoy.extensions.network.socket_interface.sockmap] + +// Configuration for the ``sockmap`` socket interface. It accelerates same-host TCP hops by +// loading eBPF ``sock_ops`` and ``sk_msg`` programs that redirect payloads between local sockets +// through a ``BPF_MAP_TYPE_SOCKHASH``, bypassing the kernel TCP/IP stack. Connections whose peer +// is not on the same host are not present in the map and transparently fall back to TCP/IP. +// +// This interface requires a Linux kernel 4.18 or later and the capabilities to load and attach the +// eBPF network programs (``CAP_SYS_ADMIN``, or ``CAP_BPF`` and ``CAP_NET_ADMIN`` on newer kernels). +// When the programs cannot be loaded or attached, the interface logs the failure and every socket +// falls back to the standard datapath, so traffic is never interrupted. +// [#next-free-field: 6] +message Sockmap { + // Filesystem path to the compiled eBPF object that holds the ``sock_ops`` and ``sk_msg`` + // programs and the ``sockhash`` map. Envoy does not ship this object. Build it from the + // extension's ``sockmap_kern.c`` source, or supply a custom build that exports the + // ``envoy_sockops`` and ``envoy_sk_msg`` programs and the ``envoy_sockhash`` map with a matching + // key layout. If not specified, acceleration is disabled and all sockets use the standard + // datapath. + string bpf_program_path = 1; + + // Path to the cgroup v2 directory the ``sock_ops`` program is attached to. While attached, every + // socket that reaches the established state inside this cgroup is added to the ``sockhash``, + // which accelerates application-to-proxy hops. If not specified, the ``sock_ops`` program + // is not attached and only sockets accepted or connected by Envoy are registered, which still + // accelerates proxy-to-proxy hops on the same host. + string cgroup_path = 2; + + // Maximum number of entries in the ``sockhash`` map. Each accelerated socket consumes one entry. + // If not specified, defaults to ``65536``. + google.protobuf.UInt32Value sockhash_max_entries = 3 [(validate.rules).uint32 = {gte: 1}]; + + // Whether sockets accepted or connected by Envoy are registered into the ``sockhash`` from user + // space. This is independent of ``cgroup_path`` and lets proxy-to-proxy hops be accelerated + // without attaching the ``sock_ops`` program. If not specified, defaults to ``true``. + google.protobuf.BoolValue register_user_space_sockets = 4; + + // Proxy listener port ranges that scope which connections the ``sock_ops`` program adds to the + // ``sockhash``. Each range is half-open ``[start, end)`` with ``1 <= start < end <= 65536``, so a + // single port ``P`` is ``{ start: P, end: P + 1 }``. When set, only a connection whose local or + // peer port falls in one of these ranges is registered, so other same-host connections in the + // cgroup stay on the standard datapath. This applies only when ``cgroup_path`` is set. If empty, + // every such connection is registered. At most ``128`` ranges are allowed. + repeated type.v3.Int64Range accelerated_ports = 5 [(validate.rules).repeated = {max_items: 128}]; +} diff --git a/api/src/main/proto/envoy/extensions/network/socket_interface/v3/default_socket_interface.proto b/api/src/main/proto/envoy/extensions/network/socket_interface/v3/default_socket_interface.proto index 69b413eba..ab80421c3 100644 --- a/api/src/main/proto/envoy/extensions/network/socket_interface/v3/default_socket_interface.proto +++ b/api/src/main/proto/envoy/extensions/network/socket_interface/v3/default_socket_interface.proto @@ -5,6 +5,7 @@ package envoy.extensions.network.socket_interface.v3; import "google/protobuf/wrappers.proto"; import "udpa/annotations/status.proto"; +import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.extensions.network.socket_interface.v3"; option java_outer_classname = "DefaultSocketInterfaceProto"; @@ -14,33 +15,81 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Default socket interface configuration] -// Configuration for default socket interface that relies on OS dependent syscall to create +// Configuration for the default socket interface that relies on OS-dependent syscalls to create // sockets. message DefaultSocketInterface { - // io_uring options. io_uring is only valid in Linux with at least kernel version 5.11. Otherwise, - // Envoy will fall back to use the default socket API. If not set then io_uring will not be - // enabled. + // Options for ``io_uring``-based socket I/O. ``io_uring`` is only supported on Linux with + // kernel version 5.11 or later. On unsupported platforms, Envoy falls back to the default + // socket API. + // + // .. note:: + // + // If not set, ``io_uring`` will not be enabled and the standard epoll-based I/O path + // is used. IoUringOptions io_uring_options = 1; } +// Configuration for ``io_uring``-based asynchronous I/O. +// +// Each worker thread creates its own ``io_uring`` instance during initialization. Operations +// are submitted to the submission queue (SQ) and completions are reaped from the completion +// queue (CQ) via an eventfd integrated with the worker's event loop. +// +// .. warning:: +// +// ``io_uring`` support is experimental and its performance characteristics depend heavily on +// the kernel version. +// +// [#next-free-field: 8] message IoUringOptions { - // The size for io_uring submission queues (SQ). io_uring is built with a fixed size in each - // thread during configuration, and each io_uring operation creates a submission queue - // entry (SQE). The default is 1000. + // The number of entries in the ``io_uring`` submission queue (SQ). Each in-flight I/O + // operation requires one SQE. The completion queue (CQ) is sized at ``2x`` this value + // to provide overflow headroom. If not specified, defaults to 1000. google.protobuf.UInt32Value io_uring_size = 1; - // Enable io_uring submission queue polling (SQPOLL). io_uring SQPOLL mode polls all SQEs in the - // SQ in the kernel thread. io_uring SQPOLL mode may reduce latency and increase CPU usage as a - // cost. The default is false. + // Enables ``io_uring`` submission queue polling (``SQPOLL``). When enabled, a dedicated + // kernel thread polls the SQ for new entries, eliminating the ``io_uring_enter()`` syscall + // on submission. This may reduce latency at the cost of increased CPU usage. + // If not specified, defaults to false. bool enable_submission_queue_polling = 2; - // The size of an io_uring socket's read buffer. Each io_uring read operation will allocate a - // buffer of the given size. If the given buffer is too small, the socket will have read multiple - // times for all the data. The default is 8192. + // The starting size in bytes of the buffer for each ``readv``-based ``io_uring`` read. Envoy + // grows the next read up to 16 times this size while reads keep filling the buffer and resets it + // otherwise, so large transfers use fewer reads. When ``enable_multishot_receive`` is set, this + // is also the size of each kernel-provided buffer. If not specified, defaults to 8192. google.protobuf.UInt32Value read_buffer_size = 3; - // The write timeout of an io_uring socket on closing in ms. io_uring writes and closes - // asynchronously. If the remote stops reading, the io_uring write operation may never complete. - // The operation is canceled and the socket is closed after the timeout. The default is 1000. + // The timeout in milliseconds to wait for pending write operations to complete when closing + // a socket. ``io_uring`` writes are asynchronous. If the remote peer stops reading, a write + // may never complete. After this timeout, pending writes are canceled and the socket is + // closed. If not specified, defaults to 1000. google.protobuf.UInt32Value write_timeout_ms = 4; + + // The high watermark in bytes for the write buffer. When the amount of pending write data + // exceeds this threshold, the socket stops accepting new writes from the connection so that + // backpressure propagates to the upper layers. If not specified, defaults to 131072 (128 KiB). + // When set, the value must be at least 4096 (4 KiB). + google.protobuf.UInt32Value write_high_watermark_bytes = 5 + [(validate.rules).uint32 = {gte: 4096}]; + + // The low watermark in bytes for the write buffer. After the buffer has exceeded + // ``write_high_watermark_bytes`` and writes were paused, the socket resumes accepting writes + // once the pending write data drops to or below this value. + // If not specified, defaults to 16384 (16 KiB). + // When set, the value must be at least 1024 (1 KiB). + // + // .. note:: + // + // This value must be less than ``write_high_watermark_bytes``. If misconfigured, it is + // clamped to ``write_high_watermark_bytes / 2``. + google.protobuf.UInt32Value write_low_watermark_bytes = 6 [(validate.rules).uint32 = {gte: 1024}]; + + // Enables ``multishot`` reads backed by a kernel-provided buffer ring. A single ``recv`` is armed + // per socket and the kernel keeps delivering data as it arrives without a new submission per + // read, which reduces event loop wakeups and read submissions for read-heavy workloads. The ring + // holds ``io_uring_size`` buffers rounded up to a power of two and capped at 4096, each + // ``read_buffer_size`` bytes, so each worker thread uses up to that buffer count times + // ``read_buffer_size`` bytes for the pool. Requires Linux kernel 6.0 or later. On older kernels, + // Envoy falls back to ``readv``-based reads. If not specified, defaults to false. + bool enable_multishot_receive = 7; } diff --git a/api/src/main/proto/envoy/extensions/path/match/uri_template/v3/uri_template_match.proto b/api/src/main/proto/envoy/extensions/path/match/uri_template/v3/uri_template_match.proto index 27579f5b4..fb5cba97f 100644 --- a/api/src/main/proto/envoy/extensions/path/match/uri_template/v3/uri_template_match.proto +++ b/api/src/main/proto/envoy/extensions/path/match/uri_template/v3/uri_template_match.proto @@ -31,6 +31,10 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // * ``{name=**}`` : A named variable matching zero or more path segments. // +// * ``prefix{name}suffix`` : A named variable with surrounding literal text within a single path +// segment. For example, ``v{version}`` or ``{id}.json``. The variable captures only the +// dynamic portion; the prefix and suffix must match literally. +// // // For example: // @@ -39,6 +43,9 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // * ``/videos/{file}`` would match ``/videos/1080p5000_00001.m4s`` // // * ``/**.mpd`` would match ``/content/123/india/dash/55/manifest.mpd`` +// +// * ``/api/v{version}/users/{id}.json`` would match ``/api/v2/users/456.json`` and +// capture ``version=2`` and ``id=456``. message UriTemplateMatchConfig { string path_template = 1 [(validate.rules).string = {min_len: 1 max_len: 256}]; } diff --git a/api/src/main/proto/envoy/extensions/resource_monitors/fixed_heap/v3/fixed_heap.proto b/api/src/main/proto/envoy/extensions/resource_monitors/fixed_heap/v3/fixed_heap.proto index 4a9f07d10..1728ec57a 100644 --- a/api/src/main/proto/envoy/extensions/resource_monitors/fixed_heap/v3/fixed_heap.proto +++ b/api/src/main/proto/envoy/extensions/resource_monitors/fixed_heap/v3/fixed_heap.proto @@ -2,9 +2,10 @@ syntax = "proto3"; package envoy.extensions.resource_monitors.fixed_heap.v3; +import "envoy/config/core/v3/base.proto"; + import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; -import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.extensions.resource_monitors.fixed_heap.v3"; option java_outer_classname = "FixedHeapProto"; @@ -22,5 +23,14 @@ message FixedHeapConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.config.resource_monitor.fixed_heap.v2alpha.FixedHeapConfig"; - uint64 max_heap_size_bytes = 1 [(validate.rules).uint64 = {gt: 0}]; + // Static value for max heap size in bytes set at startup. + // Exactly one of max_heap_size_bytes or max_heap_size_bytes_runtime must be set. + // If set, the expected value must be greater than ``0``, otherwise validation will fail. + uint64 max_heap_size_bytes = 1; + + // Runtime overlay for max heap size in bytes. When set, the value can be overridden + // at runtime during startup or later without restart. + // Exactly one of max_heap_size_bytes or max_heap_size_bytes_runtime must be set. + // If set, the expected value must be greater than ``0``, otherwise validation will fail. + config.core.v3.RuntimeUInt64 max_heap_size_bytes_runtime = 2; } diff --git a/api/src/main/proto/envoy/extensions/stat_sinks/dynamic_modules/v3/dynamic_modules.proto b/api/src/main/proto/envoy/extensions/stat_sinks/dynamic_modules/v3/dynamic_modules.proto new file mode 100644 index 000000000..2f49626dd --- /dev/null +++ b/api/src/main/proto/envoy/extensions/stat_sinks/dynamic_modules/v3/dynamic_modules.proto @@ -0,0 +1,63 @@ +syntax = "proto3"; + +package envoy.extensions.stat_sinks.dynamic_modules.v3; + +import "envoy/extensions/dynamic_modules/v3/dynamic_modules.proto"; + +import "google/protobuf/any.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.stat_sinks.dynamic_modules.v3"; +option java_outer_classname = "DynamicModulesProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/stat_sinks/dynamic_modules/v3;dynamic_modulesv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Dynamic Modules Stats Sink] +// [#extension: envoy.stat_sinks.dynamic_modules] + +// Configuration for the Dynamic Modules Stats Sink. This sink allows loading shared object +// files via ``dlopen`` to implement custom stats sink behavior. +// +// A module can be loaded by multiple stat sinks. It is loaded only once and shared +// across multiple sink instances. +// +// The stats sink receives periodic metric snapshots of counters, gauges, and text readouts, +// and is also called synchronously when histogram observations are recorded. +message DynamicModuleStatsSink { + // Specifies the shared-object level configuration. This field is required. + envoy.extensions.dynamic_modules.v3.DynamicModuleConfig dynamic_module_config = 1 + [(validate.rules).message = {required: true}]; + + // The name for this sink configuration. If not specified, defaults to an empty string. + // + // This can be used to distinguish between different sink implementations inside a dynamic + // module. When Envoy receives this configuration, it passes the ``sink_name`` to the dynamic + // module's sink config init function together with the ``sink_config``. + string sink_name = 2; + + // The configuration for the sink chosen by ``sink_name``. If not specified, an empty + // configuration is passed to the module. + // + // ``google.protobuf.Struct`` is serialized as JSON before passing it to the module. + // ``google.protobuf.BytesValue`` and ``google.protobuf.StringValue`` are passed directly + // without the wrapper. + // + // .. code-block:: yaml + // + // # Passing a JSON struct configuration + // sink_config: + // "@type": "type.googleapis.com/google.protobuf.Struct" + // value: + // endpoint: "metrics.example.com:9125" + // prefix: "envoy" + // + // # Passing a simple string configuration + // sink_config: + // "@type": "type.googleapis.com/google.protobuf.StringValue" + // value: "metrics.example.com:9125" + // + google.protobuf.Any sink_config = 3; +} diff --git a/api/src/main/proto/envoy/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto b/api/src/main/proto/envoy/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto index fdc9a0a29..d2a852ee6 100644 --- a/api/src/main/proto/envoy/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto +++ b/api/src/main/proto/envoy/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto @@ -24,7 +24,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // Stats configuration proto schema for ``envoy.stat_sinks.open_telemetry`` sink. // [#extension: envoy.stat_sinks.open_telemetry] -// [#next-free-field: 10] +// [#next-free-field: 11] message SinkConfig { // ConversionAction is used to convert a stat to a metric. If a stat matches, // the metric_name and static_metric_labels will be @@ -94,4 +94,8 @@ message SinkConfig { // - ``envoy.extensions.stat_sinks.open_telemetry.v3.SinkConfig.ConversionAction``. // If stats are not matched, they will be directly converted to OTLP metrics as usual. xds.type.matcher.v3.Matcher custom_metric_conversions = 8; + + // Maximum number of data points per request. If explicitly set to 0, there is no limit. If unset, it currently defaults to no limit. + // When the maximum number of data points is reached, the remaining data points will be sent in subsequent requests. + uint32 max_data_points_per_request = 10; } diff --git a/api/src/main/proto/envoy/extensions/transport_sockets/dynamic_modules/v3/dynamic_modules.proto b/api/src/main/proto/envoy/extensions/transport_sockets/dynamic_modules/v3/dynamic_modules.proto new file mode 100644 index 000000000..90e1d5a79 --- /dev/null +++ b/api/src/main/proto/envoy/extensions/transport_sockets/dynamic_modules/v3/dynamic_modules.proto @@ -0,0 +1,55 @@ +syntax = "proto3"; + +package envoy.extensions.transport_sockets.dynamic_modules.v3; + +import "envoy/extensions/dynamic_modules/v3/dynamic_modules.proto"; + +import "google/protobuf/any.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.transport_sockets.dynamic_modules.v3"; +option java_outer_classname = "DynamicModulesProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/dynamic_modules/v3;dynamic_modulesv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Dynamic Module Transport Socket] +// [#extension: envoy.transport_sockets.dynamic_modules] + +// Configuration for a transport socket implemented by a dynamic module. The transport socket +// performs the raw I/O for a connection and may transform the bytes that flow over it, for example +// to implement a custom encryption scheme. +// +// Example: +// +// .. code-block:: yaml +// +// transport_socket: +// name: envoy.transport_sockets.dynamic_modules +// typed_config: +// "@type": type.googleapis.com/envoy.extensions.transport_sockets.dynamic_modules.v3.DynamicModuleTransportSocket +// dynamic_module_config: +// name: my_module +// transport_socket_name: my_transport_socket +// +message DynamicModuleTransportSocket { + // Dynamic module configuration. See :ref:`dynamic module configuration + // ` for details. + envoy.extensions.dynamic_modules.v3.DynamicModuleConfig dynamic_module_config = 1 + [(validate.rules).message = {required: true}]; + + // The name of the transport socket implementation in the dynamic module. This is passed to the + // module's ``envoy_dynamic_module_on_transport_socket_factory_config_new`` function. + string transport_socket_name = 2 [(validate.rules).string = {min_len: 1}]; + + // Optional configuration for the transport socket. This is passed as bytes to the dynamic module. + // If not specified, no configuration bytes are passed to the module. + google.protobuf.Any transport_socket_config = 3; + + // Whether the transport socket implements secure transport. Set this to true for modules that + // provide encryption so that Envoy treats connections using this transport socket as secure. If + // not specified, defaults to false. + bool implements_secure_transport = 4; +} diff --git a/api/src/main/proto/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto b/api/src/main/proto/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto index 9756ff5a0..652e37ed2 100644 --- a/api/src/main/proto/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto +++ b/api/src/main/proto/envoy/extensions/transport_sockets/quic/v3/quic_transport.proto @@ -27,6 +27,10 @@ message QuicDownstreamTransport { // If false, QUIC will tell TLS to reject any early data and to stop issuing 0-RTT credentials with resumption session tickets. This will prevent clients from sending 0-RTT requests. // Default to true. google.protobuf.BoolValue enable_early_data = 2; + + // If false, TLS session tickets are not issued and accepted by QUIC. + // Default to true. + google.protobuf.BoolValue enable_resumption = 3; } // Configuration for Upstream QUIC transport socket. This provides Google's implementation of Google QUIC and IETF QUIC to Envoy. diff --git a/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto b/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto index 9bc5fb5d0..3a3b753a0 100644 --- a/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto +++ b/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/common.proto @@ -57,9 +57,44 @@ message TlsParameters { // // .. attention:: // - // Please refer to `BoringSSL policies `_ + // Please refer to the `BoringSSL FIPS_202205 compliance policy `_ // for details. FIPS_202205 = 0; + + // CNSA2_202603 configures a TLS connection to use: + // + // * Only TLS 1.3, with AES-256-GCM. + // * Only ML-KEM-1024 for key agreement. + // * For handshake signatures, only ECDSA with P-384 and SHA-384, or RSA + // with SHA-384. + // + // Note: this setting aids with compliance with CNSA requirements but does not + // guarantee it. Careful reading of ``draft-becker-cnsa2-tls-profile`` is + // recommended. + // + // .. attention:: + // + // Please refer to the `BoringSSL CNSA2_202603 compliance policy `_ + // for details. + CNSA2_202603 = 1; + + // CNSA1_202603 configures a TLS connection to use: + // * TLS 1.2 or TLS 1.3. + // * For TLS 1.2, only TLS_ECDHE_[ECDSA|RSA]_WITH_AES_256_GCM_SHA384. + // * For TLS 1.3, only AES-256-GCM. + // * ML-KEM-1024 or P-384 for key agreement, preferring ML-KEM-1024 if the + // client supports it. + // * For handshake signatures, only ECDSA with P-384 and SHA-384, or RSA + // with SHA-384. + // + // Note: this setting aids with compliance with CNSA requirements but does not + // guarantee it. Careful reading of RFC 9151 is recommended. + // + // .. attention:: + // + // Please refer to the `BoringSSL CNSA1_202603 compliance policy `_ + // for details. + CNSA1_202603 = 2; } // Minimum TLS protocol version. By default, it's ``TLSv1_2`` for both clients and servers. @@ -369,7 +404,7 @@ message SubjectAltNameMatcher { string oid = 3; } -// [#next-free-field: 18] +// [#next-free-field: 19] message CertificateValidationContext { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.auth.CertificateValidationContext"; @@ -594,4 +629,28 @@ message CertificateValidationContext { // in OpenSSL 1.1.x and newer versions of BoringSSL in that the trust anchor is included. // Trusted issues are specified by setting :ref:`trusted_ca ` google.protobuf.UInt32Value max_verify_depth = 16 [(validate.rules).uint32 = {lte: 100}]; + + // If true, the server does not include the trusted-CA distinguished names in the + // TLS ``CertificateRequest`` message. CAs from :ref:`trusted_ca + // ` + // are still used to validate presented client certificates; only the wire + // advertisement changes. + // + // This is useful when the configured CA set is large enough that the + // ``CertificateRequest`` would exceed client-side TLS record limits, or when + // clients mishandle the CA set in some way. + // + // .. attention:: + // + // When enabled, clients that rely on the advertised CA list to select among + // multiple client certificates may now send no certificate or the wrong one; + // validation will then fail with the standard TLS alert. + // + // This option only affects downstream (server) TLS connections where Envoy sends a + // ``CertificateRequest`` to clients. It has no effect on upstream connections. + // + // Honored by the built-in validator and the SPIFFE validator. Validators that do + // not set a client CA list themselves (e.g., the dynamic-modules validator) are + // unaffected. Defaults to false. + bool suppress_client_ca_list = 18; } diff --git a/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto b/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto index 4f470c945..648dd5b56 100644 --- a/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto +++ b/api/src/main/proto/envoy/extensions/transport_sockets/tls/v3/tls.proto @@ -73,14 +73,13 @@ message UpstreamTlsContext { // Defaults to 1, setting this to 0 disables session resumption. google.protobuf.UInt32Value max_session_keys = 4; - // Controls enforcement of the ``keyUsage`` extension in peer certificates. If set to ``true``, the handshake will fail if - // the ``keyUsage`` is incompatible with TLS usage. + // Controls enforcement of the ``keyUsage`` extension in peer certificates. If set to ``true``, + // the handshake will fail if the ``keyUsage`` is incompatible with TLS usage. // - // .. note:: - // The default value is ``true`` (i.e., enforcement on). + // .. attention:: // - // The ``ssl.was_key_usage_invalid`` in :ref:`listener metrics ` metric will be incremented - // for configurations that would fail if this option were enabled. + // This field is deprecated and ignored. Envoy now always enforces the ``keyUsage`` extension + // in peer certificates, making this option unconfigurable. google.protobuf.BoolValue enforce_rsa_key_usage = 5 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; } diff --git a/api/src/main/proto/envoy/extensions/upstreams/http/reverse_tunnel/v3/reverse_tunnel_codec.proto b/api/src/main/proto/envoy/extensions/upstreams/http/reverse_tunnel/v3/reverse_tunnel_codec.proto new file mode 100644 index 000000000..dc417c4cd --- /dev/null +++ b/api/src/main/proto/envoy/extensions/upstreams/http/reverse_tunnel/v3/reverse_tunnel_codec.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +package envoy.extensions.upstreams.http.reverse_tunnel.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.upstreams.http.reverse_tunnel.v3"; +option java_outer_classname = "ReverseTunnelCodecProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/reverse_tunnel/v3;reverse_tunnelv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Reverse Tunnel Upstream Codec] +// [#extension: envoy.upstreams.http.reverse_tunnel] +// Per-cluster upstream (client) HTTP/2 codec options for reverse-tunnel clusters. When attached to +// a cluster via :ref:`typed_extension_protocol_options +// `, the upstream +// HTTP/2 client codec becomes drain-aware: it can emit a GOAWAY when the reverse tunnel is +// draining, mirroring the server-side drain-aware HTTP Connection Manager. + +// Configuration for the drain-aware reverse-tunnel upstream codec. +message ReverseTunnelUpstreamCodecOptions { + // When true, the upstream HTTP/2 client codec emits a GOAWAY when the reverse tunnel begins + // draining. Defaults to false, in which case the stock HTTP/2 client codec is used unchanged. + bool enable_drain_with_goaway = 1; +} diff --git a/api/src/main/proto/envoy/service/network_ext_proc/v3/network_external_processor.proto b/api/src/main/proto/envoy/service/network_ext_proc/v3/network_external_processor.proto index c148baf31..e2cb83131 100644 --- a/api/src/main/proto/envoy/service/network_ext_proc/v3/network_external_processor.proto +++ b/api/src/main/proto/envoy/service/network_ext_proc/v3/network_external_processor.proto @@ -95,7 +95,7 @@ message ProcessingRequest { // ProcessingResponse contains the response from the external processing server to Envoy. // Each response corresponds to a ProcessingRequest and indicates how the network // traffic should be handled. -// [#next-free-field: 6] +// [#next-free-field: 7] message ProcessingResponse { // DataProcessedStatus indicates whether the data was modified by the external processor. enum DataProcessedStatus { @@ -157,4 +157,21 @@ message ProcessingResponse { // The metadata is not automatically propagated from request to response. // The external processor must include any needed metadata in its response. google.protobuf.Struct dynamic_metadata = 5; + + // If set to true, Envoy will close the gRPC stream to the external processor + // after applying this response. Subsequent data will bypass the ext_proc filter + // as if it were configured in SKIP mode. + // + // .. note:: + // This should only be used when there is a strong protocol guarantee + // that no additional data chunks are in-flight on the wire. Because Envoy + // immediately drains its local buffer when forwarding bytes to the external + // processor, if Envoy has already dispatched subsequent data chunks before this + // stream is closed, those in-flight bytes will be permanently lost and not + // injected back into the filter chain. + // + // This feature is primarily designed for tightly-coupled synchronous protocols, + // such as reading the ClientHello during a TLS handshake, where the sender + // naturally halts transmission while awaiting the receiver's response. + bool close_stream_to_ext_proc_server = 6; } diff --git a/api/src/main/proto/envoy/service/ratelimit/v3/rls.proto b/api/src/main/proto/envoy/service/ratelimit/v3/rls.proto index 63f2477a6..8399255fe 100644 --- a/api/src/main/proto/envoy/service/ratelimit/v3/rls.proto +++ b/api/src/main/proto/envoy/service/ratelimit/v3/rls.proto @@ -209,7 +209,9 @@ message RateLimitResponse { // filter. This metadata lives in a namespace specified by the canonical name of extension filter // that requires it: // - // - :ref:`envoy.filters.http.ratelimit ` for HTTP filter. + // - :ref:`envoy.filters.http.ratelimit ` for HTTP filter. The default namespace can + // be modified by setting the :ref:`metadata_namespace ` + // in the filter configuration. // - :ref:`envoy.filters.network.ratelimit ` for network filter. // - :ref:`envoy.filters.thrift.rate_limit ` for Thrift filter. google.protobuf.Struct dynamic_metadata = 6; diff --git a/api/src/main/proto/envoy/type/v3/scope.proto b/api/src/main/proto/envoy/type/v3/scope.proto new file mode 100644 index 000000000..2c65669a3 --- /dev/null +++ b/api/src/main/proto/envoy/type/v3/scope.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; + +package envoy.type.v3; + +import "google/protobuf/wrappers.proto"; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.type.v3"; +option java_outer_classname = "ScopeProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/type/v3;typev3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Scope] + +// Stats scope configuration. +// This configuration can be used to create a singleton scope that is shared +// across multiple instances within the process. +// [#next-free-field: 7] +message Scope { + // Max number of counters allowed in this scope. + google.protobuf.UInt32Value max_counters = 1; + + // Max number of gauges allowed in this scope. + google.protobuf.UInt32Value max_gauges = 2; + + // Max number of histograms allowed in this scope. + google.protobuf.UInt32Value max_histograms = 3; + + // Whether the scope and its stats can be evicted from the store caches. + // The eviction policy is a mark-and-sweep approach where stats are evicted + // if they are not updated or accessed between two successive eviction sweeps. + // The eviction will happen only if the :ref:`stats_eviction_interval ` is configured in + // the bootstrap. + bool enable_eviction = 4; + + // The stats scope prefix. + string prefix = 5; + + // The sharing name of the scope. If non-empty, the scope is shared across + // multiple instances with the same sharing_name if all fields in this message + // have the same values. + string sharing_name = 6; +} diff --git a/api/src/main/proto/envoy/type/v3/token_bucket.proto b/api/src/main/proto/envoy/type/v3/token_bucket.proto index 157a271ef..1f91adb25 100644 --- a/api/src/main/proto/envoy/type/v3/token_bucket.proto +++ b/api/src/main/proto/envoy/type/v3/token_bucket.proto @@ -22,8 +22,9 @@ message TokenBucket { option (udpa.annotations.versioning).previous_message_type = "envoy.type.TokenBucket"; // The maximum tokens that the bucket can hold. This is also the number of tokens that the bucket - // initially contains. - uint32 max_tokens = 1 [(validate.rules).uint32 = {gt: 0}]; + // initially contains. A value of 0 means the bucket will always be empty and all requests will + // be rate limited (i.e., always reject). + uint32 max_tokens = 1 [(validate.rules).uint32 = {gte: 0}]; // The number of tokens added to the bucket during each fill interval. If not specified, defaults // to a single token. diff --git a/server/src/test/java/io/envoyproxy/controlplane/server/EnvoyContainer.java b/server/src/test/java/io/envoyproxy/controlplane/server/EnvoyContainer.java index 41a647385..61c514663 100644 --- a/server/src/test/java/io/envoyproxy/controlplane/server/EnvoyContainer.java +++ b/server/src/test/java/io/envoyproxy/controlplane/server/EnvoyContainer.java @@ -24,7 +24,7 @@ class EnvoyContainer extends GenericContainer { EnvoyContainer(String config, Supplier controlPlanePortSupplier) { // this version is changed automatically by /tools/update-sha.sh:57 // if you change it make sure to reflect changes there - super("envoyproxy/envoy:v1.38.3"); + super("envoyproxy/envoy:v1.39.0"); this.config = config; this.controlPlanePortSupplier = controlPlanePortSupplier; } diff --git a/tools/API_SHAS b/tools/API_SHAS index b19c2f90a..5dc5561b5 100644 --- a/tools/API_SHAS +++ b/tools/API_SHAS @@ -1,9 +1,9 @@ # Update the versions here and run update-api.sh # envoy (source: SHA from https://github.com/envoyproxy/envoy) -ENVOY_SHA="0ebfcfe5b0484b89ca85b761da9e05ce75dbda8d" +ENVOY_SHA="8eea3285d6bdb89f8ea34632cfe7ce1608a8f374" -# dependencies (source: https://github.com/envoyproxy/envoy/blob/0ebfcfe5b0484b89ca85b761da9e05ce75dbda8d/api/bazel/repository_locations.bzl) +# dependencies (source: https://github.com/envoyproxy/envoy/blob/8eea3285d6bdb89f8ea34632cfe7ce1608a8f374/api/bazel/repository_locations.bzl) GOOGLEAPIS_SHA="fd52b5754b2b268bc3a22a10f29844f206abb327" # PGV_VERSION="1.3.3" # PROMETHEUS_SHA="0.6.2" # diff --git a/tools/envoy_release b/tools/envoy_release index ab964bd65..5b813750d 100644 --- a/tools/envoy_release +++ b/tools/envoy_release @@ -1 +1 @@ -v1.38.3 +v1.39.0