From 691725ba23113394140ae6c1bd1e3f9dbb6918ee Mon Sep 17 00:00:00 2001 From: Frank Budinsky Date: Wed, 21 Oct 2020 18:20:51 -0400 Subject: [PATCH] Understanding TLS configuration doc (#8330) * Understanding TLS configuration doc * make gen * address lint and review comments * Update content/en/faq/traffic-management/difference-between-mutual-and-istio-mutual.md --- .spelling | 1 + DOC_OWNERS.md | 5 +- .../common-problems/network-issues/index.md | 254 +++++++++++++++++- .../tls-configuration/gateway-connections.svg | 1 + .../tls-configuration/index.md | 167 ++++++++++++ .../tls-configuration/sidecar-connections.svg | 1 + ...ference-between-mutual-and-istio-mutual.md | 9 + 7 files changed, 427 insertions(+), 11 deletions(-) create mode 100644 content/en/docs/ops/configuration/traffic-management/tls-configuration/gateway-connections.svg create mode 100644 content/en/docs/ops/configuration/traffic-management/tls-configuration/index.md create mode 100644 content/en/docs/ops/configuration/traffic-management/tls-configuration/sidecar-connections.svg create mode 100644 content/en/faq/traffic-management/difference-between-mutual-and-istio-mutual.md diff --git a/.spelling b/.spelling index bafb1f1ce0..b32edf5688 100644 --- a/.spelling +++ b/.spelling @@ -239,6 +239,7 @@ DNS docker-compose's docker.io dogfood +double-tls Drucker Duggirala e.g. diff --git a/DOC_OWNERS.md b/DOC_OWNERS.md index 92d9bfa1e0..e18a3cc40e 100644 --- a/DOC_OWNERS.md +++ b/DOC_OWNERS.md @@ -1,7 +1,7 @@ # Istio.io Document Owners -There are 145 owned istio.io docs. +There are 146 owned istio.io docs. ## istio/wg-docs-maintainers: 15 docs @@ -61,7 +61,7 @@ There are 145 owned istio.io docs. - [docs/setup/platform-setup/openshift/index.md](https://preliminary.istio.io/latest/docs/setup/platform-setup/openshift) - [docs/setup/upgrade/index.md](https://preliminary.istio.io/latest/docs/setup/upgrade) -## istio/wg-networking-maintainers: 24 docs +## istio/wg-networking-maintainers: 25 docs - [docs/concepts/traffic-management/index.md](https://preliminary.istio.io/latest/docs/concepts/traffic-management) - [docs/ops/best-practices/traffic-management/index.md](https://preliminary.istio.io/latest/docs/ops/best-practices/traffic-management) @@ -69,6 +69,7 @@ There are 145 owned istio.io docs. - [docs/ops/configuration/traffic-management/locality-load-balancing/index.md](https://preliminary.istio.io/latest/docs/ops/configuration/traffic-management/locality-load-balancing) - [docs/ops/configuration/traffic-management/network-topologies/index.md](https://preliminary.istio.io/latest/docs/ops/configuration/traffic-management/network-topologies) - [docs/ops/configuration/traffic-management/protocol-selection/index.md](https://preliminary.istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection) +- [docs/ops/configuration/traffic-management/tls-configuration/index.md](https://preliminary.istio.io/latest/docs/ops/configuration/traffic-management/tls-configuration) - [docs/tasks/traffic-management/circuit-breaking/index.md](https://preliminary.istio.io/latest/docs/tasks/traffic-management/circuit-breaking) - [docs/tasks/traffic-management/egress/egress-control/index.md](https://preliminary.istio.io/latest/docs/tasks/traffic-management/egress/egress-control) - [docs/tasks/traffic-management/egress/egress-gateway-tls-origination/index.md](https://preliminary.istio.io/latest/docs/tasks/traffic-management/egress/egress-gateway-tls-origination) diff --git a/content/en/docs/ops/common-problems/network-issues/index.md b/content/en/docs/ops/common-problems/network-issues/index.md index cd1e01fa5b..e94f167878 100644 --- a/content/en/docs/ops/common-problems/network-issues/index.md +++ b/content/en/docs/ops/common-problems/network-issues/index.md @@ -95,7 +95,7 @@ Let's assume you are using an ingress `Gateway` and corresponding `VirtualServic For example, your `VirtualService` looks something like this: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: myapp @@ -118,7 +118,7 @@ spec: You also have a `VirtualService` which routes traffic for the helloworld service to a particular subset: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: helloworld @@ -143,7 +143,7 @@ helloworld `VirtualService` which directs traffic exclusively to subset v1. To control the traffic from the gateway, you need to also include the subset rule in the myapp `VirtualService`: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: myapp @@ -167,7 +167,7 @@ spec: Alternatively, you can combine both `VirtualServices` into one unit if possible: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: myapp @@ -233,7 +233,243 @@ server { } {{< /text >}} -## 404 errors occur when multiple gateways configured with same TLS certificate +## TLS configuration mistakes + +Many traffic management problems +are caused by incorrect [TLS configuration](/docs/ops/configuration/traffic-management/tls-configuration/). +The following sections describe some of the most common misconfigurations. + +### Sending HTTPS to an HTTP port + +If your application sends an HTTPS request to a service declared to be HTTP, +the Envoy sidecar will attempt to parse the request as HTTP while forwarding the request, +which will fail because the HTTP is unexpectedly encrypted. + +{{< text yaml >}} +apiVersion: networking.istio.io/v1beta1 +kind: ServiceEntry +metadata: + name: httpbin +spec: + hosts: + - httpbin.org + ports: + - number: 443 + name: http + protocol: HTTP + resolution: DNS +{{< /text >}} + +Although the above configuration may be correct if you are intentionally sending plaintext on port 443 (e.g., `curl http://httpbin.org:443`), +generally port 443 is dedicated for HTTPS traffic. + +Sending an HTTPS request like `curl https://httpbin.org`, which defaults to port 443, will result in an error like +`curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number`. +The access logs may also show an error like `400 DPE`. + +To fix this, you should change the port protocol to HTTPS: + +{{< text yaml >}} +spec: + ports: + - number: 443 + name: https + protocol: HTTPS +{{< /text >}} + +### Gateway to virtual service TLS mismatch {#gateway-mismatch} + +There are two common TLS mismatches that can occur when binding a virtual service to a gateway. + +1. The gateway terminates TLS while the virtual service configures TLS routing. +1. The gateway does TLS passthrough while the virtual service configures HTTP routing. + +#### Gateway with TLS termination + +{{< text yaml >}} +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: gateway + namespace: istio-system +spec: + selector: + istio: ingressgateway + servers: + - port: + number: 443 + name: https + protocol: HTTPS + hosts: + - "*" + tls: + mode: SIMPLE + credentialName: sds-credential +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: httpbin +spec: + hosts: + - "*.example.com" + gateways: + - istio-system/gateway + tls: + - match: + - sniHosts: + - "*.example.com" + route: + - destination: + host: httpbin.org +{{< /text >}} + +In this example, the gateway is terminating TLS while the virtual service is using TLS based routing. +The TLS route rules will have no effect since the TLS is already terminated when the route rules are evaluated. + +With this misconfiguration, you will end up getting 404 responses because the requests will be +sent to HTTP routing but there are no HTTP routes configured. +You can confirm this using the `istioctl proxy-config routes` command. + +To fix this problem, you should switch the virtual service to specify `http` routing, instead of `tls`: + +{{< text yaml >}} +spec: + ... + http: + - match: ... +{{< /text >}} + +#### Gateway with TLS passthrough + +{{< text yaml >}} +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: gateway +spec: + selector: + istio: ingressgateway + servers: + - hosts: + - "*" + port: + name: https + number: 443 + protocol: HTTPS + tls: + mode: PASSTHROUGH +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: virtual-service +spec: + gateways: + - gateway + hosts: + - httpbin.example.com + http: + - route: + - destination: + host: httpbin.org +{{< /text >}} + +In this configuration, the virtual service is attempting to match HTTP traffic against TLS traffic passed through the gateway. +This will result in the virtual service configuration having no effect. You can observe that the HTTP route is not applied using +the `istioctl proxy-config listener` and `istioctl proxy-config route` commands. + +To fix this, you should switch the virtual service to configure `tls` routing: + +{{< text yaml >}} +spec: + tls: + - match: + - sniHosts: ["httpbin.example.com"] + route: + - destination: + host: httpbin.org +{{< /text >}} + +Alternatively, you could terminate TLS, rather than passing it through, by switching the `tls` configuration in the gateway: + +{{< text yaml >}} +spec: + ... + tls: + credentialName: sds-credential + mode: SIMPLE +{{< /text >}} + +### Double TLS (TLS origination for a TLS request) {#double-tls} + +When configuring Istio to perform {{< gloss >}}TLS origination{{< /gloss >}}, you need to make sure +that the application sends plaintext requests to the sidecar, which will then originate the TLS. + +The following `DestinationRule` originates TLS for requests to the `httpbin.org` service, +but the corresponding `ServiceEntry` defines the protocol as HTTPS on port 443. + +{{< text yaml >}} +apiVersion: networking.istio.io/v1beta1 +kind: ServiceEntry +metadata: + name: httpbin +spec: + hosts: + - httpbin.org + ports: + - number: 443 + name: https + protocol: HTTPS + resolution: DNS +--- +apiVersion: networking.istio.io/v1beta1 +kind: DestinationRule +metadata: + name: originate-tls +spec: + host: httpbin.org + trafficPolicy: + tls: + mode: SIMPLE +{{< /text >}} + +With this configuration, the sidecar expects the application to send TLS traffic on port 443 +(e.g., `curl https://httpbin.org`), but it will also perform TLS origination before forwarding requests. +This will cause the requests to be double encrypted. + +For example, sending a request like `curl https://httpbin.org` will result in an error: +`(35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number`. + +You can fix this example by changing the port protocol in the `ServiceEntry` to HTTP: + +{{< text yaml >}} +spec: + hosts: + - httpbin.org + ports: + - number: 443 + name: http + protocol: HTTP +{{< /text >}} + +Note that with this configuration your application will need to send plaintext requests to port 433, +like `curl http://httpbin.org:443`, because TLS origination does not change the port. +However, starting in Istio 1.8, you can expose HTTP port 80 to the application (e.g., `curl http://httpbin.org`) +and then redirect requests to `targetPort` 443 for the TLS origination: + +{{< text yaml >}} +spec: + hosts: + - httpbin.org + ports: + - number: 80 + name: http + protocol: HTTP + targetPort: 443 +{{< /text >}} + +### 404 errors occur when multiple gateways configured with same TLS certificate Configuring more than one gateway using the same TLS certificate will cause browsers that leverage [HTTP/2 connection reuse](https://httpwg.org/specs/rfc7540.html#reuse) @@ -261,7 +497,7 @@ Then, simply bind both `VirtualServices` to it like this: - `VirtualService` configuration `vs1` with host `service1.test.com` and gateway `gw` - `VirtualService` configuration `vs2` with host `service2.test.com` and gateway `gw` -## Port conflict when configuring multiple TLS hosts in a gateway +### Port conflict when configuring multiple TLS hosts in a gateway If you apply a `Gateway` configuration that has the same `selector` labels as another existing `Gateway`, then if they both expose the same HTTPS port you must ensure that they have @@ -269,7 +505,7 @@ unique port names. Otherwise, the configuration will be applied without an immed but it will be ignored in the runtime gateway configuration. For example: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: mygateway @@ -288,7 +524,7 @@ spec: hosts: - "myhost.com" --- -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: mygateway2 @@ -327,7 +563,7 @@ To avoid this problem, ensure that multiple uses of the same `protocol: HTTPS` p For example, change the second one to `https2`: {{< text yaml >}} -apiVersion: networking.istio.io/v1alpha3 +apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: mygateway2 diff --git a/content/en/docs/ops/configuration/traffic-management/tls-configuration/gateway-connections.svg b/content/en/docs/ops/configuration/traffic-management/tls-configuration/gateway-connections.svg new file mode 100644 index 0000000000..bf7562a2a6 --- /dev/null +++ b/content/en/docs/ops/configuration/traffic-management/tls-configuration/gateway-connections.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/en/docs/ops/configuration/traffic-management/tls-configuration/index.md b/content/en/docs/ops/configuration/traffic-management/tls-configuration/index.md new file mode 100644 index 0000000000..7d5655f636 --- /dev/null +++ b/content/en/docs/ops/configuration/traffic-management/tls-configuration/index.md @@ -0,0 +1,167 @@ +--- +title: Understanding TLS Configuration +linktitle: TLS Configuration +description: How to configure TLS settings to secure network traffic. +weight: 30 +keywords: [traffic-management,proxy] +owner: istio/wg-networking-maintainers +test: n/a +--- + +One of Istio's most important features is the ability to lock down and secure network traffic to, from, +and within the mesh. However, configuring TLS settings can be confusing and a common source of misconfiguration. +This document attempts to explain the various connections involved when sending requests in Istio and how +their associated TLS settings are configured. +Refer to [TLS configuration mistakes](/docs/ops/common-problems/network-issues/#tls-configuration-mistakes) +for a summary of some the most common TSL configuration problems. + +## Sidecars + +Sidecar traffic has a variety of associated connections. Let's break them down one at a time. + +{{< image width="100%" + link="sidecar-connections.svg" + alt="Sidecar proxy network connections" + title="Sidecar connections" + caption="Sidecar proxy network connections" + >}} + +1. **External inbound traffic** + This is traffic coming from an outside client that is captured by the sidecar. + If the client is inside the mesh, this traffic may be encrypted with Istio mutual TLS. + By default, the sidecar will be configured to accept both mTLS and non-mTLS traffic, known as `PERMISSIVE` mode. + The mode can alternatively be configured to `STRICT`, where traffic must be mTLS, or `DISABLE`, where traffic must be plaintext. + The mTLS mode is configured using a [`PeerAuthentication` resource](/docs/reference/config/security/peer_authentication/). + +1. **Local inbound traffic** + This is traffic going to your application service, from the sidecar. This traffic will always be forwarded as-is. + Note that this does not mean it's always plaintext; the sidecar may pass a TLS connection through. + It just means that a new TLS connection will never be originated from the sidecar. + +1. **Local outbound traffic** + This is outgoing traffic from your application service that is intercepted by the sidecar. + Your application may be sending plaintext or TLS traffic. + If [automatic protocol selection](/docs/ops/configuration/traffic-management/protocol-selection/#automatic-protocol-selection) + is enabled, Istio will automatically detect the protocol. Otherwise you should use the port name in the destination service to + [manually specify the protocol](/docs/ops/configuration/traffic-management/protocol-selection/#explicit-protocol-selection). + +1. **External outbound traffic** + This is traffic leaving the sidecar to some external destination. Traffic can be forwarded as is, or a TLS connection can + be initiated (mTLS or standard TLS). This is controlled using the TLS mode setting in the `trafficPolicy` of a + [`DestinationRule` resource](/docs/reference/config/networking/destination-rule/). + A mode setting of `DISABLE` will send plaintext, while `SIMPLE`, `MUTUAL`, and `ISTIO_MUTUAL` will originate a TLS connection. + +The key takeaways are: + +- `PeerAuthentication` is used to configure what type of mTLS traffic the sidecar will accept. +- `DestinationRule` is used to configure what type of TLS traffic the sidecar will send. +- Port names, or automatic protocol selection, determines which protocol the sidecar will parse traffic as. + +## Auto mTLS + +As described above, a `DestinationRule` controls whether outgoing traffic uses mTLS or not. +However, configuring this for every workload can be tedious. Typically, you want Istio to always use mTLS +wherever possible, and only send plaintext to workloads that are not part of the mesh (i.e., ones without sidecars). + +Istio makes this easy with a feature called "Auto mTLS". Auto mTLS works by doing exactly that. If TLS settings are +not explicitly configured in a `DestinationRule`, the sidecar will automatically determine if +[Istio mutual TLS](/faq/traffic-management/#difference-between-mutual-and-istio-mutual) should be sent. +This means that without any configuration, all inter-mesh traffic will be mTLS encrypted. + +## Gateways + +Any given request to a gateway will have two connections. + +{{< image width="100%" + link="gateway-connections.svg" + alt="Gateway network connections" + title="Gateway connections" + caption="Gateway network connections" + >}} + +1. The inbound request, initiated by some client such as `curl` or a web browser. This is often called the "downstream" connection. + +1. The outbound request, initiated by the gateway to some backend. This is often called the "upstream" connection. + +Both of these connections have independent TLS configurations. + +Note that the configuration of ingress and egress gateways are identical. +The `istio-ingress-gateway` and `istio-egress-gateway` are just two specialized gateway deployments. +The difference is that the client of an ingress gateway is running outside of the mesh while in the case of an egress gateway, +the destination is outside of the mesh. + +### Inbound + +As part of the inbound request, the gateway must decode the traffic in order to apply routing rules. +This is done based on the server configuration in a [`Gateway` resource](/docs/reference/config/networking/gateway/). +For example, if an inbound connection is plaintext HTTP, the port protocol is configured as `HTTP`: + +{{< text yaml >}} +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +... + servers: + - port: + number: 80 + name: http + protocol: HTTP +{{< /text >}} + +Similarly, for raw TCP traffic, the protocol would be set to `TCP`. + +For TLS connections, there are a few more options: + +1. What protocol is encapsulated? + If the connection is HTTPS, the server protocol should be configured as `HTTPS`. + Otherwise, for a raw TCP connection encapsulated with TLS, the protocol should be set to `TLS`. + +1. Is the TLS connection terminated or passed through? + For passthrough traffic, configure the TLS mode field to `PASSTHROUGH`: + + {{< text yaml >}} + apiVersion: networking.istio.io/v1beta1 + kind: Gateway + ... + servers: + - port: + number: 443 + name: https + protocol: HTTPS + tls: + mode: PASSTHROUGH + {{< /text >}} + + In this mode, Istio will route based on SNI information and forward the connection as-is to the destination. + +1. Should mutual TLS be used? + Mutual TLS can be configured through the TLS mode `MUTUAL`. When this is configured, a client certificate will be + requested and verified against the configured `caCertificates` or `credentialName`: + + {{< text yaml >}} + apiVersion: networking.istio.io/v1beta1 + kind: Gateway + ... + servers: + - port: + number: 443 + name: https + protocol: HTTPS + tls: + mode: MUTUAL + caCertificates: ... + {{< /text >}} + +### Outbound + +While the inbound side configures what type of traffic to expect and how to process it, the outbound configuration controls +what type of traffic the gateway will send. This is configured by the TLS settings in a `DestinationRule`, +just like external outbound traffic from [sidecars](#sidecars), or [auto mTLS](#auto-mtls) by default. + +The only difference is that you should be careful to consider the `Gateway` settings when configuring this. +For example, if the `Gateway` is configured with TLS `PASSTHROUGH` while the `DestinationRule` configures TLS origination, +you will end up with [double encryption](/docs/ops/common-problems/network-issues/#double-tls). +This works, but is often not the desired behavior. + +A `VirtualService` bound to the gateway needs care as well to +[ensure it is consistent](/docs/ops/common-problems/network-issues/#gateway-mismatch) +with the `Gateway` definition. diff --git a/content/en/docs/ops/configuration/traffic-management/tls-configuration/sidecar-connections.svg b/content/en/docs/ops/configuration/traffic-management/tls-configuration/sidecar-connections.svg new file mode 100644 index 0000000000..74d252d3f0 --- /dev/null +++ b/content/en/docs/ops/configuration/traffic-management/tls-configuration/sidecar-connections.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/content/en/faq/traffic-management/difference-between-mutual-and-istio-mutual.md b/content/en/faq/traffic-management/difference-between-mutual-and-istio-mutual.md new file mode 100644 index 0000000000..f3a310ea61 --- /dev/null +++ b/content/en/faq/traffic-management/difference-between-mutual-and-istio-mutual.md @@ -0,0 +1,9 @@ +--- +title: What is the difference between MUTUAL and ISTIO_MUTUAL TLS modes? +weight: 30 +--- + +Both of these `DestinationRule` settings will send mutual TLS traffic. +With `ISTIO_MUTUAL`, Istio certificates will automatically be used. +For `MUTUAL`, the key, certificate, and trusted CA must be configured. +This allows initiating mutual TLS with non-Istio applications.