Canaries with Istio and Argo RolloutsSchritt 7 von 13: Enabling mTLS in our Namespace
Alle Labs

Enabling mTLS in our Namespace

At the moment, communication between our services is not encrypted. Service meshes like Istio provide the ability to encrypt communication between services using mTLS (mutual TLS). This means that both the client and the server authenticate each other using certificates, and the communication is encrypted. These certificates are managed by Istio and are automatically rotated.

Before we enable mTLS, let’s create a pod in another namespace and see if it can access our demo application. To do this, create a new pod in the default namespace using the following command:

kubectl run test --image=nginx -n default

After the pod is created, you can exec into it and try to access the frontend service of our demo application:

kubectl exec -it test -n default -- /bin/bash
curl http://learning-tracker-frontend.learning-tracker.svc.cluster.local
curl http://learning-tracker-api.learning-tracker.svc.cluster.local/api/health

With a bit of imagination, you should see the HTML page of the frontend service and the health endpoint of the API service. This is because there are no restrictions on who can access the services in our demo application. This is the intended behavior for now, but what if we want to authorize only certain services to access our demo application? This is where mTLS comes into play.

There are various ways to enable mTLS in Istio. For example, this can already be done during the installation of Istio, but also globally or per namespace using PeerAuthentication resources. If a PeerAuthentication resource is defined in the istio-system namespace, it applies to all namespaces unless overridden by a more specific resource. In our case, we will enable mTLS in the learning-tracker namespace using a PeerAuthentication resource.

Create a file named peer-authentication.yaml with the following content:

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: learning-tracker
spec:
  mtls:
    mode: STRICT

This resource enables mTLS in the learning-tracker namespace in strict mode. This means that all services in this namespace must use mTLS to communicate with each other. If a service tries to communicate without mTLS, the communication will be denied. This resource can be applied using the command kubectl apply -f peer-authentication.yaml. After that, you can verify that this works by trying to access the frontend service from the test pod again:

curl http://learning-tracker-frontend.learning-tracker.svc.cluster.local

Now you should see an error message indicating that the connection was refused. This is because the test pod is not using mTLS to communicate with the frontend service, and therefore the communication is denied. Let’s try to create another namespace and a pod in this namespace that is allowed to access our demo application. To do this, create a new namespace named trusted and a pod in this namespace:

kubectl create namespace trusted
kubectl label namespace trusted istio-injection=enabled
kubectl run trusted-test --image=nginx -n trusted

When opening a shell in the trusted-test pod, you should be able to access the frontend service of our demo application:

kubectl exec -it trusted-test -n trusted -- /bin/bash
curl http://learning-tracker-frontend.learning-tracker.svc.cluster.local
curl http://learning-tracker-api.learning-tracker.svc.cluster.local/api/health

This works because the trusted namespace has Istio sidecar injection enabled, and therefore the pod in this namespace is using mTLS to communicate with the frontend service. With this, we have successfully enabled mTLS in our demo application and restricted access to it. In the next steps, we will configure some basic authorization rules to further restrict access to our demo application.