// 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 "networking/v1alpha3/gateway.proto";

package istio.networking.v1alpha3;

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

// `ServiceEntry` enables adding additional entries into Istio's internal
// service registry, so that auto-discovered services in the mesh can
// access/route to these manually specified services. A service entry
// describes the properties of a service (DNS name, VIPs ,ports, protocols,
// endpoints). These services could be external to the mesh (e.g., web
// APIs) or mesh-internal services that are not part of the platform's
// service registry (e.g., a set of VMs talking to services in Kubernetes).
//
// The following configuration adds a set of MongoDB instances running on
// unmanaged VMs to Istio's registry, so that these services can be treated
// as any other service in the mesh. The associated DestinationRule is used
// to initiate mTLS connections to the database instances.
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: ServiceEntry
//     metadata:
//       name: external-svc-mongocluster
//     spec:
//       hosts:
//       - mymongodb.somedomain
//       addresses:
//       - 192.192.192.192/24 # VIPs
//       ports:
//       - number: 27018
//         name: mongodb
//         protocol: MONGO
//       location: MESH_INTERNAL
//       resolution: STATIC
//       endpoints:
//       - address: 2.2.2.2
//       - address: 3.3.3.3
//
// and the associated DestinationRule
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: DestinationRule
//     metadata:
//       name: mtls-mongocluster
//     spec:
//       name: mymongodb.somedomain
//       trafficPolicy:
//         tls:
//           mode: MUTUAL
//           clientCertificate: /etc/certs/myclientcert.pem
//           privateKey: /etc/certs/client_private_key.pem
//           caCertificates: /etc/certs/rootcacerts.pem
//
// The following example demonstrates the use of wildcards in the hosts for
// external services. If the connection has to be routed to the IP address
// requested by the application (i.e. application resolves DNS and attempts
// to connect to a specific IP), the discovery mode must be set to `NONE`.
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: ServiceEntry
//     metadata:
//       name: external-svc-wildcard-example
//     spec:
//       hosts:
//       - "*.bar.com"
//       location: MESH_EXTERNAL
//       ports:
//       - number: 80
//         name: http
//         protocol: HTTP
//       resolution: NONE
//
//
// The following example demonstrates a service that is available via a
// Unix Domain Socket on the host of the client. The resolution must be
// set to STATIC to use unix address endpoints.
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: ServiceEntry
//     metadata:
//       name: unix-domain-socket-example
//     spec:
//       hosts:
//       - "example.unix.local"
//       location: MESH_EXTERNAL
//       ports:
//       - number: 80
//         name: http
//         protocol: HTTP
//       resolution: STATIC
//       endpoints:
//       - address: unix:///var/run/example/socket
//
// For HTTP based services, it is possible to create a VirtualService
// backed by multiple DNS addressible endpoints. In such a scenario, the
// application can use the HTTP_PROXY environment variable to transparently
// reroute API calls for the VirtualService to a chosen backend. For
// example, the following configuration creates a non-existent external
// service called foo.bar.com backed by three domains: us.foo.bar.com:8443,
// uk.foo.bar.com:9443, and in.foo.bar.com:7443
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: ServiceEntry
//     metadata:
//       name: external-svc-dns
//     spec:
//       hosts:
//       - foo.bar.com
//       location: MESH_EXTERNAL
//       ports:
//       - number: 443
//         name: https
//         protocol: HTTP
//       resolution: DNS
//       endpoints:
//       - address: us.foo.bar.com
//         ports:
//           https: 8443
//       - address: uk.foo.bar.com
//         ports:
//           https: 9443
//       - address: in.foo.bar.com
//         ports:
//           https: 7443
//
// and a DestinationRule to initiate TLS connections to the ServiceEntry.
//
//     apiVersion: networking.istio.io/v1alpha3
//     kind: DestinationRule
//     metadata:
//       name: tls-foobar
//     spec:
//       name: foo.bar.com
//       trafficPolicy:
//         tls:
//           mode: SIMPLE # initiates HTTPS
//
// With HTTP_PROXY=http://localhost:443, calls from the application to
// http://foo.bar.com will be upgraded to HTTPS and load balanced across
// the three domains specified above. In other words, a call to
// http://foo.bar.com/baz would be translated to
// https://uk.foo.bar.com/baz.
message ServiceEntry {
  // REQUIRED. The hosts associated with the ServiceEntry. Could be a DNS
  // name with wildcard prefix (external services only). DNS names in hosts
  // will be ignored if the application accesses the service over non-HTTP
  // protocols such as mongo/opaque TCP/even HTTPS. In such scenarios, the
  // IP addresses specified in the Addresses field or the port will be used
  // to uniquely identify the destination.
  repeated string hosts = 1;

  // The virtual IP addresses associated with the service. Could be CIDR
  // prefix.  For HTTP services, the addresses field will be ignored and
  // the destination will be identified based on the HTTP Host/Authority
  // header. For non-HTTP protocols such as mongo/opaque TCP/even HTTPS,
  // the hosts will be ignored. If one or more IP addresses are specified,
  // the incoming traffic will be idenfified as belonging to this service
  // if the destination IP matches the IP/CIDRs specified in the addresses
  // field. If the Addresses field is empty, traffic will be identified
  // solely based on the destination port. In such scenarios, the port on
  // which the service is being accessed must not be shared by any other
  // service in the mesh. In other words, the sidecar will behave as a
  // simple TCP proxy, forwarding incoming traffic on a specified port to
  // the specified destination endpoint IP/host. Unix domain socket
  // addresses are not supported in this field.
  repeated string addresses = 2;

  // REQUIRED. The ports associated with the external service. If the
  // Endpoints are unix domain socket addresses, there must be exactly one
  // port.
  repeated Port ports = 3;

  // Location specifies whether the service is part of Istio mesh or
  // outside the mesh.  Location determines the behavior of several
  // features, such as service-to-service mTLS authentication, policy
  // enforcement, etc. When communicating with services outside the mesh,
  // Istio's mTLS authentication is disabled, and policy enforcements are
  // performed on the client-side as opposed to server-side.
  enum Location {
    // Signifies that the service is external to the mesh. Typically used
    // to indicate external services consumed through APIs.
    MESH_EXTERNAL = 0;

    // Signifies that the service is part of the mesh. Typically used to
    // indicate services added explicitly as part of expanding the service
    // mesh to include unmanaged infrastructure (e.g., VMs added to a
    // Kubernetes based service mesh).
    MESH_INTERNAL = 1;
  };

  // Specify whether the service should be considered external to the mesh
  // or part of the mesh.
  Location location = 4;

  // Resolution determines how the proxy will resolve the IP addresses of
  // the network endpoints associated with the service, so that it can
  // route to one of them. The resolution mode specified here has no impact
  // on how the application resolves the IP address associated with the
  // service. The application may still have to use DNS to resolve the
  // service to an IP so that the outbound traffic can be captured by the
  // Proxy. Alternatively, for HTTP services, the application could
  // directly communicate with the proxy (e.g., by setting HTTP_PROXY) to
  // talk to these services.
  enum Resolution {
    // Assume that incoming connections have already been resolved (to a
    // specific destination IP address). Such connections are typically
    // routed via the proxy using mechanisms such as IP table REDIRECT/
    // eBPF. After performing any routing related transformations, the
    // proxy will forward the connection to the IP address to which the
    // connection was bound.
    NONE = 0;

    // Use the static IP addresses specified in endpoints (see below) as the
    // backing instances associated with the service.
    STATIC = 1;

    // Attempt to resolve the IP address by querying the ambient DNS,
    // during request processing. If no endpoints are specified, the proxy
    // will resolve the DNS address specified in the hosts field, if
    // wildcards are not used. If endpoints are specified, the DNS
    // addresses specified in the endpoints will be resolved to determine
    // the destination IP address.  DNS resolution cannot be used with unix
    // domain socket endpoints.
    DNS = 2;
  };

  // Service discovery mode for the hosts. If not set, Istio will attempt
  // to infer the discovery mode based on the value of hosts and endpoints.
  Resolution resolution = 5;

  // Endpoint defines a network address (IP or hostname) associated with
  // the mesh service.
  message Endpoint {
    // REQUIRED: Address associated with the network endpoint without the
    // port.  Domain names can be used if and only if the resolution is set
    // to DNS, and must be fully-qualified without wildcards. Use the form
    // unix:///absolute/path/to/socket for unix domain socket endpoints.
    string address = 1;

    // Set of ports associated with the endpoint. The ports must be
    // associated with a port name that was declared as part of the
    // service. Do not use for unix:// addresses.
    map<string, uint32> ports = 2;
    
    // One or more labels associated with the endpoint.
    map<string, string> labels = 3;
  };

  // One or more endpoints associated with the service.
  repeated Endpoint endpoints = 6;
}
