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

// $title: Service Entry
// $description: Configuration affecting service registry.
// $location: https://istio.io/docs/reference/config/networking/service-entry.html
// $aliases: [/docs/reference/config/networking/v1alpha3/service-entry.html]

// `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 example declares a few external APIs accessed by internal
// applications over HTTPS. The sidecar inspects the SNI value in the
// ClientHello message to route to the appropriate external service.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-https
// spec:
//   hosts:
//   - api.dropboxapi.com
//   - www.googleapis.com
//   - api.facebook.com
//   location: MESH_EXTERNAL
//   ports:
//   - number: 443
//     name: https
//     protocol: TLS
//   resolution: DNS
// ```
//
// 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.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-mongocluster
// spec:
//   hosts:
//   - mymongodb.somedomain # not used
//   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
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: DestinationRule
// metadata:
//   name: mtls-mongocluster
// spec:
//   host: 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 uses a combination of service entry and TLS
// routing in a virtual service to steer traffic based on the SNI value to
// an internal egress firewall.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-redirect
// spec:
//   hosts:
//   - wikipedia.org
//   - "*.wikipedia.org"
//   location: MESH_EXTERNAL
//   ports:
//   - number: 443
//     name: https
//     protocol: TLS
//   resolution: NONE
// ```
//
// And the associated VirtualService to route based on the SNI value.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: tls-routing
// spec:
//   hosts:
//   - wikipedia.org
//   - "*.wikipedia.org"
//   tls:
//   - match:
//     - sniHosts:
//       - wikipedia.org
//       - "*.wikipedia.org"
//     route:
//     - destination:
//         host: internal-egress-firewall.ns1.svc.cluster.local
// ```
//
// The virtual service with TLS match serves to override the default SNI
// match. In the absence of a virtual service, traffic will be forwarded to
// the wikipedia domains.
//
// The following example demonstrates the use of a dedicated egress gateway
// through which all external service traffic is forwarded.
// The 'exportTo' field allows for control over the visibility of a service
// declaration to other namespaces in the mesh. By default, a service is exported
// to all namespaces. The following example restricts the visibility to the
// current namespace, represented by ".", so that it cannot be used by other
// namespaces.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-httpbin
//   namespace : egress
// spec:
//   hosts:
//   - httpbin.com
//   exportTo:
//   - "."
//   location: MESH_EXTERNAL
//   ports:
//   - number: 80
//     name: http
//     protocol: HTTP
//   resolution: DNS
// ```
//
// Define a gateway to handle all egress traffic.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//  name: istio-egressgateway
//  namespace: istio-system
// spec:
//  selector:
//    istio: egressgateway
//  servers:
//  - port:
//      number: 80
//      name: http
//      protocol: HTTP
//    hosts:
//    - "*"
// ```
//
// And the associated `VirtualService` to route from the sidecar to the
// gateway service (`istio-egressgateway.istio-system.svc.cluster.local`), as
// well as route from the gateway to the external service. Note that the
// virtual service is exported to all namespaces enabling them to route traffic
// through the gateway to the external service. Forcing traffic to go through
// a managed middle proxy like this is a common practice.
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: gateway-routing
//   namespace: egress
// spec:
//   hosts:
//   - httpbin.com
//   exportTo:
//   - "*"
//   gateways:
//   - mesh
//   - istio-egressgateway
//   http:
//   - match:
//     - port: 80
//       gateways:
//       - mesh
//     route:
//     - destination:
//         host: istio-egressgateway.istio-system.svc.cluster.local
//   - match:
//     - port: 80
//       gateways:
//       - istio-egressgateway
//     route:
//     - destination:
//         host: httpbin.com
// ```
//
// 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`.
//
// ```yaml
// 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.
//
// ```yaml
// 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 addressable 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:8080,
// uk.foo.bar.com:9080, and in.foo.bar.com:7080
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: external-svc-dns
// spec:
//   hosts:
//   - foo.bar.com
//   location: MESH_EXTERNAL
//   ports:
//   - number: 80
//     name: http
//     protocol: HTTP
//   resolution: DNS
//   endpoints:
//   - address: us.foo.bar.com
//     ports:
//       https: 8080
//   - address: uk.foo.bar.com
//     ports:
//       https: 9080
//   - address: in.foo.bar.com
//     ports:
//       https: 7080
// ```
//
// With `HTTP_PROXY=http://localhost/`, calls from the application to
// `http://foo.bar.com` will be load balanced across the three domains
// specified above. In other words, a call to `http://foo.bar.com/baz` would
// be translated to `http://uk.foo.bar.com/baz`.
//
// The following example illustrates the usage of a `ServiceEntry`
// containing a subject alternate name
// whose format conforms to the [SPIFFE standard](https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md):
//
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: ServiceEntry
// metadata:
//   name: httpbin
//   namespace : httpbin-ns
// spec:
//   hosts:
//   - httpbin.com
//   location: MESH_INTERNAL
//   ports:
//   - number: 80
//     name: http
//     protocol: HTTP
//   resolution: STATIC
//   endpoints:
//   - address: 2.2.2.2
//   - address: 3.3.3.3
//   subjectAltNames:
//   - "spiffe://cluster.local/ns/httpbin-ns/sa/httpbin-service-account"
// ```
//
package istio.networking.v1alpha3;

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

