Intégrer IAP à Cloud Service Mesh

Ce guide explique comment intégrer Identity-Aware Proxy (IAP) avec Cloud Service Mesh. L'intégration d'IAP à Cloud Service Mesh vous permet d'accéder en toute sécurité aux services conformément aux principes de BeyondCorp de Google. IAP vérifie l'identité de l'utilisateur et le contexte de la requête pour déterminer si cet utilisateur doit être autorisé à accéder à une application ou à une ressource. L'intégration d'IAP à Cloud Service Mesh offre les avantages suivants :

  • Contrôle complet de l'accès contextuel aux charges de travail exécutées sur Cloud Service Mesh. Vous pouvez définir des règles d'accès précises en fonction d'attributs de la requête d'origine, tels que l'identité de l'utilisateur, l'adresse IP et le type d'appareil. Vous pouvez combiner vos règles d'accès avec des restrictions basées sur le nom d'hôte et le chemin d'une URL de requête.

  • Activez la compatibilité des revendications contextuelles dans l'autorisation Cloud Service Mesh.

  • Accès évolutif, sécurisé et hautement disponible à votre application via un équilibreur de charge Google Cloud. L'équilibrage de charge hautes performances offre une protection intégrée contre les attaques par déni de service distribué (DDoS) et une compatibilité avec l'adressage IP Anycast.

Prérequis

Suivez les étapes de la page Installer les outils dépendants et valider le cluster pour effectuer les opérations suivantes :

Dans ce guide, nous partons également du principe que vous disposez des éléments suivants :

Configurer un cluster avec Cloud Service Mesh

Cette section explique comment configurer l'intégration IAP pour les nouvelles installations et les mises à niveau de Cloud Service Mesh.

Nouvelles installations

  1. Activer iap.googleapis.com Dans la commande suivante, remplacez PROJECT_ID par le projet dans lequel vous allez installer Cloud Service Mesh :

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. L'option --addons=HttpLoadBalancing doit être définie pur le cluster que vous mettez à jour. Le module complémentaire HttpLoadBalancing active un contrôleur d'équilibrage de charge HTTP (L7) pour le cluster. Exécutez la commande suivante pour mettre à jour le cluster avec les options requises par Cloud Service Mesh : À moins que vous n'ayez défini une zone ou une région par défaut, vous devez indiquer la région (--region=REGION) ou la zone (--zone=ZONE) dans la commande.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID \
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Par défaut, le fichier iap-operator.yaml a comme port d'état le port 31223 et le port 31224 en tant que port http. Si le port 31223 est déjà utilisé dans votre cluster, exécutez la commande suivante pour définir un autre port d'état :

    kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT
    

    Si le port 31224 est déjà utilisé dans votre cluster, exécutez la commande suivante pour définir un autre port HTTP:

    kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
    
  4. Suivez les étapes de la page Installer les fonctionnalités par défaut et Mesh CA pour installer Cloud Service Mesh à l'aide d'un script fourni par Google. Lorsque vous exécutez le script, incluez l'option suivante :

    --option iap-operator
    

    Exemple :

    ./asmcli install \
      --project_id "PROJECT_ID" \
      --cluster_name "CLUSTER_NAME" \
      --cluster_location "CLUSTER_LOCATION" \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --option iap-operator
    

    Lorsque vous installez Cloud Service Mesh, le fichier iap-operator.yaml définit le champ type du service istio-ingressgateway sur NodePort, ce qui configure la passerelle pour qu'elle ouvre un port spécifique sur le maillage de services. Cela vous permet de configurer un équilibreur de charge qui achemine le trafic envoyé à votre nom de domaine vers ce port.

  5. Si vous installez le service géré Cloud Service Mesh, effectuez également la en suivant les étapes ci-dessous:

    1. Appliquez le libellé de révision à l'espace de noms istio-system.

    2. Téléchargez les spécifications du service de passerelle d'entrée Istio pour IAP et nommez le fichier iap_operator.yaml.

    3. Installez l'entrée en tant que service NodePort. Pour en savoir plus, consultez la page Migrer depuis IstioOperator.

      asmcli experimental mcp-migrate-check -f iap_operator.yaml
      
      istioctl install -f /asm-generated-configs/gateways-istiooperator/"GATEWAY_NAME".yaml
      

Après avoir installé Cloud Service Mesh, revenez à ce guide et poursuivez avec pour configurer l'intégration avec IAP.

Mises à niveau

