Intégrer IAP avec Anthos Service Mesh

Ce guide explique comment intégrer Identity-Aware Proxy (IAP) à Anthos Service Mesh. L'intégration d'IAP à Anthos 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 à Anthos Service Mesh offre les avantages suivants :

  • Contrôle complet de l'accès contextuel aux charges de travail exécutées sur Anthos 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 Anthos 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

Ce guide suppose que vous disposez des éléments suivants :

Configurer un cluster avec Anthos Service Mesh

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

Nouvelles installations

  1. Activer iap.googleapis.com Dans la commande suivante, remplacez PROJECT_ID par le projet dans lequel vous allez installer Anthos 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 Anthos 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. Téléchargez le package asm, qui contient un fichier de configuration appelé iap-operator.yaml dans le répertoire asm/istio/options :

    kpt pkg get \
    https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm@release-1.7-asm asm
    

    Lorsque vous installez Anthos 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.

  4. 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
    
  5. 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
    
  6. Suivez les étapes de la page Installer Anthos Service Mesh sur GKE afin d'utiliser un script fourni par Google pour installer Anthos Service Mesh. Lorsque vous exécutez le script, incluez l'option suivante :

    --custom_overlay asm/istio/options/iap-operator.yaml
    

    Exemple :

    ./install_asm \
      --project_id PROJECT_ID \
      --cluster_name CLUSTER_NAME \
      --cluster_location CLUSTER_LOCATION \
      --mode install \
      --enable_apis \
      --custom_overlay asm/istio/options/iap-operator.yaml
    

Après avoir installé Anthos Service Mesh, revenez à ce guide et passez à la section suivante pour configurer l'intégration avec IAP.

Licences

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 Anthos 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 Anthos Service Mesh.

  • Vous mettez à niveau Anthos Service Mesh et souhaitez configurer l'intégration avec IAP pour la première fois. Dans ce cas, vous devez suivre toutes les étapes ci-dessous, mettre à niveau Anthos 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_ID par le projet dans lequel vous allez installer Anthos 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 Anthos 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. Téléchargez le package asm, qui contient un fichier de configuration appelé iap-operator.yaml dans le répertoire asm/istio/options :

    kpt pkg get \
    https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm@release-1.7-asm asm
    

    Lorsque vous mettez à niveau Anthos 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.

  4. 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}')
    
  5. Suivez les étapes de la page Installer Anthos Service Mesh sur GKE afin d'utiliser un script fourni par Google pour mettre à jour Anthos Service Mesh. Lorsque vous exécutez le script, incluez l'option suivante :

    --custom_overlay asm/istio/options/iap-operator.yaml
    

    Exemple :

    ./install_asm \
      --project_id PROJECT_ID \
      --cluster_name CLUSTER_NAME \
      --cluster_location CLUSTER_LOCATION \
      --mode upgrade \
      --enable_apis \
      --custom_overlay asm/istio/options/iap-operator.yaml
    

Réserver une adresse IP statique et configurer le DNS

Pour intégrer Identity-Aware Proxy à Anthos 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é Anthos 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/v1beta1
    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 de vérification de l'état 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 de l'état d'istio-ingress.

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

    cat <<EOF | kubectl apply -n istio-system -f -
    apiVersion: cloud.google.com/v1beta1
    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 create -f -
    apiVersion: extensions/v1beta1
    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:
      backend:
        serviceName: istio-ingressgateway
        servicePort: 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ées"

    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 Anthos Service Mesh, vous pouvez configurer IAP pour générer un jeton 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 Anthos Service Mesh pour une autorisation précise.

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

  1. Créez une variable d'environnement pour votre numéro de projet. Il s'agit du numéro généré automatiquement et attribué à votre projet lors de sa création. (Cette valeur est différente de l'ID de projet).

    export PROJECT_NUMBER=YOUR_PROJECT_NUMBER
  2. 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"
    
  3. Récupérez les paramètres IAP existants

    gcloud beta iap settings get --format json \
    --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=BACKEND_SERVICE > 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 beta iap settings set updatedIapSettings.json --format json \
    --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=BACKEND_SERVICE
    
  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 :

      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: ["*"]
      

  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 :

    echo $(cat <<EOF
    {
       "name": "projects/YOUR_PROJECT_NUMBER/iap_web/compute/services/BACKEND_SERVICE",
       "applicationSettings": {
         "csmSettings": {
           "rctokenAud": "some-other-arbitrary-string"
         }
       }
     }
    EOF
    ) > request.txt
  2. Appelez l'API IapSettings pour définir l'audience du jeton RCToken.

    gcloud beta iap settings update request.txt --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=${BACKEND_SERVICE}
  3. Envoyez une requête au service productpage Bookinfo. Celle-ci devrait échouer :

    http://DOMAIN_NAME/productpage

Nettoyer

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 la ressource Ingress, 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, qui supprime les ressources qui le composent, telles que les instances de calcul, les disques et les ressources réseau:

    gcloud container clusters delete ${CLUSTER_NAME}