Integra IAP en Anthos Service Mesh

En esta guía, se describe cómo integrar Identity-Aware Proxy (IAP) en Anthos Service Mesh. La integración de IAP en Anthos Service Mesh te permite acceder de forma segura a los servicios según los principios de BeyondCorp de Google. IAP verifica la identidad del usuario y el contexto de la solicitud para determinar si el usuario debe tener acceso a una aplicación o un recurso. La integración de IAP en Anthos Service Mesh te brinda los siguientes beneficios:

  • Completa el control de acceso adaptado al contexto en las cargas de trabajo que se ejecutan en Anthos Service Mesh. Puedes configurar políticas de acceso detalladas según los atributos de la solicitud de origen, como la identidad del usuario, la dirección IP y el tipo de dispositivo. Puedes combinar tus políticas de acceso con restricciones según el nombre de host y la ruta de acceso de una URL de solicitud.

  • Habilita la compatibilidad con reclamaciones contextuales en la autorización de Anthos Service Mesh.

  • Proporciona acceso escalable, seguro y con alta disponibilidad a tu aplicación a través de un balanceador de cargas de Google Cloud. El balanceo de cargas de alto rendimiento proporciona protección integrada contra ataques de denegación de servicio distribuido (DSD) y compatibilidad con direcciones IP Anycast globales.

Requisitos previos

En esta guía, suponemos que ya tienes lo siguiente:

Configura un clúster con Anthos Service Mesh

La integración de IAP requiere una configuración específica en tu proyecto, tu clúster y los archivos de configuración que usas cuando instalas Anthos Service Mesh.

Instalaciones nuevas

Los pasos de esta sección complementan los pasos en la guía Instalación avanzada en GKE. En estos pasos, se usan las variables de entorno que creas en la guía de instalación.

  1. Cuando configuras tu proyecto, habilita iap.googleapis.com además de las otras API requeridas.

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. Cuando actualizas tu clúster, habilita el complemento HttpLoadBalancing además de las otras actualizaciones del clúster requeridas. El complemento HttpLoadBalancing habilita un controlador de balanceo de cargas de HTTP (L7) para el clúster.

    gcloud container clusters update ${CLUSTER_NAME} \
      --project=PROJECT_ID \
      --update-addons=HttpLoadBalancing=ENABLED
    

    Si no configuraste una zona o una región predeterminada, debes proporcionar la región (--region=${CLUSTER_LOCATION}) o la zona (--zone=${CLUSTER_LOCATION}) en el comando anterior.

  3. Después de actualizar el clúster, continúa con la guía de instalación para configurar credenciales y permisos y descargar el archivo de instalación. Detente en la sección Prepara archivos de configuración de los recursos y realiza los siguientes pasos en su lugar.

    1. Crea un directorio nuevo para los archivos de configuración de recursos del paquete de Anthos Service Mesh. Recomendamos que uses el nombre del clúster como el nombre del directorio.

    2. Cambia al directorio en el que deseas descargar el paquete de Anthos Service Mesh.

    3. Descarga el paquete asm-iap. Este paquete configura el campo type en el servicio istio-ingressgateway como NodePort. En esta configuración, istio-ingressgateway abre un puerto específico en la malla de servicios. Esto te permite configurar un balanceador de cargas, que enruta el tráfico enviado a tu nombre de dominio a este puerto.

      kpt pkg get https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm-iap@release-1.6-asm asm
      
    4. Configura el ID del proyecto en el que se creó el clúster:

      kpt cfg set asm gcloud.core.project PROJECT_ID
      
    5. Configura el número de proyecto para el proyecto host de la flota:

      kpt cfg set asm gcloud.project.environProjectNumber ${FLEET_PROJECT_NUMBER}
      
    6. Configura el nombre del clúster:

      kpt cfg set asm gcloud.container.cluster ${CLUSTER_NAME}
      
    7. Establece la zona o región predeterminada:

      kpt cfg set asm gcloud.compute.location ${CLUSTER_LOCATION}
      
    8. Configura el webhook de validación para usar una etiqueta de revisión:

      kpt cfg set asm anthos.servicemesh.rev asm-1614-2
      
    9. Establece el perfil de configuración. Para la integración de IAP, configura el perfil asm-gcp:

      kpt cfg set asm anthos.servicemesh.profile asm-gcp
      
    10. Configura los puertos de estado y HTTP para el balanceador de cargas. El puerto de estado predeterminado es 31223, y el puerto HTTP predeterminado es 31224. Si estos puertos ya están en uso, configúralos:

      kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
      
      kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT
      
    11. Muestra los valores de los métodos set de kpt:

      kpt cfg list-setters asm
      

      En el resultado del comando, verifica que los valores de los siguientes métodos set sean correctos:

      • anthos.servicemesh.rev
      • gcloud.compute.location
      • gcloud.container.cluster
      • gcloud.container.cluster.ingress.httpPort
      • gcloud.container.cluster.ingress.statusPort
      • gcloud.core.project
      • gcloud.project.environProjectNumber
  4. Continúa con la guía de instalación en la sección Instala Anthos Service Mesh. Después de instalar Anthos Service Mesh, regresa a esta guía y continúa con la siguiente sección para configurar la integración con IAP.

