A lo largo de este curso hemos ido dejando cabos sueltos, y todos son el mismo cabo. En 03-01 escribimos una regla de firewall que permite SSH desde el rango de IAP, y dijimos que el firewall no distingue personas: que "solo Marta y Lucía puedan entrar" se resuelve en otro sitio. En 02-02 limitamos a Lucía al prefijo exportaciones/ del bucket con una condición que no llegamos a explicar. En 02-05 vinculamos los pods de GKE a una cuenta de servicio sin ficheros de clave. En 03-03 dijimos que invalidar la caché exige un rol que no conviene repartir. Ese otro sitio, esa condición y ese rol son IAM.

IAM es el sistema que responde a una única pregunta, formulada millones de veces al día en cada proyecto: ¿puede esta identidad realizar esta acción sobre este recurso? Es, sin exagerar, el servicio más importante de Google Cloud. Una VM mal dimensionada cuesta dinero; un permiso mal dado cuesta la empresa. Y es también el servicio que más gente configura mal, casi siempre de la misma forma: dando Editor a todo el mundo para que las cosas funcionen y prometiéndose ordenarlo más adelante.

En esta lección vas a construir el modelo de permisos real de AlpinaShop: entenderás la ecuación identidad + rol + recurso, sabrás por qué los permisos se dan a grupos y nunca a personas, crearás un rol personalizado para Lucía, diseñarás la matriz completa de accesos de Marta, Dani y Lucía sobre los cuatro proyectos, entenderás las cuentas de servicio y por qué una clave JSON descargada es una bomba de relojería, aprenderás a limitar accesos con condiciones, a diagnosticar por qué alguien no puede hacer algo, y a publicar aplicaciones internas y abrir sesiones SSH sin VPN gracias a IAP.

Aviso. El diseño de permisos tiene implicaciones de seguridad y, según el sector, regulatorias. Lo que sigue es un modelo docente sólido y aplicable, pero antes de llevar a producción un esquema de accesos que gobierne datos personales o financieros, debe revisarlo un profesional de seguridad y cumplimiento.

Contenido

  1. La ecuación de IAM: identidad + rol + recurso
  2. Permisos, roles y políticas: los tres objetos que hay que distinguir
  3. Tipos de identidad
  4. Grupos de Google: la decisión que más simplifica todo
  5. Tipos de rol: básicos, predefinidos y personalizados
  6. Un rol personalizado real: "analista de catálogo" para Lucía
  7. Herencia por la jerarquía y política efectiva
  8. El diseño de accesos de AlpinaShop
  9. Cuentas de servicio: identidades para el software
  10. Impersonación y credenciales de corta duración
  11. Claves JSON: por qué son el problema y qué usar en su lugar
  12. Condiciones de IAM: acceso limitado en el tiempo y por recurso
  13. Diagnóstico: policy-troubleshooter, política efectiva y Recommender
  14. Mínimo privilegio y separación de funciones, paso a paso
  15. IAP: SSH sin IP pública y aplicaciones internas sin VPN

  1. La ecuación de IAM: identidad + rol + recurso

Todo IAM se reduce a una frase:

Una política de permisos vincula quién (identidad) con qué puede hacer (rol) sobre dónde (recurso).

flowchart LR
    subgraph QUIEN["QUIÉN — identidad"]
      U["Usuario<br/>[email protected]"]
      G["Grupo<br/>[email protected]"]
      SA["Cuenta de servicio<br/>sa-catalogo-web@..."]
      F["Identidad federada<br/>GitHub Actions, Entra ID"]
    end
    subgraph QUE["QUÉ — rol"]
      R["roles/storage.objectViewer<br/>= conjunto de permisos<br/>storage.objects.get<br/>storage.objects.list"]
    end
    subgraph DONDE["DÓNDE — recurso"]
      ORG["Organización alpinashop.example"]
      CAR["Carpeta produccion"]
      PRO["Proyecto alpinashop-prod"]
      BUC["Bucket alpinashop-catalogo"]
    end

    QUIEN -->|vinculación| QUE
    QUE -->|aplicada sobre| DONDE
    ORG --> CAR --> PRO --> BUC

Tres consecuencias inmediatas de este modelo:

  • Todo se deniega por defecto. Una identidad sin vinculaciones no puede hacer absolutamente nada. No hay que "quitar" permisos: hay que darlos.
  • La política se adjunta al recurso, no a la persona. No existe "los permisos de Lucía"; existe "la política del proyecto alpinashop-datos", en la que Lucía aparece. Por eso hay que saber dónde mirar.
  • Los permisos son aditivos y se heredan hacia abajo. Un rol concedido en la carpeta produccion se aplica a todos los proyectos de dentro. Y salvo que uses políticas de denegación, nada quita lo que se ha concedido más arriba.

  1. Permisos, roles y políticas: los tres objetos que hay que distinguir

Objeto Qué es Ejemplo ¿Se asigna?
Permiso La unidad atómica, con la forma servicio.recurso.verbo storage.objects.get No. Nunca se asignan permisos sueltos
Rol Un conjunto con nombre de permisos roles/storage.objectViewer Sí. Es lo único que se asigna
Vinculación La pareja (identidad, rol) group:gcp-datos@… → roles/bigquery.dataViewer Es lo que creas con add-iam-policy-binding
Política El conjunto de vinculaciones de un recurso La política de alpinashop-prod Se lee entera con get-iam-policy

Los permisos se corresponden casi uno a uno con llamadas a la API. Cuando la consola te dice "no tienes permiso para realizar esta acción", lo que falta es un permiso concreto; el trabajo consiste en encontrar qué rol lo contiene.

# Que permisos contiene un rol
gcloud iam roles describe roles/storage.objectViewer \
  --format="value(includedPermissions)"

# Que roles predefinidos contienen un permiso concreto
gcloud iam roles list --filter="includedPermissions:compute.urlMaps.invalidateCache" \
  --format="table(name, title)"

Ese segundo comando es oro puro: convierte "necesito poder invalidar la caché del CDN" en "necesito roles/compute.loadBalancerAdmin" sin buscar en la documentación.

  1. Tipos de identidad

En el argot de IAM, una identidad se llama principal y se escribe con un prefijo que indica su tipo:

