• Mutual TLS over HTTPS
    • Before you begin
      • Generate certificates and configmap
    • Deploy an HTTPS service without the Istio sidecar
      • Create an HTTPS service with the Istio sidecar and mutual TLS disabled
      • Create an HTTPS service with Istio sidecar with mutual TLS enabled
    • Cleanup
    • See also

    Mutual TLS over HTTPS

    This task shows how mutual TLS works with HTTPS services. It includes:

    • Deploying an HTTPS service without Istio sidecar

    • Deploying an HTTPS service with Istio with mutual TLS disabled

    • Deploying an HTTPS service with mutual TLS enabled. For each deployment, connect to this service and verify it works.

    When the Istio sidecar is deployed with an HTTPS service, the proxy automatically downgradesfrom L7 to L4 (no matter mutual TLS is enabled or not), which means it does not terminate theoriginal HTTPS traffic. And this is the reason Istio can work on HTTPS services.

    Before you begin

    Set up Istio by following the instructions in thequick start.Note that default mutual TLS authentication should be disabled when installing Istio using the demo profile.

    The demo is also assumed to be running in a namespace where automatic sidecar injection isdisabled, and Istio sidecars are instead manually injected with istioctl.

    Generate certificates and configmap

    The following examples consider an NGINX service pod which can encrypt traffic using HTTPS.Before beginning, generate the TLS certificate and key that this service will use.

    You need to have openssl installed to run these commands:

    1. $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/nginx.key -out /tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
    2. $ kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
    3. secret "nginxsecret" created

    Create a configmap used for the HTTPS service

    1. $ kubectl create configmap nginxconfigmap --from-file=samples/https/default.conf
    2. configmap "nginxconfigmap" created

    Deploy an HTTPS service without the Istio sidecar

    This section creates a NGINX-based HTTPS service.

    Zip

    1. $ kubectl apply -f @samples/https/nginx-app.yaml@
    2. service "my-nginx" created
    3. replicationcontroller "my-nginx" created

    Then, create another pod to call this service.

    Zip

    1. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)

    Get the pods

    1. $ kubectl get pod
    2. NAME READY STATUS RESTARTS AGE
    3. my-nginx-jwwck 1/1 Running 0 1h
    4. sleep-847544bbfc-d27jg 2/2 Running 0 18h

    Ssh into the istio-proxy container of sleep pod.

    1. $ kubectl exec -it $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy /bin/bash

    Call my-nginx

    1. $ curl https://my-nginx -k
    2. ...
    3. <h1>Welcome to nginx!</h1>
    4. ...

    You can actually combine the above three command into one:

    1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
    2. ...
    3. <h1>Welcome to nginx!</h1>
    4. ...

    Create an HTTPS service with the Istio sidecar and mutual TLS disabled

    In “Before you begin” section, the Istio control plane is deployed with mutual TLSdisabled. So you only need to redeploy the NGINX HTTPS service with sidecar.

    Delete the HTTPS service.

    Zip

    1. $ kubectl delete -f @samples/https/nginx-app.yaml@

    Deploy it with a sidecar

    Zip

    1. $ kubectl apply -f <(istioctl kube-inject -f @samples/https/nginx-app.yaml@)

    Make sure the pod is up and running

    1. $ kubectl get pod
    2. NAME READY STATUS RESTARTS AGE
    3. my-nginx-6svcc 2/2 Running 0 1h
    4. sleep-847544bbfc-d27jg 2/2 Running 0 18h

    And run

    1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl https://my-nginx -k
    2. ...
    3. <h1>Welcome to nginx!</h1>
    4. ...

    If you run from the istio-proxy container, it should work as well:

    1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
    2. ...
    3. <h1>Welcome to nginx!</h1>
    4. ...

    This example is borrowed from Kubernetes examples.

    Create an HTTPS service with Istio sidecar with mutual TLS enabled

    You need to deploy Istio control plane with mutual TLS enabled. If you have the Istiocontrol plane with mutual TLS disabled installed, please delete it. For example, ifyou followed the quick start:

    1. $ istioctl manifest generate --set profile=demo | kubectl delete -f -

    And wait for everything to have been deleted, i.e., there is no pod in the control plane namespace (istio-system):

    1. $ kubectl get pod -n istio-system
    2. No resources found.

    Install Istio with the strict mutual TLS mode enabled:

    1. $ istioctl manifest apply --set profile=demo,values.global.controlPlaneSecurityEnabled=true,values.global.mtls.enabled=true

    Make sure everything is up and running:

    1. $ kubectl get po -n istio-system
    2. NAME READY STATUS RESTARTS AGE
    3. grafana-6f6dff9986-r6xnq 1/1 Running 0 23h
    4. istio-citadel-599f7cbd46-85mtq 1/1 Running 0 1h
    5. istio-cleanup-old-ca-mcq94 0/1 Completed 0 23h
    6. istio-egressgateway-78dd788b6d-jfcq5 1/1 Running 0 23h
    7. istio-ingressgateway-7dd84b68d6-dxf28 1/1 Running 0 23h
    8. istio-mixer-post-install-g8n9d 0/1 Completed 0 23h
    9. istio-pilot-d5bbc5c59-6lws4 2/2 Running 0 23h
    10. istio-policy-64595c6fff-svs6v 2/2 Running 0 23h
    11. istio-sidecar-injector-645c89bc64-h2dnx 1/1 Running 0 23h
    12. istio-statsd-prom-bridge-949999c4c-mv8qt 1/1 Running 0 23h
    13. istio-telemetry-cfb674b6c-rgdhb 2/2 Running 0 23h
    14. istio-tracing-754cdfd695-wqwr4 1/1 Running 0 23h
    15. prometheus-86cb6dd77c-ntw88 1/1 Running 0 23h

    Then redeploy the HTTPS service and sleep service

    ZipZipZipZip

    1. $ kubectl delete -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)
    2. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)
    3. $ kubectl delete -f <(istioctl kube-inject -f @samples/https/nginx-app.yaml@)
    4. $ kubectl apply -f <(istioctl kube-inject -f @samples/https/nginx-app.yaml@)

    Make sure the pod is up and running

    1. $ kubectl get pod
    2. NAME READY STATUS RESTARTS AGE
    3. my-nginx-9dvet 2/2 Running 0 1h
    4. sleep-77f457bfdd-hdknx 2/2 Running 0 18h

    And run

    1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl https://my-nginx -k
    2. ...
    3. <h1>Welcome to nginx!</h1>
    4. ...

    The reason is that for the workflow “sleep -> sleep-proxy -> nginx-proxy -> nginx”,the whole flow is L7 traffic, and there is a L4 mutual TLS encryption between sleep-proxyand nginx-proxy. In this case, everything works fine.

    However, if you run this command from the istio-proxy container, it will not work:

    1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://my-nginx -k
    2. curl: (35) gnutls_handshake() failed: Handshake failed
    3. command terminated with exit code 35

    The reason is that for the workflow “sleep-proxy -> nginx-proxy -> nginx”,nginx-proxy is expected mutual TLS traffic from sleep-proxy. In the command above,sleep-proxy does not provide client cert. As a result, it won’t work. Moreover,even sleep-proxy provides client cert in above command, it won’t work eithersince the traffic will be downgraded to http from nginx-proxy to nginx.

    Cleanup

    ZipZip

    1. $ kubectl delete -f @samples/sleep/sleep.yaml@
    2. $ kubectl delete -f @samples/https/nginx-app.yaml@
    3. $ kubectl delete configmap nginxconfigmap
    4. $ kubectl delete secret nginxsecret

    See also

    Mutual TLS Deep-Dive

    Shows you how to verify and test Istio's automatic mutual TLS authentication.

    DNS Certificate Management

    Provision and manage DNS certificates in Istio.

    Introducing the Istio v1beta1 Authorization Policy

    Introduction, motivation and design principles for the Istio v1beta1 Authorization Policy.

    Secure Webhook Management

    A more secure way to manage Istio webhooks.

    Istio as a Proxy for External Services

    Configure Istio ingress gateway to act as a proxy for external services.

    Multi-Mesh Deployments for Isolation and Boundary Protection

    Deploy environments that require isolation into separate meshes and enable inter-mesh communication by mesh federation.