// Copyright Istio Authors
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

syntax = "proto3";

import "google/api/field_behavior.proto";
import "google/protobuf/struct.proto";
import "networking/v1alpha3/sidecar.proto";

// $schema: istio.networking.v1alpha3.EnvoyFilter
// $title: Envoy Filter
// $description: Customizing Envoy configuration generated by Istio.
// $location: https://istio.io/docs/reference/config/networking/envoy-filter.html
// $aliases: [/docs/reference/config/networking/v1alpha3/envoy-filter]

// `EnvoyFilter` provides a mechanism to customize the Envoy
// configuration generated by Istio Pilot. Use EnvoyFilter to modify
// values for certain fields, add specific filters, or even add
// entirely new listeners, clusters, etc. This feature must be used
// with care, as incorrect configurations could potentially
// destabilize the entire mesh. Unlike other Istio networking objects,
// EnvoyFilters are additively applied. Any number of EnvoyFilters can
// exist for a given workload in a specific namespace. The order of
// application of these EnvoyFilters is as follows: all EnvoyFilters
// in the config [root
// namespace](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig),
// followed by all matching EnvoyFilters in the workload's namespace.
//
// **NOTE 1**: Some aspects of this API is deeply tied to the internal
// implementation in Istio networking subsystem as well as Envoy's XDS
// API. While the EnvoyFilter API by itself will maintain backward
// compatibility, any envoy configuration provided through this
// mechanism should be carefully monitored across Istio proxy version
// upgrades, to ensure that deprecated fields are removed and replaced
// appropriately.
//
// **NOTE 2**: When multiple EnvoyFilters are bound to the same
// workload in a given namespace, all patches will be processed
// sequentially in order of creation time.  The behavior is undefined
// if multiple EnvoyFilter configurations conflict with each other.
//
// **NOTE 3**: To apply an EnvoyFilter resource to all workloads
// (sidecars and gateways) in the system, define the resource in the
// config [root
// namespace](https://istio.io/docs/reference/config/istio.mesh.v1alpha1/#MeshConfig),
// without a workloadSelector.
//
// The example below declares a global default EnvoyFilter resource in
// the root namespace called `istio-config`, that adds a custom
// protocol filter on all sidecars in the system, for outbound port
// 9307. The filter should be added before the terminating tcp_proxy
// filter to take effect. In addition, it sets a 30s idle timeout for
// all HTTP connections in both gateways and sidecars.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: custom-protocol
//   namespace: istio-config # as defined in meshConfig resource.
// spec:
//   configPatches:
//   - applyTo: NETWORK_FILTER
//     match:
//       context: SIDECAR_OUTBOUND # will match outbound listeners in all sidecars
//       listener:
//         portNumber: 9307
//         filterChain:
//           filter:
//             name: "envoy.filters.network.tcp_proxy"
//     patch:
//       operation: INSERT_BEFORE
//       value:
//         # This is the full filter config including the name and config or typed_config section.
//         name: "envoy.config.filter.network.custom_protocol"
//         config:
//          ...
//   - applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
//     match:
//       # context omitted so that this applies to both sidecars and gateways
//       listener:
//         filterChain:
//           filter:
//             name: "envoy.filters.network.http_connection_manager"
//     patch:
//       operation: MERGE
//       value:
//         name: "envoy.filters.network.http_connection_manager"
//         typed_config:
//           "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
//           common_http_protocol_options:
//             idle_timeout: 30s
//```
//
// The following example enables Envoy's Lua filter for all inbound
// HTTP calls arriving at service port 8080 of the reviews service pod
// with labels "app: reviews", in the bookinfo namespace. The lua
// filter calls out to an external service internal.org.net:8888 that
// requires a special cluster definition in envoy. The cluster is also
// added to the sidecar as part of this configuration.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: reviews-lua
//   namespace: bookinfo
// spec:
//   workloadSelector:
//     labels:
//       app: reviews
//   configPatches:
//     # The first patch adds the lua filter to the listener/http connection manager
//   - applyTo: HTTP_FILTER
//     match:
//       context: SIDECAR_INBOUND
//       listener:
//         portNumber: 8080
//     patch:
//       operation: ADD
//       filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
//       value: # lua filter specification
//         name: envoy.filters.http.lua
//         typed_config:
//           "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
//           inlineCode: |
//            function envoy_on_request(request_handle)
//              -- Make an HTTP call to an upstream host with the following headers, body, and timeout.
//              local headers, body = request_handle:httpCall(
//               "lua_cluster",
//               {
//                [":method"] = "POST",
//                [":path"] = "/acl",
//                [":authority"] = "internal.org.net"
//               },
//              "authorize call",
//              5000)
//            end
//   # The second patch adds the cluster that is referenced by the lua code
//   # cds match is omitted as a new cluster is being added
//   - applyTo: CLUSTER
//     match:
//       context: SIDECAR_OUTBOUND
//     patch:
//       operation: ADD
//       value: # cluster specification
//         name: "lua_cluster"
//         type: STRICT_DNS
//         connect_timeout: 0.5s
//         lb_policy: ROUND_ROBIN
//         hosts:
//         - socket_address:
//             protocol: TCP
//             address: "internal.org.net"
//             port_value: 8888
//
// ```
//
// The following example overwrites certain fields (HTTP idle timeout
// and X-Forward-For trusted hops) in the HTTP connection manager in a
// listener on the ingress gateway in istio-system namespace for the
// SNI host app.example.com:
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: hcm-tweaks
//   namespace: istio-system
// spec:
//   workloadSelector:
//     labels:
//       istio: ingressgateway
//   configPatches:
//   - applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
//     match:
//       context: GATEWAY
//       listener:
//         filterChain:
//           sni: app.example.com
//           filter:
//             name: "envoy.filters.network.http_connection_manager"
//     patch:
//       operation: MERGE
//       value:
//         common_http_protocol_options:
//           idle_timeout: 30s
//         xff_num_trusted_hops: 5
//```
//
// The following example inserts an attributegen filter
// that produces `istio_operationId` attribute which is consumed
// by the istio.stats fiter. `filterClass: STATS` encodes this dependency.
//
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: reviews-request-operation
//   namespace: myns
// spec:
//   workloadSelector:
//     labels:
//       app: reviews
//   configPatches:
//   - applyTo: HTTP_FILTER
//     match:
//       context: SIDECAR_INBOUND
//     patch:
//       operation: ADD
//       filterClass: STATS # This filter will run *before* the Istio stats filter.
//       value:
//         name: istio.request_operation
//         typed_config:
//          "@type": type.googleapis.com/udpa.type.v1.TypedStruct
//          type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
//          value:
//            config:
//              configuration: |
//                {
//                  "attributes": [
//                    {
//                      "output_attribute": "istio_operationId",
//                      "match": [
//                        {
//                          "value": "ListReviews",
//                          "condition": "request.url_path == '/reviews' && request.method == 'GET'"
//                        }]
//                    }]
//                }
//              vm_config:
//                runtime: envoy.wasm.runtime.null
//                code:
//                  local: { inline_string: "envoy.wasm.attributegen" }
// ```
//
// The following example inserts an http ext_authz filter in the `myns` namespace.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: myns-ext-authz
//   namespace: myns
// spec:
//   configPatches:
//   - applyTo: HTTP_FILTER
//     match:
//       context: SIDECAR_INBOUND
//     patch:
//       operation: ADD
//       filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
//       value:
//         name: envoy.filters.http.ext_authz
//         typed_config:
//           "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
//           grpc_service:
//             envoy_grpc:
//               cluster_name: acme-ext-authz
//               initial_metadata:
//               - key: foo
//                 value: myauth.acme # required by local ext auth server.
// ```
//
// A workload in the `myns` namespace needs to access a different ext_auth server
// that does not accept initial metadata. Since proto merge cannot remove fields, the
// following configuration uses the `REPLACE` operation. If you do not need to inherit
// fields, REPLACE is preferred over MERGE.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: mysvc-ext-authz
//   namespace: myns
// spec:
//   workloadSelector:
//     labels:
//       app: mysvc
//   configPatches:
//   - applyTo: HTTP_FILTER
//     match:
//       context: SIDECAR_INBOUND
//     patch:
//       operation: REPLACE
//       value:
//         name: envoy.filters.http.ext_authz
//         typed_config:
//           "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
//           grpc_service:
//             envoy_grpc:
//               cluster_name: acme-ext-authz-alt
// ```
//
// The following example deploys a Wasm extension for all inbound sidecar HTTP requests.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: wasm-example
//   namespace: myns
// spec:
//   configPatches:
//   # The first patch defines a named Wasm extension and provides a URL to fetch Wasm binary from,
//   # and the binary configuration. It should come before the next patch that applies it.
//   # This resource is visible to all proxies in the namespace "myns". It is possible to provide
//   # multiple definitions for the same name "my-wasm-extension" in multiple namespaces. We recommend that:
//   # - if overriding is desired, then the root level definition can be overriden per namespace with REPLACE.
//   # - if overriding is not desired, then the name should be qualified with the namespace "myns/my-wasm-extension",
//   #   to avoid accidental name collisions.
//   - applyTo: EXTENSION_CONFIG
//     patch:
//       operation: ADD # REPLACE is also supported, and would override a cluster level resource with the same name.
//       value:
//         name: my-wasm-extension
//         typed_config:
//           "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
//           config:
//             root_id: my-wasm-root-id
//             vm_config:
//               vm_id: my-wasm-vm-id
//               runtime: envoy.wasm.runtime.v8
//               code:
//                 remote:
//                   http_uri:
//                     uri: http://my-wasm-binary-uri
//             configuration: |
//               {}
//   # The second patch instructs to apply the above Wasm filter to the listener/http connection manager.
//   - applyTo: HTTP_FILTER
//     match:
//       context: SIDECAR_INBOUND
//     patch:
//       operation: ADD
//       filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
//       value:
//         name: my-wasm-extension # This must match the name above
//         config_discovery:
//           config_source:
//             api_config_source:
//               api_type: GRPC
//               transport_api_version: V3
//               grpc_services:
//               - envoy_grpc:
//                   cluster_name: xds-grpc
//           type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"]
// ```

