Integra IAP en Cloud Service Mesh
En esta guía, se describe cómo integrar Identity-Aware Proxy (IAP) con Cloud Service Mesh. La integración de IAP en Cloud 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 Cloud Service Mesh te brinda los siguientes beneficios:
Completa el control de acceso adaptado al contexto en las cargas de trabajo que se ejecutan en Cloud 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 Cloud 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
Sigue los pasos que se indican en Instala herramientas dependientes y valida el clúster para hacer lo siguiente:- Instala las herramientas requeridas
- Descarga
asmcli
- Otorga permisos de administrador del clúster
- Valida tu proyecto y clúster
Además, en esta guía se supone que cuentas con lo siguiente:
Configura un clúster con Cloud Service Mesh
En esta sección, se explica cómo prepararse para la integración de IAP tanto para las nuevas instalaciones de Cloud Service Mesh como para las actualizaciones.
Instalaciones nuevas
Habilita
iap.googleapis.com
. En el siguiente comando, reemplazaPROJECT_ID
por el proyecto en el que instalarás Cloud Service Mesh:gcloud services enable \ --project=PROJECT_ID \ iap.googleapis.com
El clúster que actualizas debe tener establecida la opción
--addons=HttpLoadBalancing
. El complementoHttpLoadBalancing
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 Cloud 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
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. 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
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
Sigue los pasos que se indican en Instala funciones predeterminadas y la CA de Mesh usar una secuencia de comandos proporcionada por Google para instalar Cloud Service Mesh. Cuando ejecutes la secuencia de comandos, incluye la siguiente opción:
--option iap-operator
Por ejemplo:
./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
Cuando instalas Cloud Service Mesh, el archivo
iap-operator.yaml
configura el campotype
en el servicioistio-ingressgateway
comoNodePort
, 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.Si instalas Cloud Service Mesh administrado, completa también los siguientes pasos:
Aplica la etiqueta de revisión al espacio de nombres
istio-system
.Descarga la especificación del servicio de puerta de enlace de entrada de Istio para IAP y asígnale el nombre
iap_operator.yaml
.Instala el puerto de entrada como un servicio de NodePort. Si quieres obtener más información, consulta Migra desde IstioOperator.
asmcli experimental mcp-migrate-check -f iap_operator.yaml istioctl install -f /asm-generated-configs/gateways-istiooperator/"GATEWAY_NAME".yaml
Después de instalar Cloud Service Mesh, regresa a esta guía y continúa con en 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 con IAP actualizando Cloud Service Mesh. En este caso, ya habilitaste
iap.googleapis.com
en tu proyecto y el complementoHttpLoadBalancing
en tu clúster. Ve al paso 3 para descargar el paqueteasm
y actualizar Cloud Service Mesh.Estás actualizando Cloud Service Mesh y quieres configurar la integración con IAP por primera vez. En este caso, debes completar todos los pasos siguientes, actualizar Cloud Service Mesh y volver a esta guía después de la actualización para completar la integración.
Habilita
iap.googleapis.com
. En el siguiente comando, reemplazaPROJECT_ID
por el proyecto en el que instalarás Cloud Service Mesh.gcloud services enable \ --project=PROJECT_ID \ iap.googleapis.com
El clúster que actualizas debe tener establecida la opción
--addons=HttpLoadBalancing
. El complementoHttpLoadBalancing
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 Cloud 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
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}')
Sigue los pasos que se indican en Actualiza Cloud Service Mesh usar una secuencia de comandos proporcionada por Google para actualizar Cloud Service Mesh.
Cuando actualizas Cloud Service Mesh, el archivo
iap-operator.yaml
establece latype
del servicioistio-ingressgateway
aNodePort
, 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.Cuando ejecutes la secuencia de comandos, incluye la siguiente opción:
--option iap-operator
Por ejemplo:
./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
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 Cloud 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.
Reserva una dirección IP externa estática:
gcloud compute addresses create example-static-ip --global
Obtén la dirección IP estática:
gcloud compute addresses describe example-static-ip --global
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 registroA
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 Cloud 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 de 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.
Configura la pantalla de consentimiento
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
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
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]
Usa el ID de cliente (
CLIENT_ID
en el paso anterior) yCLIENT_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 se aprovisionan, renuevan y administran para tu dominio.
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, reemplazaDOMAIN_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
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 del Ingress: Esta es la ruta de acceso de la verificación de estado de 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
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}'
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
comoistio-ingressgateway
, que se usa en el recurso Gateway para la muestra de 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
En la consola de Google Cloud, ve a la página Kubernetes Engine > Ingress y servicios.
Ir a la página Ingress y servicios
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
.
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 Cloud Service Mesh, puedes configurar IAP para 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 cadena arbitraria, que se puede usar en las políticas de Cloud Service Mesh para obtener una autorización detallada.
Para configurar el RCToken, haz lo siguiente:
Crea una variable de entorno para el público del RCToken. Puede ser cualquier string que desees:
export RCTOKEN_AUD="your-rctoken-aud"
Opcional: En el siguiente paso, se requiere
BACKEND_SERVICE_ID
. Si necesitas averiguarBACKEND_SERVICE_ID
, ejecuta el siguiente comando:kubectl -n istio-system get Ingress example-ingress -o json | jq \ '.metadata.annotations."ingress.kubernetes.io/backends"'
El resultado esperado es similar a
"{\"BACKEND_SERVICE_ID\":\"HEALTHY\"}"
. Por ejemplo:"ingress.kubernetes.io/backends": "{\"k8s-be-31224--51f3b55cd1457fb6\":\"HEALTHY\"}"
ElBACKEND_SERVICE_ID
en este ejemplo esk8s-be-31224--51f3b55cd1457fb6
.Recupera la configuración de IAP existente.
gcloud iap settings get --format json \ --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID > iapSettings.json
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=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID
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
Opcional: Asegúrate de que se rechacen las solicitudes que no tienen JWT válidos:
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
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:
Crea un objeto de solicitud
IapSettings
, pero establecerctokenAud
en una string diferente:cat iapSettings.json | jq --arg RCTOKEN_AUD_STR wrong-rctoken-aud \ '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \ > wrongIapSettings.json
Llama a la API de
IapSettings
para configurar el público del RCToken:gcloud beta iap settings set wrongIapSettings.json --project=PROJECT_ID --resource-type=compute --service=BACKEND_SERVICE
Realiza una solicitud a la
productpage
de Bookinfo, que debería fallar:http://DOMAIN_NAME/productpage
Realiza una limpieza
Después de completar este instructivo, quita los siguientes recursos para evitar que se realicen cargos no deseados en tu cuenta:
Borra el certificado administrado:
kubectl delete managedcertificates example-certificate
Borra el Ingress, lo que quita la asignación de los recursos del balanceo de cargas:
kubectl -n istio-system delete ingress example-ingress
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.
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