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

En esta sección, se explica cómo configurar la integración de IAP para instalaciones nuevas de Anthos Service Mesh y actualizaciones.

Instalaciones nuevas

  1. Habilita iap.googleapis.com. En el siguiente comando, reemplaza PROJECT_ID por el proyecto en el que instalarás Anthos Service Mesh:

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. El clúster que actualizas debe tener establecida la opción --addons=HttpLoadBalancing. El complemento HttpLoadBalancing habilita un controlador de balanceo de cargas de HTTP (L7) para el clúster. Ejecuta el siguiente comando para actualizar el clúster con las opciones que requiere Anthos Service Mesh. A menos que hayas configurado una zona o región predeterminada, debes proporcionar la región (--region=REGION) o la zona (--zone=ZONE) en el comando.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID \
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Descarga el paquete asm, que contiene un archivo de configuración llamado iap-operator.yaml en el directorio asm/istio/options:

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

    Cuando instalas Anthos Service Mesh, el archivo iap-operator.yaml configura el campo type en el servicio istio-ingressgateway como NodePort, que configura la puerta de enlace para abrir 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.

    De forma predeterminada, el archivo iap-operator.yaml tiene el puerto 31223 como el puerto de estado y el puerto 31224 configurado como el puerto http.

  4. Si el puerto 31223 ya está en uso en tu clúster, ejecuta el siguiente comando para configurar otro puerto de estado:

    kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT
    
  5. Si el puerto 31224 ya está en uso en tu clúster, ejecuta el siguiente comando para configurar otro puerto http:

    kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
    
  6. Sigue los pasos en Instala Anthos Service Mesh en GKE para usar la secuencia de comandos que proporciona Google a fin de instalar Anthos Service Mesh. Cuando ejecutes la secuencia de comandos, incluye la siguiente opción:

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

    Por ejemplo:

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

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

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 tu proyecto y el complemento HttpLoadBalancing en tu clúster. Omite el paso 3 para descargar el paquete asm y actualizar Anthos Service Mesh.

  • 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. En el siguiente comando, reemplaza PROJECT_ID por el proyecto en el que instalarás Anthos Service Mesh.

    gcloud services enable \
      --project=PROJECT_ID \
      iap.googleapis.com
    
  2. El clúster que actualizas debe tener establecida la opción --addons=HttpLoadBalancing. El complemento HttpLoadBalancing habilita un controlador de balanceo de cargas de HTTP (L7) para el clúster. Ejecuta el siguiente comando para actualizar el clúster con las opciones que requiere Anthos Service Mesh. A menos que hayas configurado una zona o región predeterminada, debes proporcionar la región (--region=REGION) o la zona (--zone=ZONE) en el comando.

    gcloud container clusters update CLUSTER_NAME \
      --project=PROJECT_ID
      --update-addons=HttpLoadBalancing=ENABLED
    
  3. Descarga el paquete asm, que contiene un archivo de configuración llamado iap-operator.yaml en el directorio asm/istio/options:

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

    Cuando actualizas Anthos Service Mesh, el archivo iap-operator.yaml establece el campo type en el servicio istio-ingressgateway en NodePort, que configura la puerta de enlace para abrir un puerto específico en 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.

    De forma predeterminada, el archivo iap-operator.yaml tiene el puerto 31223 como el puerto de estado y el puerto 31224 configurado como el puerto http.

  4. Si quieres actualizar un balanceador de cargas HTTP existente de Cloud Run, ejecuta lo siguiente para preservar 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}')
    
  5. Sigue los pasos en Actualiza Anthos Service Mesh en GKE para usar la secuencia de comandos que proporciona Google a fin de actualizar Anthos Service Mesh. Cuando ejecutes la secuencia de comandos, incluye la siguiente opción:

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

    Por ejemplo:

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

    Cuando ejecutes la secuencia de comandos, asegúrate de incluir revisioned-istio-ingressgateway.yaml como se muestra en el ejemplo anterior. Con esta opción, la secuencia de comandos crea una Deployment istio-ingressgateway revisado. Esto te permite controlar el cambio a la nueva versión. Si no incluyes esta opción, la secuencia de comandos realiza una actualización in situ de istio-ingressgateway.

  6. Para completar la actualización, activa la inserción automática de proxy de sidecar en las cargas de trabajo. Para obtener más información, consulta Implementa y vuelve a implementar cargas de trabajo.

    Después de completar la actualización, regresa a esta guía y continúa con la siguiente sección para configurar la integración con IAP.

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/v1
    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/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. 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 iap settings get --format json \
    --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=BACKEND_SERVICE > 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 iap settings set updatedIapSettings.json --format json \
    --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=BACKEND_SERVICE
    
  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. Opcional: Asegúrate de que se rechacen las solicitudes que no tienen JWT válidos:

      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. 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/YOUR_PROJECT_NUMBER/iap_web/compute/services/BACKEND_SERVICE",
       "applicationSettings": {
         "csmSettings": {
           "rctokenAud": "some-other-arbitrary-string"
         }
       }
     }
    EOF
    ) > request.txt
  2. Llama a la API de IapSettings para configurar el público del RCToken:

    gcloud beta iap settings update request.txt --project=YOUR_PROJECT_NUMBER --resource-type=compute --service=${BACKEND_SERVICE}
  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}