Actualizaciones

Los pasos de esta sección complementan los pasos en la guía Actualiza Anthos Service Mesh en GKE. En estos pasos, se usan las variables de entorno que creas en la guía de actualización. En esta sección, se abarcan los siguientes casos de uso de actualización:

  • Ya configuraste la integración de IAP y realizas la actualización de Anthos Service Mesh. En este caso, ya habilitaste iap.googleapis.com en el proyecto y el complemento HttpLoadBalancing en el clúster, por lo que puedes pasar al paso 3.

  • Estás actualizando Anthos Service Mesh y quieres configurar la integración con IAP por primera vez. En este caso, debes completar todos los pasos siguientes, actualizar Anthos Service Mesh y volver a esta guía después de la actualización para completar la integración.

  1. Habilita iap.googleapis.com.

    gcloud services enable \
      --project=$PROJECT_ID \
      iap.googleapis.com
    
  2. Habilita el complemento HttpLoadBalancing. El complemento HttpLoadBalancing habilita un controlador de balanceo de cargas HTTP (L7) para el clúster.

    gcloud container clusters update ${CLUSTER_NAME} \
      --project=PROJECT_ID \
      --update-addons=HttpLoadBalancing=ENABLED
    

    Si no configuraste una zona o una región predeterminada, debes proporcionar la región (--region=${CLUSTER_LOCATION}) o la zona (--zone=${CLUSTER_LOCATION}) en el comando anterior.

  3. Continúa con la guía de actualización para configurar credenciales y permisos y descargar el archivo de instalación. Detente en la sección Prepara archivos de configuración de los recursos y realiza los siguientes pasos en su lugar.

    1. Crea un directorio nuevo para los archivos de configuración de recursos del paquete de Anthos Service Mesh. Recomendamos que uses el nombre del clúster como el nombre del directorio.

    2. Cambia al directorio en el que deseas descargar el paquete de Anthos Service Mesh.

    3. Descarga el paquete asm-iap. Este paquete configura el campo type en el servicio istio-ingressgateway como NodePort. En esta configuración, istio-ingressgateway abre un puerto específico en la malla de servicios. Esto te permite configurar un balanceador de cargas, que enruta el tráfico enviado a tu nombre de dominio a este puerto.

      kpt pkg get https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm-iap@release-1.6-asm asm
      
    4. Configura el ID del proyecto en el que se creó el clúster:

      kpt cfg set asm gcloud.core.project PROJECT_ID
      
    5. Configura el número de proyecto para el proyecto host de la flota:

      kpt cfg set asm gcloud.project.environProjectNumber ${FLEET_PROJECT_NUMBER}
      
    6. Configura el nombre del clúster:

      kpt cfg set asm gcloud.container.cluster ${CLUSTER_NAME}
      
    7. Establece la zona o región predeterminada:

      kpt cfg set asm gcloud.compute.location ${CLUSTER_LOCATION}
      
    8. Configura el webhook de validación para usar una etiqueta de revisión:

      kpt cfg set asm anthos.servicemesh.rev asm-1614-2
      
    9. Establece el perfil de configuración. Para la integración de IAP, configura el perfil asm-gcp:

      kpt cfg set asm anthos.servicemesh.profile asm-gcp
      
    10. Configura los puertos de estado y HTTP para el balanceador de cargas. El puerto de estado predeterminado es 31223, y el puerto HTTP predeterminado es 31224.

      Si actualizas un balanceador de cargas HTTP existente de Cloud, ejecuta lo siguiente para conservar los puertos HTTP y de estado existentes:

      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}')
      

      Si es necesario, puedes usar los métodos set kpt anteriores a fin de establecer otros valores para los puertos.

    11. Muestra los valores de los métodos set de kpt:

      kpt cfg list-setters asm
      

      En el resultado del comando, verifica que los valores de los siguientes métodos set sean correctos:

      • anthos.servicemesh.rev
      • gcloud.compute.location
      • gcloud.container.cluster
      • gcloud.container.cluster.ingress.httpPort
      • gcloud.container.cluster.ingress.statusPort
      • gcloud.core.project
      • gcloud.project.environProjectNumber
  4. Continúa con la guía de actualización en la sección Actualiza Anthos Service Mesh.

