
Enforcing TLS within your service mesh – Implementing Traffic Management, Security, and Observability with Istio-1
As we know by now, by default, Istio provides TLS encryption for communication between workloads that have sidecar proxies injected. However, it’s important to note that this default setting operates in compatibility mode. In this mode, traffic between two services with sidecar proxies injected is encrypted. However, workloads without sidecar proxies can still communicate with backend microservices over plaintext HTTP. This design choice is made to simplify the adoption of Istio, as teams newly introducing Istio don’t need to immediately address the issue of making all source traffic TLS-enabled.
Let’s create and get a shell to a pod in the default namespace. The backend traffic will be plaintext because the namespace does not have automatic sidecar injection. We will then curl the frontend microservice from there and see whether we get a response. Run the following command to do so:
$ kubectl run -it –rm –image=curlimages/curl curly — curl -v http://frontend.blog-app
- Trying 10.71.246.145:80…
- Connected to frontend (10.71.246.145) port 80 > GET / HTTP/1.1
Host: frontend
User-Agent: curl/8.4.0
Accept: /
< HTTP/1.1 200 OK < server: envoy < date: Sat, 21 Oct 2023 07:19:18 GMT < content-type: text/html; charset=utf-8 < content-length: 5950 < x-envoy-upstream-service-time: 32
…
As we can see, we get an HTTP 200 response back.
This approach balances security and compatibility, allowing a gradual transition to a fully encrypted communication model. Over time, as more services have sidecar proxies injected, the overall security posture of the microservices application improves. However, as we are starting fresh, enforcing strict TLS for our Blog App would make sense. So, let’s do that.
To enable strict TLS on a workload, namespace, or the entire cluster, Istio provides peer authentication policies using the PeerAuthentication resource. As we only need to implement strict TLS on the Blog App, enabling it at the namespace level would make sense. To do that, we will use the following PeerAuthentication resource:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: blog-app
spec:
mtls:
mode: STRICT
Now, let’s apply this using the following commands:
$ cp ~/modern-devops/ch15/security/strict-mtls.yaml \ ~/mdo-environments/manifests/blog-app/
$ git add –all
$ git commit -m “Enable strict TLS”
$ git push
Argo CD should pick up the new configuration and apply the strict TLS policy as soon as we push the changes. Wait for the Argo CD sync to be in a clean state, and run the following commands to check whether strict TLS is working:
$ kubectl run -it –rm –image=curlimages/curl curly — curl -v http://frontend.blog-app
- Trying 10.71.246.145:80…
- Connected to frontend.blog-app (10.71.246.145) port 80 > GET / HTTP/1.1
Host: frontend.blog-app
User-Agent: curl/8.4.0
Accept: /
- Recv failure: Connection reset by peer
- Closing connection
curl: (56) Recv failure: Connection reset by peer
As we can see, the request has now been rejected as it is a plaintext request, and the backend will only allow TLS. This shows that strict TLS is working fine. Now, let’s move on and secure our services even better.
From our design, we know how services interact with each other:
• The frontend microservice can only connect to the posts, reviews, and users microservices
• Only the reviews microservice can connect to the ratings microservice.
• Only the posts, reviews, users, and ratings microservices can connect to the mongodb database
Leave a Reply