Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Du VPN au Gateway externe avec IAP : moderniser l'accès aux applications internes GKE

By Nir ForerJan 13, 20256 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

Abandonner le VPN au profit d'une solution Zero Trust moderne pour les applications HTTPS internes

Vous gérez encore des connexions VPN pour permettre à vos équipes distantes d'accéder à vos applications internes GKE (Google Kubernetes Engine) ? Il existe une meilleure approche. Dans cet article, nous verrons comment remplacer l'accès VPN traditionnel par l'Identity-Aware Proxy (IAP) de Google Cloud, via le GKE External Gateway. Cette approche moderne réduit la charge opérationnelle tout en offrant un contrôle d'accès plus fin grâce à l'authentification et à l'autorisation IAM.

Pourquoi franchir le pas ?

L'accès VPN traditionnel aux applications internes présente plusieurs limites :

  • Charge opérationnelle élevée pour gérer les tunnels VPN
  • Coûts supplémentaires liés à l'infrastructure VPN
  • Configurations de routage réseau complexes
  • Contrôle d'accès granulaire limité

En déployant un External Gateway avec IAP, vous pouvez :

  • Regrouper plusieurs applications derrière un seul load balancer HTTPS
  • Gérer efficacement les accès entre différents namespaces GKE
  • Tirer parti du système d'authentification robuste de Google Cloud
  • Réduire les coûts et la complexité de l'infrastructure

GKE Ingress ou Gateway : comparaison de l'implémentation IAP

Pour mettre en place IAP avec GKE, deux approches principales s'offrent à vous : GKE Ingress ou GKE Gateway. Bien comprendre leurs différences est essentiel pour choisir la solution adaptée à votre environnement.

Limites de GKE Ingress

  • Restrictions de namespace : GKE Ingress ne peut référencer que les Services présents dans le même namespace que la ressource Ingress :

Un GKE Ingress dans le namespace Fu ne peut pas référencer un Service dans le namespace Bar

  • Ressources de load balancer : plusieurs load balancers peuvent être nécessaires si les applications sont réparties sur différents namespaces :

Deux LB HTTPS distincts sont indispensables lorsque les services sont répartis sur des namespaces différents — il faut alors recourir à un routage par domaine, ce qui ajoute une couche de complexité supplémentaire

Atouts de GKE Gateway

  • Prise en charge cross-namespace : route le trafic vers des Services situés dans différents namespaces depuis une seule ressource Gateway
  • Architecture simplifiée : un seul load balancer prend en charge plusieurs applications, quel que soit leur namespace
  • Routage plus souple : facilite la mise en œuvre de schémas de routage complexes entre namespaces

Un GKE Gateway dans un namespace peut acheminer le trafic vers des Services d'autres namespaces via un seul LB HTTPS

Guide d'implémentation

Prérequis

  • GKE Standard v1.24+ ou GKE Autopilot v1.26+
  • Cluster en configuration VPC-native
  • Add-on HttpLoadBalancing activé

Étape 1 : créer le cluster GKE

gcloud container clusters create test-gateway \
 --region=us-central1 \
 --release-channel=regular \
 --enable-ip-alias \
 --num-nodes=1 \
 --addons HttpLoadBalancing \
 --gateway-api=standard

gcloud container clusters get-credentials test-gateway --region us-central1

Étape 2 : configurer le certificat SSL

cat <<EOF | kubectl apply -f -
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
 name: gateway-nir-dns-tests-google-com
 namespace: default
spec:
 domains:
 - gateway.nir-dns-tests-google-com
EOF

Étape 3 : configurer l'IP externe et faire pointer un enregistrement DNS A vers cette IP

Pour que le ManagedCertificate soit provisionné, vous devez disposer d'un enregistrement DNS A pointant vers le LB HTTPS et avoir attaché le certificat à ce LB HTTPS (ce qui sera fait à l'étape suivante)

gcloud compute addresses create gateway --project=nir-playground --global
RESERVED_IP=$(gcloud compute addresses describe gateway --global | grep address: | awk '{print $2}')

gcloud dns --project=nir-playground record-sets create gateway.nir-dns-tests-google-com. \
  --zone="nir-dns-tests-google-com" --type="A" --ttl="60" --rrdatas=$RESERVED_IP

Étape 4 : déployer la ressource Gateway

À noter : gatewayClassName correspond à un LB HTTPS Global External, et le tableau listeners autorise le rattachement de HTTPRoutes depuis n'importe quel namespace. Notez également que l'IP réservée est définie via addresses[0].type à la valeur NamedAddresses, dont la valeur reprend le nom utilisé lors de la réservation de l'IP statique (gateway dans cet exemple) :

CERT_NAME=$(kubectl get managedcertificate gateway-nir-dns-tests-google-com -o=jsonpath="{.status.certificateName}")

cat <<EOF | kubectl apply -f -
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
 name: external-http
spec:
 gatewayClassName: gke-l7-global-external-managed
 listeners:
 - name: https
   protocol: HTTPS
   port: 443
   allowedRoutes:
     namespaces:
       from: All
   tls:
     mode: Terminate
     options:
       networking.gke.io/pre-shared-certs: $CERT_NAME
 addresses:
 - type: NamedAddress
   value: gateway
EOF

