// Copyright 2017 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";

// $schema: istio.networking.v1alpha3.Gateway
// $title: Gateway
// $description: Configuration affecting edge load balancer.
// $location: https://istio.io/docs/reference/config/networking/gateway.html
// $aliases: [/docs/reference/config/networking/v1alpha3/gateway]

// `Gateway` describes a load balancer operating at the edge of the mesh
// receiving incoming or outgoing HTTP/TCP connections. The specification
// describes a set of ports that should be exposed, the type of protocol to
// use, SNI configuration for the load balancer, etc.
//
// For example, the following Gateway configuration sets up a proxy to act
// as a load balancer exposing port 80 and 9080 (http), 443 (https),
// 9443(https) and port 2379 (TCP) for ingress.  The gateway will be
// applied to the proxy running on a pod with labels `app:
// my-gateway-controller`. While Istio will configure the proxy to listen
// on these ports, it is the responsibility of the user to ensure that
// external traffic to these ports are allowed into the mesh.
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//   name: my-gateway
//   namespace: some-config-namespace
// spec:
//   selector:
//     app: my-gateway-controller
//   servers:
//   - port:
//       number: 80
//       name: http
//       protocol: HTTP
//     hosts:
//     - uk.bookinfo.com
//     - eu.bookinfo.com
//     tls:
//       httpsRedirect: true # sends 301 redirect for http requests
//   - port:
//       number: 443
//       name: https-443
//       protocol: HTTPS
//     hosts:
//     - uk.bookinfo.com
//     - eu.bookinfo.com
//     tls:
//       mode: SIMPLE # enables HTTPS on this port
//       serverCertificate: /etc/certs/servercert.pem
//       privateKey: /etc/certs/privatekey.pem
//   - port:
//       number: 9443
//       name: https-9443
//       protocol: HTTPS
//     hosts:
//     - "bookinfo-namespace/*.bookinfo.com"
//     tls:
//       mode: SIMPLE # enables HTTPS on this port
//       credentialName: bookinfo-secret # fetches certs from Kubernetes secret
//   - port:
//       number: 9080
//       name: http-wildcard
//       protocol: HTTP
//     hosts:
//     - "*"
//   - port:
//       number: 2379 # to expose internal service via external port 2379
//       name: mongo
//       protocol: MONGO
//     hosts:
//     - "*"
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: Gateway
// metadata:
//   name: my-gateway
//   namespace: some-config-namespace
// spec:
//   selector:
//     app: my-gateway-controller
//   servers:
//   - port:
//       number: 80
//       name: http
//       protocol: HTTP
//     hosts:
//     - uk.bookinfo.com
//     - eu.bookinfo.com
//     tls:
//       httpsRedirect: true # sends 301 redirect for http requests
//   - port:
//       number: 443
//       name: https-443
//       protocol: HTTPS
//     hosts:
//     - uk.bookinfo.com
//     - eu.bookinfo.com
//     tls:
//       mode: SIMPLE # enables HTTPS on this port
//       serverCertificate: /etc/certs/servercert.pem
//       privateKey: /etc/certs/privatekey.pem
//   - port:
//       number: 9443
//       name: https-9443
//       protocol: HTTPS
//     hosts:
//     - "bookinfo-namespace/*.bookinfo.com"
//     tls:
//       mode: SIMPLE # enables HTTPS on this port
//       credentialName: bookinfo-secret # fetches certs from Kubernetes secret
//   - port:
//       number: 9080
//       name: http-wildcard
//       protocol: HTTP
//     hosts:
//     - "*"
//   - port:
//       number: 2379 # to expose internal service via external port 2379
//       name: mongo
//       protocol: MONGO
//     hosts:
//     - "*"
// ```
// {{</tab>}}
// {{</tabset>}}
//
// The Gateway specification above describes the L4-L6 properties of a load
// balancer. A `VirtualService` can then be bound to a gateway to control
// the forwarding of traffic arriving at a particular host or gateway port.
//
// For example, the following VirtualService splits traffic for
// `https://uk.bookinfo.com/reviews`, `https://eu.bookinfo.com/reviews`,
// `http://uk.bookinfo.com:9080/reviews`,
// `http://eu.bookinfo.com:9080/reviews` into two versions (prod and qa) of
// an internal reviews service on port 9080. In addition, requests
// containing the cookie "user: dev-123" will be sent to special port 7777
// in the qa version. The same rule is also applicable inside the mesh for
// requests to the "reviews.prod.svc.cluster.local" service. This rule is
// applicable across ports 443, 9080. Note that `http://uk.bookinfo.com`
// gets redirected to `https://uk.bookinfo.com` (i.e. 80 redirects to 443).
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: bookinfo-rule
//   namespace: bookinfo-namespace
// spec:
//   hosts:
//   - reviews.prod.svc.cluster.local
//   - uk.bookinfo.com
//   - eu.bookinfo.com
//   gateways:
//   - some-config-namespace/my-gateway
//   - mesh # applies to all the sidecars in the mesh
//   http:
//   - match:
//     - headers:
//         cookie:
//           exact: "user=dev-123"
//     route:
//     - destination:
//         port:
//           number: 7777
//         host: reviews.qa.svc.cluster.local
//   - match:
//     - uri:
//         prefix: /reviews/
//     route:
//     - destination:
//         port:
//           number: 9080 # can be omitted if it's the only port for reviews
//         host: reviews.prod.svc.cluster.local
//       weight: 80
//     - destination:
//         host: reviews.qa.svc.cluster.local
//       weight: 20
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//   name: bookinfo-rule
//   namespace: bookinfo-namespace
// spec:
//   hosts:
//   - reviews.prod.svc.cluster.local
//   - uk.bookinfo.com
//   - eu.bookinfo.com
//   gateways:
//   - some-config-namespace/my-gateway
//   - mesh # applies to all the sidecars in the mesh
//   http:
//   - match:
//     - headers:
//         cookie:
//           exact: "user=dev-123"
//     route:
//     - destination:
//         port:
//           number: 7777
//         host: reviews.qa.svc.cluster.local
//   - match:
//     - uri:
//         prefix: /reviews/
//     route:
//     - destination:
//         port:
//           number: 9080 # can be omitted if it's the only port for reviews
//         host: reviews.prod.svc.cluster.local
//       weight: 80
//     - destination:
//         host: reviews.qa.svc.cluster.local
//       weight: 20
// ```
// {{</tab>}}
// {{</tabset>}}
//
// The following VirtualService forwards traffic arriving at (external)
// port 27017 to internal Mongo server on port 5555. This rule is not
// applicable internally in the mesh as the gateway list omits the
// reserved name `mesh`.
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: VirtualService
// metadata:
//   name: bookinfo-mongo
//   namespace: bookinfo-namespace
// spec:
//   hosts:
//   - mongosvr.prod.svc.cluster.local # name of internal Mongo service
//   gateways:
//   - some-config-namespace/my-gateway # can omit the namespace if gateway is in same
//                                        namespace as virtual service.
//   tcp:
//   - match:
//     - port: 27017
//     route:
//     - destination:
//         host: mongo.prod.svc.cluster.local
//         port:
//           number: 5555
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: VirtualService
// metadata:
//   name: bookinfo-mongo
//   namespace: bookinfo-namespace
// spec:
//   hosts:
//   - mongosvr.prod.svc.cluster.local # name of internal Mongo service
//   gateways:
//   - some-config-namespace/my-gateway # can omit the namespace if gateway is in same
//                                        namespace as virtual service.
//   tcp:
//   - match:
//     - port: 27017
//     route:
//     - destination:
//         host: mongo.prod.svc.cluster.local
//         port:
//           number: 5555
// ```
// {{</tab>}}
// {{</tabset>}}
//
// It is possible to restrict the set of virtual services that can bind to
// a gateway server using the namespace/hostname syntax in the hosts field.
// For example, the following Gateway allows any virtual service in the ns1
// namespace to bind to it, while restricting only the virtual service with
// foo.bar.com host in the ns2 namespace to bind to it.
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//   name: my-gateway
//   namespace: some-config-namespace
// spec:
//   selector:
//     app: my-gateway-controller
//   servers:
//   - port:
//       number: 80
//       name: http
//       protocol: HTTP
//     hosts:
//     - "ns1/*"
//     - "ns2/foo.bar.com"
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: Gateway
// metadata:
//   name: my-gateway
//   namespace: some-config-namespace
// spec:
//   selector:
//     app: my-gateway-controller
//   servers:
//   - port:
//       number: 80
//       name: http
//       protocol: HTTP
//     hosts:
//     - "ns1/*"
//     - "ns2/foo.bar.com"
// ```
// {{</tab>}}
// {{</tabset>}}
//
package istio.networking.v1alpha3;

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

