Istio, or any service mesh as a matter of fact, represents an abstraction layer of the service to service communication in a distributed architecture. This opens the door to a lot of powerful feature and control over the traffic flowing in and out of the system such as Observability , Traffic Management and Security which will be the main course for this blog entry.
Laying the ground
Chronologically speaking the shift from Monolithic applications to distributed architecture started with the heavy use of APIs before shifting into microservices, you may checkout this blog post by dzone to understand the difference between APIs and Microservices. The rise of APIs introduced new challenges, especially on the security level where the main challenge was flowing claims to establish User and Client’s identity. There are mainly two security patterns that have been used to mitigate those concerns
- Impersonation and Delegation
- Trusted Subsystem
Our focus is the Trusted Subsystem pattern which is defined by ,in a multi-layered application architecture, downstream services often trust the upstream services to perform a specific set of security functionality.
In simple English words, when you have a distributed system and the services are internal and not publicly accessible that’s called a trusted subsystem. In such a setup, It’s so tempting not to encrypt the internal communication, but those temptations go away so fast when the system will run on a third-party provider and Security in depth becomes an obligation in this case.
Implementing such a concept requires changing the code source of the applications and the involvement of the IT operations team to maintain the certificates used in the encryption process.
This brings us back to Istio and one of its powerful security features, mutual TLS, allowing a sort of upgrade from HTTP to HTTPS without changing source code nor managing certificates.
Istio - mTLS explained!
Istio provides custom resources to secure the communication with mutual TLS mainly MeshPolicy and Policy but the client side of that mTLS does get configured in the DestinationRule. The main difference is the level on which they get applied to, So the MeshPolicy defines the default for the entire service mesh (all services, all namespaces) on the other hand the Policy will only apply to a specific target.
apiVersion: authentication.istio.io/v1alpha1
kind: MeshPolicy #Default policy for all namespaces
metadata:
name: default
spec:
peers: #Authentication for calling service
- mtls: {}
apiVersion: authentication.istio.io/v1alpha1
kind: Policy #Policy for specific target
metadata:
name: default
namespace: default
spec:
peers:
- mtls: {} #Require mtls
targets:
- name: productpage
At this stage of the architecture we have the following state:
- Legacy Pods without Istio sidecar can’t communicate with the details application over port 80.
-
The productpage can’t communicate with the details cause mTLS isn’t configured on the client side.
-> The DestinationRule need to be configured
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: default
namespace: default
spec:
host: "*.default.svc.cluster.local" #Any host
trafficPolicy:
tls: #Us mutual TLS
mode: ISTIO_MUTUAL #Istio managed certs
In a production environment, It might be that not all of the services are registered with Istio, in our case it’s the legacy application. Therefor, Istio mutual TLS has a permissive mode, which allows a service to accept both plaintext traffic and mutual TLS traffic at the same time.
apiVersion: authentication.istio.io/v1alpha1
kind: Policy
metadata:
name: default
namespace: default
spec:
peers:
- mtls:
mode: PERMISSIVE
targets:
- name: productpage
TLS certificates
After setting up the DestinationRule that configures transport layer security using Istio certificates, we can check the certificates by connecting to the product page proxy (the example is using docker kubernets).
docker container ls --filter name=istio-proxy_productpage
docker container exec -it $(docker container ls --filter name=istio-proxy_productpage --format '') sh
ls /etc/certs
cat /etc/certs/cert-chain.pem | openssl x509 -text -noout | grep 'Subject Alternative Name' -A 1
Istio uses the service account that the port is running under to generate subject, which is the service identity. So the identity actually comes from the underlying platform (Kubernetes in our case), and Istio is using that as a secure way to identify all the components.
Limitations
Although the productpage container doesn’t contain the certificates, So basic network operations like CURL will be denied, the application communicates via the Istio_proxy which means if an end user hack the system he will be able send a malicious request to our details api. So in the next post we will tackle securing end user access and the AuthorizationPolicy to secure access to services.