Prefijo Tipo Ejemplo Uso
user: Persona con cuenta de Google user:[email protected] Solo para excepciones justificadas
group: Grupo de Google group:[email protected] La forma normal de dar permisos a personas
serviceAccount: Identidad de una carga de trabajo serviceAccount:[email protected] Aplicaciones, VM, pods, pipelines
domain: Todo el dominio domain:alpinashop.example Muy amplio; usar con mucho cuidado
principalSet:// Conjunto federado Repositorio de GitHub, grupo de un IdP externo Federación de identidades
allUsers / allAuthenticatedUsers Público — Prácticamente solo para contenido público explícito

Las dos formas de federación merecen distinguirse bien, porque se confunden:

  • Workforce Identity Federation — para personas que ya tienen identidad en un proveedor externo (Microsoft Entra ID, Okta, cualquier OIDC/SAML). Permite que los empleados entren en Google Cloud con las credenciales corporativas sin crear cuentas de Google. Se configura a nivel de organización.
  • Workload Identity Federation — para máquinas y procesos externos: un pipeline de GitHub Actions, un clúster de Kubernetes fuera de Google, una carga en otra nube. El proceso externo presenta su propio token (por ejemplo, el token OIDC que GitHub emite a cada ejecución) y Google se lo cambia por credenciales temporales de una cuenta de servicio.

Esta segunda es hoy la respuesta correcta a "¿cómo despliego desde GitHub sin subir una clave JSON al repositorio?". La veremos aplicada en 06-01, pero conviene saber que existe desde ya, porque elimina de raíz el peor riesgo de esta lección.

  1. Grupos de Google: la decisión que más simplifica todo

Es tentador dar permisos directamente a las personas. Es también la decisión que hace ingobernable el acceso al cabo de un año. Compara:

Permisos a personas Permisos a grupos
Alta de un empleado Repetir N vinculaciones en M proyectos Añadirlo a 1-2 grupos
Baja de un empleado Buscar sus vinculaciones en toda la jerarquía y confiar en no olvidar ninguna Sacarlo del grupo. Fin
Cambio de puesto Auditoría manual completa Cambiar de grupo
Auditoría "¿Quién puede leer producción?" es una búsqueda por toda la jerarquía Mirar quién está en el grupo
Reproducibilidad en Terraform (06-07) El código cambia con cada persona El código nombra grupos, estable durante años

La regla, sin excepciones prácticas:

Los roles se conceden a grupos. Las personas se añaden a grupos. Una vinculación user: en la política de un proyecto es un olor de diseño: o es temporal y lleva una condición de caducidad, o está mal.

Los grupos de AlpinaShop se crean en Google Workspace (o Cloud Identity, que es gratuito para este uso) y deben tener nombres que digan qué son, no quién está dentro:

[email protected]        → infraestructura y redes
[email protected]   → desarrollo de la aplicación
[email protected]        → analítica y datos
[email protected]  → visibilidad de costes
[email protected]    → revisión y auditoría

Un matiz importante: IAM no crea ni gestiona grupos. Los grupos viven en Cloud Identity / Workspace y IAM solo los referencia. La gestión de miembros la hace el administrador de identidad, que puede ser una persona distinta del administrador de la nube. Eso, lejos de ser un inconveniente, es una separación de funciones sana.

  1. Tipos de rol: básicos, predefinidos y personalizados

Tipo Ejemplos Granularidad Veredicto
Básicos (antes "primitivos") roles/owner, roles/editor, roles/viewer Miles de permisos, todo el proyecto Antipatrón. Solo viewer en entornos de juguete
Predefinidos roles/storage.objectViewer, roles/cloudsql.client, roles/compute.networkAdmin Por servicio y por tarea La opción por defecto. Google los mantiene
Personalizados alpinashop.analistaCatalogo La que tú decidas Cuando ningún predefinido encaja. Los mantienes tú

Por qué los básicos son un antipatrón, con concreción y no como dogma:

  • roles/editor incluye la capacidad de crear cuentas de servicio y concederse permisos a través de ellas en muchos escenarios, además de modificar o borrar prácticamente cualquier recurso del proyecto. Es una escalada de privilegios esperando a ocurrir.
  • roles/owner añade la capacidad de modificar la política IAM: quien lo tiene puede darse a sí mismo y a cualquiera todo lo demás, y quitártelo a ti.
  • Los tres son anteriores a la existencia de la mayoría de los servicios. Cuando Google lanza un producto nuevo, sus permisos se incorporan automáticamente a editor. Es decir, los permisos de tus usuarios crecen sin que nadie decida nada.
  • Rompen cualquier auditoría: "¿quién puede borrar la base de datos de producción?" se responde con una lista de veinte personas.

Excepción razonable: en un proyecto de laboratorio personal, roles/owner para ti mismo. En alpinashop-prod, jamás.

Los predefinidos son la respuesta el 90 % de las veces. Están agrupados por servicio y suelen venir en tres sabores: viewer (leer), user/developer (usar), admin (gestionar). Búscalos así:

# Roles predefinidos de Cloud SQL
gcloud iam roles list --filter="name:roles/cloudsql" \
  --format="table(name, title)"

  1. Un rol personalizado real: "analista de catálogo" para Lucía

Lucía necesita, en alpinashop-datos, poder:

  • Consultar las tablas del catálogo y lanzar consultas.
  • Leer las exportaciones del bucket, pero no escribir ni borrar.
  • Ver el estado de las instancias para saber si un informe falló porque la VM estaba parada, pero no apagarlas ni encenderlas.

Ningún rol predefinido dice exactamente eso. roles/viewer le daría acceso de lectura a todo el proyecto, incluidas las políticas IAM y las configuraciones de red. Este es el caso de libro de un rol personalizado.

Primero, descubre qué permisos existen y cuáles se pueden usar en un rol personalizado:

# Permisos aplicables en el proyecto (util para explorar)
gcloud iam list-testable-permissions \
  //cloudresourcemanager.googleapis.com/projects/alpinashop-datos \
  --filter="customRolesSupportLevel!=NOT_SUPPORTED" \
  --format="value(name)" | grep -E "^(bigquery|storage|compute\.instances)"

Ahora el rol, en un fichero YAML que debe estar en el repositorio de infraestructura, porque un rol es código:

# roles/analista-catalogo.yaml
title: "Analista de catálogo"
description: "Consulta de datos del catálogo y lectura de exportaciones. Sin escritura."
stage: "GA"
includedPermissions:
  # --- BigQuery: leer datos y lanzar consultas ---
  - bigquery.datasets.get
  - bigquery.tables.get
  - bigquery.tables.list
  - bigquery.tables.getData
  - bigquery.jobs.create          # necesario para EJECUTAR consultas
  - bigquery.jobs.list
  # --- Cloud Storage: leer las exportaciones ---
  - storage.buckets.get
  - storage.objects.get
  - storage.objects.list
  # --- Compute: ver el estado, nada mas ---
  - compute.instances.get
  - compute.instances.list
  # --- Observabilidad basica ---
  - monitoring.timeSeries.list
