Google Cloud:
IAM, jerarquía de recursos y los errores típicos
Seguridad en la nube | unfantasmaenelsistema.com
Google Cloud Platform tiene un modelo de permisos elegante sobre el papel y traicionero en la práctica. Elegante porque todo cuelga de un árbol: la organización arriba, las carpetas y los proyectos debajo, y cada recurso hereda las políticas de todo lo que tiene encima. Traicionero porque esa herencia significa que un rol concedido dos niveles más arriba se aplica a cosas que quien lo concedió probablemente ni miró, y porque las cuentas de servicio — la identidad de las máquinas — son la vía de escalada más explotada de GCP.
Este artículo recorre el modelo de IAM de Google Cloud desde la raíz: la jerarquía de recursos y cómo se propaga una política, los tipos de rol y por qué Owner y Editor son un problema, las cuentas de servicio y la suplantación, y el catálogo de errores de configuración que aparecen una y otra vez en las auditorías. El enfoque es defensivo: cómo revisar tu propia organización y cerrar los huecos. Es el espejo en GCP de lo que ya contamos para AWS IAM y para Entra ID.
Qué aprenderas en este articulo
Cómo se hereda una política IAM a través de organización, carpeta, proyecto y recurso · La diferencia entre roles básicos, predefinidos y personalizados, y por qué Owner/Editor sobran casi siempre · Qué es una cuenta de servicio, cómo se suplanta con actAs y por qué las claves descargadas son un riesgo · Allow policies frente a deny policies y para qué sirven las Organization Policies · Los errores de configuración más habituales y las herramientas de Google para detectarlos
1. La jerarquía de recursos: todo cuelga de un árbol
En GCP cada recurso vive en un único punto de una jerarquía con cuatro niveles. Entender esta estructura es imprescindible porque las políticas de permisos se heredan hacia abajo y nunca hacia arriba ni hacia los lados.
| Nivel | Qué es | Papel en seguridad |
|---|---|---|
| Organización | La raíz, ligada a un dominio de Cloud Identity o Google Workspace | Donde se fijan las barreras duras (Organization Policies) y los roles de administración global |
| Carpeta | Agrupación de proyectos, normalmente por departamento, entorno o filial | Punto natural para delegar administración y aplicar políticas por área |
| Proyecto | El contenedor de trabajo real: aquí viven las APIs, la facturación y los recursos | Frontera de aislamiento principal; un compromiso debería quedarse dentro de un proyecto |
| Recurso | La instancia concreta: un bucket, una VM, un dataset de BigQuery, un tópico de Pub/Sub | Permite políticas muy finas, pero conceder aquí a mano no escala y se olvida |
La política efectiva sobre un recurso es la unión de su propia política y la de todos sus ancestros. Si a alguien se le da el rol de editor a nivel de carpeta, lo tiene sobre todos los proyectos presentes y futuros de esa carpeta. No hay forma de restar un permiso concedido más arriba con una allow policy: para eso están las deny policies y las Organization Policies, que vemos más abajo.
Un proyecto sin carpeta es una señal
Los proyectos creados sueltos, colgando directamente de la organización o sin organización ninguna, se escapan de las políticas que aplicas por carpeta · Obliga a que todo proyecto nazca dentro de una carpeta con la Organization Policy `constraints/resourcemanager.uniformBucketLevelAccess` y demás barreras ya aplicadas · Revisa periódicamente el nivel de organización en busca de proyectos huérfanos
2. Cómo se concede el acceso: miembros, roles y bindings
Una política de IAM en GCP es una lista de bindings. Cada binding asocia un rol a uno o varios miembros (principals). Un miembro puede ser una cuenta de usuario de Google, un grupo de Google, una cuenta de servicio, todo un dominio de Workspace, o los identificadores especiales `allUsers` y `allAuthenticatedUsers`.
Un rol es una colección de permisos con el formato `servicio.recurso.verbo`, por ejemplo `storage.objects.get` o `compute.instances.start`. Nunca se conceden permisos sueltos: siempre se concede un rol que los agrupa.
2.1 Los tres tipos de rol
- Roles básicos (Owner, Editor, Viewer): heredados de la época anterior a IAM. Son enormes y transversales a todos los servicios. `Editor` puede modificar casi cualquier recurso; `Owner` además gestiona permisos y facturación. Google recomienda no usarlos salvo en cajas de arena personales
- Roles predefinidos: creados y mantenidos por Google para cada servicio, con un alcance razonable (`roles/storage.objectViewer`, `roles/bigquery.dataEditor`). Son la opción por defecto correcta para la mayoría de casos
- Roles personalizados: los defines tú con la lista exacta de permisos, a nivel de organización o de proyecto. Útiles para el mínimo privilegio estricto, a cambio de tener que mantenerlos cuando Google añade permisos nuevos
Owner y Editor son el comodín doble de GCP
`roles/owner` y `roles/editor` concedidos a personas son la causa número uno de sobre-permiso en las auditorías de GCP · Un miembro con Editor sobre un proyecto puede crear cuentas de servicio, desplegar Cloud Functions y leer casi todos los datos: es una ruta de escalada, no un rol de trabajo · Sustitúyelos por el conjunto mínimo de roles predefinidos que cada persona use de verdad, concedidos preferentemente a un grupo de Google y no a cuentas individuales
3. Cuentas de servicio: la identidad de las máquinas
Una cuenta de servicio es una identidad sin persona detrás que usan las cargas de trabajo (una VM, un pod de GKE, una Cloud Function) para autenticarse ante las APIs de Google. Es a la vez un principal (se le conceden roles) y un recurso (se le pueden conceder permisos a otros sobre ella). Esa doble naturaleza es lo que la convierte en el eje de la escalada de privilegios en GCP.
3.1 Suplantación: el permiso actAs
Si un principal tiene el rol `roles/iam.serviceAccountUser` (o el permiso `iam.serviceAccounts.actAs`) sobre una cuenta de servicio, puede actuar como ella: adjuntarla a una VM que él controla, o pedir un token de acceso con `roles/iam.serviceAccountTokenCreator`. Si esa cuenta de servicio tiene más privilegios que el principal, acaba de escalar. Un caso clásico: un desarrollador con permiso para desplegar una Cloud Function y capacidad de actAs sobre la cuenta de servicio por defecto del proyecto, que arrastra el rol Editor.
3.2 Claves descargadas frente a Workload Identity
- Una clave de cuenta de servicio es un fichero JSON con una clave privada. No caduca, viaja en repositorios, imágenes de contenedor y portátiles, y es el secreto más filtrado de GCP. Evítalas: aplica la Organization Policy `constraints/iam.disableServiceAccountKeyCreation`
- Para cargas dentro de GCP, usa la cuenta de servicio adjunta al recurso: la VM o la función obtiene tokens temporales del metadata server, sin ninguna clave
- Para cargas fuera de GCP (GitHub Actions, otra nube, on-premise), usa Workload Identity Federation: el sistema externo presenta su propio token OIDC y GCP se lo cambia por credenciales temporales, sin clave estática que robar
# Suplantar una cuenta de servicio para una sola orden (sin descargar clave)
gcloud storage ls --impersonate-service-account=svc-informes@mi-proyecto.iam.gserviceaccount.com
# Ver quien puede suplantar una cuenta de servicio concreta
gcloud iam service-accounts get-iam-policy \
svc-informes@mi-proyecto.iam.gserviceaccount.com --format=json
# Listar las claves de una cuenta de servicio (las de tipo USER_MANAGED son las peligrosas)
gcloud iam service-accounts keys list \
--iam-account=svc-informes@mi-proyecto.iam.gserviceaccount.com4. Poner techos: deny policies y Organization Policies
Las allow policies solo suman permisos. Para restar o prohibir de forma que no se pueda deshacer más abajo, GCP ofrece dos mecanismos distintos que a menudo se confunden.
| Mecanismo | Qué controla | Ejemplo de uso |
|---|---|---|
| IAM Deny Policy | Deniega permisos concretos (`iam.googleapis.com/…`) a principals concretos, gane quien gane en las allow policies | Impedir que nadie fuera del equipo de seguridad use `resourcemanager.projects.setIamPolicy` |
| Organization Policy | Restringe la configuración de los recursos, no los permisos de los principals | Prohibir IPs públicas en VMs, limitar regiones, exigir OS Login, desactivar claves de cuenta de servicio |
| VPC Service Controls | Crea un perímetro alrededor de servicios y datos para frenar la exfiltración | Que BigQuery y Cloud Storage de un proyecto solo sean accesibles desde la red corporativa |
El orden mental es: primero se evalúan las deny policies (si alguna aplica, denegado); después la unión de allow policies de todo el árbol; y de forma paralela, las Organization Policies determinan qué configuraciones son siquiera posibles. Un deny explícito gana siempre, igual que en AWS.
Barreras de organización que conviene poner el primer día
`iam.disableServiceAccountKeyCreation` — nada de claves JSON descargables · `iam.automaticIamGrantsForDefaultServiceAccounts` — que la cuenta por defecto no nazca con Editor · `compute.vmExternalIpAccess` — lista blanca de qué VMs pueden tener IP pública · `compute.requireOsLogin` — acceso SSH gestionado por IAM, no por claves en metadatos · `gcp.resourceLocations` — limitar en qué regiones se pueden crear recursos
5. Los errores típicos
Ninguno de estos patrones es exótico. Todos se detectan con las herramientas de la sección siguiente, y casi todos se previenen con una Organization Policy.
| Error | Por qué es peligroso | Mitigación |
|---|---|---|
| Binding a `allUsers` o `allAuthenticatedUsers` | Expone el recurso (bucket, imagen, función, dataset) a todo internet o a cualquier cuenta de Google | Organization Policy `iam.allowedPolicyMemberDomains`; revisar con Security Command Center |
| Roles básicos (Owner/Editor) concedidos a personas | Permiso transversal enorme; cualquier compromiso de esa cuenta es casi total sobre el proyecto | Sustituir por roles predefinidos mínimos concedidos a grupos; Policy Analyzer para ver el uso real |
| Clave USER_MANAGED de cuenta de servicio en un repo o imagen | No caduca, se filtra con facilidad, da acceso persistente sin MFA | Desactivar la creación de claves; migrar a Workload Identity Federation; rotar y borrar las existentes |
| Cuenta de servicio por defecto con Editor adjunta a cargas de trabajo | Un fallo en la aplicación (SSRF, RCE) hereda Editor sobre todo el proyecto | Crear una cuenta de servicio dedicada por carga con roles mínimos; desactivar los grants automáticos |
| `iam.serviceAccountUser` concedido de forma amplia | Permite suplantar cuentas de servicio más privilegiadas: escalada silenciosa | Conceder actAs solo sobre la cuenta de servicio concreta que esa persona necesita |
| Proyecto huérfano fuera de toda carpeta | No recibe las Organization Policies aplicadas por carpeta; punto ciego de auditoría | Forzar la creación bajo carpeta; inventario periódico con Cloud Asset Inventory |
6. Auditar tu propia organización
Google Cloud incluye herramientas de análisis que revisan una organización entera en minutos, todas de solo lectura sobre tu propia infraestructura.
| Herramienta | Qué hace | Coste |
|---|---|---|
| Cloud Asset Inventory | Inventario y exportación de todos los recursos y todas las políticas IAM del árbol, con histórico | Gratuito |
| Policy Analyzer | Responde a «quién puede hacer qué sobre qué» y qué permisos se han usado de verdad | Gratuito |
| IAM Recommender | Sugiere reducir roles sobredimensionados a partir de 90 días de uso real | Gratuito |
| Security Command Center | Detecta bindings a allUsers, claves antiguas, cuentas con roles básicos, buckets públicos | Nivel estándar gratuito |
| Scout Suite / Prowler (GCP) | Auditoría open source multi-nube con informe navegable por severidad | Open source |
# Todos los bindings de IAM del proyecto, expandiendo los grupos
gcloud projects get-iam-policy mi-proyecto --format=json
# Buscar quien tiene un rol basico (owner/editor) en toda la organizacion
gcloud asset search-all-iam-policies --scope=organizations/123456789012 \
--query='policy.role.permissions:"resourcemanager.projects.setIamPolicy"'
# Analizar quien puede leer un bucket concreto y por que herencia
gcloud asset analyze-iam-policy --organization=123456789012 \
--full-resource-name='//storage.googleapis.com/mi-bucket-datos' \
--permissions='storage.objects.get'Uso solo sobre infraestructura propia y con autorización
Ejecutar herramientas de enumeración o análisis de IAM contra organizaciones de Google Cloud que no son tuyas y sin autorización escrita del titular es un acceso ilícito a un sistema informático · En España es aplicable el Código Penal: art. 197 bis (acceso no autorizado), art. 197 ter (facilitación de medios para cometerlo) y art. 264 y siguientes (daños informáticos) · Practica con tu propia organización, con un proyecto de laboratorio creado para ello, o con entornos formativos diseñados a tal fin
7. Mínimo privilegio en GCP, en la práctica
- Concede roles a grupos de Google, no a personas: la baja de un empleado se resuelve en el directorio y no deja permisos sueltos
- Usa roles predefinidos por defecto; sube a roles personalizados solo donde el mínimo privilegio lo justifique; baja de roles básicos siempre
- Concede en el nivel más bajo que tenga sentido: mejor en el proyecto que en la carpeta, mejor en la carpeta que en la organización
- Ninguna clave de cuenta de servicio descargable: cuenta adjunta dentro de GCP, Workload Identity Federation fuera
- Pon las barreras duras como Organization Policies desde el primer día y revísalas cuando Google publica constraints nuevas
- Revisa cada trimestre con Policy Analyzer e IAM Recommender: roles sin usar, bindings a allUsers, cuentas de servicio con exceso de permisos, claves antiguas
Referencias
cloud.google.com/iam/docs — Documentación oficial de IAM y de la jerarquía de recursos · cloud.google.com/iam/docs/deny-overview y cloud.google.com/resource-manager/docs/organization-policy — Deny y Organization Policies · cloud.google.com/iam/docs/workload-identity-federation — Federación de identidad para cargas externas · cloud.google.com/security-command-center/docs — Detección de configuraciones inseguras · Nuestros artículos sobre AWS IAM y sobre Entra ID, para comparar los tres modelos
Conclusión
El modelo de IAM de Google Cloud es coherente y potente, pero su punto fuerte — la herencia a través de la jerarquía — es también donde se cometen los errores: un rol amplio concedido arriba se propaga a sitios que nadie revisó. Y las cuentas de servicio, con su doble papel de identidad y de recurso, son la palanca de escalada que un atacante busca primero.
La defensa es la de siempre y es aburrida: jerarquía ordenada con todo bajo carpetas, roles predefinidos mínimos concedidos a grupos, cero claves descargables, Organization Policies como barreras duras, y una revisión trimestral con las herramientas gratuitas de Google que caduque lo que ya nadie usa. El proyecto abierto al mundo casi nunca es un ataque sofisticado: es un binding a allUsers que nadie volvió a mirar.
unfantasmaenelsistema.com | Seguridad, sistemas y todo lo que no debería funcionar (pero funciona)