package istio.networking.v1alpha3;

option go_package = "istio.io/api/networking/v1alpha3";

// EnvoyFilter provides a mechanism to customize the Envoy configuration
// generated by Istio Pilot.
//
// <!-- crd generation tags
// +cue-gen:EnvoyFilter:groupName:networking.istio.io
// +cue-gen:EnvoyFilter:version:v1alpha3
// +cue-gen:EnvoyFilter:storageVersion
// +cue-gen:EnvoyFilter:annotations:helm.sh/resource-policy=keep
// +cue-gen:EnvoyFilter:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
// +cue-gen:EnvoyFilter:subresource:status
// +cue-gen:EnvoyFilter:scope:Namespaced
// +cue-gen:EnvoyFilter:resource:categories=istio-io,networking-istio-io
// +cue-gen:EnvoyFilter:preserveUnknownFields:true
// -->
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
// +genclient
// +k8s:deepcopy-gen=true
// -->
message EnvoyFilter {
  // `ApplyTo` specifies where in the Envoy configuration, the given patch should be applied.
  enum ApplyTo {

    INVALID = 0;

    // Applies the patch to the listener.
    LISTENER = 1;

    // Applies the patch to the filter chain.
    FILTER_CHAIN = 2;

    // Applies the patch to the network filter chain, to modify an
    // existing filter or add a new filter.
    NETWORK_FILTER = 3;

    // Applies the patch to the HTTP filter chain in the http
    // connection manager, to modify an existing filter or add a new
    // filter.
    HTTP_FILTER = 4;

    // Applies the patch to the Route configuration (rds output)
    // inside a HTTP connection manager. This does not apply to the
    // virtual host. Currently, only `MERGE` operation is allowed on the
    // route configuration objects.
    ROUTE_CONFIGURATION = 5;

    // Applies the patch to a virtual host inside a route configuration.
    VIRTUAL_HOST = 6;

    // Applies the patch to a route object inside the matched virtual
    // host in a route configuration.
    HTTP_ROUTE = 7;

    // Applies the patch to a cluster in a CDS output. Also used to add new clusters.
    CLUSTER = 8;

    // Applies the patch to or adds an extension config in ECDS output. Note that ECDS
    // is only supported by HTTP filters.
    EXTENSION_CONFIG = 9;
  };

  // PatchContext selects a class of configurations based on the
  // traffic flow direction and workload type.
  enum PatchContext {
    // All listeners/routes/clusters in both sidecars and gateways.
    ANY = 0;

    // Inbound listener/route/cluster in sidecar.
    SIDECAR_INBOUND = 1;

    // Outbound listener/route/cluster in sidecar.
    SIDECAR_OUTBOUND = 2;

    // Gateway listener/route/cluster.
    GATEWAY = 3;
  };

  // One or more properties of the proxy to match on.
  message ProxyMatch {
    // A regular expression in golang regex format (RE2) that can be
    // used to select proxies using a specific version of istio
    // proxy. The Istio version for a given proxy is obtained from the
    // node metadata field `ISTIO_VERSION` supplied by the proxy when
    // connecting to Pilot. This value is embedded as an environment
    // variable (`ISTIO_META_ISTIO_VERSION`) in the Istio proxy docker
    // image. Custom proxy implementations should provide this metadata
    // variable to take advantage of the Istio version check option.
    string proxy_version = 1;

    // Match on the node metadata supplied by a proxy when connecting
    // to Istio Pilot. Note that while Envoy's node metadata is of
    // type Struct, only string key-value pairs are processed by
    // Pilot. All keys specified in the metadata must match with exact
    // values. The match will fail if any of the specified keys are
    // absent or the values fail to match.
    map<string, string> metadata = 2;
  };

  // Conditions specified in `ClusterMatch` must be met for the patch
  // to be applied to a cluster.
  message ClusterMatch {
    // The service port for which this cluster was generated.  If
    // omitted, applies to clusters for any port.
    uint32 port_number = 1;

    // The fully qualified service name for this cluster. If omitted,
    // applies to clusters for any service. For services defined
    // through service entries, the service name is same as the hosts
    // defined in the service entry.
    string service = 2;

    // The subset associated with the service. If omitted, applies to
    // clusters for any subset of a service.
    string subset = 3;

    // The exact name of the cluster to match. To match a specific
    // cluster by name, such as the internally generated `Passthrough`
    // cluster, leave all fields in clusterMatch empty, except the
    // name.
    string name = 4;
  };

  // Conditions specified in RouteConfigurationMatch must be met for
  // the patch to be applied to a route configuration object or a
  // specific virtual host within the route configuration.
  message RouteConfigurationMatch {
    // Match a specific route inside a virtual host in a route configuration.
    message RouteMatch {
      // The Route objects generated by default are named as
      // default.  Route objects generated using a virtual service
      // will carry the name used in the virtual service's HTTP
      // routes.
      string name = 1;

      // Action refers to the route action taken by Envoy when a http route matches.
      enum Action {
	// All three route actions
	ANY = 0;
	// Route traffic to a cluster / weighted clusters.
	ROUTE = 1;
	// Redirect request.
	REDIRECT = 2;
	// directly respond to a request with specific payload.
	DIRECT_RESPONSE = 3;
      };

      // Match a route with specific action type.
      Action action = 2;
    }

    // Match a specific virtual host inside a route configuration.
    message VirtualHostMatch {
      // The VirtualHosts objects generated by Istio are named as
      // host:port, where the host typically corresponds to the
      // VirtualService's host field or the hostname of a service in the
      // registry.
      string name = 1;

      // Match a specific route within the virtual host.
      RouteMatch route = 2;
    }

    // The service port number or gateway server port number for which
    // this route configuration was generated. If omitted, applies to
    // route configurations for all ports.
    uint32 port_number = 1;

    // Applicable only for GATEWAY context. The gateway server port
    // name for which this route configuration was generated.
    string port_name = 2;

    // The Istio gateway config's namespace/name for which this route
    // configuration was generated. Applies only if the context is
    // GATEWAY. Should be in the namespace/name format. Use this field
    // in conjunction with the `portNumber` and `portName` to accurately
    // select the Envoy route configuration for a specific HTTPS
    // server within a gateway config object.
    string gateway = 3;

    // Match a specific virtual host in a route configuration and
    // apply the patch to the virtual host.
    VirtualHostMatch vhost = 4;

    // Route configuration name to match on. Can be used to match a
    // specific route configuration by name, such as the internally
    // generated `http_proxy` route configuration for all sidecars.
    string name = 5;
  };

  // Conditions specified in a listener match must be met for the
  // patch to be applied to a specific listener across all filter
  // chains, or a specific filter chain inside the listener.
  message ListenerMatch {
    // For listeners with multiple filter chains (e.g., inbound
    // listeners on sidecars with permissive mTLS, gateway listeners
    // with multiple SNI matches), the filter chain match can be used
    // to select a specific filter chain to patch.
    message FilterChainMatch {
      // The name assigned to the filter chain.
      string name = 1;

      // The SNI value used by a filter chain's match condition.  This
      // condition will evaluate to false if the filter chain has no
      // sni match.
      string sni = 2;

      // Applies only to `SIDECAR_INBOUND` context. If non-empty, a
      // transport protocol to consider when determining a filter
      // chain match.  This value will be compared against the
      // transport protocol of a new connection, when it's detected by
      // the `tls_inspector` listener filter.
      //
      // Accepted values include:
      //
      // * `raw_buffer` - default, used when no transport protocol is detected.
      // * `tls` - set when TLS protocol is detected by the TLS inspector.
      string transport_protocol = 3;

      // Applies only to sidecars. If non-empty, a comma separated set
      // of application protocols to consider when determining a
      // filter chain match.  This value will be compared against the
      // application protocols of a new connection, when it's detected
      // by one of the listener filters such as the `http_inspector`.
      //
      // Accepted values include: h2, http/1.1, http/1.0
      string application_protocols = 4;

      // The name of a specific filter to apply the patch to. Set this
      // to `envoy.filters.network.http_connection_manager` to add a filter or apply a
      // patch to the HTTP connection manager.
      FilterMatch filter = 5;
    };

    // Conditions to match a specific filter within a filter chain.
    message FilterMatch {
      // The filter name to match on.
      // For standard Envoy filters, [canonical filter](https://www.envoyproxy.io/docs/envoy/latest/version_history/v1.14.0#deprecated)
      // names should be used.
      string name = 1;
      // The next level filter within this filter to match
      // upon. Typically used for HTTP Connection Manager filters and
      // Thrift filters.
      SubFilterMatch sub_filter = 2;
    };

    // Conditions to match a specific filter within another
    // filter. This field is typically useful to match a HTTP filter
    // inside the `envoy.filters.network.http_connection_manager` network filter.
    // This could also be applicable for thrift filters.
    message SubFilterMatch {
      // The filter name to match on.
      string name = 1;
    };

    // The service port/gateway port to which traffic is being
    // sent/received. If not specified, matches all listeners. Even though
    // inbound listeners are generated for the instance/pod ports, only
    // service ports should be used to match listeners.
    uint32 port_number = 1;

    // Instead of using specific port numbers, a set of ports matching
    // a given service's port name can be selected. Matching is case
    // insensitive.
    // Not implemented.
    // $hide_from_docs
    string port_name = 2;

    // Match a specific filter chain in a listener. If specified, the
    // patch will be applied to the filter chain (and a specific
    // filter if specified) and not to other filter chains in the
    // listener.
    FilterChainMatch filter_chain = 3;

    // Match a specific listener by its name. The listeners generated
    // by Pilot are typically named as IP:Port.
    string name = 4;
  };

  // Patch specifies how the selected object should be modified.
  message Patch {

    // Operation denotes how the patch should be applied to the selected
    // configuration.
    enum Operation {
      INVALID = 0;

      // Merge the provided config with the generated config using
      // proto merge semantics. If you are specifying config in its
      // entirity, use `REPLACE` instead.
      MERGE = 1;

      // Add the provided config to an existing list (of listeners,
      // clusters, virtual hosts, network filters, or http
      // filters). This operation will be ignored when `applyTo` is set
      // to `ROUTE_CONFIGURATION`, or `HTTP_ROUTE`.
      ADD = 2;

      // Remove the selected object from the list (of listeners,
      // clusters, virtual hosts, network filters, routes, or http
      // filters). Does not require a value to be specified. This
      // operation will be ignored when `applyTo` is set to
      // `ROUTE_CONFIGURATION`, or `HTTP_ROUTE`.
      REMOVE = 3;

      // Insert operation on an array of named objects. This operation
      // is typically useful only in the context of filters or routes,
      // where the order of elements matter. Routes should be ordered 
      // based on most to least specific matching criteria since the 
      // first matching element is selected. For clusters and virtual hosts,
      // order of the element in the array does not matter. Insert
      // before the selected filter or sub filter. If no filter is
      // selected, the specified filter will be inserted at the front
      // of the list.
      INSERT_BEFORE = 4;

      // Insert operation on an array of named objects. This operation
      // is typically useful only in the context of filters or routes,
      // where the order of elements matter. Routes should be ordered 
      // based on most to least specific matching criteria since the 
      // first matching element is selected. For clusters and virtual hosts,
      // order of the element in the array does not matter. Insert
      // after the selected filter or sub filter. If no filter is
      // selected, the specified filter will be inserted at the end
      // of the list.
      INSERT_AFTER = 5;

      // Insert operation on an array of named objects. This operation
      // is typically useful only in the context of filters or routes,
      // where the order of elements matter. Routes should be ordered 
      // based on most to least specific matching criteria since the 
      // first matching element is selected. For clusters and virtual hosts,
      // order of the element in the array does not matter. Insert
      // first in the list based on the presence of selected filter or not.
      // This is specifically useful when you want your filter first in the
      // list based on a match condition specified in Match clause.
      INSERT_FIRST = 6;

      // Replace contents of a named filter with new contents.
      // `REPLACE` operation is only valid for `HTTP_FILTER` and
      // `NETWORK_FILTER`. If the named filter is not found, this operation
      // has no effect.
      REPLACE = 7;
    }

    // Determines how the patch should be applied.
    Operation operation = 1;

    // The JSON config of the object being patched. This will be merged using
    // proto merge semantics with the existing proto in the path.
    google.protobuf.Struct value = 2;

    // FilterClass determines the filter insertion point in the filter chain
    // relative to the filters implicitly inserted by the control plane.
    // It is used in conjuction with the `ADD` operation.
    // This is the preferred insertion mechanism for adding filters over
    // the `INSERT_*` operations since those operations rely on potentially unstable
    // filter names.
    // Filter ordering is important if your filter depends on or affects the
    // functioning of a another filter in the filter chain.
    // Within a filter class, filters are inserted in the order of processing.
    enum FilterClass {
      // Control plane decides where to insert the filter.
      // Do not specify `FilterClass` if the filter is independent of others.
      UNSPECIFIED = 0;

      // Insert filter after Istio authentication filters.
      AUTHN = 1;

      // Insert filter after Istio authorization filters.
      AUTHZ = 2;

      // Insert filter before Istio stats filters.
      STATS = 3;
    };

    // Determines the filter insertion order.
    FilterClass filter_class = 3;
  };

  // One or more match conditions to be met before a patch is applied
  // to the generated configuration for a given proxy.
  message EnvoyConfigObjectMatch {
    // The specific config generation context to match on. Istio Pilot
    // generates envoy configuration in the context of a gateway,
    // inbound traffic to sidecar and outbound traffic from sidecar.
    PatchContext context = 1;

    // Match on properties associated with a proxy.
    ProxyMatch proxy = 2;

    oneof object_types {
      // Match on envoy listener attributes.
      ListenerMatch listener = 3;
      // Match on envoy HTTP route configuration attributes.
      RouteConfigurationMatch route_configuration = 4;
      // Match on envoy cluster attributes.
      ClusterMatch cluster = 5;
    }
  };

  // Changes to be made to various envoy config objects.
  message EnvoyConfigObjectPatch {
    // Specifies where in the Envoy configuration, the patch should be
    // applied.  The match is expected to select the appropriate
    // object based on applyTo.  For example, an applyTo with
    // `HTTP_FILTER` is expected to have a match condition on the
    // listeners, with a network filter selection on
    // `envoy.filters.network.http_connection_manager` and a sub filter selection on the
    // HTTP filter relative to which the insertion should be
    // performed. Similarly, an applyTo on `CLUSTER` should have a match
    // (if provided) on the cluster and not on a listener.
    ApplyTo apply_to = 1;

    // Match on listener/route configuration/cluster.
    EnvoyConfigObjectMatch match = 2;

    // The patch to apply along with the operation.
    Patch patch = 3;
  }

  reserved 1, 2;
  reserved "filters", "workload_labels";

  // Criteria used to select the specific set of pods/VMs on which
  // this patch configuration should be applied. If omitted, the set
  // of patches in this configuration will be applied to all workload
  // instances in the same namespace.  If omitted, the `EnvoyFilter`
  // patches will be applied to all workloads in the same
  // namespace. If the `EnvoyFilter` is present in the config root
  // namespace, it will be applied to all applicable workloads in any
  // namespace.
  WorkloadSelector workload_selector = 3;

  // One or more patches with match conditions.
  repeated EnvoyConfigObjectPatch config_patches = 4 [(google.api.field_behavior) = REQUIRED];
}
