Lorsque vos applications envoient du HTTP en clair vers des services externes, le trafic quittant le maillage n'est pas chiffré. La passerelle de sortie Service Mesh (ASM) agit comme un point de sortie unique pour tout le trafic sortant du maillage. Elle intercepte les requêtes sortantes et établit des connexions mTLS avec les services externes au nom de vos charges de travail, offrant ainsi un chiffrement de bout en bout sans modification du code.
Ce guide explique comment router le trafic HTTP sortant via une passerelle de sortie et le convertir en mTLS.
Cas d'utilisation
Routez le trafic via une passerelle de sortie avec initiation mTLS dans les situations suivantes :
Votre politique de sécurité impose un chiffrement du trafic sortant. Les applications envoient du HTTP en clair, mais tout le trafic quittant le maillage doit être chiffré. La passerelle de sortie gère l'initiation TLS sans aucune modification de l'application.
Vous avez besoin d'un contrôle centralisé du trafic sortant. Tout le trafic sortant doit transiter par des nœuds de passerelle dédiés pour l'audit, la surveillance et l'application des politiques.
Le service externe requiert une authentification par certificat client. Le maillage doit présenter un certificat client spécifique (TLS mutuel) au nom de vos charges de travail.
Fonctionnement
Le schéma suivant illustre le chemin complet du trafic une fois toutes les étapes de configuration de ce guide terminées :
sleep pod ──mesh mTLS──> egress gateway ──external mTLS──> external ingress gateway ──mTLS──> httpbin
Le pod
sleepenvoie une requête HTTP en clair verstest.com.Le proxy sidecar intercepte la requête et la transmet à la passerelle de sortie via mTLS interne au maillage (certificats gérés par ASM).
La passerelle de sortie initie une nouvelle connexion mTLS avec le service externe en utilisant un certificat client fourni par l'utilisateur.
La passerelle d'entrée externe termine la session mTLS et route la requête vers le service
httpbinen amont.
Ce guide construit ce chemin de manière incrémentale. Après l'étape 3, le segment entre la passerelle de sortie et le service externe reste en clair. L'étape 4 convertit ce segment en mTLS, comblant ainsi la faille de sécurité.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Effectué toutes les étapes décrites dans Configurer un service mTLS sur la passerelle d'entrée ASM et restreindre l'accès à des clients spécifiques. Ce tutoriel déploie le serveur mTLS utilisé comme service externe dans ce guide.
Une instance ASM distincte et un cluster Container Service for Kubernetes (ACK) servant d'environnement principal pour ce guide.
Activé l'injection automatique de sidecars. Pour plus d'informations, consultez la section Configurer les politiques d'injection de proxy sidecar.
Dans les étapes ci-dessous, $INGRESS_GATEWAY_IP fait référence à l'adresse IP de la passerelle d'entrée issue du tutoriel des prérequis. « Cluster ACK » et « Instance ASM » désignent les ressources de l'environnement principal.
Définissez la variable shell utilisée tout au long de ce guide. Avec le fichier kubeconfig du cluster ACK, exécutez :
# Replace with the actual ingress gateway IP from the prerequisite tutorial
export INGRESS_GATEWAY_IP=<ingress-gateway-ip>
Étape 1 : Déployer l'application de test sleep
Déployez l'application sleep en tant que client de test. Pour les instructions de déploiement, consultez la section Opérations associées.
Vérifier le déploiement
Avec le fichier kubeconfig du cluster ACK, vérifiez que le pod sleep peut atteindre le service HTTPBin externe :
kubectl exec deploy/sleep -- curl --header "host:test.com" $INGRESS_GATEWAY_IP/status/418
Résultat attendu :
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
La réponse HTTP 418 (teapot) confirme la connectivité avec le service HTTPBin externe.
Étape 2 : Activer REGISTRY_ONLY et créer une entrée de service (ServiceEntry)
Restreindre l'accès sortant (facultatif)
Définissez la politique de trafic sortant sur REGISTRY_ONLY afin d'empêcher les pods d'atteindre tout service non explicitement enregistré via une entrée de service (ServiceEntry). Pour plus d'informations, consultez l'étape Étape 2 : Activer REGISTRY_ONLY.
Après avoir activé REGISTRY_ONLY, les requêtes vers des services non enregistrés renvoient une erreur 502 Bad Gateway.
Enregistrer le service externe
Créez une entrée de service (ServiceEntry) pour test.com afin que les pods du maillage puissent y accéder. Pour plus d'informations, consultez la section Créer un service externe.
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: test-com
namespace: default
spec:
endpoints:
- address: <ingress-gateway-ip> # IP address of the external ingress gateway
hosts:
- test.com
location: MESH_EXTERNAL
ports:
- name: http
number: 80
protocol: HTTP
- name: https
number: 443
protocol: HTTPS
resolution: STATIC
Remplacez <ingress-gateway-ip> par l'adresse IP de la passerelle d'entrée issue du tutoriel des prérequis.
Vérification
Après avoir appliqué l'entrée de service, exécutez la même commande curl que lors de l'étape 1 pour confirmer que le pod sleep peut toujours atteindre le service HTTPBin sur test.com.
Étape 3 : Créer la passerelle de sortie et router le trafic HTTP via celle-ci
3a. Créer la passerelle de sortie
Créez une passerelle de sortie pour le trafic HTTP sur le port 80 avec l'authentification TLS mutuelle activée. Les charges de travail du maillage chiffrent automatiquement le trafic vers la passerelle à l'aide de certificats gérés par ASM. Pour plus d'informations, consultez la section Créer une passerelle de sortie.
3b. Créer des règles de passerelle
Créez une ressource Gateway qui déclare l'écouteur de la passerelle de sortie. La passerelle écoute sur le port 80 avec le mode TLS ISTIO_MUTUAL (certificats gérés par ASM). Pour plus d'informations, consultez la section Créer des règles de passerelle.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: egress-gateway
namespace: default
spec:
selector:
istio: egressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTPS
tls:
mode: ISTIO_MUTUAL
3c. Créer un VirtualService
Créez un VirtualService qui route le trafic test.com en deux étapes :
Du maillage à la passerelle de sortie : le sidecar transfère le trafic sur le port 80 vers la passerelle de sortie.
De la passerelle de sortie au service externe : la passerelle de sortie transfère le trafic vers l'entrée de service (ServiceEntry)
test.comsur le port 80.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: egressgateway-vs
spec:
hosts:
- test.com
gateways:
- egress-gateway # Gateway created in step 3b
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
port:
number: 80
weight: 100
- match:
- gateways:
- egress-gateway
port: 80
route:
- destination:
host: test.com
port:
number: 80
weight: 100
Vérifier que le trafic transite par la passerelle de sortie
-
Accédez à
test.comdepuis le podsleep: Résultat attendu : l'art ASCII de la théière HTTP 418 (identique à l'étape 1).kubectl exec deploy/sleep -- curl --header "host:test.com" $INGRESS_GATEWAY_IP/status/418 -
Vérifiez le journal d'accès de la passerelle de sortie. Avec le fichier kubeconfig de l'instance ASM, exécutez : L'entrée de journal doit afficher
"upstream_cluster":"outbound|80||test.com", ce qui confirme que la requête est passée par la passerelle de sortie.export EGRESS_POD=$(kubectl get pod -l istio=egressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') kubectl -n istio-system logs $EGRESS_POD | tail -1
Flux de trafic à cette étape
sleep pod ──mTLS──> egress gateway ──plaintext──> external ingress gateway ──mTLS──> httpbin
Le segment entre la passerelle de sortie et le service externe est toujours en clair. L'étape 4 convertit ce segment en mTLS.
Étape 4 : Convertir le trafic de sortie en mTLS
4a. Mettre à jour le VirtualService
Mettez à jour le VirtualService pour router le trafic de la passerelle de sortie vers le port 443 au lieu du port 80. La seule modification concerne le port de destination pour la correspondance egress-gateway :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: egressgateway-vs
spec:
hosts:
- test.com
gateways:
- egress-gateway
- mesh
http:
- match:
- gateways:
- mesh
port: 80
route:
- destination:
host: istio-egressgateway.istio-system.svc.cluster.local
port:
number: 80
weight: 100
- match:
- gateways:
- egress-gateway
port: 80
route:
- destination:
host: test.com
port:
number: 443 # Changed from 80 to 443
weight: 100
4b. Importer le certificat client mTLS
Importez le certificat mTLS issu du tutoriel Configurer un service mTLS sur la passerelle d'entrée ASM et restreindre l'accès à des clients spécifiques. Nommez le certificat test.client. Pour plus d'informations, consultez la section Utiliser la fonctionnalité de gestion des certificats d'ASM.
Vous pouvez également créer le secret directement avec kubectl. Avec le fichier kubeconfig du cluster ACK, exécutez :
kubectl create -n istio-system secret generic test.client \
--from-file=tls.key=client.key.pem \
--from-file=tls.crt=clientcert.pem \
--from-file=ca.crt=cacert.pem
4c. Créer une règle DestinationRule pour l'initiation mTLS
Créez une règle DestinationRule qui configure la passerelle de sortie pour initier une connexion mTLS lors de la connexion à test.com sur le port 443 :
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: originate-mtls-for-test-com
spec:
host: test.com
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 443
tls:
mode: MUTUAL
credentialName: test.client
sni: test.com
| Champ | Description |
|---|---|
mode: MUTUAL |
Active le TLS mutuel. La passerelle de sortie présente un certificat client et valide le certificat du serveur. |
credentialName |
Fait référence au secret test.client contenant le certificat client, la clé privée et le certificat CA. |
sni |
Définit l'extension Server Name Indication (SNI) sur test.com pour le handshake TLS. |
Vérifier l'initiation mTLS
-
Testez un chemin auquel le certificat client est autorisé à accéder : Résultat attendu :
kubectl exec deploy/sleep -it -- curl --header "host:test.com" $INGRESS_GATEWAY_IP/status/200 -IHTTP/1.1 200 OK server: envoy date: Mon, 29 Jul 2024 03:33:50 GMT content-type: text/html; charset=utf-8 access-control-allow-origin: * access-control-allow-credentials: true content-length: 0 x-envoy-upstream-service-time: 5 -
Testez un chemin auquel le certificat client est interdit d'accès : Résultat attendu : La requête est refusée car le certificat
test.clientest configuré dans le tutoriel des prérequis pour bloquer l'accès au chemin/status/418.kubectl exec deploy/sleep -it -- curl --header "host:test.com" $INGRESS_GATEWAY_IP/status/418RBAC: access denied% -
Confirmez que la passerelle de sortie se connecte via le port 443. Avec le fichier kubeconfig de l'instance ASM, exécutez : L'entrée de journal doit afficher
"upstream_cluster":"outbound|443||test.com"et"upstream_host":"...:443", ce qui confirme que la passerelle de sortie se connecte au service externe via le port mTLS.kubectl -n istio-system logs $EGRESS_POD | tail -1
Flux de trafic après la conversion en mTLS
sleep pod ──mTLS──> egress gateway ──mTLS──> external ingress gateway ──mTLS──> httpbin
Tous les segments sont désormais chiffrés avec mTLS. La faille de trafic en clair de l'étape 3 est éliminée.
Étape 5 : Configurer des politiques d'autorisation
Avec le mTLS de bout en bout en place, le maillage authentifie les identités des clients à chaque saut. Les politiques d'autorisation appliquent un contrôle d'accès granulaire à deux niveaux.
Restreindre l'accès au niveau de la passerelle de sortie
Appliquez une AuthorizationPolicy sur la passerelle de sortie pour contrôler quels services du maillage peuvent atteindre test.com. L'exemple suivant refuse l'accès au compte de service sleep au chemin /headers :
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
labels:
gateway: egressgateway
name: test
namespace: istio-system
spec:
action: DENY
rules:
- from:
- source:
principals:
- cluster.local/ns/default/sa/sleep
to:
- operation:
hosts:
- test.com
paths:
- /headers
selector:
matchLabels:
istio: egressgateway
Après avoir appliqué cette politique, les requêtes du pod sleep vers test.com/headers via la passerelle de sortie sont refusées.
Restreindre l'accès au niveau de la passerelle d'entrée externe
La AuthorizationPolicy sur la passerelle d'entrée externe (issue du tutoriel Configurer un service mTLS sur la passerelle d'entrée ASM et restreindre l'accès à des clients spécifiques) restreint l'accès en fonction de l'identité du certificat client. La politique du tutoriel des prérequis empêche le certificat test.client d'accéder à /status/418.
Ensemble, ces deux points d'autorisation offrent un contrôle d'accès en couches :
| Point d'autorisation | Portée |
|---|---|
| Politiques de la passerelle de sortie | Contrôlent quels services du maillage peuvent atteindre quels hôtes et chemins externes. |
| Politiques de la passerelle d'entrée externe | Contrôlent quels certificats clients peuvent accéder à quels chemins backend. |