// Gateway describes a load balancer operating at the edge of the mesh
// receiving incoming or outgoing HTTP/TCP connections.
//
// <!-- crd generation tags
// +cue-gen:Gateway:groupName:networking.istio.io
// +cue-gen:Gateway:version:v1alpha3
// +cue-gen:Gateway:storageVersion
// +cue-gen:Gateway:annotations:helm.sh/resource-policy=keep
// +cue-gen:Gateway:labels:app=istio-pilot,chart=istio,heritage=Tiller,release=istio
// +cue-gen:Gateway:subresource:status
// +cue-gen:Gateway:scope:Namespaced
// +cue-gen:Gateway:resource:categories=istio-io,networking-istio-io,shortNames=gw
// +cue-gen:Gateway:preserveUnknownFields:false
// -->
//
// <!-- go code generation tags
// +kubetype-gen
// +kubetype-gen:groupVersion=networking.istio.io/v1alpha3
// +genclient
// +k8s:deepcopy-gen=true
// -->
message Gateway {
  // A list of server specifications.
  repeated Server servers = 1 [(google.api.field_behavior) = REQUIRED];

  // One or more labels that indicate a specific set of pods/VMs
  // on which this gateway configuration should be applied.
  // By default workloads are searched across all namespaces based on label selectors.
  // This implies that a gateway resource in the namespace "foo" can select pods in
  // the namespace "bar" based on labels.
  // This behavior can be controlled via the `PILOT_SCOPE_GATEWAY_TO_NAMESPACE`
  // environment variable in istiod. If this variable is set
  // to true, the scope of label search is restricted to the configuration
  // namespace in which the the resource is present. In other words, the Gateway
  // resource must reside in the same namespace as the gateway workload
  // instance.
  // If selector is nil, the Gateway will be applied to all workloads.
  map<string, string> selector = 2 [(google.api.field_behavior) = REQUIRED];
}

