Antes de que un DAG de Composer pueda lanzar un job de Dataflow, y antes de que ese job pueda escribir en una tabla de BigQuery, alguien tiene que decidir qué identidad hace cada cosa y con qué permisos. Eso es IAM, y en un proyecto de datos es tan importante como el propio pipeline.
Tres tipos de roles, tres niveles de riesgo
En Google Cloud, un rol es un conjunto de permisos, y a cada principal (una persona, un grupo o una cuenta de servicio) se le concede acceso asignándole uno o varios roles sobre un recurso. Existen tres categorías:
Roles básicos (también llamados heredados): Owner, Editor y Viewer. Incluyen miles de permisos a lo ancho de todos los servicios de Google Cloud. La propia documentación de Google es tajante al respecto: en entornos de producción no deberían concederse salvo que no exista alternativa.
Roles predefinidos: creados y mantenidos por Google para servicios y casos de uso concretos, como roles/bigquery.dataViewer o roles/storage.objectAdmin. Se actualizan automáticamente cuando un servicio añade funcionalidad, y son la opción recomendada para la mayoría de los casos.
Roles personalizados: definidos por ti, combinando exactamente los permisos que necesitas, ni uno más. Son la herramienta para cuando ni siquiera el rol predefinido más ajustado encaja con lo que un proceso concreto necesita hacer.
El principio de mínimo privilegio no es una recomendación abstracta de seguridad, es una pregunta muy concreta que conviene hacerse por cada rol que concedes: «¿esta identidad necesita de verdad este permiso para hacer su trabajo, o se lo estoy dando porque es más rápido que pensarlo dos veces?».
Cuentas de servicio: la identidad de tus pipelines
Una cuenta de servicio es una identidad especial, no asociada a una persona, pensada para que la use una aplicación o una carga de trabajo. Se identifica por una dirección de correo propia y, como cualquier principal, se le pueden conceder roles de IAM. Cuando un job de Dataflow se ejecuta, o cuando una tarea de un DAG en Composer llama a la API de BigQuery, no lo hace con tu usuario personal: lo hace con la cuenta de servicio que tenga asociada ese recurso.
Por eso, tanto los entornos de Cloud Composer como los jobs de Dataflow llevan asociada una cuenta de servicio (por defecto, una genérica del proyecto, aunque lo recomendable es usar una dedicada) sobre la que se conceden únicamente los roles necesarios: por ejemplo, roles/bigquery.dataEditor para escribir en una tabla concreta, o roles/storage.objectViewer para leer archivos de un bucket, en lugar de un rol amplio sobre todo el proyecto.
Buenas prácticas para un equipo de datos
- Usa una cuenta de servicio distinta por pipeline o por entorno, nunca una única cuenta compartida por todos los jobs del proyecto.
- Concede roles a nivel de dataset o de bucket concreto cuando sea posible, en lugar de a nivel de proyecto completo.
- Evita generar y descargar claves JSON de cuentas de servicio; en Compute Engine, Dataflow o Composer, la identidad ya se puede vincular al recurso sin necesidad de gestionar claves.
- Nombra las cuentas de servicio de forma descriptiva (por ejemplo, algo como
dataflow-ingesta-eventos) para saber de un vistazo qué proceso hay detrás. - Revisa periódicamente qué cuentas de servicio existen en el proyecto y desactiva las que ya no use ningún pipeline activo.
- Prefiere roles predefinidos sobre roles básicos siempre que cubran el caso de uso, y reserva los roles personalizados para las excepciones reales.
IAM no es la parte más vistosa de un proyecto de datos en Google Cloud, pero es la que decide si un incidente de seguridad se queda en un susto contenido o se convierte en un problema serio. Diseñar bien los roles y las cuentas de servicio desde el principio del proyecto sale mucho más barato que reordenarlo todo cuando ya hay veinte pipelines en producción.
Si quieres ver cómo encajan estas cuentas de servicio en la práctica, en el artículo sobre Cloud Composer explico cómo un entorno usa la suya para orquestar Dataflow y BigQuery.
Leer sobre Cloud Composer y Airflow