Egress TLS Origination

    Consider a legacy application that performs HTTP calls to external sites. Suppose the organization that operates the application receives a new requirement which states that all the external traffic must be encrypted. With Istio, this requirement can be achieved just by configuration, without changing any code in the application. The application can send unencrypted HTTP requests and Istio will then encrypt them for the application.

    Another benefit of sending unencrypted HTTP requests from the source, and letting Istio perform the TLS upgrade, is that Istio can produce better telemetry and provide more routing control for requests that are not encrypted.

    Before you begin

    • Setup Istio by following the instructions in the .

    • Start the sleep sample which will be used as a test source for external calls.

      If you have enabled , deploy the sleep application:

      Zip

      Otherwise, you have to manually inject the sidecar before deploying the sleep application:

      1. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)
    • Create a shell variable to hold the name of the source pod for sending requests to external services. If you used the sleep sample, run:

      1. $ export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})

    First start by configuring access to an external service, edition.cnn.com, using the same technique shown in the task. This time, however, use a single ServiceEntry to enable both HTTP and HTTPS access to the service.

    1. Create a ServiceEntry to enable access to edition.cnn.com:

    2. Make a request to the external HTTP service:

      1. $ kubectl exec "${SOURCE_POD}" -c sleep -- curl -sSL -o /dev/null -D - http://edition.cnn.com/politics
      2. HTTP/1.1 301 Moved Permanently
      3. ...
      4. location: https://edition.cnn.com/politics
      5. ...
      6. HTTP/2 200

      The output should be similar to the above (some details replaced by ellipsis).

    Notice the -L flag of curl which instructs curl to follow redirects. In this case, the server returned a redirect response (301 Moved Permanently) for the HTTP request to http://edition.cnn.com/politics. The redirect response instructs the client to send an additional request, this time using HTTPS, to https://edition.cnn.com/politics. For the second request, the server returned the requested content and a 200 OK status code.

    Although the curl command handled the redirection transparently, there are two issues here. The first issue is the redundant request, which doubles the latency of fetching the content of http://edition.cnn.com/politics. The second issue is that the path of the URL, politics in this case, is sent in clear text. If there is an attacker who sniffs the communication between your application and , the attacker would know which specific topics of edition.cnn.com the application fetched. For privacy reasons, you might want to prevent such disclosure.

    Both of these issues can be resolved by configuring Istio to perform TLS origination.

    TLS origination for egress traffic

      1. $ kubectl apply -f - <<EOF
      2. apiVersion: networking.istio.io/v1alpha3
      3. kind: ServiceEntry
      4. metadata:
      5. name: edition-cnn-com
      6. spec:
      7. hosts:
      8. - edition.cnn.com
      9. ports:
      10. - number: 80
      11. name: http-port
      12. protocol: HTTP
      13. targetPort: 443
      14. - number: 443
      15. name: https-port
      16. protocol: HTTPS
      17. resolution: DNS
      18. ---
      19. apiVersion: networking.istio.io/v1alpha3
      20. metadata:
      21. name: edition-cnn-com
      22. spec:
      23. host: edition.cnn.com
      24. trafficPolicy:
      25. portLevelSettings:
      26. - port:
      27. number: 80
      28. tls:
      29. mode: SIMPLE # initiates HTTPS when accessing edition.cnn.com
      30. EOF

      The above DestinationRule will perform TLS origination for HTTP requests on port 80 and the ServiceEntry will then redirect the requests on port 80 to target port 443.

    1. Send an HTTP request to http://edition.cnn.com/politics, as in the previous section:

      This time you receive 200 OK as the first and the only response. Istio performed TLS origination for curl so the original HTTP request was forwarded to edition.cnn.com as HTTPS. The server returned the content directly, without the need for redirection. You eliminated the double round trip between the client and the server, and the request left the mesh encrypted, without disclosing the fact that your application fetched the politics section of edition.cnn.com.

      Note that you used the same command as in the previous section. For applications that access external services programmatically, the code does not need to be changed. You get the benefits of TLS origination by configuring Istio, without changing a line of code.

    2. Note that the applications that used HTTPS to access the external service continue to work as before:

      1. $ kubectl exec "${SOURCE_POD}" -c sleep -- curl -sSL -o /dev/null -D - https://edition.cnn.com/politics
      2. HTTP/2 200
      3. ...

    Because the traffic between the application pod and the sidecar proxy on the local host is still unencrypted, an attacker that is able to penetrate the node of your application would still be able to see the unencrypted communication on the local network of the node. In some environments a strict security requirement might state that all the traffic must be encrypted, even on the local network of the nodes. With such a strict requirement, applications should use HTTPS (TLS) only. The TLS origination described in this example would not be sufficient.

    Also note that even with HTTPS originated by the application, an attacker could know that requests to edition.cnn.com are being sent by inspecting . The SNI field is sent unencrypted during the TLS handshake. Using HTTPS prevents the attackers from knowing specific topics and articles but does not prevent an attackers from learning that edition.cnn.com is accessed.

    Cleanup

    1. Remove the Istio configuration items you created:

      1. $ kubectl delete serviceentry edition-cnn-com
    2. Zip