// `Server` describes the properties of the proxy on a given load balancer
// port. For example,
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//   name: my-ingress
// spec:
//   selector:
//     app: my-ingressgateway
//   servers:
//   - port:
//       number: 80
//       name: http2
//       protocol: HTTP2
//     hosts:
//     - "*"
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: Gateway
// metadata:
//   name: my-ingress
// spec:
//   selector:
//     app: my-ingressgateway
//   servers:
//   - port:
//       number: 80
//       name: http2
//       protocol: HTTP2
//     hosts:
//     - "*"
// ```
// {{</tab>}}
// {{</tabset>}}
//
// Another example
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//   name: my-tcp-ingress
// spec:
//   selector:
//     app: my-tcp-ingressgateway
//   servers:
//   - port:
//       number: 27018
//       name: mongo
//       protocol: MONGO
//     hosts:
//     - "*"
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: Gateway
// metadata:
//   name: my-tcp-ingress
// spec:
//   selector:
//     app: my-tcp-ingressgateway
//   servers:
//   - port:
//       number: 27018
//       name: mongo
//       protocol: MONGO
//     hosts:
//     - "*"
// ```
// {{</tab>}}
// {{</tabset>}}
//
// The following is an example of TLS configuration for port 443
//
// {{<tabset category-name="example">}}
// {{<tab name="v1alpha3" category-value="v1alpha3">}}
// ```yaml
// apiVersion: networking.istio.io/v1alpha3
// kind: Gateway
// metadata:
//   name: my-tls-ingress
// spec:
//   selector:
//     app: my-tls-ingressgateway
//   servers:
//   - port:
//       number: 443
//       name: https
//       protocol: HTTPS
//     hosts:
//     - "*"
//     tls:
//       mode: SIMPLE
//       serverCertificate: /etc/certs/server.pem
//       privateKey: /etc/certs/privatekey.pem
// ```
// {{</tab>}}
//
// {{<tab name="v1beta1" category-value="v1beta1">}}
// ```yaml
// apiVersion: networking.istio.io/v1beta1
// kind: Gateway
// metadata:
//   name: my-tls-ingress
// spec:
//   selector:
//     app: my-tls-ingressgateway
//   servers:
//   - port:
//       number: 443
//       name: https
//       protocol: HTTPS
//     hosts:
//     - "*"
//     tls:
//       mode: SIMPLE
//       serverCertificate: /etc/certs/server.pem
//       privateKey: /etc/certs/privatekey.pem
// ```
// {{</tab>}}
// {{</tabset>}}
//
message Server {
  // The Port on which the proxy should listen for incoming
  // connections.
  Port port = 1 [(google.api.field_behavior) = REQUIRED];

  // $hide_from_docs
  // The ip or the Unix domain socket to which the listener should be bound
  // to. Format: `x.x.x.x` or `unix:///path/to/uds` or `unix://@foobar`
  // (Linux abstract namespace). When using Unix domain sockets, the port
  // number should be 0.
  string bind = 4;

  // One or more hosts exposed by this gateway.
  // While typically applicable to
  // HTTP services, it can also be used for TCP services using TLS with SNI.
  // A host is specified as a `dnsName` with an optional `namespace/` prefix.
  // The `dnsName` should be specified using FQDN format, optionally including
  // a wildcard character in the left-most component (e.g., `prod/*.example.com`).
  // Set the `dnsName` to `*` to select all `VirtualService` hosts from the
  // specified namespace (e.g.,`prod/*`).
  //
  // The `namespace` can be set to `*` or `.`, representing any or the current
  // namespace, respectively. For example, `*/foo.example.com` selects the
  // service from any available namespace while `./foo.example.com` only selects
  // the service from the namespace of the sidecar. The default, if no `namespace/`
  // is specified, is `*/`, that is, select services from any namespace.
  // Any associated `DestinationRule` in the selected namespace will also be used.
  //
  // A `VirtualService` must be bound to the gateway and must have one or
  // more hosts that match the hosts specified in a server. The match
  // could be an exact match or a suffix match with the server's hosts. For
  // example, if the server's hosts specifies `*.example.com`, a
  // `VirtualService` with hosts `dev.example.com` or `prod.example.com` will
  // match. However, a `VirtualService` with host `example.com` or
  // `newexample.com` will not match.
  //
  // NOTE: Only virtual services exported to the gateway's namespace
  // (e.g., `exportTo` value of `*`) can be referenced.
  // Private configurations (e.g., `exportTo` set to `.`) will not be
  // available. Refer to the `exportTo` setting in `VirtualService`,
  // `DestinationRule`, and `ServiceEntry` configurations for details.
  repeated string hosts = 2 [(google.api.field_behavior) = REQUIRED];

  // Set of TLS related options that govern the server's behavior. Use
  // these options to control if all http requests should be redirected to
  // https, and the TLS modes to use.
  ServerTLSSettings tls = 3;

  // The loopback IP endpoint or Unix domain socket to which traffic should
  // be forwarded to by default. Format should be `127.0.0.1:PORT` or
  // `unix:///path/to/socket` or `unix://@foobar` (Linux abstract namespace).
  // NOT IMPLEMENTED.
  // $hide_from_docs
  string default_endpoint = 5;

  // An optional name of the server, when set must be unique across all servers.
  // This will be used for variety of purposes like prefixing stats generated with
  // this name etc.
  string name = 6;
}