Cette section couvre les cas d'utilisation suivants pour la mise à niveau :

  • Vous avez déjà configuré l'intégration IAP et vous mettez à niveau Cloud Service Mesh. Dans ce cas, vous avez déjà activé iap.googleapis.com sur votre projet et le module complémentaire HttpLoadBalancing sur votre cluster. Passez à l'étape 3 pour télécharger le package asm et mettre à niveau Cloud Service Mesh.

  • Vous mettez à niveau Cloud Service Mesh et souhaitez configurer l'intégration avec IAP pour la première fois. Dans ce cas, vous devez terminer toutes les étapes suivantes, mettre à niveau Cloud Service Mesh et revenir à ce guide après la mise à niveau pour terminer l'intégration.

  1. Activer iap.googleapis.com Dans la commande suivante, remplacez PROJECT_IDpar le projet que vous allez installer. Cloud Service Mesh.

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. L'option --addons=HttpLoadBalancing doit être définie pur le cluster que vous mettez à jour. Le module complémentaire HttpLoadBalancing active un contrôleur d'équilibrage de charge HTTP (L7) pour le cluster. Exécutez la commande suivante pour mettre à jour le cluster avec les options requises par Cloud Service Mesh. À moins que vous n'ayez défini une zone ou une région par défaut, vous devez indiquer la région (--region=REGION) ou la zone (--zone=ZONE) dans la commande.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Si vous mettez à jour un équilibreur de charge Cloud HTTP existant, exécutez la commande suivante pour conserver vos ports HTTP et d'état existants:

    kpt cfg set asm gcloud.container.cluster.ingress.httpPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
    
    kpt cfg set asm gcloud.container.cluster.ingress.statusPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')
    
  4. Suivez la procédure décrite dans l'article Mettre à niveau Cloud Service Mesh d'utiliser un script fourni par Google pour mettre à niveau Cloud Service Mesh.

    Lorsque vous mettez à niveau Cloud Service Mesh, le fichier iap-operator.yaml définit le champ type du service istio-ingressgateway sur NodePort, ce qui configure la passerelle pour qu'elle ouvre un port spécifique sur le maillage de services. Cela vous permet de configurer un équilibreur de charge qui achemine le trafic envoyé à votre nom de domaine vers ce port.

    Par défaut, le fichier iap-operator.yaml a comme port d'état le port 31223 et le port 31224 en tant que port http.

    Lorsque vous exécutez le script, incluez l'option suivante :

    --option iap-operator
    

    Exemple :

    ./asmcli install \
      --project_id "PROJECT_ID" \
      --cluster_name "CLUSTER_NAME" \
      --cluster_location "CLUSTER_LOCATION" \
      --fleet_id FLEET_PROJECT_ID \
      --output_dir DIR_PATH \
      --enable_all \
      --option iap-operator
    
  5. Terminez la mise à niveau en déclenchant l'injection automatique de proxy side-car sur vos charges de travail. Pour en savoir plus, consultez la page Déployer et redéployer des charges de travail.

    Une fois la mise à niveau terminée, revenez à ce guide et passez à la section suivante pour configurer l'intégration avec IAP.

Réserver une adresse IP statique et configurer le DNS

Pour intégrer Identity-Aware Proxy à Cloud Service Mesh, vous devez configurer un équilibreur de charge HTTP(S) Google Cloud qui nécessite un nom de domaine pointant vers une adresse IP statique. Vous pouvez réserver une adresse IP externe statique, qui est alors attribuée à votre projet pour une durée indéterminée, jusqu'à ce que vous la libériez explicitement.

  1. Réservez une adresse IP externe statique :

    gcloud compute addresses create example-static-ip --global
    
  2. Obtenez l'adresse IP statique :

    gcloud compute addresses describe example-static-ip --global
    
  3. Dans votre service d'enregistrement de noms de domaine, configurez un nom de domaine complet avec l'adresse IP statique. En règle générale, vous ajoutez un enregistrement A à vos paramètres DNS. Les étapes de configuration et la terminologie permettant d'ajouter un enregistrement A pour un nom de domaine complet varient selon votre service d'enregistrement de noms de domaine.

    La propagation du paramètre DNS peut prendre entre 24 et 48 heures. Vous pouvez continuer à tout configurer dans ce guide, mais vous ne pouvez pas tester la configuration tant que les paramètres DNS ne sont pas propagés.

Déployer un exemple d'application

Avant d'activer IAP, vous avez besoin d'une application s'exécutant sur votre cluster GKE afin de vérifier que toutes les requêtes ont une identité. Ce guide utilise l'exemple de Bookinfo pour montrer comment configurer l'équilibreur de charge HTTP(S) et activer IAP.