# Crear el rol EN EL PROYECTO (tambien puede crearse a nivel de organizacion)
gcloud iam roles create analistaCatalogo \
  --project=alpinashop-datos \
  --file=roles/analista-catalogo.yaml

# Concederselo al grupo, no a Lucia
gcloud projects add-iam-policy-binding alpinashop-datos \
  --member="group:[email protected]" \
  --role="projects/alpinashop-datos/roles/analistaCatalogo"

# Actualizar el rol mas adelante (misma sintaxis, verbo update)
gcloud iam roles update analistaCatalogo \
  --project=alpinashop-datos \
  --file=roles/analista-catalogo.yaml

Cinco cosas que hay que saber sobre los roles personalizados y que solo se aprenden sufriéndolas:

  1. bigquery.jobs.create es el permiso olvidado. Sin él, Lucía ve las tablas pero cualquier consulta falla. La lectura de datos y la ejecución de trabajos son permisos distintos.
  2. stage puede ser ALPHA, BETA, GA o DISABLED. Poner DISABLED es la forma de desactivar un rol sin borrarlo, útil para comprobar si alguien dependía de él.
  3. Se crean en un proyecto o en una organización, no en una carpeta. Si el rol lo van a usar varios proyectos, créalo a nivel de organización (--organization=ORG_ID); si no, se duplica.
  4. Los mantienes tú. Cuando Google añade un permiso nuevo a un servicio, los predefinidos lo incorporan solos; tu rol personalizado, no. Revísalos periódicamente.
  5. Empieza copiando un predefinido y quita, en lugar de partir de cero: gcloud iam roles copy --source=roles/bigquery.dataViewer --destination=... --dest-project=....

  1. Herencia por la jerarquía y política efectiva

La jerarquía de AlpinaShop, que definiste en 01-04:

flowchart TD
    O["Organización<br/>alpinashop.example"]
    F1["Carpeta produccion"]
    F2["Carpeta desarrollo"]
    F3["Carpeta compartido"]
    P1["alpinashop-prod"]
    P2["alpinashop-dev"]
    P3["alpinashop-datos"]
    P4["alpinashop-cicd"]
    R["Bucket alpinashop-catalogo<br/>Instancia alpinashop-pedidos"]

    O --> F1 --> P1 --> R
    O --> F2 --> P2
    O --> F3 --> P3
    F3 --> P4

La política efectiva de un recurso es la unión de las políticas de todos sus ancestros más la suya propia. Consecuencias:

  • Un rol dado en la organización se aplica a los cuatro proyectos y a todos sus recursos. Por eso hay muy pocas cosas que deban concederse ahí.
  • No se puede restar heredando. Si alguien tiene roles/editor en la carpeta produccion, no hay forma de "quitárselo" en alpinashop-prod mediante una política de permisos. La única herramienta que resta son las políticas de denegación (gcloud iam policies), que se evalúan antes que las de permiso y ganan siempre; son la excepción, no el mecanismo habitual, y se tratan junto con el gobierno a escala en 07-07.
  • La regla práctica: concede en el nivel más bajo que resuelva el problema. Si el permiso solo hace falta sobre un bucket, dalo sobre el bucket, no sobre el proyecto.

Muchos recursos aceptan política propia. Compara la granularidad:

# Nivel proyecto
gcloud projects add-iam-policy-binding alpinashop-datos \
  --member="group:[email protected]" \
  --role="roles/bigquery.jobUser"

# Nivel bucket: mucho mas fino
gcloud storage buckets add-iam-policy-binding gs://alpinashop-catalogo \
  --member="serviceAccount:[email protected]" \
  --role="roles/storage.objectViewer"

# Nivel secreto (03-06): lo mas fino posible
gcloud secrets add-iam-policy-binding db-password-catalogo \
  --member="serviceAccount:[email protected]" \
  --role="roles/secretmanager.secretAccessor"

  1. El diseño de accesos de AlpinaShop

Este es el resultado del ejercicio de diseño, y el que debes poder justificar línea a línea:

Grupo Miembros alpinashop-prod alpinashop-dev alpinashop-datos alpinashop-cicd
gcp-infra@ Marta compute.admin, compute.networkAdmin, compute.loadBalancerAdmin, cloudsql.admin, iap.tunnelResourceAccessor owner viewer editor
gcp-desarrollo@ Dani compute.viewer, logging.viewer, errorreporting.viewer, iap.tunnelResourceAccessor editor bigquery.dataViewer cloudbuild.builds.viewer, artifactregistry.writer
gcp-datos@ Lucía (ninguno directo) — analistaCatalogo (personalizado), bigquery.jobUser —
gcp-facturacion@ Marta, dirección billing.viewer a nivel de organización
gcp-seguridad@ Marta (y auditoría externa) iam.securityReviewer a nivel de organización

Léelo con atención, porque las decisiones interesantes son las que no aparecen:

  • Nadie tiene owner en alpinashop-prod. Ni siquiera Marta. La administración de la política IAM de producción se hace mediante una elevación temporal explícita (apartado 12), no con un rol permanente.
  • Dani no puede modificar producción. Puede mirar —métricas, logs, estado de las instancias— porque necesita diagnosticar incidentes, y puede entrar por SSH vía IAP para depurar. Pero no puede desplegar a mano: los cambios entran por el pipeline de alpinashop-cicd (06-01). Eso no es desconfianza, es trazabilidad: todo cambio en producción tiene un commit detrás.
  • Marta sí es owner en alpinashop-dev. El entorno de desarrollo se rompe y se rehace; ahí la fricción no aporta.
  • Lucía no tiene absolutamente nada en producción. Sus datos llegan a alpinashop-datos por replicación y exportación. Si necesitara leer directamente de la réplica alpinashop-pedidos-replica-informes, el permiso sería roles/cloudsql.client sobre esa instancia concreta, con condición, y no un rol de proyecto.
  • La facturación se ve a nivel de organización, no de proyecto, porque las preguntas de coste son transversales (07-05).
  • roles/iam.securityReviewer permite leer todas las políticas IAM sin poder modificar ninguna. Es el rol correcto para auditoría y para responder a "¿quién tiene acceso a qué?".

Aplicado con gcloud, el diseño se escribe así:

ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)