// Port describes the properties of a specific port of a service.
message Port {
  // A valid non-negative integer port number.
  uint32 number = 1 [(google.api.field_behavior) = REQUIRED];

  // The protocol exposed on the port.
  // MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS.
  // TLS implies the connection will be routed based on the SNI header to
  // the destination without terminating the TLS connection.
  string protocol = 2 [(google.api.field_behavior) = REQUIRED];

  // Label assigned to the port.
  string name = 3 [(google.api.field_behavior) = REQUIRED];

  // The port number on the endpoint where the traffic will be
  // received. Applicable only when used with ServiceEntries.
  uint32 target_port = 4;
}

message ServerTLSSettings {
  // If set to true, the load balancer will send a 301 redirect for
  // all http connections, asking the clients to use HTTPS.
  bool https_redirect = 1;

  // TLS modes enforced by the proxy
  enum TLSmode {
    // The SNI string presented by the client will be used as the
    // match criterion in a VirtualService TLS route to determine
    // the destination service from the service registry.
    PASSTHROUGH = 0;

    // Secure connections with standard TLS semantics.
    SIMPLE = 1;

    // Secure connections to the downstream using mutual TLS by
    // presenting server certificates for authentication.
    MUTUAL = 2;

    // Similar to the passthrough mode, except servers with this TLS
    // mode do not require an associated VirtualService to map from
    // the SNI value to service in the registry. The destination
    // details such as the service/subset/port are encoded in the
    // SNI value. The proxy will forward to the upstream (Envoy)
    // cluster (a group of endpoints) specified by the SNI
    // value. This server is typically used to provide connectivity
    // between services in disparate L3 networks that otherwise do
    // not have direct connectivity between their respective
    // endpoints. Use of this mode assumes that both the source and
    // the destination are using Istio mTLS to secure traffic.
    AUTO_PASSTHROUGH = 3;

    // Secure connections from the downstream using mutual TLS by
    // presenting server certificates for authentication.  Compared
    // to Mutual mode, this mode uses certificates, representing
    // gateway workload identity, generated automatically by Istio
    // for mTLS authentication. When this mode is used, all other
    // fields in `TLSOptions` should be empty.
    ISTIO_MUTUAL = 4;
  };

  // Optional: Indicates whether connections to this port should be
  // secured using TLS. The value of this field determines how TLS is
  // enforced.
  TLSmode mode = 2;

  // REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
  // holding the server-side TLS certificate to use.
  string server_certificate = 3;

  // REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
  // holding the server's private key.
  string private_key = 4;

  // REQUIRED if mode is `MUTUAL`. The path to a file containing
  // certificate authority certificates to use in verifying a presented
  // client side certificate.
  string ca_certificates = 5;

  // For gateways running on Kubernetes, the name of the secret that
  // holds the TLS certs including the CA certificates. Applicable
  // only on Kubernetes. The secret (of type `generic`) should
  // contain the following keys and values: `key:
  // <privateKey>` and `cert: <serverCert>`. For mutual TLS, 
  // `cacert: <CACertificate>` can be provided in the same secret or 
  // a separate secret named `<secret>-cacert`.
  // Secret of type tls for server certificates along with
  // ca.crt key for CA certificates is also supported.
  // Only one of server certificates and CA certificate
  // or credentialName can be specified.
  string credential_name = 10;

  // A list of alternate names to verify the subject identity in the
  // certificate presented by the client.
  repeated string subject_alt_names = 6;

  // An optional list of base64-encoded SHA-256 hashes of the SKPIs of
  // authorized client certificates.
  // Note: When both verify_certificate_hash and verify_certificate_spki
  // are specified, a hash matching either value will result in the
  // certificate being accepted.
  repeated string verify_certificate_spki = 11;

  // An optional list of hex-encoded SHA-256 hashes of the
  // authorized client certificates. Both simple and colon separated
  // formats are acceptable.
  // Note: When both verify_certificate_hash and verify_certificate_spki
  // are specified, a hash matching either value will result in the
  // certificate being accepted.
  repeated string verify_certificate_hash = 12;

  // TLS protocol versions.
  enum TLSProtocol {
    // Automatically choose the optimal TLS version.
    TLS_AUTO = 0;

    // TLS version 1.0
    TLSV1_0 = 1;

    // TLS version 1.1
    TLSV1_1 = 2;

    // TLS version 1.2
    TLSV1_2 = 3;

    // TLS version 1.3
    TLSV1_3 = 4;
  }

  // Optional: Minimum TLS protocol version.
  TLSProtocol min_protocol_version = 7;

  // Optional: Maximum TLS protocol version.
  TLSProtocol max_protocol_version = 8;

  // Optional: If specified, only support the specified cipher list.
  // Otherwise default to the default cipher list supported by Envoy.
  repeated string cipher_suites = 9;
}