Reserva una dirección IP estática y configura el DNS

Para integrar Identity-Aware Proxy en Anthos Service Mesh, debes configurar un balanceador de cargas HTTP(S) de Google Cloud, que requiere un nombre de dominio que apunte a una dirección IP estática. Puedes reservar una dirección IP externa estática, que asigna la dirección a tu proyecto de forma indefinida hasta que se libere de manera explícita.

  1. Reserva una dirección IP externa estática:

    gcloud compute addresses create example-static-ip --global
    
  2. Obtén la dirección IP estática:

    gcloud compute addresses describe example-static-ip --global
    
  3. En tu registrador de nombres de dominio, configura un nombre de dominio completamente calificado (FQDN) con la dirección IP estática. Por lo general, agregas un registro A a tu configuración de DNS. Los pasos de configuración y la terminología necesarias a fin de agregar un registro A para un FQDN varían según el registrador de nombres de dominio.

    La propagación de la configuración de DNS puede llevar entre 24 y 48 horas. Puedes seguir con los otros ajustes en esta guía, pero no podrás probarla hasta que se propague la configuración del DNS.

Implementa una aplicación de muestra

Antes de habilitar IAP, necesitas una aplicación que se ejecute en tu clúster de GKE para que puedas verificar que todas las solicitudes tengan una identidad. En esta guía, se usa el ejemplo de Bookinfo para demostrar cómo configurar el balanceador de cargas de HTTP(S) y habilitar IAP.

Sigue los pasos para implementar Bookinfo. Hasta que implementes el balanceador de cargas, la aplicación Bookinfo no será accesible fuera de tu clúster de GKE (por ejemplo, desde un navegador).

Solicitudes externas

El recurso de puerta de enlace de Bookinfo (definido en samples/bookinfo/networking/bookinfo-gateway.yaml) usa istio-ingressgateway preconfigurado. Recuerda que cuando implementaste Anthos Service Mesh, especificaste NodePort para istio-ingressgateway, que abre un puerto específico en la malla de servicios. Aunque los nodos de tu clúster tienen direcciones IP externas, las reglas de firewall de Google Cloud bloquean las solicitudes que provienen de afuera del clúster. Con IAP, la forma correcta de exponer las aplicaciones a la Internet pública es mediante un balanceador de cargas. No expongas las direcciones del nodo mediante reglas de firewall, que podrían omitir IAP.

Para enrutar solicitudes a Bookinfo, configura un balanceador de cargas HTTP(S) en tu proyecto de Google Cloud. Debido a que el balanceador de cargas está en tu proyecto, está dentro del firewall y puede acceder a los nodos en tu clúster. Después de configurar el balanceador de cargas con la dirección IP estática y tu nombre de dominio, puedes enviar solicitudes al nombre de dominio, y el balanceador de cargas reenviará las solicitudes a los nodos del clúster.