# --- Infraestructura en produccion: administracion, no propiedad ---
for ROL in roles/compute.admin roles/compute.networkAdmin \
           roles/compute.loadBalancerAdmin roles/cloudsql.admin \
           roles/iap.tunnelResourceAccessor; do
  gcloud projects add-iam-policy-binding alpinashop-prod \
    --member="group:[email protected]" \
    --role="$ROL" --condition=None
done

# --- Desarrollo: lectura en produccion, mando en dev ---
for ROL in roles/compute.viewer roles/logging.viewer \
           roles/iap.tunnelResourceAccessor; do
  gcloud projects add-iam-policy-binding alpinashop-prod \
    --member="group:[email protected]" \
    --role="$ROL" --condition=None
done

gcloud projects add-iam-policy-binding alpinashop-dev \
  --member="group:[email protected]" \
  --role="roles/editor" --condition=None

# --- Seguridad y facturacion a nivel de organizacion ---
gcloud organizations add-iam-policy-binding "$ORG_ID" \
  --member="group:[email protected]" \
  --role="roles/iam.securityReviewer"

gcloud organizations add-iam-policy-binding "$ORG_ID" \
  --member="group:[email protected]" \
  --role="roles/billing.viewer"

--condition=None es obligatorio cuando la política ya contiene vinculaciones condicionales; sin él, gcloud pregunta de forma interactiva y el bucle se detiene.

  1. Cuentas de servicio: identidades para el software

Una cuenta de servicio es una identidad que pertenece a la aplicación, no a una persona. Tiene un correo con la forma [email protected] y es a la vez dos cosas, lo cual desconcierta al principio:

  • Una identidad: se le conceden roles, como a un usuario.
  • Un recurso: tiene su propia política IAM, que dice quién puede usarla.

Esa segunda faceta es la que casi nadie ve al principio y la que explica la mitad de los errores de permisos.

# Crear una cuenta de servicio por carga de trabajo
gcloud iam service-accounts create sa-informes-nocturnos \
  --display-name="Proceso nocturno de informes" \
  --description="Lee la replica de pedidos y escribe en BigQuery"

SA="[email protected]"

# 1) Como IDENTIDAD: que puede hacer ella
gcloud projects add-iam-policy-binding alpinashop-datos \
  --member="serviceAccount:$SA" --role="roles/bigquery.dataEditor"

gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="serviceAccount:$SA" --role="roles/cloudsql.client"

# 2) Como RECURSO: quien puede actuar como ella
gcloud iam service-accounts add-iam-policy-binding "$SA" \
  --member="group:[email protected]" \
  --role="roles/iam.serviceAccountTokenCreator"

Las cuentas de servicio de AlpinaShop hasta ahora, y por qué son varias y no una:

Cuenta Carga de trabajo Roles
sa-catalogo-web La aplicación Flask en el MIG storage.objectViewer sobre el bucket, cloudsql.client, secretmanager.secretAccessor sobre dos secretos
sa-migracion-catalogo El proceso puntual de subida inicial storage.objectCreator sobre el bucket
sa-catalogo-gke Los pods del namespace tienda Igual que sa-catalogo-web, vía Workload Identity
sa-informes-nocturnos El proceso batch de Lucía Lectura de la réplica, escritura en BigQuery

Una cuenta de servicio por carga de trabajo. No una por proyecto, no una por equipo. Cuando una credencial se ve comprometida, el radio de daño es exactamente el de esa carga. Y cuando revisas los logs, sabes quién hizo qué sin ambigüedad.

Dos avisos concretos:

  • Nunca uses la cuenta de servicio por defecto de Compute Engine. Se crea automáticamente, viene con roles/editor en el proyecto y todas las VM la usan si no dices otra cosa. Es decir: cualquier código en cualquier VM puede hacer casi cualquier cosa en el proyecto. Créate la tuya y asígnala explícitamente en la plantilla de instancia.
  • roles/iam.serviceAccountUser sobre una cuenta de servicio es más poderoso de lo que parece. Permite lanzar recursos con esa identidad, y por tanto heredar sus permisos. Dárselo sobre una cuenta potente equivale a dar esos permisos.

  1. Impersonación y credenciales de corta duración

La forma correcta de que una persona ejecute algo con los permisos de una cuenta de servicio no es descargarse su clave: es suplantarla (impersonation). Google emite un token de vida corta —típicamente una hora— y no existe ningún fichero de credenciales que robar.

# Requisito: tener roles/iam.serviceAccountTokenCreator sobre esa cuenta
gcloud storage ls gs://alpinashop-catalogo/exportaciones/ \
  --impersonate-service-account=sa-informes-nocturnos@alpinashop-datos.iam.gserviceaccount.com

# Fijarlo para toda la sesion
gcloud config set auth/impersonate_service_account \
  [email protected]

# Obtener un token puntual (para curl contra una API)
gcloud auth print-access-token \
  --impersonate-service-account=sa-informes-nocturnos@alpinashop-datos.iam.gserviceaccount.com

Y para las bibliotecas cliente de Python, la impersonación también funciona sin claves:

from google.auth import default, impersonated_credentials
from google.cloud import storage

credenciales_base, _ = default()

credenciales = impersonated_credentials.Credentials(
    source_credentials=credenciales_base,
    target_principal="[email protected]",
    target_scopes=["https://www.googleapis.com/auth/cloud-platform"],
    lifetime=3600,  # segundos; el maximo habitual es una hora
)

cliente = storage.Client(credentials=credenciales, project="alpinashop-datos")

Ventajas frente a una clave descargada, que conviene enumerar porque es el argumento que tendrás que dar a alguien:

  • Caduca sola. Una hora después no vale nada.
  • Deja rastro. Los logs de auditoría registran que lucia@ suplantó a sa-informes-nocturnos, con lo que la acción tiene dueño humano.
  • Se revoca quitando un rol, no persiguiendo ficheros por los portátiles del equipo.
  • Encadena bien: un proceso puede suplantar a otra cuenta si la política lo permite, formando cadenas auditables.

Relacionado, y muy útil desde el punto de vista organizativo: Privileged Access Manager permite conceder elevaciones temporales con aprobación y caducidad automática —"Marta necesita ser administradora de IAM en producción durante dos horas para arreglar esto"— sin que nadie tenga ese rol de forma permanente. Es la respuesta moderna a "nadie tiene owner en producción, pero alguien tiene que poder arreglarlo a las 3 de la mañana".

  1. Claves JSON: por qué son el problema y qué usar en su lugar