# Vérifier l'attribution de l'IP du Gateway
while true; do
 GATEWAY_IP=$(kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}")
 if [ "$GATEWAY_IP" != "" ]; then
   break
 fi
 sleep 3
done

Étape 5 : vérifier le statut du ManagedCertificate

# Vérifier le statut du certificat
while true; do
 STATUS=$(kubectl get managedcertificate gateway-nir-dns-tests-google-com -o=jsonpath="{.status.certificateStatus}")
 if [ "$STATUS" = "Active" ]; then
   break
 fi
 echo "Le certificat est au statut $STATUS, nouvelle vérification dans 3 secondes"
 sleep 3
done

Étape 6 : déployer les applications de démonstration

kubectl create namespace first-namespace
kubectl create namespace second-namespace

# Déployer App A dans first-namespace
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: apps/v1
kind: Deployment
metadata:
 name: app-a
spec:
 replicas: 2
 selector:
   matchLabels:
     app: app-a
 template:
   metadata:
     labels:
       app: app-a
   spec:
     containers:
     - name: app-a
       image: hashicorp/http-echo
       args: ["-text=Hello from App A"]
       ports:
       - containerPort: 5678
EOF

# Créer le Service pour App A
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: v1
kind: Service
metadata:
 name: service-a
spec:
 selector:
   app: app-a
 ports:
 - protocol: TCP
   port: 80
   targetPort: 5678
EOF

# Déployer App B dans second-namespace
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: apps/v1
kind: Deployment
metadata:
 name: app-b
spec:
 replicas: 2
 selector:
   matchLabels:
     app: app-b
 template:
   metadata:
     labels:
       app: app-b
   spec:
     containers:
     - name: app-b
       image: hashicorp/http-echo
       args: ["-text=Hello from App B"]
       ports:
       - containerPort: 5678
EOF

# Créer le Service pour App B
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: v1
kind: Service
metadata:
 name: service-b
spec:
 selector:
   app: app-b
 ports:
 - protocol: TCP
   port: 80
   targetPort: 5678
EOF

Étape 7 : activer IAP et créer un Secret k8s pour les identifiants IAP

echo -n CLIENT_SECRET_REDACTED > iap-secret.txt
kubectl create secret generic iap --from-file=key=iap-secret.txt

Étape 8 : créer la GCPBackendPolicy qui applique IAP

# Activer IAP pour App A
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
 name: backend-policy
spec:
 default:
   iap:
     enabled: true
     oauth2ClientSecret:
       name: iap
     clientID: REPLACE_WITH_YOUR_IAP_OAUTH_CLIENT_ID
 targetRef:
   group: ""
   kind: Service
   name: service-a
EOF

# Activer IAP pour App B
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
 name: backend-policy
spec:
 default:
   iap:
     enabled: true
     oauth2ClientSecret:
       name: iap
     clientID: REPLACE_WITH_YOUR_IAP_OAUTH_CLIENT_ID
 targetRef:
   group: ""
   kind: Service
   name: service-b
EOF

Étape 9 : créer la HTTPRoute

# Créer la route pour App A
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
 name: route-a
 namespace: first-namespace
spec:
 parentRefs:
 - name: external-http
   kind: Gateway
   namespace: default
 rules:
 - matches:
   - path:
       value: /first
   backendRefs:
   - name: service-a
     port: 80
EOF

# Créer la route pour App B
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
 name: route-b
 namespace: second-namespace
spec:
 parentRefs:
 - name: external-http
   kind: Gateway
   namespace: default
 rules:
 - matches:
   - path:
       value: /second
   backendRefs:
   - name: service-b
     port: 80
EOF

Étape 10 : accéder aux applications protégées par IAP

Rendez-vous sur l'URL protégée par IAP. La page de connexion Google s'affiche. Tout utilisateur appartenant à la même organisation Google Cloud que celle où l'application est déployée et disposant des permissions IAM IAP-Secured Web App User pourra accéder à l'application :

[email protected] est un utilisateur de l'organisation GCP doit.com et dispose des permissions IAM requises pour accéder à l'application. [email protected] n'appartient pas à cette organisation et ne pourra donc pas y accéder

Lorsqu'un utilisateur extérieur à l'organisation, ou un utilisateur sans les permissions adéquates, tente de se connecter à l'application, une page de refus d'accès s'affiche :

Page de refus d'accès affichée pour les utilisateurs non autorisés

Moderniser vos schémas d'accès GKE en passant du VPN à un External Gateway avec IAP n'est qu'une des nombreuses manières de renforcer la sécurité et l'efficacité opérationnelle de votre infrastructure Google Cloud. Cette approche améliore votre posture de sécurité tout en réduisant la charge opérationnelle et les coûts.

Bien que ce guide se concentre sur la modernisation de l'accès à GKE, des opportunités de transformation similaires existent dans l'ensemble de votre infrastructure cloud. De l'optimisation des coûts à l'automatisation de l'infrastructure, en passant par le renforcement de la sécurité et la conception d'architectures cloud, DoiT International met à votre disposition une expertise étendue couvrant de nombreux domaines du cloud. Pour découvrir comment DoiT peut vous aider à moderniser d'autres pans de votre infrastructure cloud ou en savoir plus sur nos solutions de cloud engineering, rendez-vous sur doit.com/expertise/.