// Copyright 2018 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/protobuf/struct.proto";

package istio.networking.v1alpha3;

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

// `EnvoyFilter` describes Envoy proxy-specific filters that can be used to
// customize the Envoy proxy configuration generated by Istio networking
// subsystem (Pilot). This feature must be used with care, as incorrect
// configurations could potentially destabilize the entire mesh.
//
// NOTE 1: Since this is break glass configuration, there will not be any
// backward compatibility across different Istio releases. In other words,
// this configuration is subject to change based on internal implementation
// of Istio networking subsystem.
//
// NOTE 2: When multiple EnvoyFilters are bound to the same workload, all filter
// configurations will be processed sequentially in order of creation time.
// The behavior is undefined if multiple EnvoyFilter configurations conflict
// with each other.
//
// The following example for Kubernetes enables Envoy's Lua filter for all
// inbound calls arriving at service port 8080 of the reviews service pod with
// labels "app: reviews".
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: EnvoyFilter
// metadata:
//   name: reviews-lua
// spec:
//   workloadLabels:
//     app: reviews
//   filters:
//   - listenerMatch:
//       portNumber: 8080
//       listenerType: SIDECAR_INBOUND #will match with the inbound listener for reviews:8080
//     filterName: envoy.lua
//     filterType: HTTP
//     filterConfig:
//       inlineCode: |
//         ... lua code ...
// ```
message EnvoyFilter {
  // One or more labels that indicate a specific set of pods/VMs whose
  // proxies should be configured to use these additional filters.  The
  // scope of label search is platform dependent. On Kubernetes, for
  // example, the scope includes pods running in all reachable
  // namespaces. Omitting the selector applies the filter to all proxies in
  // the mesh.
  // NOTE: There can be only one EnvoyFilter bound to a specific workload.
  // The behavior is undefined if multiple EnvoyFilter configurations are
  // specified for the same workload.
  map<string, string> workload_labels = 1;

  // Select a listener to add the filter to based on the match conditions.
  // All conditions specified in the ListenerMatch must be met for the filter
  // to be applied to a listener.
  message ListenerMatch {
    // 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 port name prefix can be selected. E.g., "mongo" selects ports
    // named mongo-port, mongo, mongoDB, MONGO, etc. Matching is case
    // insensitive.
    string port_name_prefix = 2;

    enum ListenerType {
      // All listeners
      ANY = 0;

      // Inbound listener in sidecar
      SIDECAR_INBOUND = 1;

      // Outbound listener in sidecar
      SIDECAR_OUTBOUND = 2;

      // Gateway listener
      GATEWAY = 3;
    };

    // Inbound vs outbound sidecar listener or gateway listener. If not specified,
    // matches all listeners.
    ListenerType listener_type = 3;

    enum ListenerProtocol {
      // All protocols
      ALL = 0;
      // HTTP or HTTPS (with termination) / HTTP2/gRPC
      HTTP = 1;
      // Any non-HTTP listener
      TCP = 2;
    };

    // Selects a class of listeners for the same protocol. If not
    // specified, applies to listeners on all protocols. Use the protocol
    // selection to select all HTTP listeners (includes HTTP2/gRPC/HTTPS
    // where Envoy terminates TLS) or all TCP listeners (includes HTTPS
    // passthrough using SNI).
    ListenerProtocol listener_protocol = 4;

    // One or more IP addresses to which the listener is bound. If
    // specified, should match at least one address in the list.
    repeated string address = 5;
  };

  // Indicates the relative index in the filter chain where the filter should be inserted.
  message InsertPosition {

    // Index/position in the filter chain.
    enum Index {
      // Insert first
      FIRST = 0;

      // Insert last
      LAST = 1;

      // Insert before the named filter.
      BEFORE = 2;
      // Insert after the named filter.
      AFTER = 3;
    };

    // Position of this filter in the filter chain.
    Index index = 1;

    // If BEFORE or AFTER position is specified, specify the name of the
    // filter relative to which this filter should be inserted.
    string relative_to = 2;
  };

  // Envoy filters to be added to a network or http filter chain.
  message Filter {
    // Filter will be added to the listener only if the match conditions are true.
    // If not specified, the filters will be applied to all listeners.
    ListenerMatch listener_match = 1;

    // Insert position in the filter chain. Defaults to FIRST
    InsertPosition insert_position = 2;

    enum FilterType {
      // placeholder
      INVALID = 0;

      // Http filter
      HTTP = 1;

      // Network filter
      NETWORK = 2;
    };

    // REQUIRED: The type of filter to instantiate.
    FilterType filter_type = 3;

    // REQUIRED: The name of the filter to instantiate. The name must match a supported
    // filter _compiled into_ Envoy.
    string filter_name = 4;

    // REQUIRED: Filter specific configuration which depends on the filter being
    // instantiated.
    google.protobuf.Struct filter_config = 5;
  };

  // REQUIRED: Envoy network filters/http filters to be added to matching
  // listeners.  When adding network filters to http connections, care
  // should be taken to ensure that the filter is added before
  // envoy.http_connection_manager.
  repeated Filter filters = 2;
}
