Mutual TLS Migration

    Istio automatically configures workload sidecars to use mutual TLS when calling other workloads. By default, Istio configures the destination workloads using mode. When PERMISSIVE mode is enabled, a service can accept both plain text and mutual TLS traffic. In order to only allow mutual TLS traffic, the configuration needs to be changed to STRICT mode.

    You can use the to check which workloads are still sending plaintext traffic to the workloads in PERMISSIVE mode and choose to lock them down once the migration is done.

    • Understand Istio authentication policy and related concepts.

    • Read the authentication policy task to learn how to configure authentication policy.

    • Have a Kubernetes cluster with Istio installed, without global mutual TLS enabled (e.g use the demo configuration profile as described in ).

    In this task, you can try out the migration process by creating sample workloads and modifying the policies to enforce STRICT mutual TLS between the workloads.

    Set up the cluster

    • Create two namespaces, foo and bar, and deploy and sleep with sidecars on both of them:

      ZipZip

    • Create another namespace, legacy, and deploy without a sidecar:

      1. $ kubectl create ns legacy
      2. $ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy
    • Verify setup by sending an http request (using curl command) from any sleep pod (among those in namespace foo, bar or legacy) to httpbin.foo. All requests should success with HTTP code 200.

      1. $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
      2. sleep.foo to httpbin.foo: 200
      3. sleep.bar to httpbin.foo: 200
      4. sleep.bar to httpbin.bar: 200
      5. sleep.legacy to httpbin.foo: 200
    • Also verify that there are no authentication policies or destination rules (except control plane ones) in the system:

      1. $ kubectl get peerauthentication --all-namespaces | grep -v istio-system
      2. NAMESPACE NAME AGE

    After migrating all clients to Istio and injecting the Envoy sidecar, you can lock down workloads in the foo namespace to only accept mutual TLS traffic.

    1. $ kubectl apply -n foo -f - <<EOF
    2. apiVersion: "security.istio.io/v1beta1"
    3. kind: "PeerAuthentication"
    4. metadata:
    5. name: "default"
    6. spec:
    7. mtls:
    8. mode: STRICT
    9. EOF

    Now, you should see the request from sleep.legacy to httpbin.foo failing.

    1. sleep.foo to httpbin.foo: 200
    2. sleep.foo to httpbin.bar: 200
    3. sleep.bar to httpbin.foo: 200
    4. sleep.legacy to httpbin.foo: 000
    5. command terminated with exit code 56
    6. sleep.legacy to httpbin.bar: 200

    If you installed Istio with values.global.proxy.privileged=true, you can use tcpdump to verify traffic is encrypted or not.

    1. $ kubectl exec -nfoo "$(kubectl get pod -nfoo -lapp=httpbin -ojsonpath={.items..metadata.name})" -c istio-proxy -it -- sudo tcpdump dst port 80 -A
    2. tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    3. listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

    You will see plain text and encrypted text in the output when requests are sent from sleep.legacy and sleep.foo respectively.

    If you can’t migrate all your services to Istio (i.e., inject Envoy sidecar in all of them), you will need to continue to use PERMISSIVE mode. However, when configured with PERMISSIVE mode, no authentication or authorization checks will be performed for plaintext traffic by default. We recommend you use Istio Authorization to configure different paths with different authorization policies.

    Lock down mutual TLS for the entire mesh

    Now, both the foo and bar namespaces enforce mutual TLS only traffic, so you should see requests from sleep.legacy failing for both.

    1. $ for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:8000/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
    1. To remove all authentication policies
    1. $ kubectl delete peerauthentication --all-namespaces --all
    1. If you are not planning to explore any follow-on tasks, you can remove all test namespaces.
    1. $ kubectl delete ns foo bar legacy

    See also

    Authorization Policy Trust Domain Migration

    Shows how to migrate from one trust domain to another without changing authorization policy.

    Describes Istio’s authorization and authentication functionality.

    Introducing Workload Entries

    Describing the new functionality of Workload Entries.

    A vision statement and roadmap for Istio in 2020.

    Remove cross-pod unix domain sockets