github.com/projectcontour/contour@v1.28.2/site/content/docs/v1.9.0/httpproxy.md (about)

     1  # HTTPProxy Reference
     2  
     3  <div id="toc" class="navigation"></div>
     4  
     5  The [Ingress][1] object was added to Kubernetes in version 1.1 to describe properties of a cluster-wide reverse HTTP proxy.
     6  Since that time, the Ingress object has not progressed beyond the beta stage, and its stagnation inspired an [explosion of annotations][2] to express missing properties of HTTP routing.
     7  
     8  The goal of the HTTPProxy (which replaces the now-removed IngressRoute) Custom Resource Definition (CRD) is to expand upon the functionality of the Ingress API to allow for a richer user experience as well addressing the limitations of the latter's use in multi tenant environments.
     9  
    10  ## Key HTTPProxy Benefits
    11  
    12  - Safely supports multi-team Kubernetes clusters, with the ability to limit which Namespaces may configure virtual hosts and TLS credentials.
    13  - Enables including of routing configuration for a path or domain from another HTTPProxy, possibly in another Namespace.
    14  - Accepts multiple services within a single route and load balances traffic across them.
    15  - Natively allows defining service weighting and load balancing strategy without annotations.
    16  - Validation of HTTPProxy objects at creation time and status reporting for post-creation validity.
    17  
    18  ## Ingress to HTTPProxy
    19  
    20  A minimal Ingress object might look like:
    21  
    22  ```yaml
    23  # ingress.yaml
    24  apiVersion: networking.k8s.io/v1beta1
    25  kind: Ingress
    26  metadata:
    27    name: basic
    28  spec:
    29    rules:
    30    - host: foo-basic.bar.com
    31      http:
    32        paths:
    33        - backend:
    34            serviceName: s1
    35            servicePort: 80
    36  ```
    37  
    38  This Ingress object, named `basic`, will route incoming HTTP traffic with a `Host:` header for `foo-basic.bar.com` to a Service named `s1` on port `80`.
    39  Implementing similar behavior using an HTTPProxy looks like this:
    40  
    41  {% highlight yaml linenos %}
    42  # httpproxy.yaml
    43  apiVersion: projectcontour.io/v1
    44  kind: HTTPProxy
    45  metadata:
    46    name: basic
    47  spec:
    48    virtualhost:
    49      fqdn: foo-basic.bar.com
    50    routes:
    51      - conditions:
    52        - prefix: /
    53        services:
    54          - name: s1
    55            port: 80
    56  {% endhighlight %}
    57  
    58  **Lines 1-5**: As with all other Kubernetes objects, an HTTPProxy needs apiVersion, kind, and metadata fields.
    59  
    60  **Lines 7-8**: The presence of the `virtualhost` field indicates that this is a root HTTPProxy that is the top level entry point for this domain.
    61  The `fqdn` field specifies the fully qualified domain name that will be used to match against `Host:` HTTP headers.
    62  
    63  **Lines 9-14**: Each HTTPProxy **must** have one or more routes, each of which **must** have one or more services which will handle the HTTP traffic. In addition, each route **may** have one or more conditions to match against.
    64  
    65  **Lines 12-14**: The `services` field is an array of named Service & Port combinations that will be used for this HTTPProxy path.
    66  HTTP traffic will be sent directly to the Endpoints corresponding to the Service.
    67  
    68  ## Interacting with HTTPProxies
    69  
    70  As with all Kubernetes objects, you can use `kubectl` to create, list, describe, edit, and delete HTTPProxy CRDs.
    71  
    72  Creating an HTTPProxy:
    73  
    74  ```bash
    75  $ kubectl create -f basic.httpproxy.yaml
    76  httpproxy "basic" created
    77  ```
    78  
    79  Listing HTTPProxies:
    80  
    81  ```bash
    82  $ kubectl get httpproxy
    83  NAME      AGE
    84  basic     24s
    85  ```
    86  
    87  Describing HTTPProxy:
    88  
    89  ```bash
    90  $ kubectl describe httpproxy basic
    91  Name:         basic
    92  Namespace:    default
    93  Labels:       <none>
    94  API Version:  projectcontour.io/v1
    95  Kind:         HTTPProxy
    96  Metadata:
    97    Cluster Name:
    98    Creation Timestamp:  2019-07-05T19:26:54Z
    99    Resource Version:    19373717
   100    Self Link:           /apis/projectcontour.io/v1/namespaces/default/httpproxy/basic
   101    UID:                 6036a9d7-8089-11e8-ab00-f80f4182762e
   102  Spec:
   103    Routes:
   104      Conditions:
   105        Prefix: /
   106      Services:
   107        Name:  s1
   108        Port:  80
   109    Virtualhost:
   110      Fqdn:  foo-basic.bar.com
   111  Events:    <none>
   112  ```
   113  
   114  Deleting HTTPProxies:
   115  
   116  ```bash
   117  $ kubectl delete httpproxy basic
   118  httpproxy "basic" deleted
   119  ```
   120  
   121  ## HTTPProxy API Specification
   122  
   123  There are a number of [working examples][3] of HTTPProxy objects in the `examples/example-workload` directory.
   124  
   125  We will use these examples as a mechanism to describe HTTPProxy API functionality.
   126  
   127  ### Virtual Host Configuration
   128  
   129  #### Fully Qualified Domain Name
   130  
   131  Similar to Ingress, HTTPProxy support name-based virtual hosting.
   132  Name-based virtual hosts use multiple host names with the same IP address.
   133  
   134  ```
   135  foo.bar.com --|                 |-> foo.bar.com s1:80
   136                | 178.91.123.132  |
   137  bar.foo.com --|                 |-> bar.foo.com s2:80
   138  ```
   139  
   140  Unlike Ingress, HTTPProxy only support a single root domain per HTTPProxy object.
   141  As an example, this Ingress object:
   142  
   143  ```yaml
   144  # ingress-name.yaml
   145  apiVersion: extensions/v1beta1
   146  kind: Ingress
   147  metadata:
   148    name: name-example
   149  spec:
   150    rules:
   151    - host: foo1.bar.com
   152      http:
   153        paths:
   154        - backend:
   155            serviceName: s1
   156            servicePort: 80
   157    - host: bar1.bar.com
   158      http:
   159        paths:
   160        - backend:
   161            serviceName: s2
   162            servicePort: 80
   163  ```
   164  
   165  must be represented by two different HTTPProxy objects:
   166  
   167  ```yaml
   168  # httpproxy-name.yaml
   169  apiVersion: projectcontour.io/v1
   170  kind: HTTPProxy
   171  metadata:
   172    name: name-example-foo
   173    namespace: default
   174  spec:
   175    virtualhost:
   176      fqdn: foo1.bar.com
   177    routes:
   178      - services:
   179        - name: s1
   180          port: 80
   181  ---
   182  apiVersion: projectcontour.io/v1
   183  kind: HTTPProxy
   184  metadata:
   185    name: name-example-bar
   186    namespace: default
   187  spec:
   188    virtualhost:
   189      fqdn: bar1.bar.com
   190    routes:
   191      - services:
   192          - name: s2
   193            port: 80
   194  ```
   195  
   196  #### TLS
   197  
   198  HTTPProxy follows a similar pattern to Ingress for configuring TLS credentials.
   199  
   200  You can secure a HTTPProxy by specifying a Secret that contains TLS private key and certificate information.
   201  If multiple HTTPProxies utilize the same Secret, the certificate must include the necessary Subject Authority Name (SAN) for each fqdn.
   202  
   203  Contour (via Envoy) requires that clients send the Server Name Indication (SNI) TLS extension so that requests can be routed to the correct virtual host.
   204  Virtual hosts are strongly bound to SNI names.
   205  This means that the Host header in HTTP requests must match the SNI name that was sent at the start of the TLS session.
   206  
   207  Contour also follows a "secure first" approach.
   208  When TLS is enabled for a virtual host, any request to the insecure port is redirected to the secure interface with a 301 redirect.
   209  Specific routes can be configured to override this behavior and handle insecure requests by enabling the `spec.routes.permitInsecure` parameter on a Route.
   210  
   211  The TLS secret must contain keys named tls.crt and tls.key that contain the certificate and private key to use for TLS, e.g.:
   212  
   213  ```yaml
   214  # ingress-tls.secret.yaml
   215  apiVersion: v1
   216  data:
   217    tls.crt: base64 encoded cert
   218    tls.key: base64 encoded key
   219  kind: Secret
   220  metadata:
   221    name: testsecret
   222    namespace: default
   223  type: kubernetes.io/tls
   224  ```
   225  
   226  The HTTPProxy can be configured to use this secret using `tls.secretName` property:
   227  
   228  ```yaml
   229  # httpproxy-tls.yaml
   230  apiVersion: projectcontour.io/v1
   231  kind: HTTPProxy
   232  metadata:
   233    name: tls-example
   234    namespace: default
   235  spec:
   236    virtualhost:
   237      fqdn: foo2.bar.com
   238      tls:
   239        secretName: testsecret
   240    routes:
   241      - services:
   242          - name: s1
   243            port: 80
   244  ```
   245  
   246  If the `tls.secretName` property contains a slash, eg. `somenamespace/somesecret` then, subject to TLS Certificate Delegation, the TLS certificate will be read from `somesecret` in `somenamespace`.
   247  See TLS Certificate Delegation below for more information.
   248  
   249  The TLS **Minimum Protocol Version** a vhost should negotiate can be specified by setting the `spec.virtualhost.tls.minimumProtocolVersion`:
   250  
   251  - 1.3
   252  - 1.2
   253  - 1.1 (Default)
   254  
   255  ##### Fallback Certificate
   256  
   257  Contour provides virtual host based routing, so that any TLS request is routed to the appropriate service based on both the server name requested by the TLS client and the HOST header in the HTTP request.
   258  
   259  As the HOST Header is encrypted during TLS handshake, it can’t be used for virtual host based routing unless the client sends HTTPS requests specifying hostname using the TLS server name, or the request is first decrypted using a default TLS certificate.
   260  
   261  Some legacy TLS clients do not send the server name, so Envoy does not know how to select the right certificate. A fallback certificate is needed for these clients.
   262  
   263  _Note: The minimum TLS protocol version for any fallback request is defined by the `minimum TLS protocol version` set in the Contour configuration file. Enabling the fallback certificate is not compatible with TLS client authentication._
   264  
   265  ###### Configuration
   266  
   267  First define the `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which will be used as the fallback certificate.
   268  Any HTTPProxy which enables fallback certificate delegation must have the fallback certificate delegated to the namespace in which the HTTPProxy object resides.
   269  
   270  To do that, configure `TLSCertificateDelegation` to delegate the fallback certificate to specific or all namespaces (e.g. `*`) which should be allowed to enable the fallback certificate.
   271  Finally, for each root HTTPProxy, set the `Spec.TLS.enableFallbackCertificate` parameter to allow that HTTPProxy to opt-in to the fallback certificate routing.
   272  
   273  ```yaml
   274  apiVersion: projectcontour.io/v1
   275  kind: HTTPProxy
   276  metadata:
   277    name: fallback-tls-example
   278    namespace: defaultub
   279  spec:
   280    virtualhost:
   281      fqdn: fallback.bar.com
   282      tls:
   283        secretName: testsecret
   284        enableFallbackCertificate: true
   285    routes:
   286      - services:
   287          - name: s1
   288            port: 80
   289  ---
   290  apiVersion: projectcontour.io/v1
   291  kind: TLSCertificateDelegation
   292  metadata:
   293    name: fallback-delegation
   294    namespace: www-admin
   295  spec:
   296    delegations:
   297      - secretName: fallback-secret-name
   298        targetNamespaces:
   299        - "*"
   300  ```
   301  
   302  
   303  
   304  #### Upstream TLS
   305  
   306  A HTTPProxy can proxy to an upstream TLS connection by annotating the upstream Kubernetes Service or by specifying the upstream protocol in the HTTPProxy [`services`][10] field.
   307  Applying the `projectcontour.io/upstream-protocol.tls` annotation to a Service object tells Contour that TLS should be enabled and which port should be used for the TLS connection.
   308  The same configuration can be specified by setting the protocol name in the `spec.routes.services[].protocol` field on the HTTPProxy object.
   309  If both the annotation and the protocol field are specified, the protocol field takes precedence.
   310  By default, the upstream TLS server certificate will not be validated, but validation can be requested by setting the `spec.routes.services[].validation` field.
   311  This field has mandatory `caSecret` and `subjectName` fields, which specify the trusted root certificates with which to validate the server certificate and the expected server name.
   312  
   313  _Note: If `spec.routes.services[].validation` is present, `spec.routes.services[].{name,port}` must point to a Service with a matching `projectcontour.io/upstream-protocol.tls` Service annotation._
   314  
   315  In the example below, the upstream service is named `secure-backend` and uses port `8443`:
   316  
   317  ```yaml
   318  # httpproxy-example.yaml
   319  apiVersion: projectcontour.io/v1
   320  kind: HTTPProxy
   321  metadata:
   322    name: example
   323  spec:
   324    virtualhost:
   325      fqdn: www.example.com
   326    routes:
   327    - services:
   328      - name: secure-backend
   329        port: 8443
   330        validation:
   331          caSecret: my-certificate-authority
   332          subjectName: backend.example.com
   333  ```
   334  
   335  ```yaml
   336  # service-secure-backend.yaml
   337  apiVersion: v1
   338  kind: Service
   339  metadata:
   340    name: secure-backend
   341    annotations:
   342      projectcontour.io/upstream-protocol.tls: "8443"
   343  spec:
   344    ports:
   345    - name: https
   346      port: 8443
   347    selector:
   348      app: secure-backend
   349  
   350  ```
   351  
   352  ##### Envoy Client Certificate
   353  
   354  Contour can be configured with a `namespace/name` in the [Contour configuration file][11] of a Kubernetes secret which Envoy uses as a client certificate when upstream TLS is configured for the backend.
   355  Envoy will send the certificate during TLS handshake when the backend applications request the client to present its certificate.
   356  Backend applications can validate the certificate to ensure that the connection is coming from Envoy.
   357  
   358  ##### Error conditions
   359  
   360  If the `validation` spec is defined on a service, but the secret which it references does not exist, Contour will reject the update and set the status of the HTTPProxy object accordingly.
   361  This helps prevent the case of proxying to an upstream where validation is requested, but not yet available.
   362  
   363  ```yaml
   364  Status:
   365    Current Status:  invalid
   366    Description:     route "/": service "tls-nginx": upstreamValidation requested but secret not found or misconfigured
   367  ```
   368  
   369  #### TLS Certificate Delegation
   370  
   371  In order to support wildcard certificates, TLS certificates for a `*.somedomain.com`, which are stored in a namespace controlled by the cluster administrator, Contour supports a facility known as TLS Certificate Delegation.
   372  This facility allows the owner of a TLS certificate to delegate, for the purposes of referencing the TLS certificate, permission to Contour to read the Secret object from another namespace. Delegation works for both HTTPProxy and Ingress resources.
   373  
   374  The `TLSCertificateDelegation` resource defines a set of `delegations` in the `spec`.
   375  Each delegation references a `secretName` from the namespace where the `TLSCertificateDelegation` is created as well as describing a set of `targetNamespaces` in which the certificate can be referenced.
   376  If all namespaces should be able to reference the secret, then set `"*"` as the value of `targetNamespaces` (see example below).
   377  
   378  ```yaml
   379  apiVersion: projectcontour.io/v1
   380  kind: TLSCertificateDelegation
   381  metadata:
   382    name: example-com-wildcard
   383    namespace: www-admin
   384  spec:
   385    delegations:
   386      - secretName: example-com-wildcard
   387        targetNamespaces:
   388        - example-com
   389      - secretName: another-com-wildcard
   390        targetNamespaces:
   391        - "*"
   392  ---
   393  apiVersion: projectcontour.io/v1
   394  kind: HTTPProxy
   395  metadata:
   396    name: www
   397    namespace: example-com
   398  spec:
   399    virtualhost:
   400      fqdn: foo2.bar.com
   401      tls:
   402        secretName: www-admin/example-com-wildcard
   403    routes:
   404      - services:
   405          - name: s1
   406            port: 80
   407  ```
   408  
   409  In this example, the permission for Contour to reference the Secret `example-com-wildcard` in the `admin` namespace has been delegated to HTTPProxy objects in the `example-com` namespace.
   410  Also, the permission for Contour to reference the Secret `another-com-wildcard` from all namespaces has been delegated to all HTTPProxy objects in the cluster.
   411  
   412  #### CORS policy
   413  
   414  A CORS (Cross-origin resource sharing) policy can be set for a HTTPProxy in order to allow cross-domain requests for trusted sources. If a policy is set, it will be applied to all the routes of the virtual host.
   415  
   416  Contour allows configuring the headers involved in cross-domain requests. In this example, cross-domain requests will be allowed for any domain (note the `*` value).
   417  
   418  ```yaml
   419  apiVersion: projectcontour.io/v1
   420  kind: HTTPProxy
   421  spec:
   422    virtualhost:
   423      fqdn: www.example.com
   424      corsPolicy:
   425          allowCredentials: true
   426          allowOrigin: 
   427            - "*" # allows any origin
   428          allowMethods:
   429            - GET
   430            - POST
   431            - OPTIONS
   432          allowHeaders: 
   433            - authorization
   434            - cache-control
   435          exposeHeaders: 
   436            - Content-Length
   437            - Content-Range
   438          maxAge: "10m" # preflight requests can be cached for 10 minutes. 
   439    routes:
   440      - conditions:
   441        - prefix: /
   442        services:
   443          - name: s1
   444            port: 80
   445  ```
   446  
   447  In the following example, cross-domain requests are restricted to https://client.example.com only.
   448  
   449  ```yaml
   450  apiVersion: projectcontour.io/v1
   451  kind: HTTPProxy
   452  spec:
   453    virtualhost:
   454      fqdn: www.example.com
   455      corsPolicy:
   456          allowCredentials: true
   457          allowOrigin: 
   458            - "https://client.example.com"
   459          allowMethods:
   460            - GET
   461            - POST
   462            - OPTIONS
   463          allowHeaders: 
   464            - authorization
   465            - cache-control
   466          exposeHeaders: 
   467            - Content-Length
   468            - Content-Range
   469          maxAge: "10m"
   470    routes:
   471      - conditions:
   472        - prefix: /
   473        services:
   474          - name: s1
   475            port: 80
   476  ```
   477  
   478  `MaxAge` durations are expressed in the Go [duration format](https://godoc.org/time#ParseDuration). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". Only positive values are allowed and 0 disables the cache requiring a preflight OPTIONS check for all cross-origin requests.
   479  
   480  ### Conditions
   481  
   482  Each Route entry in a HTTPProxy **may** contain one or more conditions.
   483  These conditions are combined with an AND operator on the route passed to Envoy.
   484  
   485  Conditions can be either a `prefix` or a `header` condition.
   486  
   487  #### Prefix conditions
   488  
   489  For `prefix`, this adds a path prefix.
   490  
   491  Up to one prefix condition may be present in any condition block.
   492  
   493  Prefix conditions **must** start with a `/` if they are present.
   494  
   495  #### Header conditions
   496  
   497  For `header` conditions there is one required field, `name`, and five operator fields: `present`, `contains`, `notcontains`, `exact`, and `notexact`.
   498  
   499  - `present` is a boolean and checks that the header is present. The value will not be checked.
   500  
   501  - `contains` is a string, and checks that the header contains the string. `notcontains` similarly checks that the header does *not* contain the string.
   502  
   503  - `exact` is a string, and checks that the header exactly matches the whole string. `notexact` checks that the header does *not* exactly match the whole string.
   504  
   505  ### Routes
   506  
   507  HTTPProxy must have at least one route or include defined.
   508  Paths defined are matched using prefix conditions.
   509  In this example, any requests to `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*` will be routed to the Service `s2`.
   510  All other requests to the host `multi-path.bar.com` will be routed to the Service `s1`.
   511  
   512  ```yaml
   513  # httpproxy-multiple-paths.yaml
   514  apiVersion: projectcontour.io/v1
   515  kind: HTTPProxy
   516  metadata:
   517    name: multiple-paths
   518    namespace: default
   519  spec:
   520    virtualhost:
   521      fqdn: multi-path.bar.com
   522    routes:
   523      - conditions:
   524        - prefix: / # matches everything else
   525        services:
   526          - name: s1
   527            port: 80
   528      - conditions:
   529        - prefix: /blog # matches `multi-path.bar.com/blog` or `multi-path.bar.com/blog/*`
   530        services:
   531          - name: s2
   532            port: 80
   533  ```
   534  
   535  In the following example, we match on headers and send to different services, with a default route if those do not match.
   536  
   537  ```yaml
   538  # httpproxy-multiple-headers.yaml
   539  apiVersion: projectcontour.io/v1
   540  kind: HTTPProxy
   541  metadata:
   542    name: multiple-paths
   543    namespace: default
   544  spec:
   545    virtualhost:
   546      fqdn: multi-path.bar.com
   547    routes:
   548      - conditions:
   549        - header:
   550            name: x-os
   551            contains: ios
   552        services:
   553          - name: s1
   554            port: 80
   555      - conditions:
   556        - header:
   557            name: x-os
   558            contains: android
   559        services:
   560          - name: s2
   561            port: 80
   562      - services:
   563          - name: s3
   564            port: 80
   565  ```
   566  
   567  #### Multiple Upstreams
   568  
   569  One of the key HTTPProxy features is the ability to support multiple services for a given path:
   570  
   571  ```yaml
   572  # httpproxy-multiple-upstreams.yaml
   573  apiVersion: projectcontour.io/v1
   574  kind: HTTPProxy
   575  metadata:
   576    name: multiple-upstreams
   577    namespace: default
   578  spec:
   579    virtualhost:
   580      fqdn: multi.bar.com
   581    routes:
   582      - services:
   583          - name: s1
   584            port: 80
   585          - name: s2
   586            port: 80
   587  ```
   588  
   589  In this example, requests for `multi.bar.com/` will be load balanced across two Kubernetes Services, `s1`, and `s2`.
   590  This is helpful when you need to split traffic for a given URL across two different versions of an application.
   591  
   592  #### Upstream Weighting
   593  
   594  Building on multiple upstreams is the ability to define relative weights for upstream Services.
   595  This is commonly used for canary testing of new versions of an application when you want to send a small fraction of traffic to a specific Service.
   596  
   597  ```yaml
   598  # httpproxy-weight-shfiting.yaml
   599  apiVersion: projectcontour.io/v1
   600  kind: HTTPProxy
   601  metadata:
   602    name: weight-shifting
   603    namespace: default
   604  spec:
   605    virtualhost:
   606      fqdn: weights.bar.com
   607    routes:
   608      - services:
   609          - name: s1
   610            port: 80
   611            weight: 10
   612          - name: s2
   613            port: 80
   614            weight: 90
   615  ```
   616  
   617  In this example, we are sending 10% of the traffic to Service `s1`, while Service `s2` receives the remaining 90% of traffic.
   618  
   619  HTTPProxy weighting follows some specific rules:
   620  
   621  - If no weights are specified for a given route, it's assumed even distribution across the Services.
   622  - Weights are relative and do not need to add up to 100. If all weights for a route are specified, then the "total" weight is the sum of those specified. As an example, if weights are 20, 30, 20 for three upstreams, the total weight would be 70. In this example, a weight of 30 would receive approximately 42.9% of traffic (30/70 = .4285).
   623  - If some weights are specified but others are not, then it's assumed that upstreams without weights have an implicit weight of zero, and thus will not receive traffic.
   624  
   625  #### Request and Response Header Policies
   626  
   627  Manipulating headers is also supported per-Service or per-Route.  Headers can be set or
   628  removed from the request or response as follows:
   629  
   630  per-Service:
   631  
   632  ```yaml
   633  apiVersion: projectcontour.io/v1
   634  kind: HTTPProxy
   635  metadata:
   636    name: header-manipulation
   637    namespace: default
   638  spec:
   639    virtualhost:
   640      fqdn: headers.bar.com
   641    routes:
   642      - services:
   643          - name: s1
   644            port: 80
   645            requestHeadersPolicy:
   646              set:
   647                - name: X-Foo
   648                  value: bar
   649              remove:
   650                - X-Baz
   651            responseHeadersPolicy:
   652              set:
   653                - name: X-Service-Name
   654                  value: s1
   655              remove:
   656                - X-Internal-Secret
   657  ```
   658  
   659  per-Route:
   660  
   661  ```yaml
   662  apiVersion: projectcontour.io/v1
   663  kind: HTTPProxy
   664  metadata:
   665    name: header-manipulation
   666    namespace: default
   667  spec:
   668    virtualhost:
   669      fqdn: headers.bar.com
   670    routes:
   671      - services:
   672          - name: s1
   673            port: 80
   674        requestHeadersPolicy:
   675          set:
   676            - name: X-Foo
   677              value: bar
   678          remove:
   679            - X-Baz
   680        responseHeadersPolicy:
   681          set:
   682            - name: X-Service-Name
   683              value: s1
   684          remove:
   685            - X-Internal-Secret
   686  ```
   687  
   688  In these examples we are setting the header `X-Foo` with value `baz` on requests
   689  and stripping `X-Baz`.  We are then setting `X-Service-Name` on the response with
   690  value `s1`, and removing `X-Internal-Secret`.
   691  
   692  #### Traffic mirroring
   693  
   694  Per route a service can be nominated as a mirror.
   695  The mirror service will receive a copy of the read traffic sent to any non mirror service.
   696  The mirror traffic is considered _read only_, any response by the mirror will be discarded.
   697  
   698  This service can be useful for recording traffic for later replay or for smoke testing new deployments.
   699  
   700  ```yaml
   701  apiVersion: projectcontour.io/v1
   702  kind: HTTPProxy
   703  metadata:
   704    name: traffic-mirror
   705    namespace: default
   706  spec:
   707    virtualhost:
   708      fqdn: www.example.com
   709    routes:
   710      - conditions:
   711        - prefix: /
   712        services:
   713          - name: www
   714            port: 80
   715          - name: www-mirror
   716            port: 80
   717            mirror: true
   718  ```
   719  
   720  #### Response Timeout
   721  
   722  Each Route can be configured to have a timeout policy and a retry policy as shown:
   723  
   724  ```yaml
   725  # httpproxy-response-timeout.yaml
   726  apiVersion: projectcontour.io/v1
   727  kind: HTTPProxy
   728  metadata:
   729    name: response-timeout
   730    namespace: default
   731  spec:
   732    virtualhost:
   733      fqdn: timeout.bar.com
   734    routes:
   735    - timeoutPolicy:
   736        response: 1s
   737        idle: 10s
   738      retryPolicy:
   739        count: 3
   740        perTryTimeout: 150ms
   741      services:
   742      - name: s1
   743        port: 80
   744  ```
   745  
   746  In this example, requests to `timeout.bar.com/` will have a response timeout policy of 1s.
   747  This refers to the time that spans between the point at which complete client request has been processed by the proxy, and when the response from the server has been completely processed.
   748  
   749  - `timeoutPolicy.response` This field can be any positive time period or "infinity".
   750  This timeout covers the time from the *end of the client request* to the *end of the upstream response*.
   751  By default, Envoy has a 15 second value for this timeout.
   752  More information can be found in [Envoy's documentation][4].
   753  Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   754  - `timeoutPolicy.idle` This field can be any positive time period or "infinity".
   755  By default, there is no per-route idle timeout.
   756  Note that the default connection manager idle timeout of 5 minutes will apply if this is not set.
   757  More information can be found in [Envoy's documentation][6].
   758  Note that a value of **0s** will be treated as if the field were not set, i.e. by using Envoy's default behavior.
   759  
   760  TimeoutPolicy durations are expressed as per the format specified in the [ParseDuration documentation][5].
   761  Example input values: "300ms", "5s", "1m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
   762  The string 'infinity' is also a valid input and specifies no timeout.
   763  
   764  - `retryPolicy`: A retry will be attempted if the server returns an error code in the 5xx range, or if the server takes more than `retryPolicy.perTryTimeout` to process a request.
   765    - `retryPolicy.count` specifies the maximum number of retries allowed. This parameter is optional and defaults to 1.
   766    - `retryPolicy.perTryTimeout` specifies the timeout per retry. If this field is greater than the request timeout, it is ignored. This parameter is optional.
   767    If left unspecified, `timeoutPolicy.request` will be used.
   768  
   769  #### Load Balancing Strategy
   770  
   771  Each route can have a load balancing strategy applied to determine which of its Endpoints is selected for the request.
   772  The following list are the options available to choose from:
   773  
   774  - `RoundRobin`: Each healthy upstream Endpoint is selected in round robin order (Default strategy if none selected).
   775  - `WeightedLeastRequest`: The least request strategy uses an O(1) algorithm which selects two random healthy Endpoints and picks the Endpoint which has fewer active requests. Note: This algorithm is simple and sufficient for load testing. It should not be used where true weighted least request behavior is desired.
   776  - `Random`: The random strategy selects a random healthy Endpoints.
   777  
   778  More information on the load balancing strategy can be found in [Envoy's documentation][7].
   779  
   780  The following example defines the strategy for the route `/` as `WeightedLeastRequest`.
   781  
   782  ```yaml
   783  # httpproxy-lb-strategy.yaml
   784  apiVersion: projectcontour.io/v1
   785  kind: HTTPProxy
   786  metadata:
   787    name: lb-strategy
   788    namespace: default
   789  spec:
   790    virtualhost:
   791      fqdn: strategy.bar.com
   792    routes:
   793      - conditions:
   794        - prefix: /
   795        services:
   796          - name: s1-strategy
   797            port: 80
   798          - name: s2-strategy
   799            port: 80
   800        loadBalancerPolicy:
   801          strategy: WeightedLeastRequest
   802  ```
   803  
   804  #### Session Affinity
   805  
   806  Session affinity, also known as _sticky sessions_, is a load balancing strategy whereby a sequence of requests from a single client are consistently routed to the same application backend.
   807  Contour supports session affinity on a per route basis with `loadBalancerPolicy` `strategy: Cookie`.
   808  
   809  ```yaml
   810  # httpproxy-sticky-sessions.yaml
   811  apiVersion: projectcontour.io/v1
   812  kind: HTTPProxy
   813  metadata:
   814    name: httpbin
   815    namespace: default
   816  spec:
   817    virtualhost:
   818      fqdn: httpbin.davecheney.com
   819    routes:
   820    - services:
   821      - name: httpbin
   822        port: 8080
   823      loadBalancerPolicy:
   824        strategy: Cookie
   825  ```
   826  
   827  ##### Limitations
   828  
   829  Session affinity is based on the premise that the backend servers are robust, do not change ordering, or grow and shrink according to load.
   830  None of these properties are guaranteed by a Kubernetes cluster and will be visible to applications that rely heavily on session affinity.
   831  
   832  Any perturbation in the set of pods backing a service risks redistributing backends around the hash ring.
   833  
   834  #### Per route health checking
   835  
   836  Active health checking can be configured on a per route basis.
   837  Contour supports HTTP health checking and can be configured with various settings to tune the behavior.
   838  
   839  During HTTP health checking Envoy will send an HTTP request to the upstream Endpoints.
   840  It expects a 200 response if the host is healthy.
   841  The upstream host can return 503 if it wants to immediately notify Envoy to no longer forward traffic to it.
   842  It is important to note that these are health checks which Envoy implements and are separate from any other system such as those that exist in Kubernetes.
   843  
   844  ```yaml
   845  # httpproxy-health-checks.yaml
   846  apiVersion: projectcontour.io/v1
   847  kind: HTTPProxy
   848  metadata:
   849    name: health-check
   850    namespace: default
   851  spec:
   852    virtualhost:
   853      fqdn: health.bar.com
   854    routes:
   855    - conditions:
   856      - prefix: /
   857      healthCheckPolicy:
   858        path: /healthy
   859        intervalSeconds: 5
   860        timeoutSeconds: 2
   861        unhealthyThresholdCount: 3
   862        healthyThresholdCount: 5
   863      services:
   864        - name: s1-health
   865          port: 80
   866        - name: s2-health
   867          port: 80
   868  ```
   869  
   870  Health check configuration parameters:
   871  
   872  - `path`: HTTP endpoint used to perform health checks on upstream service (e.g. `/healthz`). It expects a 200 response if the host is healthy. The upstream host can return 503 if it wants to immediately notify downstream hosts to no longer forward traffic to it.
   873  - `host`: The value of the host header in the HTTP health check request. If left empty (default value), the name "contour-envoy-healthcheck" will be used.
   874  - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set.
   875  - `timeoutSeconds`: The time to wait (seconds) for a health check response. If the timeout is reached the health check attempt will be considered a failure. Defaults to 2 seconds if not set.
   876  - `unhealthyThresholdCount`: The number of unhealthy health checks required before a host is marked unhealthy. Note that for http health checking if a host responds with 503 this threshold is ignored and the host is considered unhealthy immediately. Defaults to 3 if not defined.
   877  - `healthyThresholdCount`: The number of healthy health checks required before a host is marked healthy. Note that during startup, only a single successful health check is required to mark a host healthy.
   878  
   879  #### WebSocket Support
   880  
   881  WebSocket support can be enabled on specific routes using the `enableWebsockets` field:
   882  
   883  ```yaml
   884  # httpproxy-websockets.yaml
   885  apiVersion: projectcontour.io/v1
   886  kind: HTTPProxy
   887  metadata:
   888    name: chat
   889    namespace: default
   890  spec:
   891    virtualhost:
   892      fqdn: chat.example.com
   893    routes:
   894      - services:
   895          - name: chat-app
   896            port: 80
   897      - conditions:
   898        - prefix: /websocket
   899        enableWebsockets: true # Setting this to true enables websocket for all paths that match /websocket
   900        services:
   901          - name: chat-app
   902            port: 80
   903  ```
   904  
   905  #### Permit Insecure
   906  
   907  A HTTPProxy can be configured to permit insecure requests to specific Routes.
   908  In this example, any request to `foo2.bar.com/blog` will not receive a 301 redirect to HTTPS, but the `/` route will:
   909  
   910  ```yaml
   911  apiVersion: projectcontour.io/v1
   912  kind: HTTPProxy
   913  metadata:
   914    name: tls-example-insecure
   915    namespace: default
   916  spec:
   917    virtualhost:
   918      fqdn: foo2.bar.com
   919      tls:
   920        secretName: testsecret
   921    routes:
   922      - services:
   923          - name: s1
   924            port: 80
   925      - conditions:
   926        - prefix: /blog
   927        permitInsecure: true
   928        services:
   929          - name: s2
   930            port: 80
   931  ```
   932  
   933  #### Path Rewriting
   934  
   935  HTTPProxy supports rewriting the HTTP request URL path prior to delivering the request to the backend service.
   936  Rewriting is performed after a routing decision has been made, and never changes the request destination.
   937  
   938  The `pathRewritePolicy` field specifies how the path prefix should be rewritten.
   939  The `replacePrefix` rewrite policy specifies a replacement string for a HTTP request path prefix match.
   940  When this field is present, the path prefix that the request matched is replaced by the text specified in the `replacement` field.
   941  If the HTTP request path is longer than the matched prefix, the remainder of the path is unchanged.
   942  
   943  ```yaml
   944  apiVersion: projectcontour.io/v1
   945  kind: HTTPProxy
   946  metadata:
   947    name: rewrite-example
   948    namespace: default
   949  spec:
   950    virtualhost:
   951      fqdn: rewrite.bar.com
   952    routes:
   953    - services:
   954      - name: s1
   955        port: 80
   956      pathRewritePolicy:
   957        replacePrefix:
   958        - replacement: /new/prefix
   959  ```
   960  
   961  The `replacePrefix` field accepts an array of possible replacements.
   962  When more than one `replacePrefix` array element is present, the `prefix` field can be used to disambiguate which replacement to apply.
   963  
   964  If no `prefix` field is present, the replacement is applied to all prefix matches made against the route.
   965  If a `prefix` field is present, the replacement is applied only to routes that have an exactly matching [prefix condition](#prefix-conditions).
   966  Specifying more than one `replacePrefix` entry is mainly useful when a HTTPProxy document is included into multiple parent documents.
   967  
   968  ```yaml
   969  apiVersion: projectcontour.io/v1
   970  kind: HTTPProxy
   971  metadata:
   972    name: rewrite-example
   973    namespace: default
   974  spec:
   975    virtualhost:
   976      fqdn: rewrite.bar.com
   977    routes:
   978    - services:
   979      - name: s1
   980        port: 80
   981      conditions:
   982      - prefix: /v1/api
   983      pathRewritePolicy:
   984        replacePrefix:
   985        - prefix: /v1/api
   986          replacement: /app/api/v1
   987        - prefix: /
   988          replacement: /app
   989  ```
   990  
   991  ### Header Policy
   992  
   993  HTTPProxy supports rewriting HTTP request and response headers.
   994  The `Set` operation sets a HTTP header value, creating it if it doesn't already exist or overwriting it if it does.
   995  The `Remove` operation removes a HTTP header.
   996  The `requestHeadersPolicy` field is used to rewrite headers on a HTTP request, and the `responseHeadersPolicy` is used to rewrite headers on a HTTP response.
   997  These fields can be specified on a route or on a specific service, depending on the rewrite granularity you need.
   998  
   999  
  1000  ```yaml
  1001  apiVersion: projectcontour.io/v1
  1002  kind: HTTPProxy
  1003  metadata:
  1004    name: header-rewrite-example
  1005  spec:
  1006    virtualhost:
  1007      fqdn: header.bar.com
  1008    routes:
  1009    - services:
  1010      - name: s1
  1011        port: 80
  1012      requestHeadersPolicy:
  1013        set:
  1014        - name: Host
  1015          value: external.dev
  1016        remove:
  1017        - Some-Header
  1018        - Some-Other-Header
  1019  ```
  1020  
  1021  ### ExternalName
  1022  
  1023  HTTPProxy supports routing traffic to `ExternalName` service types.
  1024  Contour looks at the `spec.externalName` field of the service and configures the route to use that DNS name instead of utilizing EDS.
  1025  
  1026  There's nothing specific in the HTTPProxy object that needs to be configured other than referencing a service of type `ExternalName`.
  1027  HTTPProxy supports the `requestHeadersPolicy` field to rewrite the `Host` header after first handling a request and before proxying to an upstream service.
  1028  This field can be used to ensure that the forwarded HTTP request contains the hostname that the external resource is expecting.
  1029  
  1030  NOTE: The ports are required to be specified.
  1031  
  1032  ```yaml
  1033  # httpproxy-externalname.yaml
  1034  apiVersion: v1
  1035  kind: Service
  1036  metadata:
  1037    labels:
  1038      run: externaldns
  1039    name: externaldns
  1040    namespace: default
  1041  spec:
  1042    externalName: foo-basic.bar.com
  1043    ports:
  1044    - name: http
  1045      port: 80
  1046      protocol: TCP
  1047      targetPort: 80
  1048    type: ExternalName
  1049  ```
  1050  
  1051  #### Proxy to external resource
  1052  
  1053  To proxy to another resource outside the cluster (e.g. A hosted object store bucket for example), configure that external resource in a service type `externalName`.
  1054  Then define a `requestHeadersPolicy` which replaces the `Host` header with the value of the external name service defined previously.
  1055  Finally, if the upstream service is served over TLS, set the `protocol` field on the service to `tls` or annotate the external name service with: `projectcontour.io/upstream-protocol.tls: 443,https` assuming your service had a port 443 and name `https`.
  1056  
  1057  ## HTTPProxy inclusion
  1058  
  1059  HTTPProxy permits the splitting of a system's configuration into separate HTTPProxy instances using **inclusion**.
  1060  
  1061  Inclusion, as the name implies, allows for one HTTPProxy object to be included in another, optionally with some conditions inherited from the parent.
  1062  Contour reads the inclusion tree and merges the included routes into one big object internally before rendering Envoy config.
  1063  Importantly, the included HTTPProxy objects do not have to be in the same namespace.
  1064  
  1065  Each tree of HTTPProxy starts with a root, the top level object of the configuration for a particular virtual host.
  1066  Each root HTTPProxy defines a `virtualhost` key, which describes properties such as the fully qualified name of the virtual host, TLS configuration, etc.
  1067  
  1068  HTTPProxies included from the root must not contain a virtualhost key.
  1069  Root objects cannot include other roots either transitively or directly.
  1070  This permits the owner of an HTTPProxy root to allow the inclusion of a portion of the route space inside a virtual host, and to allow that route space to be further subdivided with inclusions.
  1071  Because the path is not necessarily used as the only key, the route space can be multi-dimensional.
  1072  
  1073  ### Conditions and Inclusion
  1074  
  1075  Like Routes, Inclusion may specify a set of [conditions][8].
  1076  These conditions are added to any conditions on the routes included.
  1077  This process is recursive.
  1078  
  1079  Conditions are sets of individual condition statements, for example `prefix: /blog` is the condition that the matching request's path must start with `/blog`.
  1080  When conditions are combined through inclusion Contour merges the conditions inherited via inclusion with any conditions specified on the route.
  1081  This may result in duplicates, for example two `prefix:` conditions, or two header match conditions with the same name and value.
  1082  To resolve this Contour applies the following logic.
  1083  
  1084  - `prefix:` conditions are concatenated together in the order they were applied from the root object. For example the conditions, `prefix: /api`, `prefix: /v1` becomes a single `prefix: /api/v1` conditions. Note: Multiple prefixes cannot be supplied on a single set of Route conditions.
  1085  - Proxies with repeated identical `header:` conditions of type "exact match" (the same header keys exactly) are marked as "Invalid" since they create an un-routable configuration.
  1086  
  1087  ### Configuring inclusion
  1088  
  1089  Inclusion is a top-level part of the HTTPProxy `spec` element.
  1090  It requires one field, `name`, and has two optional fields:
  1091  
  1092  - `namespace`. This will assume the included HTTPProxy is in the same namespace if it's not specified.
  1093  - a `conditions` block.
  1094  
  1095  #### Within the same namespace
  1096  
  1097  HTTPProxies can include other HTTPProxy objects in the namespace by specifying the name of the object and its namespace in the top-level `includes` block.
  1098  Note that `includes` is a list, and so it must use the YAML list construct.
  1099  
  1100  In this example, the HTTPProxy `include-root` has included the configuration for paths matching `/service2` from the HTTPProxy named `service2` in the same namespace as `include-root` (the `default` namespace).
  1101  It's important to note that `service2` HTTPProxy has not defined a `virtualhost` property as it is NOT a root HTTPProxy.
  1102  
  1103  ```yaml
  1104  # httpproxy-inclusion-samenamespace.yaml
  1105  apiVersion: projectcontour.io/v1
  1106  kind: HTTPProxy
  1107  metadata:
  1108    name: include-root
  1109    namespace: default
  1110  spec:
  1111    virtualhost:
  1112      fqdn: root.bar.com
  1113    includes:
  1114    # Includes the /service2 path from service2 in the same namespace
  1115    - name: service2
  1116      namespace: default
  1117      conditions:
  1118      - prefix: /service2
  1119    routes:
  1120      - conditions:
  1121        - prefix: /
  1122        services:
  1123          - name: s1
  1124            port: 80
  1125  ---
  1126  apiVersion: projectcontour.io/v1
  1127  kind: HTTPProxy
  1128  metadata:
  1129    name: service2
  1130    namespace: default
  1131  spec:
  1132    routes:
  1133      - services: # matches /service2
  1134          - name: s2
  1135            port: 80
  1136      - conditions:
  1137        - prefix: /blog # matches /service2/blog
  1138        services:
  1139          - name: blog
  1140            port: 80
  1141  ```
  1142  
  1143  #### Virtualhost aliases
  1144  
  1145  To present the same set of routes under multiple dns entries, for example www.example.com and example.com, including a service with a `prefix` condition of `/` can be used.
  1146  
  1147  ```yaml
  1148  # httpproxy-inclusion-multipleroots.yaml
  1149  ---
  1150  apiVersion: projectcontour.io/v1
  1151  kind: HTTPProxy
  1152  metadata:
  1153    name: multiple-root
  1154    namespace: default
  1155  spec:
  1156    virtualhost:
  1157      fqdn: bar.com
  1158    includes:
  1159    - name: main
  1160      namespace: default
  1161  ---
  1162  apiVersion: projectcontour.io/v1
  1163  kind: HTTPProxy
  1164  metadata:
  1165    name: multiple-root-www
  1166    namespace: default
  1167  spec:
  1168    virtualhost:
  1169      fqdn: www.bar.com
  1170    includes:
  1171    - name: main
  1172      namespace: default
  1173  ---
  1174  apiVersion: projectcontour.io/v1
  1175  kind: HTTPProxy
  1176  metadata:
  1177    name: main
  1178    namespace: default
  1179  spec:
  1180    routes:
  1181    - services:
  1182      - name: s2
  1183        port: 80
  1184  ```
  1185  
  1186  #### Across namespaces
  1187  
  1188  Inclusion can also happen across Namespaces by specifying a `namespace` in the `inclusion`.
  1189  This is a particularly powerful paradigm for enabling multi-team Ingress management.
  1190  
  1191  In this example, the root HTTPProxy has included configuration for paths matching `/blog` to the `blog` HTTPProxy object in the `marketing` namespace.
  1192  
  1193  ```yaml
  1194  # httpproxy-inclusion-across-namespaces.yaml
  1195  ---
  1196  apiVersion: projectcontour.io/v1
  1197  kind: HTTPProxy
  1198  metadata:
  1199    name: namespace-include-root
  1200    namespace: default
  1201  spec:
  1202    virtualhost:
  1203      fqdn: ns-root.bar.com
  1204    includes:
  1205    # delegate the subpath, `/blog` to the HTTPProxy object in the marketing namespace with the name `blog`
  1206    - name: blog
  1207      namespace: marketing
  1208      conditions:
  1209      - prefix: /blog
  1210    routes:
  1211      - services:
  1212          - name: s1
  1213            port: 80
  1214  
  1215  ---
  1216  apiVersion: projectcontour.io/v1
  1217  kind: HTTPProxy
  1218  metadata:
  1219    name: blog
  1220    namespace: marketing
  1221  spec:
  1222    routes:
  1223      - services:
  1224          - name: s2
  1225            port: 80
  1226  ```
  1227  
  1228  ### Orphaned HTTPProxy children
  1229  
  1230  It is possible for HTTPProxy objects to exist that have not been delegated to by another HTTPProxy.
  1231  These objects are considered "orphaned" and will be ignored by Contour in determining ingress configuration.
  1232  
  1233  ### Restricted root namespaces
  1234  
  1235  HTTPProxy inclusion allows for Administrators to limit which users/namespaces may configure routes for a given domain, but it does not restrict where root HTTPProxy may be created.
  1236  Contour has an enforcing mode which accepts a list of namespaces where root HTTPProxy are valid.
  1237  Only users permitted to operate in those namespaces can therefore create HTTPProxy with the `virtualhost` field.
  1238  
  1239  This restricted mode is enabled in Contour by specifying a command line flag, `--root-namespaces`, which will restrict Contour to only searching the defined namespaces for root HTTPProxy. This CLI flag accepts a comma separated list of namespaces where HTTPProxy are valid (e.g. `--root-namespaces=default,kube-system,my-admin-namespace`).
  1240  
  1241  HTTPProxy with a defined `virtualhost` field that are not in one of the allowed root namespaces will be flagged as `invalid` and will be ignored by Contour.
  1242  
  1243  Additionally, when defined, Contour will only watch for Kubernetes secrets in these namespaces ignoring changes in all other namespaces.
  1244  Proper RBAC rules should also be created to restrict what namespaces Contour has access matching the namespaces passed to the command line flag.
  1245  An example of this is included in the [examples directory][12] and shows how you might create a namespace called `root-httproxy`.
  1246  
  1247  > **NOTE: The restricted root namespace feature is only supported for HTTPProxy CRDs.
  1248  > `--root-namespaces` does not affect the operation of `v1beta1.Ingress` objects**
  1249  
  1250  ## TCP Proxying
  1251  
  1252  HTTPProxy supports proxying of TLS encapsulated TCP sessions.
  1253  
  1254  _Note_: The TCP session must be encrypted with TLS.
  1255  This is necessary so that Envoy can use SNI to route the incoming request to the correct service.
  1256  
  1257  ### TLS Termination at the edge
  1258  
  1259  If `spec.virtualhost.tls.secretName` is present then that secret will be used to decrypt the TCP traffic at the edge.
  1260  
  1261  ```yaml
  1262  # httpproxy-tls-termination.yaml
  1263  apiVersion: projectcontour.io/v1
  1264  kind: HTTPProxy
  1265  metadata:
  1266    name: example
  1267    namespace: default
  1268  spec:
  1269    virtualhost:
  1270      fqdn: tcp.example.com
  1271      tls:
  1272        secretName: secret
  1273    tcpproxy:
  1274      services:
  1275      - name: tcpservice
  1276        port: 8080
  1277      - name: otherservice
  1278        port: 9999
  1279        weight: 20
  1280  ```
  1281  
  1282  The `spec.tcpproxy` key indicates that this _root_ HTTPProxy will forward the de-encrypted TCP traffic to the backend service.
  1283  
  1284  ### TLS passthrough to the backend service
  1285  
  1286  If you wish to handle the TLS handshake at the backend service set `spec.virtualhost.tls.passthrough: true` indicates that once SNI demuxing is performed, the encrypted connection will be forwarded to the backend service.
  1287  The backend service is expected to have a key which matches the SNI header received at the edge, and be capable of completing the TLS handshake. This is called SSL/TLS Passthrough.
  1288  
  1289  ```yaml
  1290  # httpproxy-tls-passthrough.yaml
  1291  apiVersion: projectcontour.io/v1
  1292  kind: HTTPProxy
  1293  metadata:
  1294    name: example
  1295    namespace: default
  1296  spec:
  1297    virtualhost:
  1298      fqdn: tcp.example.com
  1299      tls:
  1300        passthrough: true
  1301    tcpproxy:
  1302      services:
  1303      - name: tcpservice
  1304        port: 8080
  1305      - name: otherservice
  1306        port: 9999
  1307        weight: 20
  1308  ```
  1309  
  1310  ### TCPProxy delegation
  1311  
  1312  There can be at most one TCPProxy stanza per root HTTPProxy, however that TCPProxy does not need to be defined in the root HTTPProxy object.
  1313  HTTPProxy authors can delegate the configuration of a TCPProxy to the TCPProxy configuration defined in a HTTPProxy child object.
  1314  
  1315  ```yaml
  1316  # httpproxy-parent-termination.yaml
  1317  apiVersion: projectcontour.io/v1
  1318  kind: HTTPProxy
  1319  metadata:
  1320    name: parent
  1321    namespace: default
  1322  spec:
  1323    virtualhost:
  1324      fqdn: tcp.example.com
  1325      tls:
  1326        secretName: secret
  1327    tcpproxy:
  1328      include:
  1329        name: child
  1330        namespace: app
  1331  ---
  1332  # httpproxy-child-termination.yaml
  1333  apiVersion: projectcontour.io/v1
  1334  kind: HTTPProxy
  1335  metadata:
  1336    name: child
  1337    namespace: app
  1338  spec:
  1339    tcpproxy:
  1340      services:
  1341      - name: tcpservice
  1342        port: 8080
  1343      - name: otherservice
  1344        port: 9999
  1345        weight: 20
  1346  ```
  1347  In this example `default/parent` delegates the configuration of the TCPProxy services to `app/child`.
  1348  
  1349  #### TCP Proxy health checking
  1350  
  1351  Active health checking can be configured on a per route basis.
  1352  Contour supports TCP health checking and can be configured with various settings to tune the behavior.
  1353  
  1354  During TCP health checking Envoy will send a connect-only health check to the upstream Endpoints.
  1355  It is important to note that these are health checks which Envoy implements and are separate from any
  1356  other system such as those that exist in Kubernetes.
  1357  
  1358  ```yaml
  1359  apiVersion: projectcontour.io/v1
  1360  kind: HTTPProxy
  1361  metadata:
  1362    name: tcp-health-check
  1363    namespace: default
  1364  spec:
  1365    virtualhost:
  1366      fqdn: health.bar.com
  1367    tcpproxy:
  1368      healthCheckPolicy:
  1369        intervalSeconds: 5
  1370        timeoutSeconds: 2
  1371        unhealthyThresholdCount: 3
  1372        healthyThresholdCount: 5
  1373      services:
  1374        - name: s1-health
  1375          port: 80
  1376        - name: s2-health
  1377          port: 80
  1378  ```
  1379  
  1380  TCP Health check policy configuration parameters:
  1381  
  1382  - `intervalSeconds`: The interval (seconds) between health checks. Defaults to 5 seconds if not set.
  1383  - `timeoutSeconds`: The time to wait (seconds) for a health check response. If the timeout is reached the health check attempt will be considered a failure. Defaults to 2 seconds if not set.
  1384  - `unhealthyThresholdCount`: The number of unhealthy health checks required before a host is marked unhealthy. Note that for http health checking if a host responds with 503 this threshold is ignored and the host is considered unhealthy immediately. Defaults to 3 if not defined.
  1385  - `healthyThresholdCount`: The number of healthy health checks required before a host is marked healthy. Note that during startup, only a single successful health check is required to mark a host healthy.
  1386  
  1387  ## Upstream Validation
  1388  
  1389  When defining upstream services on a route, it's possible to configure the connection from Envoy to the backend endpoint to communicate over TLS.
  1390  Two configuration items are required, a CA certificate and a `SubjectName` which are both used to verify the backend endpoint's identity.
  1391  
  1392  The CA certificate bundle for the backend service should be supplied in a Kubernetes Secret.
  1393  The referenced Secret must be of type "Opaque" and have a data key named `ca.crt`.
  1394  This data value must be a PEM-encoded certificate bundle.
  1395  
  1396  In addition to the CA certificate and the subject name, the Kubernetes service must also be annotated with a Contour specific annotation: `projectcontour.io/upstream-protocol.tls: <port>` ([see annotations section][9])
  1397  
  1398  _Note: This annotation is applied to the Service not the Ingress or HTTPProxy object._
  1399  
  1400  ```yaml
  1401  apiVersion: projectcontour.io/v1
  1402  kind: HTTPProxy
  1403  metadata:
  1404    name: blog
  1405    namespace: marketing
  1406  spec:
  1407    routes:
  1408      - services:
  1409          - name: s2
  1410            port: 80
  1411            validation:
  1412              caSecret: foo-ca-cert
  1413              subjectName: foo.marketing
  1414  ```
  1415  
  1416  ## Client Certificate Validation
  1417  
  1418  It is possible to protect the backend service from unauthorized external clients by requiring the client to present a valid TLS certificate.
  1419  Envoy will validate the client certificate by verifying that it is not expired and that a chain of trust can be established to the configured trusted root CA certificate.
  1420  Only those requests with a valid client certificate will be accepted and forwarded to the backend service.
  1421  
  1422  ```yaml
  1423  apiVersion: projectcontour.io/v1
  1424  kind: HTTPProxy
  1425  metadata:
  1426    name: with-client-auth
  1427  spec:
  1428    virtualhost:
  1429      fqdn: www.example.com
  1430      tls:
  1431        secretName: secret
  1432        clientValidation:
  1433          caSecret: client-root-ca
  1434    routes:
  1435      - services:
  1436          - name: s1
  1437            port: 80
  1438  ```
  1439  
  1440  The preceding example enables validation by setting the optional `clientValidation` attribute.
  1441  Its mandatory attribute `caSecret` contains a name of an existing Kubernetes Secret that must be of type "Opaque" and have a data key named `ca.crt`.
  1442  The data value of the key `ca.crt` must be a PEM-encoded certificate bundle and it must contain all the trusted CA certificates that are to be used for validating the client certificate.
  1443  
  1444  ## Status Reporting
  1445  
  1446  There are many misconfigurations that could cause an HTTPProxy or delegation to be invalid.
  1447  To aid users in resolving these issues, Contour updates a `status` field in all HTTPProxy objects.
  1448  In the current specification, invalid HTTPProxy are ignored by Contour and will not be used in the ingress routing configuration.
  1449  
  1450  If an HTTPProxy object is valid, it will have a status property that looks like this:
  1451  
  1452  ```yaml
  1453  status:
  1454    currentStatus: valid
  1455    description: valid HTTPProxy
  1456  ```
  1457  
  1458  If the HTTPProxy is invalid, the `currentStatus` field will be `invalid` and the `description` field will provide a description of the issue.
  1459  
  1460  As an example, if an HTTPProxy object has specified a negative value for weighting, the HTTPProxy status will be:
  1461  
  1462  ```yaml
  1463  status:
  1464    currentStatus: invalid
  1465    description: "route '/foo': service 'home': weight must be greater than or equal to zero"
  1466  ```
  1467  
  1468  Some examples of invalid configurations that Contour provides statuses for:
  1469  
  1470  - Negative weight provided in the route definition.
  1471  - Invalid port number provided for service.
  1472  - Prefix in parent does not match route in delegated route.
  1473  - Root HTTPProxy created in a namespace other than the allowed root namespaces.
  1474  - A given Route of an HTTPProxy both delegates to another HTTPProxy and has a list of services.
  1475  - Orphaned route.
  1476  - Delegation chain produces a cycle.
  1477  - Root HTTPProxy does not specify fqdn.
  1478  - Multiple prefixes cannot be specified on the same set of route conditions.
  1479  - Multiple header conditions of type "exact match" with the same header key.
  1480  - Contradictory header conditions on a route, e.g. a "contains" and "notcontains" condition for the same header and value.
  1481  
  1482   [1]: https://kubernetes.io/docs/concepts/services-networking/ingress/
  1483   [2]: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md
  1484   [3]: {{< param github_url >}}/tree/{{< param version >}}/examples/example-workload/httpproxy
  1485   [4]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-timeout
  1486   [5]: https://godoc.org/time#ParseDuration
  1487   [6]: https://www.envoyproxy.io/docs/envoy/v1.14.2/api-v2/api/v2/route/route_components.proto#envoy-api-field-route-routeaction-idle-timeout
  1488   [7]: https://www.envoyproxy.io/docs/envoy/v1.14.2/intro/arch_overview/upstream/load_balancing/overview
  1489   [8]: #conditions
  1490   [9]: {% link docs/{{< param version >}}/annotations.md %}
  1491   [10]: /docs/{{< param version >}}/api/#projectcontour.io/v1.Service
  1492   [11]: configuration.md#fallback-certificate
  1493   [12]: {{< param github_url >}}/tree/{{< param version >}}/examples/root-rbac