Habilita IAP

En los siguientes pasos, se describe cómo habilitar IAP.

  1. Para verificar si ya tienes una marca existente, usa el comando list. Solo puedes tener una marca por proyecto.

    gcloud iap oauth-brands list
    

    El siguiente es un ejemplo de respuesta de gcloud, si la marca existe:

    name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID]
    applicationTitle: [APPLICATION_TITLE]
    supportEmail: [SUPPORT_EMAIL]
    orgInternalOnly: true
    
  2. Si no existe una marca, usa el comando create:

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

    Los campos anteriores son obligatorios cuando se llama a esta API:

    • supportEmail: Es el correo electrónico de asistencia que se muestra en la pantalla de consentimiento de OAuth. Esta dirección de correo electrónico puede ser la dirección de un usuario o un alias de Grupos de Google. Si bien las cuentas de servicio también tienen una dirección de correo electrónico, no son direcciones de correo electrónico válidas reales y no se pueden usar cuando se crea una marca. Sin embargo, una cuenta de servicio puede ser propietaria de un Grupo de Google. Crea un Grupo de Google nuevo o configura un grupo existente y configura la cuenta de servicio deseada como propietaria del grupo.

    • applicationTitle: Es el nombre de la aplicación que se muestra en la pantalla de consentimiento de OAuth.

    La respuesta contiene los siguientes campos:

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

Crea un cliente de OAuth para IAP

  1. Usa el comando create para crear un cliente. Usa la marca name del paso anterior:

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

    La respuesta contiene los siguientes campos:

    name: projects/[PROJECT_NUMBER]/brands/[BRAND_NAME]/identityAwareProxyClients/[CLIENT_ID]
    secret: [CLIENT_SECRET]
    displayName: [NAME]
    
  2. Usa el ID de cliente (CLIENT_ID en el paso anterior) y CLIENT_SECRET para habilitar IAP. Crea un secreto de Kubernetes con los materiales de tu cliente de OAuth:

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

Implementa el balanceador de cargas

Puedes usar un recurso Ingress para crear un balanceador de cargas de HTTP(S) con certificados SSL configurados de forma automática. Los certificados SSL administrados por Google se aprovisionan, renuevan y administran para tu dominio.

  1. Crea un recurso ManagedCertificate. Este recurso especifica el dominio para el certificado SSL. La lista spec.domains debe contener solo un dominio. No se admiten dominios comodines. En el siguiente YAML, reemplaza DOMAIN_NAME por el nombre de dominio que configuraste para la dirección IP estática externa.

    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. Crea un recurso BackendConfig. Este recurso le indica a GCLB cómo realizar verificaciones de estado en la puerta de enlace de entrada y cómo configurar Identity-Aware Proxy. Primero, recopila algunos valores de la puerta de enlace de entrada sobre las verificaciones de estado:

    • Puerto de entrada de la verificación de estado: Este es el puerto de verificación de estado de istio-ingress.

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

    • Ruta de acceso de la verificación de estado de la entrada: Esta es la ruta de la verificación de estado de 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. Anota el servicio de entrada con tu 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. Crea el balanceador de cargas mediante la definición del recurso Ingress.

    • Configura la anotación networking.gke.io/managed-certificates con el nombre del certificado que creaste en el paso anterior, example-certificate.

    • Configura la anotación kubernetes.io/ingress.global-static-ip-name con el nombre de la dirección IP estática que reservaste, example-static-ip.

    • Configura serviceName como istio-ingressgateway, que se usa en el recurso Gateway para la muestra de 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. En la consola de Google Cloud, ve a la página Kubernetes Engine > Ingress y servicios.

    Ir a la página Ingress y Service

    Deberías ver el mensaje “Creando Ingress” en la columna Estado. Espera a que GKE aprovisione por completo el Ingress antes de continuar. Actualiza la página cada pocos minutos para obtener el estado más actualizado del Ingress. Después de aprovisionar el Ingress, es posible que veas el estado “Ok” o el error “Todos los servicios de backend están en EN MAL ESTADO”. Uno de los recursos que GKE aprovisiona es una verificación de estado predeterminada. Si ves el mensaje de error, significa que se aprovisiona el Ingress y que se ejecutó la verificación de estado predeterminada. Cuando veas el estado “Ok” o el error, continúa con la siguiente sección para configurar las verificaciones de estado del balanceador de cargas.