Este comando existe, funciona, y deberías tratarlo como el último recurso:

# Lo que NO se debe hacer salvo que no quede alternativa
gcloud iam service-accounts keys create clave.json \
  --iam-account=sa-informes-nocturnos@alpinashop-datos.iam.gserviceaccount.com

Ese fichero contiene una clave privada RSA que no caduca nunca y que autentica a la cuenta de servicio desde cualquier punto de internet. Sin segundo factor, sin restricción de red, sin caducidad. Lo que pasa después es siempre la misma historia: acaba en un repositorio de Git, en un canal de Slack, en un .env copiado a tres portátiles, o en la imagen de un contenedor publicada en un registro.

Alternativas, en orden de preferencia:

Escenario Solución correcta Claves
Código en una VM de Compute Engine Asignar la cuenta de servicio a la VM; las bibliotecas la detectan solas Ninguna
Pods en GKE Workload Identity (02-05) Ninguna
Cloud Run, Cloud Functions, App Engine Asignar la cuenta de servicio al servicio Ninguna
CI/CD en GitHub Actions, GitLab, Azure DevOps Workload Identity Federation Ninguna
Persona ejecutando algo puntual Impersonación Ninguna
Sistema heredado fuera de Google que no admite OIDC Clave JSON, con rotación forzada y alcance mínimo Una, vigilada

Si acabas en la última fila, al menos:

# Inventario: ¿que claves de usuario existen y desde cuando?
for SA in $(gcloud iam service-accounts list --format="value(email)"); do
  gcloud iam service-accounts keys list --iam-account="$SA" \
    --managed-by=user --format="table[no-heading](name.basename(), validAfterTime)" \
    | sed "s|^|$SA  |"
done

Y bloquea la creación de claves de forma preventiva con la restricción de política de organización constraints/iam.disableServiceAccountKeyCreation, que se explica en 07-07. Es una de las tres o cuatro medidas con mejor relación esfuerzo/riesgo de toda la plataforma.

  1. Condiciones de IAM: acceso limitado en el tiempo y por recurso

Una vinculación condicional solo concede el rol si se cumple una expresión CEL. Sirve para dos cosas muy prácticas.

Caso 1: acceso temporal. Un consultor externo necesita ver logs de producción durante una semana:

gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="user:[email protected]" \
  --role="roles/logging.viewer" \
  --condition='expression=request.time < timestamp("2026-08-20T00:00:00Z"),
               title=acceso-temporal-auditoria-agosto,
               description=Caduca solo el 20 de agosto de 2026'

Esto elimina la deuda de acceso por construcción: el permiso se retira solo, aunque nadie se acuerde. Es la forma correcta de dar cualquier acceso excepcional.

Caso 2: acceso limitado por recurso. Es la condición que dejamos pendiente en 02-02, la que restringe a Lucía al prefijo exportaciones/:

gcloud storage buckets add-iam-policy-binding gs://alpinashop-catalogo \
  --member="group:[email protected]" \
  --role="roles/storage.objectViewer" \
  --condition='expression=resource.name.startsWith("projects/_/buckets/alpinashop-catalogo/objects/exportaciones/"),
               title=solo-prefijo-exportaciones,
               description=Lectura limitada a exportaciones/'

Otros atributos disponibles en las expresiones:

Atributo Ejemplo Uso
request.time request.time < timestamp("...") Caducidad
request.time.getHours("Europe/Madrid") >= 8 && <= 20 Ventanas horarias
resource.name .startsWith(...) / .endsWith(...) Un prefijo, un recurso concreto
resource.type == "compute.googleapis.com/Instance" Un tipo de recurso
request.auth.claims Reclamaciones del token Federación

Limitaciones que hay que conocer antes de diseñar sobre esto:

  • No todos los servicios admiten condiciones sobre resource.name. Cloud Storage, Compute Engine, Secret Manager y BigQuery sí, en distinta medida; otros ignoran el atributo y la condición nunca se cumple, dejando a la persona sin acceso y a ti confundido. Compruébalo siempre en la documentación del servicio concreto.
  • Las condiciones no se pueden usar con roles básicos.
  • Complican el diagnóstico. Una persona con el rol correcto y una condición que no se cumple ve exactamente el mismo error que una persona sin el rol. Por eso existe el apartado siguiente.

  1. Diagnóstico: policy-troubleshooter, política efectiva y Recommender

La pregunta más frecuente de cualquier administrador de la nube es "¿por qué este usuario no puede hacer esto?". Hay una herramienta que la responde directamente:

gcloud policy-troubleshoot iam \
  //cloudresourcemanager.googleapis.com/projects/alpinashop-prod \
  [email protected] \
  --permission=compute.instances.setMetadata

La respuesta no es un sí o un no: es la lista de todas las vinculaciones examinadas en toda la jerarquía, con el veredicto de cada una y el motivo. Ahí se ve si el rol no está, si está pero en el proyecto equivocado, o si está con una condición que no se cumple. Es la diferencia entre diagnosticar y adivinar.

Las otras tres herramientas del kit:

# 1) La politica completa de un recurso
gcloud projects get-iam-policy alpinashop-prod --format=yaml

# 2) Que roles tiene UNA identidad en un proyecto (la consulta inversa)
gcloud projects get-iam-policy alpinashop-prod \
  --flatten="bindings[].members" \
  --filter="bindings.members:[email protected]" \
  --format="table(bindings.role, bindings.condition.title)"

# 3) Buscar una identidad en TODA la organizacion (Cloud Asset Inventory)
gcloud asset search-all-iam-policies \
  --scope="organizations/$ORG_ID" \
  --query="policy:[email protected]" \
  --format="table(resource, policy.bindings.role)"

El comando 3 es el que responde de verdad a "¿qué acceso tiene esta persona?" antes de una baja o de una auditoría. El 2 solo mira un proyecto; el 3 barre organización, carpetas, proyectos y recursos.

IAM Recommender cierra el ciclo: analiza noventa días de uso real y propone quitar permisos que nadie ha ejercido.

gcloud recommender recommendations list \
  --project=alpinashop-prod \
  --location=global \
  --recommender=google.iam.policy.Recommender \
  --format="table(content.overview.member, content.overview.removedRole, priority)"

Sobre estas recomendaciones, dos matices de sentido común: hay permisos que se usan una vez al año —el proceso de cierre contable, la restauración de una copia— y el análisis de noventa días no los ve. Revisa antes de aplicar, y aplica primero sobre las cuentas de servicio, donde el patrón de uso es mucho más estable que el de una persona.

  1. Mínimo privilegio y separación de funciones, paso a paso

