Gestion de l’authentification dans Istio

Dans une architecture distribuée, le challenge est de maintenir un réseau sécurisé et fiable entre les workloads des applications. Les microservices sont en général développés dans des environnements cloisonnés et supposés sécurisés. En s’appuyant sur les briques de sécurité déjà existantes, il serait plus simple d’autoriser les interactions entre microservices sans apporter une couche de sécurité supplémentaire pour éviter de rajouter de la complexité dans le workflow du développeur. La solution serait de mettre en place une solution qui  puisse répondre à cette problématique de sécurité sans changer la nature des interactions entre microservices. C’est tout l’intérêt d’utiliser un service mesh tel qu’Istio pour simplifier et sécuriser les workloads. Avec Istio, on ne se soucie plus du niveau de fiabilité de la couche réseau de base sur laquelle reposent les microservices. Istio attribue une identité aux entités du mesh de sorte à garantir leurs authenticités et sécuriser la communication entre elles.  Ce principe est appelé “Trusted Subsystem pattern” dont le modèle repose sur l’authentification et la vérification de l’identité du service appelant.

Trusted SubSystem Model from Microsoft

Un système d’identification et d’authentification est établi pour chaque appel de workload provenant soit d’un service ou soit d’un client (utilisateur/device). Ce qui va permettre de chiffrer le payload de chaque paquet échangé et  prévenir les attaques de type MITM, Replay, tunneling, injection de paquets, flooding etc..Voyons en détails comment Istio implémente ce mécanisme.

 

Une PKI logique au sein d’Istio

Ce point est important car les informations sensibles échangées entre deux identités peuvent juste être chiffrées, ce qui garantit la confidentialité. Mais sans certificat voire PKI, il n’y aurait aucune garantie de l’authenticité de ces entités. 

Istio implémente une PKI logique à travers sa composante Citadel qui joue le rôle de CA (Autorité de certification) et gère la signature, l’émission, la validation, la révocation et le renouvellement des certificats numériques.

Authentication architecture from Istio.io

Par défaut , le CA d’ Istio génère un certificat root et une clé auto-signés, et les utilise pour signer les certificats de format X.509.

 Pour cela, un agent Istio est installé au niveau de chaque proxy Envoy.

Pour chaque demande de signature de certificat(CSR) et de clé privée, Envoy envoie une demande via son API SDS à l’agent. A la réception de la demande, l’agent Istio crée les éléments avant de l’envoyer au CA pour signature. Le CA valide les informations d’identification contenues dans le CSR et le signe pour générer le certificat. Et enfin, l’agent transfère au proxy le certificat reçu  et la clé privée à Envoy via l’API SDS Envoy.

Si vous avez une PKI existante..

Comme décrit dans la documentation d’Istio, Istio offre également la possibilité d’utiliser une PKI existante au sein d’un SI.

Si le CA d’Istio doit utiliser un certificat root pour signer les certificats, un fichier cert-chain.pem doit être initié de sorte à indiquer la chaîne de confiance. Dans ce fichier, il doit être indiqué tous les certificats intermédiaires entre les identités et le CA racine.

Chain of trust from Wikipedia

Un exemple de configuration est décrit au niveau du lien suivant:

https://istio.io/docs/tasks/security/plugin-ca-cert/

 

Alors ServiceA veut communiquer avec ServiceB…

La méthode d’authentification peer basée sur du mTLS est utilisée lorsque deux services doivent communiquer. Tout le mécanisme d’identification et d’authentification est offloadé au niveau des sidecars à travers des policies.

Si ServiceA initie une communication vers le ServiceB, le trafic est routé entre les deux proxies des services et on a le scénario suivant:

Les certificats étant poussés au niveau des sidecars, le proxy client envoie un handshake TLS pour établir un tunnel chiffré durant lequel le secure naming est vérifié. Cette étape est assez critique dans la chaîne d’authentification.  Au niveau des certificats, on retrouve les informations encodées de l’identité. Une résolution DNS va alors permettre de mapper l’identité du service au vrai nom du service. Le secure naming va donc permettre de vérifier les autorisations au service appelant pour éviter des attaques de type Hijack lorsqu’un utilisateur malintentionné dispose des clés et certificats.

Une fois que les autorisations sont bien contrôlées, le tunnel de communication chiffré établi, le trafic est alors redirigé en se basant sur les DestinationRules

Cette authentification peut être configurée en deux modes:

  • Le mode PERMISSIVE où les workloads peuvent communiquer soit via du mTLS ou sans, dans ce cas le trafic peut passer en clair. Ce mode déconseillé est utilisé pour anticiper sur les services qui ne disposent pas de sidecar.
  • Le mode STRICT où l’utilisation du mTLS est forcé au niveau des workloads.

Un lab pratique est disponible plus bas dans l’article à ce sujet.

Et pour gérer les authentifications clients…

Du côté de l’utilisateur, les identités sont vérifiées à l’aide d’un token JWT valide. Pour chaque requête du client, un token est alors envoyé en passant d’abord par l’Ingress Gateway puis par le sidecar,  qui va autoriser, ou non, le client à y accéder . L’authentification est donc réalisée une fois que l’utilisateur aura prouvé son identité auprès de l’IdP en bout de chaîne. Istio délègue l’authentification au niveau client en utilisant les identity providers compatible avec le standard OpenID Connect tels que:

  • Hydra 
  • Keycloak 
  • Auth0 
  • Firebase 
  • Auth
  •  Google Auth Traduit 

Un peu de pratique…

Dans ce lab, nous allons utiliser une application nommée bookinfo et un client externe au mesh nommé sleep.  Dans l’application bookinfo, nous utiliserons les services productpage et details.  Nous allons configurer le mTLS en mode STRICT pour joindre le  microservice details.

Prérequis d’installation:

  • Un cluster Kubernetes avec Istio déja installé , un guide d’installation est disponible en cliquant sur le lien suivant:

https://www.beopenit.com/comment-rapidement-mettre-en-place-istio-sur-kubernetes/

  • Déployer une application Bookinfo en suivant ce lien: 

https://github.com/dakario/book-istio-labs/blob/master/deploiement-bookinfo/README.md

Dans un premier temps, nous allons déployer un conteneur que nous pouvons utiliser pour le client externe Sleep.  Ce service sera exclu du mesh donc le paramètre istio-injection aura la valeur disabled.

Copy to Clipboard

 

Output:

Copy to Clipboard

 

Copy to Clipboard

 

Output:

Copy to Clipboard

 

Le pod est bien à l’état running en lançant la commande suivante:

Copy to Clipboard

 

Output:

Copy to Clipboard

 

Sleep doit pouvoir accéder à details en http:

Copy to Clipboard

 

Copy to Clipboard

 

Maintenant , nous allons configurer l’authentificatification mTLS en mode STRICT  pour tout service voulant joindre le service details:

Copy to Clipboard

 

Output:

Copy to Clipboard

 

Appliquer cette règle de destination pour que les autres microservices envoient du trafic mTLS sur le microservice details.

Copy to Clipboard

 

Output:

Copy to Clipboard

 

Vérifier que l’API details n’est plus accessible en http depuis le client sleep:

Copy to Clipboard

 

Tester si le client sleep accéde à l’API details en https

Copy to Clipboard

 

Nous constatons que le client sleep ne peut pas accéder à details car il n’a pas de sidecar d’où l’échec de l’authentification mTLS. Par contre, le microservice productpage accéde bien à details car il embarque un sidecar  contrairement à Sleep.