Suivez les étapes pour déployer Bookinfo. Tant que vous n'avez pas déployé l'équilibreur de charge, l'application Bookinfo n'est pas accessible en dehors de votre cluster GKE (par exemple, depuis un navigateur).

Demandes externes

La ressource de passerelle de Bookinfo (définie dans samples/bookinfo/networking/bookinfo-gateway.yaml) utilise la valeur istio-ingressgateway préconfigurée. Rappelez-vous que lorsque vous avez déployé Cloud Service Mesh, vous avez spécifié NodePort pour istio-ingressgateway, qui ouvre un port spécifique sur le maillage de services. Bien que les nœuds de votre cluster aient des adresses IP externes, les requêtes provenant de l'extérieur de votre cluster sont bloquées par les règles de pare-feu Google Cloud. Avec IAP, le bon moyen d'exposer des applications à l'Internet public est d'utiliser un équilibreur de charge. N'exposez pas les adresses de nœud à l'aide de règles de pare-feu qui contournent IAP.

Pour acheminer les requêtes vers Bookinfo, vous devez configurer un équilibreur de charge HTTP(S) dans votre projet Google Cloud. Étant donné que l'équilibreur de charge se trouve dans votre projet, il se trouve dans le pare-feu et peut accéder aux nœuds de votre cluster. Une fois que vous avez configuré l'équilibreur de charge avec l'adresse IP statique et le nom de domaine, vous pouvez envoyer des requêtes au nom de domaine. L'équilibreur de charge transfère les requêtes aux nœuds du cluster.

Activer IAP

La procédure suivante explique comment activer IAP.

  1. Vérifiez que vous disposez déjà d'une marque à l'aide de la commande list. Vous ne pouvez disposer que d'une seule marque par projet.

    gcloud iap oauth-brands list

    Voici un exemple de réponse gcloud, si la marque existe :

    name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID]
    applicationTitle: [APPLICATION_TITLE]
    supportEmail: [SUPPORT_EMAIL]
    orgInternalOnly: true
    
  2. Si aucune marque n'existe, utilisez la commande create :

    gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_email=SUPPORT_EMAIL

    Les champs ci-dessus sont obligatoires lors de l'appel de cette API :

    • supportEmail : l'adresse e-mail d'assistance affichée sur l'écran d'autorisation OAuth. Il peut s'agir de l'adresse e-mail d'un utilisateur ou d'un alias d'adresses e-mail de Google Groupes. Bien que les comptes de service possèdent également une adresse e-mail, celles-ci ne sont pas valides et ne peuvent pas être utilisées lors de la création d'une marque. Toutefois, un compte de service peut être propriétaire d'un groupe Google. Créez un groupe Google ou configurez un groupe existant, puis définissez le compte de service souhaité en tant que propriétaire du groupe.

    • applicationTitle : nom de l'application affiché sur l'écran d'autorisation OAuth.

    La réponse contient les champs suivants :

    name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID]
    applicationTitle: [APPLICATION_TITLE]
    supportEmail: [SUPPORT_EMAIL]
    orgInternalOnly: true
    

Créer un client OAuth IAP

  1. Utilisez la commande "create" pour créer un client. Utilisez la marque name de l'étape précédente.

    gcloud iap oauth-clients create projects/PROJECT_NUMBER/brands/BRAND-ID --display_name=NAME

    La réponse contient les champs suivants :

    name: projects/[PROJECT_NUMBER]/brands/[BRAND_NAME]/identityAwareProxyClients/[CLIENT_ID]
    secret: [CLIENT_SECRET]
    displayName: [NAME]
    
  2. Utilisez l'ID client (CLIENT_ID dans l'exemple ci-dessus) et le CLIENT_SECRET pour activer IAP. Créez un secret Kubernetes avec les ressources de votre client OAuth :

    kubectl create secret generic -n istio-system my-secret --from-literal=client_id=CLIENT_ID \
    --from-literal=client_secret=CLIENT_SECRET

Déployer l'équilibreur de charge

