Integrar IAP con 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 con Cloud Service Mesh te permite acceder de forma segura a los servicios basados en los principios de BeyondCorp de Google. IAP verifica la identidad de los usuarios y el contexto de la solicitud para determinar si se les debe conceder acceso a una aplicación o a un recurso. La integración de IAP con Cloud Service Mesh te ofrece las siguientes ventajas:
Control contextual completo del acceso a las cargas de trabajo que se ejecutan en Cloud Service Mesh. Puedes definir políticas de acceso detalladas basadas en 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 basadas en el nombre de host y la ruta de una URL de solicitud.
Habilita la compatibilidad con las reclamaciones contextuales en la autorización de Cloud Service Mesh.
Acceso escalable, seguro y de alta disponibilidad a tu aplicación a través de un balanceador de carga de Google Cloud. El balanceo de carga de alto rendimiento ofrece protección integrada contra ataques de denegación de servicio distribuido (DDoS) y admite direcciones IP anycast globales.
Requisitos previos
Sigue los pasos que se indican en Instalar herramientas dependientes y validar el clúster para:- Instalar las herramientas necesarias
- Descargar
asmcli
- Conceder permisos de administrador de clústeres
- Validar el proyecto y el clúster
Además, en esta guía se da por hecho que tienes lo siguiente:
Configurar un clúster con Cloud Service Mesh
En esta sección se explica cómo configurar la integración de IAP tanto para las nuevas instalaciones de Cloud Service Mesh como para las actualizaciones.
Nuevas instalaciones
Habilita
iap.googleapis.com
. En el siguiente comando, sustituyePROJECT_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 estés actualizando debe tener la opción
--addons=HttpLoadBalancing
definida. El complementoHttpLoadBalancing
habilita un controlador de balanceo de carga 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 definido una zona o una región predeterminadas, debes indicar 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 configurado como puerto de estado y el puerto 31224 configurado como puerto HTTP. Si el puerto 31223 ya está en uso en tu clúster, ejecuta lo siguiente para definir 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 definir otro puerto http:
kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
Sigue los pasos que se indican en el artículo Instalar las funciones predeterminadas y Mesh CA para usar una secuencia de comandos proporcionada por Google e 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
define el campotype
del servicioistio-ingressgateway
comoNodePort
, lo que configura la puerta de enlace para que abra un puerto específico en la malla de servicios. De esta forma, puedes configurar un balanceador de carga que dirija el tráfico enviado a tu nombre de dominio a este puerto.Si vas a instalar Cloud Service Mesh gestionado, sigue también estos pasos:
Añade la etiqueta de revisión al espacio de nombres
istio-system
.Descarga la especificación del servicio de pasarela de entrada de Istio para IAP y llámala
iap_operator.yaml
.Instala el ingreso como un servicio NodePort. Para obtener más información, consulta el artículo Migrar 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, vuelve a esta guía y continúa con la sección siguiente para configurar la integración con IAP.
Actualizaciones
En esta sección se tratan los siguientes casos prácticos de actualización:
Ya has configurado la integración de IAP y vas a actualizar Cloud Service Mesh. En este caso, ya has habilitado
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, sustituyePROJECT_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 estés actualizando debe tener la opción
--addons=HttpLoadBalancing
definida. El complementoHttpLoadBalancing
habilita un controlador de balanceo de carga 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 definido una zona o una región predeterminadas, debes indicar 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 vas a actualizar un balanceador de carga HTTP de Cloud que ya funciona, ejecuta el siguiente comando para conservar los puertos HTTP y de estado:
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 Actualizar Cloud Service Mesh para usar una secuencia de comandos proporcionada por Google y actualizar Cloud Service Mesh.
Cuando actualizas Cloud Service Mesh, el archivo
iap-operator.yaml
define el campotype
del servicioistio-ingressgateway
enNodePort
, lo que configura la puerta de enlace para que abra un puerto específico en la malla de servicios. De esta forma, puedes configurar un balanceador de carga que dirija el tráfico enviado a tu nombre de dominio a este puerto.De forma predeterminada, el archivo
iap-operator.yaml
tiene el puerto 31223 configurado como puerto de estado y el puerto 31224 configurado como 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
Completa la actualización activando la inyección automática del proxy sidecar en tus cargas de trabajo. Para obtener más información, consulta Implementar y volver a implementar cargas de trabajo.
Una vez que hayas completado la actualización, vuelve a esta guía y continúa con la siguiente sección para configurar la integración con las compras en la aplicación.
Reservar una dirección IP estática y configurar DNS
Para integrar Identity-Aware Proxy con Cloud Service Mesh, debes configurar unGoogle Cloud balanceador de carga HTTP(S), lo 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 indefinidamente hasta que la liberes explícitamente.
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 completo (FQDN) con la dirección IP estática. Normalmente, se añade un registro
A
a la configuración de DNS. Los pasos de configuración y la terminología para añadir unA
registro de un FQDN varían en función del registrador de nombres de dominio.El ajuste de DNS puede tardar entre 24 y 48 horas en propagarse. Puedes seguir configurando todo lo que se indica en esta guía, pero no podrás probar la configuración hasta que se propaguen los ajustes de DNS.
Desplegar una aplicación de ejemplo
Antes de habilitar las compras en la aplicación, necesitas una aplicación que se ejecute en tu clúster de GKE para verificar que todas las solicitudes tengan una identidad. En esta guía se usa la muestra Bookinfo para mostrar cómo configurar el balanceador de carga HTTP(S) y habilitar IAP.
Sigue los pasos para desplegar Bookinfo. Hasta que despliegues el balanceador de carga, no se podrá acceder a la aplicación Bookinfo fuera del clúster de GKE (por ejemplo, desde un navegador).
Solicitudes externas
El recurso de pasarela de Bookinfo (definido en samples/bookinfo/networking/bookinfo-gateway.yaml
) usa el istio-ingressgateway
preconfigurado.
Recuerda que, cuando desplegaste Cloud Service Mesh, especificaste NodePort
para el
istio-ingressgateway
, lo que abre un puerto específico en la malla de servicios.
Aunque los nodos de tu clúster tienen direcciones IP externas, las solicitudes procedentes de fuera del clúster están bloqueadas por Google Cloud reglas de firewall. Con las compras en aplicaciones, la forma correcta de exponer las aplicaciones a Internet es mediante un balanceador de carga. No expongas las direcciones de los nodos mediante reglas de cortafuegos, ya que se saltaría IAP.
Para enrutar las solicitudes a Bookinfo, debes configurar un balanceador de carga HTTP(S) en tuGoogle Cloud proyecto. Como el balanceador de carga está en tu proyecto, se encuentra dentro del firewall y puede acceder a los nodos de tu clúster. Una vez que hayas configurado el balanceador de carga con la dirección IP estática y el nombre de dominio, podrás enviar solicitudes al nombre de dominio. El balanceador de carga reenviará las solicitudes a los nodos del clúster.
Habilitar IAP
En los siguientes pasos se describe cómo habilitar IAP.
Configurar la pantalla de consentimiento
Comprueba si ya tienes una marca con el comando list. Solo puedes tener una marca por proyecto.
gcloud iap oauth-brands list
A continuación, se muestra 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 hay ninguna marca, usa el comando create:
gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_email=SUPPORT_EMAIL
Los campos anteriores son obligatorios al llamar a esta API:
supportEmail
: el correo de asistencia que se muestra en la pantalla de consentimiento de OAuth. Esta dirección de correo puede ser la de un usuario o un alias de Grupos de Google. Aunque las cuentas de servicio también tienen una dirección de correo, no son direcciones de correo válidas y no se pueden usar para crear una marca. Sin embargo, una cuenta de servicio puede ser la propietaria de un grupo de Google. Crea un grupo de Google o configura uno que ya tengas y asigna la cuenta de servicio que quieras como propietario del grupo.applicationTitle
: 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
Crear un cliente de OAuth de 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 las compras en la aplicación. 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
Desplegar el balanceador de carga
Puedes usar un recurso Ingress para crear un balanceador de carga HTTP(S) con certificados SSL configurados automáticamente. Los certificados SSL gestionados se aprovisionan, renuevan y gestionan para tu dominio.
Crea un recurso ManagedCertificate. Este recurso especifica el dominio del certificado SSL. La lista
spec.domains
solo debe contener un dominio. No se admiten dominios comodín. En el siguiente archivo YAML, sustituyeDOMAIN_NAME
por el nombre de dominio que has configurado 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 indica a GCLB cómo realizar comprobaciones de estado en la puerta de enlace de entrada, así como configurar Identity-Aware Proxy. Primero, recoge algunos valores de la puerta de enlace Ingress sobre las comprobaciones de estado:
Puerto de entrada de comprobación del estado: es el puerto de comprobación del 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 comprobación del estado de entrada: es la ruta de comprobación del 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 carga definiendo el recurso Ingress.
Define la anotación
networking.gke.io/managed-certificates
con el nombre del certificado que has creado en el paso anterior,example-certificate
.Asigna la anotación
kubernetes.io/ingress.global-static-ip-name
al nombre de la dirección IP estática que has reservado,example-static-ip
.Asigna el valor
istio-ingressgateway
aserviceName
, que se usa en el recurso Gateway del ejemplo 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 Google Cloud consola, ve a la página Kubernetes Engine > Servicios y entradas.
Ir a la página Servicios e Ingress
Debería ver el mensaje "Creando entrada" en la columna Estado. Espera a que GKE aprovisione completamente el Ingress antes de continuar. Actualiza la página cada pocos minutos para obtener el estado más reciente de la entrada. Una vez que se haya aprovisionado el Ingress, puede que veas el estado "Ok" o el error "All backend services are in UNHEALTHY state" (Todos los servicios backend están en mal estado). Uno de los recursos que aprovisiona GKE es una comprobación del estado predeterminada. Si ves el mensaje de error, significa que el Ingress se ha aprovisionado y que se ha ejecutado la comprobación de estado predeterminada. Cuando veas el estado "Ok" o el error, ve a la siguiente sección para configurar las comprobaciones de estado del balanceador de carga.
Configurar la lista de acceso de IAP
Añade 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
donde EMAIL_ADDRESS
es la dirección de correo completa del usuario,
como alice@example.com
.
Prueba el balanceador de carga. Dirige tu navegador a:
http://DOMAIN_NAME/productpage
donde
DOMAIN_NAME
es el nombre de dominio que has configurado con la dirección IP estática externa.Deberías ver el
productpage
de la aplicación Bookinfo. Si actualiza la página varias veces, debería ver diferentes versiones de las reseñas, presentadas de forma rotatoria: estrellas rojas, estrellas negras y sin estrellas.También debes probar el acceso
https
a Bookinfo.
Habilitar la compatibilidad con RCToken en la malla de servicios
De forma predeterminada, IAP genera un JSON Web Token (JWT) cuyo ámbito es el cliente de OAuth. En Cloud Service Mesh, puedes configurar IAP para generar un RequestContextToken (RCToken), que es un JWT, pero con una audiencia configurable. RCToken te permite configurar la audiencia del JWT en una cadena arbitraria, que se puede usar en las políticas de Cloud Service Mesh para una autorización pormenorizada.
Para configurar el RCToken, sigue estos pasos:
Crea una variable de entorno para la audiencia de RCToken. Puede ser cualquier cadena que quieras.
export RCTOKEN_AUD="your-rctoken-aud"
Opcional: Para completar el siguiente paso, necesitas la
BACKEND_SERVICE_ID
. Si necesitas saber elBACKEND_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 al de
"{\"BACKEND_SERVICE_ID\":\"HEALTHY\"}"
. Por ejemplo,"ingress.kubernetes.io/backends": "{\"k8s-be-31224--51f3b55cd1457fb6\":\"HEALTHY\"}"
. ElBACKEND_SERVICE_ID
de este ejemplo esk8s-be-31224--51f3b55cd1457fb6
.Obtiene los ajustes de compra en la aplicación.
gcloud iap settings get --format json \ --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID > iapSettings.json
Actualiza
IapSettings
con la audiencia de 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 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 tengan JWTs 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
Comprueba que las solicitudes a Bookinfo
productpage
se sigan realizando correctamente:http://DOMAIN_NAME/productpage
Para probar la política, sigue estos pasos:
Crea un objeto de solicitud
IapSettings
, pero asigna arctokenAud
una cadena diferente:cat iapSettings.json | jq --arg RCTOKEN_AUD_STR wrong-rctoken-aud \ '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \ > wrongIapSettings.json
Llama a la API
IapSettings
para definir la audiencia de RCToken.gcloud beta iap settings set wrongIapSettings.json --project=PROJECT_ID --resource-type=compute --service=BACKEND_SERVICE
Haz una solicitud a Bookinfo
productpage
y debería fallar:http://DOMAIN_NAME/productpage
Eliminar los recursos utilizados
Después de completar este tutorial, elimina los siguientes recursos para evitar que se apliquen cargos no deseados a tu cuenta:
Elimina el certificado gestionado:
kubectl delete managedcertificates example-certificate
Elimina el Ingress, lo que desasigna los recursos de balanceo de carga:
kubectl -n istio-system delete ingress example-ingress
Elimina la dirección IP estática:
gcloud compute addresses delete example-static-ip --global
Si lo haces, asegúrate de eliminar la dirección IP del registrador de tu dominio.
Elimina el clúster, lo que eliminará los recursos que lo componen, como las instancias de computación, los discos y los recursos de red:
gcloud container clusters delete CLUSTER_NAME