Skip to content

TLS configuration example

In previous module we deployed an HTTP application, now it will get upgraded to a secure hosted application. Let's imagine that helloworld-v1 didn't handle any sensitive data, but helloworld-v2 requires customers to provide they personal information and if intercepted - the damage by malicious actors can be done.

Alt text

in this exercise we will demonstrate how an application can be upgraded for plain HTTP to TLS encrypted HTTPS connection. The steps will include:

  • creation of HTTPS certificate and key and storing them as Kubernetes secret
  • modification of existing Istio VS (virtual service) and GW (gateway) objects
  • running curl tests to demonstrate the behavior

More to learn and explore

Istio introduces a lot of different ways of the certificate usage. mTLS protection of the data is a use-case where Istio has a lot to offer. mTLS is covered in many blog articles that are listed on resources page. In this exercise we're focusing on HTTPS, standard industry approach of certificate protected websites that is applicable for both Istio and traditional workloads.

The prepared certificates can be downloaded from here This is self signed certs, that might expire, we also included a script

Creating secret

For this step you have 3 choices:

OR

  • download and extract the tarball archive, make sure your Kubernetes context is in the right cluster, create the secret with kubectl command:

    tar -xvf certs.tar 
    kubectl create secret -n tid-ingress-ns tls demo-credentials --cert=certs/tls-demo.crt --key=certs/tls-demo.key
    

OR

  • use the script provided to create your own certificate (we would use it in case the pre-generated certificates are expired):

    ./gen-cert.sh tls-demo helloworld.tetrate.io certs
    kubectl create secret -n tid-ingress-ns tls demo-credentials --cert=certs/tls-demo.crt --key=certs/tls-demo.key
    

Modifying Existing Istio Manifests

First we'll add the https section to tid-helloworld gateway object that previously created.

The following is added - secure port, hostname (note that helloworld.tetrate.io will match the FQDN created in previous step) and credentials section that is referring to kubernetes secret demo-credentials, which is also created in the previous step.

Below is the newly added section to the existing tid-helloworld gateway (the full yaml is available for your consumption):

  - port:                   # mtls block starts here
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - helloworld.tetrate.io
    tls:
      mode: SIMPLE
      credentialName: demo-credentials

We will modify virtual service the way that the queries to the plain http calls will go to v1 (green) of helloworld application while https calls will land on v2 (blue) of helloworld. Below is the modified spec portion of the virtual service, while full one is downloadable from here:

spec:
    gateways:
      - tid-helloworld
    hosts:
      - helloworld.tetrate.io
    http: # the routes are simplified comparing to the previous exercise 
      - match:
        - port: 80
        route: # plain http requests will go to v1 (green) helloworld
          - destination:
              host: helloworld.green.svc.cluster.local
      - match: # this part is added for HTTPS
        - port: 443
        route: # encrypted https requests will go to v2 (blue) helloworld
        - destination:
            host: helloworld.blue.svc.cluster.local

Confirming the traffic is distributed

Step 1 Obtain the public FQDN of AWS LoadBalancer and assign to a variable

ADDR=$(kubectl -n tid-ingress-ns get service tid-ingressgateway -o=jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")

validation will be helpful

$ > echo $ADDR
ab675fa5d43a848c2a18febda16b1073-872879832.ap-northeast-2.elb.amazonaws.com

Step 2A All requests to HTTP helloworld.tetrate.io server are expected to be going to v1 microservice:

for i in {1..5}; \
  do \
    curl $ADDR/hello -H "Host: helloworld.tetrate.io"; \
    curl $ADDR/hello -H "Host: helloworld.tetrate.io" -H "blue-version: on"; \
  done

in response you should only see v1:

Alt text

Step 2B All requests to HTTPS helloworld.tetrate.io server are expected to be going to v2 microservice:

for i in {1..5}; \
  do \
    curl -k --connect-to helloworld.tetrate.io:443:${ADDR} https://helloworld.tetrate.io/hello; \
    curl -k --connect-to helloworld.tetrate.io:443:${ADDR} https://helloworld.tetrate.io/hello -H "blue-version: on"; \
  done

NOTES:

  • flag -k is used to tell curl that we're calling the site with self-signed certificate and identity validation will not be checked. You can extend command and use --cacert flag instead:

    curl --connect-to helloworld.tetrate.io:443:${ADDR} https://helloworld.tetrate.io/hello --cacert /tmp/certs/tls-demo-ca.crt 
    
  • we also use --connect-to instead of header from previous exercise - it allows resolution to be happen before traffic reaches the HTTPS server. If FQDN is not resolved before - server will not be able to deterministically say what host is being called and what is the matching certificate for this server

in response you should only see v2:

Alt text

In this exercise we've demonstrated how traffic can be directed to the the endpoint that presents verifiable TLS certificate.

the video is also available

The last exercise is optional and will allow us to demonstrate how another type of AWS LB can be configured.