Mínimo privilegio: cada identidad tiene exactamente los permisos que necesita, ni uno más. En la práctica es un procedimiento, no una virtud:

  1. Parte de cero. Nunca de Editor con la intención de recortar; ese recorte no llega nunca.
  2. Deja que falle. Ejecuta el trabajo real y anota qué permiso reclama cada error.
  3. Traduce el permiso a rol con gcloud iam roles list --filter="includedPermissions:...".
  4. Concede el predefinido más pequeño que lo contenga; si aún es demasiado grande, rol personalizado.
  5. Concédelo en el nivel más bajo posible: recurso antes que proyecto, proyecto antes que carpeta.
  6. Revisa a los tres meses con Recommender y con search-all-iam-policies.

Separación de funciones: que ninguna identidad pueda completar sola una cadena crítica. Aplicado a AlpinaShop:

Cadena crítica Cómo se separa
Escribir código → desplegar a producción Dani escribe y aprueba PRs; despliega el pipeline con sa-despliegue, no Dani
Crear un permiso → usarlo Quien administra IAM (gcp-infra@) no es quien opera los datos (gcp-datos@)
Generar un gasto → aprobarlo gcp-facturacion@ ve el coste; no puede crear recursos
Actuar → auditar gcp-seguridad@ tiene securityReviewer: lee políticas, no las modifica

Y el corolario que ya está en la tabla del apartado 8: nadie es owner de producción de forma permanente. Cuando hace falta, se eleva de forma temporal, con motivo y con caducidad.

  1. IAP: SSH sin IP pública y aplicaciones internas sin VPN

Identity-Aware Proxy aplica IAM al acceso a la aplicación, no solo a la API. Es el puente entre lo que aprendiste de red en 03-01 y lo que acabas de aprender de identidad. Su idea es la de la confianza cero: la autorización depende de quién eres, no de dónde estás.

Tiene dos usos, y en AlpinaShop usamos los dos.

Uso 1: reenvío TCP para SSH. Ya escribiste la regla fw-allow-ssh-iap que permite el puerto 22 solo desde 35.235.240.0/20. Lo que faltaba era el permiso:

# Quien puede abrir tuneles hacia las VM del proyecto
gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="group:[email protected]" \
  --role="roles/iap.tunnelResourceAccessor"

# Y ademas, poder iniciar sesion en el SO (OS Login, 02-01)
gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="group:[email protected]" \
  --role="roles/compute.osLogin"

# Conexion, sin IP publica en la VM
gcloud compute ssh alpinashop-informes-1 --zone=europe-west1-b --tunnel-through-iap

Aquí está por fin la respuesta al ejercicio pendiente de 03-01: "solo Marta y Lucía pueden entrar por SSH" se implementa con roles/iap.tunnelResourceAccessor y roles/compute.osLogin, no con una regla de firewall. El firewall abre la puerta al rango de IAP; IAM decide quién la cruza. Y si quisiéramos que Lucía entrase solo a la VM de informes y no a las del catálogo, sería una vinculación condicional sobre resource.name.

Uso 2: publicar aplicaciones internas sin VPN. Marta quiere que el panel de informes internos sea accesible desde casa, sin VPN, solo para el personal autorizado. La solución tradicional sería una VPN; la de IAP consiste en poner el panel detrás de un balanceador externo y activar IAP en su servicio de backend:

gcloud compute backend-services update bs-informes-internos --global \
  --iap=enabled

# Quien puede ver la aplicacion
gcloud iap web add-iam-policy-binding \
  --resource-type=backend-services \
  --service=bs-informes-internos \
  --member="group:[email protected]" \
  --role="roles/iap.httpsResourceAccessor"

Flujo de una petición:

sequenceDiagram
    participant L as Lucía (desde casa)
    participant LB as Balanceador global
    participant IAP as Identity-Aware Proxy
    participant G as Google (login + 2FA)
    participant B as bs-informes-internos

    L->>LB: GET https://informes.alpinashop.example/
    LB->>IAP: comprueba autorización
    IAP-->>L: redirige al inicio de sesión
    L->>G: autenticación + segundo factor
    G-->>IAP: identidad verificada
    IAP->>IAP: ¿tiene iap.httpsResourceAccessor?
    IAP->>B: petición + cabecera con la identidad firmada
    B-->>L: panel de informes

Tres detalles que hacen que esto sea seguro de verdad:

  • La aplicación no ve tráfico no autenticado. IAP filtra antes.
  • IAP inyecta la identidad en cabeceras firmadas (X-Goog-IAP-JWT-Assertion), que la aplicación debe validar criptográficamente. Si te limitas a leer el correo de una cabecera sin verificar la firma, cualquiera que alcance el backend directamente puede suplantar a quien quiera.
  • Por eso mismo, el firewall debe seguir impidiendo que nadie llegue al backend saltándose el balanceador: IAP no sustituye a las reglas de red de 03-01, las complementa.

Y se combina de forma natural con lo que viene: Cloud Armor (03-05) filtra por reputación y patrones antes de que IAP pida credenciales, de modo que el tráfico automatizado ni siquiera llega a la pantalla de inicio de sesión.

Errores Comunes y Consejos

  • Conceder roles/editor "para que funcione". Es el error más caro del ecosistema. Dedica quince minutos a encontrar el rol predefinido correcto.
  • Dar permisos a personas en lugar de a grupos. Funciona el primer mes y se convierte en imposible de auditar el primer año.
  • Usar la cuenta de servicio por defecto de Compute Engine. Trae roles/editor de fábrica y la heredan todas las VM que no digan otra cosa.
  • Descargar claves JSON. No caducan, no tienen segundo factor y acaban en Git. Impersonación o Workload Identity Federation, casi siempre.
  • Olvidar que una cuenta de servicio es también un recurso. "Tiene los roles correctos pero no puede usarla" casi siempre significa que falta serviceAccountUser o serviceAccountTokenCreator en la política de la cuenta.
  • Conceder en la organización lo que solo hace falta en un proyecto. Se hereda hacia abajo y no se puede restar.
  • Creer que se puede "quitar" un permiso heredado con otra vinculación. Los permisos son aditivos; solo las políticas de denegación restan (07-07).
  • Condiciones sobre servicios que no las soportan. La vinculación se crea sin error y no funciona nunca. Verifica el soporte del servicio.
  • Confundir autenticación con autorización. gcloud auth login dice quién eres; IAM dice qué puedes. Un error de permisos no se arregla volviendo a autenticarse.
  • Aplicar las recomendaciones del Recommender a ciegas. Noventa días no ven un proceso anual.
  • Olvidar --condition=None en scripts. El comando se queda esperando entrada interactiva y el bucle se cuelga.
  • Consejo: gestiona IAM como código. Terraform (06-07) para las vinculaciones, YAML versionado para los roles personalizados. Un permiso concedido a mano en la consola es un permiso que nadie recordará por qué existe.
  • Consejo: documenta cada excepción en el propio description de la condición. Tu yo de dentro de seis meses te lo agradecerá.