Vous pouvez utiliser une ressource Ingress pour créer un équilibreur de charge HTTP(S) avec des certificats SSL automatiquement configurés. Les certificats SSL gérés par Google sont provisionnés, renouvelés et gérés pour votre domaine.

  1. Créez une ressource ManagedCertificate. Cette ressource spécifie le domaine du certificat SSL. La liste spec.domains ne doit contenir qu'un seul domaine. Les domaines avec des caractères génériques ne sont pas acceptés. Dans le fichier YAML suivant, remplacez DOMAIN_NAME par le nom de domaine que vous avez configuré pour l'adresse IP statique externe.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: example-certificate
      namespace: istio-system
    spec:
      domains:
        - DOMAIN_NAME
    EOF
  2. Créez une ressource BackendConfig. Cette ressource indique à GCLB comment effectuer des vérifications d'état sur la passerelle d'entrée et configurer Identity-Aware Proxy. Commencez par collecter quelques valeurs de la passerelle d'entrée sur les vérifications d'état :

    • Port d'entrée de la vérification de l'état : port utilisé pour la vérification de l'état d'istio-ingress.

      export HC_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')

    • Chemin d'entrée de la vérification de l'état : chemin de la vérification de l'état d'istio-ingress.

      export HC_INGRESS_PATH=$(kubectl get pods -n istio-system -l app=istio-ingressgateway -o jsonpath='{.items[0].spec.containers[?(@.name=="istio-proxy")].readinessProbe.httpGet.path}')

    cat <<EOF | kubectl apply -n istio-system -f -
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: http-hc-config
    spec:
      healthCheck:
        checkIntervalSec: 2
        timeoutSec: 1
        healthyThreshold: 1
        unhealthyThreshold: 10
        port: ${HC_INGRESS_PORT}
        type: HTTP
        requestPath: ${HC_INGRESS_PATH}
      iap:
        enabled: true
        oauthclientCredentials:
          secretName: my-secret
    EOF
  3. Annotez le service Ingress avec votre BackendConfig.

        kubectl annotate -n istio-system service/istio-ingressgateway --overwrite \
          cloud.google.com/backend-config='{"default": "http-hc-config"}' \
          cloud.google.com/neg='{"ingress":false}'
    
  4. Créez l'équilibreur de charge en définissant la ressource Ingress.

    • Définissez l'annotation networking.gke.io/managed-certificates sur le nom du certificat que vous avez créé à l'étape précédente, example-certificate.

    • Définissez l'annotation kubernetes.io/ingress.global-static-ip-name sur le nom de l'adresse IP statique que vous avez réservée, example-static-ip.

    • Définissez serviceName sur istio-ingressgateway, qui est utilisé dans la ressource de passerelle pour l'exemple Bookinfo.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: example-ingress
      namespace: istio-system
      annotations:
        kubernetes.io/ingress.global-static-ip-name: example-static-ip
        networking.gke.io/managed-certificates: example-certificate
    spec:
      defaultBackend:
        service:
          name: istio-ingressgateway
          port:
            number: 80
    EOF
  5. Dans la console Google Cloud, accédez à la page Kubernetes Engine > Services et entrée :

    Accéder à la page Services et entrée

    Le message "Création d'entrée" doit s'afficher dans la colonne État. Attendez que GKE provisionne entièrement l'entrée avant de continuer. Actualisez la page toutes les deux ou trois minutes pour obtenir l'état le plus récent de l'entrée. Une fois l'entrée provisionnée, l'état "OK" ou le message d'erreur "Tous les services de backend sont DÉFAILLANTS" peut s'afficher. L'une des ressources provisionnées par GKE est une vérification de l'état par défaut. Si le message d'erreur s'affiche, cela signifie que l'entrée est provisionnée et que la vérification de l'état par défaut a été exécutée. Lorsque l'état "OK" ou le message d'erreur s'affiche, passez à la section suivante pour configurer les vérifications de l'état pour l'équilibreur de charge.

Configurer la liste d'accès IAP

Ajoutez un utilisateur à la règle d'accès pour IAP :

gcloud beta iap web add-iam-policy-binding \
    --member=user:EMAIL_ADDRESS \
    --role=roles/iap.httpsResourceAccessor

EMAIL_ADDRESS est l'adresse e-mail complète de l'utilisateur, telle que alice@example.com.

  1. Testez l'équilibreur de charge. Pointez votre navigateur sur :

    http://DOMAIN_NAME/productpage

    DOMAIN_NAME est le nom de domaine que vous avez configuré avec l'adresse IP statique externe.

    Le service productpage de l'application Bookinfo devrait s'afficher. Si vous actualisez la page plusieurs fois, vous devriez voir différentes versions d'avis présentées à tour de rôle : étoiles rouges, étoiles noires, sans étoiles.

    Vous devez également tester l'accès https à Bookinfo.

Activer la compatibilité du jeton RCToken sur le maillage de services