Configura la lista de acceso de IAP

Agrega un usuario a la política de acceso de IAP:

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

En el ejemplo anterior, EMAIL_ADDRESS es la dirección de correo electrónico completa del usuario, como alice@example.com.

  1. Prueba el balanceador de cargas. Apunta el navegador con el siguiente comando:

    http://DOMAIN_NAME/productpage

    En el ejemplo anterior, DOMAIN_NAME es el nombre de dominio que configuraste con la dirección IP estática externa.

    Deberías ver la productpage de la aplicación Bookinfo. Si actualizas la página varias veces, deberías ver diferentes reseñas, en un estilo round robin: estrellas rojas, estrellas negras, sin estrellas.

    También debes probar el acceso de https a Bookinfo.

Habilita la compatibilidad con RCToken en la malla de servicios

De forma predeterminada, IAP genera un token web JSON (JWT) con alcance para el cliente de OAuth. Para Anthos Service Mesh, puedes configurar IAP a fin de generar un RequestContextToken (RCToken), que es un JWT pero con un público configurable. Los RCToken te permiten configurar el público del JWT en una string arbitraria, que se puede usar en las políticas de Anthos Service Mesh para obtener una autorización detallada.

Para configurar el RCToken, haz lo siguiente:

  1. Crea una variable de entorno para tu número de proyecto. Este es el número que se generó y asignó de forma automática a tu proyecto cuando lo creaste (no es lo mismo que el ID del proyecto):

    export PROJECT_NUMBER=YOUR_PROJECT_NUMBER
  2. Crea una variable de entorno para el público del RCToken. Puede ser cualquier string que desees:

    export RCTOKEN_AUD="your-rctoken-aud"
    
  3. Recupera la configuración de IAP:

    gcloud beta iap settings get --format json \
    --project=${PROJECT_NUMBER} --resource-type=compute > iapSettings.json
    
  4. Actualiza IapSettings con el público del 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=${PROJECT_NUMBER} --resource-type=compute
    
  5. Habilita la autenticación de RCToken en la puerta de enlace de entrada de 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. Asegúrate de que las solicitudes a la productpage de Bookinfo aún tengan éxito:

    http://DOMAIN_NAME/productpage

Para probar la política, haz lo siguiente:

  1. Crea un objeto de solicitud IapSettings, pero establece rctokenAud en una string diferente:

    echo $(cat <<EOF
    {
       "name": "projects/${PROJECT_NUMBER}/iap_web/compute",
       "applicationSettings": {
         "csmSettings": {
           "rctokenAud": "some-other-arbitrary-string"
         }
       }
     }
    EOF
    ) > request.txt
  2. Llama a la API de IapSettings para configurar el público del RCToken:

    curl --request PATCH --header "Authorization: Bearer $(gcloud beta auth application-default print-access-token)" ${IAP_SETTINGS_API}
  3. Realiza una solicitud a la productpage de Bookinfo, que debería fallar:

    http://DOMAIN_NAME/productpage

Realice una limpieza

Después de completar este instructivo, quita los siguientes recursos para evitar que se realicen cargos no deseados en tu cuenta:

  1. Borra el certificado administrado:

    kubectl delete managedcertificates example-certificate
  2. Borra el Ingress, lo que quita la asignación de los recursos del balanceo de cargas:

    kubectl -n istio-system delete ingress example-ingress

  3. Borra la dirección IP estática:

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

    Si haces esto, asegúrate de borrar la dirección IP del registrador de tu dominio.

  4. Borra el clúster, lo que borrará los recursos que conforman el clúster, como las instancias de procesamiento, los discos y los recursos de red:

    gcloud container clusters delete ${CLUSTER_NAME}