Ejercicios

Ejercicio 1 — "Dani no puede desplegar"

Dani intenta actualizar la plantilla del MIG en alpinashop-prod desde su portátil y recibe PERMISSION_DENIED: compute.instanceGroupManagers.update. Escribe la secuencia de diagnóstico y decide qué hacer. Ten en cuenta la matriz de accesos del apartado 8 antes de responder "concederle el rol".

Ejercicio 2 — Rol personalizado para el proceso nocturno

El proceso batch de Lucía se ejecuta cada noche en alpinashop-informes-1 y debe:

  • Leer la réplica alpinashop-pedidos-replica-informes a través del Auth Proxy.
  • Escribir un fichero CSV en gs://alpinashop-catalogo/exportaciones/<fecha>/.
  • Cargar ese fichero en una tabla de BigQuery del proyecto alpinashop-datos.
  • Leer la contraseña de la réplica desde Secret Manager.
  • No debe poder borrar nada, ni leer las imágenes del catálogo, ni ver otros secretos.

Diseña la solución completa: cuenta de servicio, roles (predefinidos o personalizados), condiciones y en qué nivel de la jerarquía se concede cada cosa. Escribe los comandos.

Ejercicio 3 — Acceso temporal de una auditoría externa

Una consultora externa hará una auditoría de seguridad durante dos semanas, del 1 al 15 de septiembre de 2026. Necesitan leer las configuraciones de red, las políticas IAM y los registros del balanceador de alpinashop-prod, pero no deben ver datos de clientes ni modificar nada. Diseña el acceso y justifica cada decisión.


Soluciones

Solución 1

Diagnóstico:

# 1) ¿Que dice el solucionador de problemas?
gcloud policy-troubleshoot iam \
  //cloudresourcemanager.googleapis.com/projects/alpinashop-prod \
  [email protected] \
  --permission=compute.instanceGroupManagers.update

# 2) ¿Que roles tiene Dani ahi?
gcloud projects get-iam-policy alpinashop-prod \
  --flatten="bindings[].members" \
  --filter="bindings.members:[email protected] OR bindings.members:[email protected]" \
  --format="table(bindings.role, bindings.condition.title)"

# 3) ¿Que rol contendria ese permiso?
gcloud iam roles list \
  --filter="includedPermissions:compute.instanceGroupManagers.update" \
  --format="value(name)"

Resultado esperado: Dani pertenece a gcp-desarrollo@, que en alpinashop-prod solo tiene roles de lectura. El permiso está en roles/compute.instanceGroupManagerAdmin y en roles/compute.admin.

Qué hacer: no concedérselo. La matriz del apartado 8 es una decisión deliberada de separación de funciones: los cambios en producción entran por el pipeline, con un commit, una revisión y trazabilidad. Concederle el rol resolvería el síntoma y destruiría la propiedad que hace confiable el sistema.

Las respuestas correctas, en orden:

  1. Desplegar por el pipeline (06-01): el cambio se hace en el repositorio, se revisa y lo aplica sa-despliegue, que sí tiene el rol en alpinashop-prod.
  2. Si es una emergencia real, una elevación temporal con Privileged Access Manager, o en su defecto una vinculación condicional con caducidad de horas y una descripción que explique el incidente:
gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="user:[email protected]" \
  --role="roles/compute.instanceGroupManagerAdmin" \
  --condition='expression=request.time < timestamp("2026-08-06T06:00:00Z"),
               title=incidente-INC-2026-08-05,
               description=Acceso de emergencia; caduca a las 06:00 UTC'
  1. Si Dani necesita esto cada semana, lo que falla no son los permisos sino el pipeline. Arregla el pipeline.

Solución 2

SA="[email protected]"

gcloud iam service-accounts create sa-informes-nocturnos \
  --project=alpinashop-datos \
  --display-name="Proceso nocturno de informes"

# 1) Leer la replica: rol de cliente EN EL PROYECTO donde vive Cloud SQL
gcloud projects add-iam-policy-binding alpinashop-prod \
  --member="serviceAccount:$SA" \
  --role="roles/cloudsql.client" --condition=None

# 2) Escribir SOLO en exportaciones/: creator, no admin, y con condicion
gcloud storage buckets add-iam-policy-binding gs://alpinashop-catalogo \
  --member="serviceAccount:$SA" \
  --role="roles/storage.objectCreator" \
  --condition='expression=resource.name.startsWith("projects/_/buckets/alpinashop-catalogo/objects/exportaciones/"),
               title=solo-escribe-exportaciones'

# 3) Cargar en BigQuery: escribir datos + poder lanzar trabajos
gcloud projects add-iam-policy-binding alpinashop-datos \
  --member="serviceAccount:$SA" \
  --role="roles/bigquery.dataEditor" --condition=None
gcloud projects add-iam-policy-binding alpinashop-datos \
  --member="serviceAccount:$SA" \
  --role="roles/bigquery.jobUser" --condition=None

# 4) Un unico secreto, a nivel de SECRETO y no de proyecto
gcloud secrets add-iam-policy-binding db-password-informes \
  --project=alpinashop-prod \
  --member="serviceAccount:$SA" \
  --role="roles/secretmanager.secretAccessor"

# 5) Asignar la cuenta a la VM (sin claves)
gcloud compute instances set-service-account alpinashop-informes-1 \
  --zone=europe-west1-b \
  --service-account="$SA" \
  --scopes=https://www.googleapis.com/auth/cloud-platform