Par défaut, IAP génère un jeton Web JSON (JWT) limité au client OAuth. Pour Cloud Service Mesh, vous pouvez configurer IAP pour générer RequestContextToken (RCToken), qui est un jeton JWT, mais avec une audience configurable. RCToken vous permet de configurer l'audience du jeton JWT vers une chaîne arbitraire, qui peut être utilisée dans les stratégies Cloud Service Mesh pour une autorisation précise.

Pour configurer le jeton RCToken, procédez comme suit :

  1. Créez une variable d'environnement pour l'audience du jeton RCToken. Vous pouvez choisir n'importe quelle chaîne.

    export RCTOKEN_AUD="your-rctoken-aud"
    
  2. Facultatif : L'étape suivante nécessite la commande BACKEND_SERVICE_ID. Si vous devez connaître la valeur de BACKEND_SERVICE_ID, exécutez la commande suivante :

    kubectl -n istio-system get Ingress example-ingress -o json | jq \
     '.metadata.annotations."ingress.kubernetes.io/backends"'
    

    Le résultat attendu est semblable à "{\"BACKEND_SERVICE_ID\":\"HEALTHY\"}". Par exemple, "ingress.kubernetes.io/backends": "{\"k8s-be-31224--51f3b55cd1457fb6\":\"HEALTHY\"}". Dans cet exemple, BACKEND_SERVICE_ID est k8s-be-31224--51f3b55cd1457fb6.

  3. Récupérez les paramètres IAP existants.

    gcloud iap settings get --format json \
    --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID > iapSettings.json
    
  4. Mettez à jour IapSettings avec l'audience du jeton RCToken.

    cat iapSettings.json | jq --arg RCTOKEN_AUD_STR $RCTOKEN_AUD \
    '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \
    > updatedIapSettings.json
    
    gcloud iap settings set updatedIapSettings.json --format json \
    --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID
    
  5. Activez l'authentification RCToken sur la passerelle d'entrée Istio.

    cat <<EOF | kubectl apply -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "RequestAuthentication"
    metadata:
      name: "ingressgateway-jwt-policy"
      namespace: "istio-system"
    spec:
      selector:
        matchLabels:
          app: istio-ingressgateway
      jwtRules:
      - issuer: "https://cloud.google.com/iap"
        jwksUri: "https://www.gstatic.com/iap/verify/public_key-jwk"
        audiences:
        - $RCTOKEN_AUD
        fromHeaders:
        - name: ingress-authorization
          prefix: "Istio "
        outputPayloadToHeader: "verified-jwt"
        forwardOriginalToken: true
    EOF
    
  6. Facultatif : assurez-vous que les requêtes ne disposant pas de jetons JWT valides sont rejetées :

      cat <<EOF | kubectl apply -f -
      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: iap-gateway-require-jwt
        namespace: istio-system
      spec:
        selector:
          matchLabels:
            app: istio-iap-ingressgateway
        action: DENY
        rules:
          - from:
              - source:
                  notRequestPrincipals: ["*"]
      EOF
      

  7. Assurez-vous que les requêtes adressées à Bookinfo productpage aboutissent :

    http://DOMAIN_NAME/productpage

Pour tester la stratégie, procédez comme suit :

  1. Créez un objet de requête IapSettings, mais définissez la valeur rctokenAud sur une chaîne différente :

    cat iapSettings.json | jq --arg RCTOKEN_AUD_STR wrong-rctoken-aud \
    '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \
    > wrongIapSettings.json
    
  2. Appelez l'API IapSettings pour définir l'audience du jeton RCToken.

    gcloud beta iap settings set wrongIapSettings.json --project=PROJECT_ID --resource-type=compute --service=BACKEND_SERVICE
  3. Envoyez une requête au service productpage Bookinfo. Celle-ci devrait échouer :

    http://DOMAIN_NAME/productpage

Effectuer un nettoyage

Une fois ce tutoriel terminé, supprimez les ressources suivantes pour éviter que des frais supplémentaires ne soient facturés sur votre compte :

  1. Supprimez le certificat géré :

    kubectl delete managedcertificates example-certificate
  2. Supprimez l'objet Ingress, ce qui libère les ressources d'équilibrage de charge :

    kubectl -n istio-system delete ingress example-ingress

  3. Supprimez l'adresse IP statique :

    gcloud compute addresses delete example-static-ip --global

    Si vous procédez ainsi, veillez à supprimer l'adresse IP de votre service d'enregistrement de noms de domaine.

  4. Supprimez le cluster : cette étape supprime les ressources qui constituent le cluster, telles que les instances de calcul, les disques et les ressources réseau :

    gcloud container clusters delete CLUSTER_NAME