// ServiceEntry enables adding additional entries into Istio's internal
// service registry.
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
// +genclient
// +k8s:deepcopy-gen=true
// -->
message ServiceEntry {
  // The hosts associated with the ServiceEntry. Could be a DNS
  // name with wildcard prefix.
  //
  // 1. The hosts field is used to select matching hosts in VirtualServices and DestinationRules.
  // 2. For HTTP traffic the HTTP Host/Authority header will be matched against the hosts field.
  // 3. For HTTPs or TLS traffic containing Server Name Indication (SNI), the SNI value
  // will be matched against the hosts field.
  //
  // Note that when resolution is set to type DNS
  // and no endpoints are specified, the host field will be used as the DNS name
  // of the endpoint to route traffic to.
  repeated string hosts = 1 [(google.api.field_behavior) = REQUIRED];

  // The virtual IP addresses associated with the service. Could be CIDR
  // prefix. For HTTP traffic, generated route configurations will include http route
  // domains for both the `addresses` and `hosts` field values and the destination will
  // be identified based on the HTTP Host/Authority header.
  // If one or more IP addresses are specified,
  // the incoming traffic will be identified 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;

  // 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 [(google.api.field_behavior) = REQUIRED];

  // 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 enforcement is
  // 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. Care must be taken
  // when setting the resolution mode to NONE for a TCP port without
  // accompanying IP addresses. In such cases, traffic to any IP on
  // said port will be allowed (i.e. 0.0.0.0:<port>).
  Resolution resolution = 5 [(google.api.field_behavior) = REQUIRED];

  // Endpoint defines a network address (IP or hostname) associated with
  // the mesh service.
  message Endpoint {
    // 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 [(google.api.field_behavior) = REQUIRED];

    // 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;

    // Network enables Istio to group endpoints resident in the same L3
    // domain/network. All endpoints in the same network are assumed to be
    // directly reachable from one another. When endpoints in different
    // networks cannot reach each other directly, an Istio Gateway can be
    // used to establish connectivity (usually using the
    // AUTO_PASSTHROUGH mode in a Gateway Server). This is
    // an advanced configuration used typically for spanning an Istio mesh
    // over multiple clusters.
    string network = 4;

    // The locality associated with the endpoint. A locality corresponds
    // to a failure domain (e.g., country/region/zone). Arbitrary failure
    // domain hierarchies can be represented by separating each
    // encapsulating failure domain by /. For example, the locality of an
    // an endpoint in US, in US-East-1 region, within availability zone
    // az-1, in data center rack r11 can be represented as
    // us/us-east-1/az-1/r11. Istio will configure the sidecar to route to
    // endpoints within the same locality as the sidecar. If none of the
    // endpoints in the locality are available, endpoints parent locality
    // (but within the same network ID) will be chosen. For example, if
    // there are two endpoints in same network (networkID "n1"), say e1
    // with locality us/us-east-1/az-1/r11 and e2 with locality
    // us/us-east-1/az-2/r12, a sidecar from us/us-east-1/az-1/r11 locality
    // will prefer e1 from the same locality over e2 from a different
    // locality. Endpoint e2 could be the IP associated with a gateway
    // (that bridges networks n1 and n2), or the IP associated with a
    // standard service endpoint.
    string locality = 5;

    // The load balancing weight associated with the endpoint. Endpoints
    // with higher weights will receive proportionally higher traffic.
    uint32 weight = 6;
  };

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

  // A list of namespaces to which this service is exported. Exporting a service
  // allows it to be used by sidecars, gateways and virtual services defined in
  // other namespaces. This feature provides a mechanism for service owners
  // and mesh administrators to control the visibility of services across
  // namespace boundaries.
  //
  // If no namespaces are specified then the service is exported to all
  // namespaces by default.
  //
  // The value "." is reserved and defines an export to the same namespace that
  // the service is declared in. Similarly the value "*" is reserved and
  // defines an export to all namespaces.
  //
  // For a Kubernetes Service, the equivalent effect can be achieved by setting
  // the annotation "networking.istio.io/exportTo" to a comma-separated list
  // of namespace names.
  //
  // NOTE: in the current release, the `exportTo` value is restricted to
  // "." or "*" (i.e., the current namespace or all namespaces).
  repeated string export_to = 7;

  // The list of subject alternate names allowed for workload instances that
  // implement this service. This information is used to enforce
  // [secure-naming](https://istio.io/docs/concepts/security/#secure-naming).
  // If specified, the proxy will verify that the server
  // certificate's subject alternate name matches one of the specified values.
  repeated string subject_alt_names = 8;
}