Decisiones clave y su porqué:

  • objectCreator en lugar de objectAdmin. Permite crear objetos pero no borrarlos ni sobrescribirlos. Cumple el requisito de "no borrar nada" por construcción, no por confianza.
  • La condición de prefijo impide que el proceso escriba en productos/ aunque tuviera un fallo de programación. Y como no tiene objectViewer, tampoco puede leer las imágenes.
  • El secreto se concede a nivel de secreto. roles/secretmanager.secretAccessor en el proyecto daría acceso a todos los secretos, incluida la clave de la pasarela de pago.
  • cloudsql.client va en alpinashop-prod, que es donde vive la instancia, aunque la cuenta de servicio pertenezca a alpinashop-datos. Una identidad de un proyecto puede tener roles en otro; es completamente normal.
  • Ninguna clave JSON. La VM lleva la cuenta asignada y las bibliotecas de Python la detectan solas.
  • Un rol personalizado no aporta aquí: los predefinidos, acotados con condiciones y aplicados al recurso correcto, ya son suficientemente estrechos. No crees roles personalizados si un predefinido bien colocado resuelve el caso.

Solución 3

# Grupo dedicado, no permisos a correos sueltos
GRUPO="group:[email protected]"
CADUCA='request.time < timestamp("2026-09-16T00:00:00Z")'

for ROL in roles/compute.networkViewer \
           roles/iam.securityReviewer \
           roles/logging.viewer \
           roles/monitoring.viewer; do
  gcloud projects add-iam-policy-binding alpinashop-prod \
    --member="$GRUPO" --role="$ROL" \
    --condition="expression=$CADUCA,
                 title=auditoria-externa-sept-2026,
                 description=Auditoria de seguridad; caduca el 16-09-2026"
done

Justificación:

  • Un grupo propio, aunque sean tres personas de fuera. Se dan de alta y de baja en el grupo, y la política no se toca.
  • Caducidad en todas las vinculaciones. El acceso desaparece solo el día 16. Este es el uso canónico de las condiciones y evita el clásico "el consultor sigue teniendo acceso dos años después".
  • roles/iam.securityReviewer permite leer las políticas IAM sin poder modificarlas: exactamente lo que necesita una auditoría.
  • roles/compute.networkViewer en lugar de roles/compute.viewer: ven la red, las reglas de firewall y el balanceador, pero no los metadatos de las instancias, que pueden contener información sensible.
  • Ningún rol sobre datos. Nada de cloudsql.viewer, storage.objectViewer ni bigquery.dataViewer: pueden auditar la configuración de la base de datos sin leer una sola fila de clientes. Si necesitasen ver datos, tendría que intervenir el responsable de protección de datos y probablemente bastaría con datos anonimizados.
  • Sin acceso a alpinashop-dev ni alpinashop-datos, salvo que el alcance de la auditoría lo exija por escrito.
  • Adicionalmente, revisar en 07-07 que los registros de auditoría de acceso a datos estén activados durante el periodo, para que quede constancia de qué consultó la consultora.

Conclusión

IAM ha dejado de ser el sitio donde uno va a "dar permisos" para convertirse en el diseño que sostiene todo lo demás. Has interiorizado la ecuación identidad + rol + recurso = política de permisos, con sus tres propiedades: todo está denegado por defecto, la política se adjunta al recurso y los permisos se heredan hacia abajo sin poder restarse. Distingues permiso, rol, vinculación y política, y sabes traducir un PERMISSION_DENIED en el rol que lo resuelve con gcloud iam roles list --filter="includedPermissions:...".

Conoces los tipos de identidad —usuarios, grupos, cuentas de servicio y las dos federaciones, Workforce para personas y Workload para máquinas— y has adoptado la regla que más simplifica la operación a largo plazo: los roles se conceden a grupos y las personas se mueven entre grupos. Sabes por qué Owner, Editor y Viewer son un antipatrón (crecen solos, permiten escalada, arruinan la auditoría) y has construido el diseño real de AlpinaShop: gcp-infra@, gcp-desarrollo@, gcp-datos@, gcp-facturacion@ y gcp-seguridad@ con roles distintos en cada uno de los cuatro proyectos, sin que nadie sea owner de producción. Has creado el rol personalizado analistaCatalogo para Lucía en YAML versionado, con el permiso bigquery.jobs.create que casi todo el mundo olvida.

Has entendido la doble naturaleza de las cuentas de servicio —identidad y recurso a la vez—, la regla de una por carga de trabajo, y por qué la cuenta por defecto de Compute Engine no debe usarse jamás. Sabes suplantar cuentas con --impersonate-service-account para obtener credenciales que caducan en una hora y dejan rastro, y tienes la lista ordenada de alternativas a la clave JSON descargada, que es la peor credencial que existe: no caduca, no tiene segundo factor y acaba en Git. Has limitado accesos en el tiempo y por prefijo de recurso con condiciones CEL, resolviendo por fin la restricción de Lucía a exportaciones/ que quedó pendiente en 02-02. Y tienes las cuatro herramientas de diagnóstico: policy-troubleshoot para el "por qué no puede", get-iam-policy para la foto, asset search-all-iam-policies para barrer la organización entera antes de una baja, y el Recommender para recortar lo que nadie usa.

Por último, IAP ha cerrado el círculo entre red e identidad: la regla fw-allow-ssh-iap de 03-01 abre la puerta al rango 35.235.240.0/20, y roles/iap.tunnelResourceAccessor decide quién la cruza; y el panel de informes de Lucía puede publicarse en internet sin VPN porque IAP exige identidad corporativa y segundo factor antes de que la petición llegue al backend.

Pero IAM protege frente a quien tiene una identidad. No dice nada sobre el visitante anónimo que recorre el catálogo a mil peticiones por segundo para copiar los precios, ni sobre el que prueba diez mil contraseñas contra el formulario de acceso, ni sobre el que inyecta ' OR 1=1-- en el buscador. Ese tráfico llega al balanceador sin identidad alguna y hay que filtrarlo antes, en el borde. En la siguiente lección, 03-05, Cloud Armor, ponemos un cortafuegos de aplicación delante del balanceador global: reglas por IP y geografía, protección frente al OWASP Top 10, limitación de tasa contra la fuerza bruta, el imprescindible modo vista previa para no bloquear a tus propios clientes, y la política pol-catalogo-web aplicada a bs-catalogo-web justo a tiempo para la campaña de otoño.

Curso de Google Cloud Platform (GCP)

Módulo 1: Introducción a Google Cloud Platform

Módulo 2: Servicios principales de GCP

Módulo 3: Redes y seguridad

Módulo 4: Datos y análisis

Módulo 5: Aprendizaje automático e IA

Módulo 6: DevOps y monitoreo

Módulo 7: Temas avanzados de GCP

Módulo 8: Proyecto final

© Copyright 2026. Todos los derechos reservados