Cómo configurar Service Accounts en Google Cloud de forma SEGURA (Sin Claves JSON)
Una Service Account no debería convertirse en un archivo JSON que acaba almacenado en un portátil, un repositorio Git o un pipeline de CI/CD. En una arquitectura GCP moderna, el objetivo es eliminar credenciales persistentes y sustituirlas por IAM de mínimo privilegio, impersonación y credenciales temporales. En esta guía de nivel Senior / Staff / Architect diseñaremos ese modelo y lo llevaremos a Terraform y CLI.
Lo que aprenderás
La decisión arquitectónica: identidad sin secretos persistentes
El error conceptual más frecuente consiste en tratar una Service Account como si fuera un usuario con contraseña. En realidad, una Service Account es una identidad no humana que puede recibir permisos IAM y utilizar mecanismos de autenticación temporales.
Para producción, la pregunta correcta no es “¿dónde guardo el JSON?”, sino “¿cómo demuestro quién soy y qué permisos necesito sin distribuir un secreto de larga duración?”.
| Patrón | Credencial | Seguridad | Operación | Coste / Riesgo | Uso recomendado |
|---|---|---|---|---|---|
| Service Account Key JSON | Larga duración | Baja frente a alternativas modernas | Rotación y almacenamiento de secretos | Alto riesgo operativo | Evitar salvo casos heredados muy justificados |
| Service Account Impersonation | Tokens temporales | Alta | IAM centralizado | Bajo riesgo de exposición persistente | Administración, desarrollo y automatización |
| Workload Identity Federation | Federación / tokens temporales | Alta | Sin secretos cloud persistentes | Excelente para CI/CD | GitHub Actions, GitLab, AWS, Azure y workloads externos |
| Attached Service Account | Identidad del runtime | Alta | Gestionada por el entorno GCP | Excelente para workloads internos | Compute Engine, GKE, Cloud Run y otros servicios compatibles |
Entender IAM antes de impersonar
La impersonación no significa que un usuario “se convierta” permanentemente en una Service Account. Significa que un principal autorizado puede solicitar credenciales temporales para actuar con la identidad de esa Service Account.
Esto crea una separación extremadamente útil entre quién solicita una operación y qué identidad ejecuta realmente la llamada contra Google Cloud.
Identidad origen
Puede ser un usuario humano, una identidad de CI/CD o una identidad federada. No necesita poseer una clave privada de la Service Account objetivo.
Permiso de impersonación
IAM determina si la identidad origen puede utilizar la Service Account. Los permisos deben asignarse sobre el recurso apropiado y con el menor alcance posible.
Identidad efectiva
El workload obtiene credenciales temporales y realiza la operación con los permisos asignados a la Service Account impersonada.
Antipatrón crítico: distribuir claves JSON
“Guardo el JSON en un Secret Manager y ya está seguro” no resuelve todo el problema
Secret Manager es una herramienta excelente para gestionar secretos cuando realmente necesitas un secreto, pero no convierte automáticamente una credencial de larga duración en una buena arquitectura de identidad.
Una clave privada de Service Account puede acabar expuesta mediante backups, logs, artefactos de CI, máquinas comprometidas, imágenes de contenedor o configuraciones incorrectas. Además, hay que diseñar rotación, revocación, distribución y monitorización.
Si el entorno permite impersonación, identidad adjunta o Workload Identity Federation, la solución arquitectónica preferible es eliminar la clave persistente en lugar de protegerla indefinidamente.
Regla práctica: si puedes eliminar una credencial estática en vez de mejorar su almacenamiento, normalmente estás reduciendo una clase completa de riesgo.
Implementación práctica con gcloud
El flujo siguiente crea una Service Account dedicada, le asigna un permiso de negocio concreto y concede a un principal la capacidad de impersonarla. No se genera ninguna clave JSON.
# Variables
PROJECT_ID="my-production-project"
SERVICE_ACCOUNT_ID="data-reader"
SERVICE_ACCOUNT="${SERVICE_ACCOUNT_ID}@${PROJECT_ID}.iam.gserviceaccount.com"
# 1. Crear la Service Account
gcloud iam service-accounts create "${SERVICE_ACCOUNT_ID}" \
--project="${PROJECT_ID}" \
--display-name="Production Data Reader"
# 2. Conceder únicamente el rol requerido por el workload.
# Ejemplo: lectura de objetos en un bucket.
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/storage.objectViewer"
# 3. Conceder impersonación al principal autorizado.
# Sustituir por el usuario, grupo o identidad federada correspondiente.
PRINCIPAL="user:developer@example.com"
gcloud iam service-accounts add-iam-policy-binding "${SERVICE_ACCOUNT}" \
--member="${PRINCIPAL}" \
--role="roles/iam.serviceAccountUser"
# 4. Ejecutar una operación utilizando impersonación.
gcloud storage ls "gs://my-data-bucket" \
--impersonate-service-account="${SERVICE_ACCOUNT}"
# 5. Verificar la identidad efectiva.
gcloud auth print-access-token \
--impersonate-service-account="${SERVICE_ACCOUNT}"
En entornos empresariales, el principal utilizado para impersonar debe gestionarse mediante grupos, identidades federadas o identidades de workload según el contexto. Evita conceder permisos amplios directamente a individuos cuando un grupo o identidad de plataforma sea más apropiado.
Cuentas de servicio GCP con Terraform
Terraform debe encargarse de declarar la identidad y sus relaciones IAM, pero no debería utilizarse para fabricar y distribuir claves privadas si existe una alternativa basada en impersonación o federación.
Un patrón limpio separa la Service Account del binding de permisos. Esto facilita revisar quién tiene acceso, qué rol se concede y cuál es el alcance del permiso.
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.0"
}
}
}
variable "project_id" {
type = string
}
provider "google" {
project = var.project_id
}
resource "google_service_account" "data_reader" {
account_id = "data-reader"
display_name = "Production Data Reader"
description = "Read-only identity for production data workloads"
}
# Permiso funcional de la Service Account.
resource "google_project_iam_member" "storage_viewer" {
project = var.project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.data_reader.email}"
}
# Principal autorizado a impersonar la Service Account.
resource "google_service_account_iam_member" "impersonation" {
service_account_id = google_service_account.data_reader.name
role = "roles/iam.serviceAccountUser"
member = "group:platform-engineering@example.com"
}
output "service_account_email" {
value = google_service_account.data_reader.email
}
Un punto especialmente importante para equipos de plataforma es evitar recursos IAM excesivamente autoritativos
cuando varios sistemas gestionan permisos sobre el mismo proyecto. La estrategia de
iam_member, iam_binding o iam_policy debe elegirse deliberadamente
para evitar que Terraform elimine permisos administrados por otros componentes.
Impersonate Service Account en Google Cloud: qué ocurre realmente
La impersonación se apoya en IAM Credentials y en credenciales temporales. El objetivo arquitectónico es que la identidad origen tenga autorización suficiente para solicitar credenciales de la Service Account, mientras que la Service Account contiene los permisos funcionales necesarios.
Principal
El usuario o workload demuestra su propia identidad mediante el mecanismo de autenticación disponible.
- Usuario corporativo
- Grupo
- Workload Identity
- Federación externa
IAM
IAM controla si el principal está autorizado a impersonar la identidad objetivo.
- Service Account User
- Service Account Token Creator
- Scope del binding
- Condiciones IAM cuando proceda
Token temporal
La identidad obtiene credenciales temporales y realiza llamadas con la identidad efectiva de la Service Account.
- Sin JSON privado
- Menor ventana de exposición
- Auditoría centralizada
- Revocación mediante IAM
Patrones de diseño recomendados para producción
La seguridad de una Service Account no depende únicamente del rol que recibe. El verdadero diseño debe considerar límites de confianza, blast radius, ciclo de vida, auditoría y ownership.
Una identidad por workload crítico
Evita una Service Account gigantesca compartida por múltiples aplicaciones. Una identidad dedicada hace que los permisos sean más comprensibles y reduce el blast radius.
Permisos cerca del recurso
Siempre que sea posible, concede permisos en el nivel mínimo necesario: recurso, bucket, dataset o proyecto, en función de los requisitos reales.
Separar identidad de autorización
Crear una Service Account no significa otorgarle acceso global. Identidad y autorización deben evolucionar como dos decisiones independientes.
Federar CI/CD
Para pipelines externos, prioriza federación de identidad frente a almacenar claves JSON dentro de variables de CI o secretos de repositorio.
Auditar impersonación
Monitoriza quién puede impersonar qué identidad y revisa regularmente los bindings IAM que conceden acceso a Service Accounts privilegiadas.
Evitar privilegios heredados innecesarios
Un rol concedido a nivel de organización o proyecto puede tener un alcance mucho mayor del que necesita el workload. El mínimo privilegio debe evaluarse jerárquicamente.
Seguridad e impacto FinOps: el coste oculto del exceso de privilegios
IAM no genera únicamente un problema de seguridad cuando está sobredimensionado. Una identidad con permisos sobre más recursos de los necesarios puede permitir operaciones accidentales a gran escala: lecturas masivas, escrituras, ejecuciones de jobs o modificaciones de infraestructura.
Por eso, una arquitectura de mínimo privilegio también es una estrategia de control operacional. El objetivo es reducir tanto el blast radius de seguridad como el blast radius financiero.
Antipatrón: “roles/editor para que Terraform no falle”
Conceder permisos amplios para solucionar rápidamente errores de autorización puede hacer que el pipeline funcione, pero convierte cada credencial comprometida en una llave potencial sobre una parte significativa del proyecto.
El enfoque profesional consiste en identificar el permiso exacto que falta, decidir si debe pertenecer al principal de Terraform o a una Service Account de workload y añadir únicamente la autorización necesaria.
Framework de implementación paso a paso
Este checklist puede utilizarse como estándar interno para revisar nuevas Service Accounts antes de llevarlas a producción.
- Define el workload. Documenta qué aplicación, pipeline o proceso necesita la identidad y qué recursos debe utilizar.
- Crea una Service Account dedicada. Evita reutilizar identidades de propósito general entre aplicaciones con diferentes niveles de riesgo.
- Define permisos funcionales. Empieza por cero y añade únicamente los roles necesarios para ejecutar el caso de uso.
-
Elimina claves JSON.
No utilices
google_service_account_keysalvo que exista una restricción técnica real, documentada y aprobada. - Elige el mecanismo de identidad. Para recursos GCP utiliza identidad adjunta cuando sea posible; para CI/CD externo considera Workload Identity Federation; para operaciones humanas utiliza impersonación.
- Controla quién puede impersonar. El binding que permite utilizar la Service Account debe ser tan restrictivo como los permisos funcionales.
- Automatiza con Terraform. Versiona Service Accounts, roles y bindings IAM para que las decisiones sean auditables.
- Configura observabilidad. Revisa Cloud Audit Logs y establece controles para detectar cambios IAM y uso inesperado de identidades.
- Revisa periódicamente. Una Service Account que originalmente necesitaba cinco permisos puede necesitar solo dos seis meses después.
- Documenta ownership y lifecycle. Cada identidad crítica debe tener responsable, propósito, entorno y procedimiento de retirada.
Preguntas frecuentes sobre Service Accounts en GCP
¿Por qué no debería utilizar claves JSON de Service Accounts en GCP?
Porque una clave JSON contiene una credencial privada de larga duración. Si se filtra, el atacante puede utilizarla hasta que sea revocada. Además, obliga a implementar procesos de almacenamiento, distribución y rotación. La impersonación y la federación permiten trabajar con credenciales temporales y reducen considerablemente la exposición.
¿Qué permisos necesito para impersonar una Service Account?
Depende de la operación. El rol
roles/iam.serviceAccountUser se utiliza habitualmente para permitir que un principal
actúe como una Service Account en escenarios de ejecución. Para determinadas operaciones de generación
de credenciales temporales puede intervenir
roles/iam.serviceAccountTokenCreator. El permiso debe concederse al principal correcto
y con el alcance mínimo necesario.
¿Cómo creo cuentas de servicio GCP con Terraform sin claves JSON?
Utiliza google_service_account para crear la identidad y recursos IAM como
google_project_iam_member o google_service_account_iam_member
para gestionar autorización. Para autenticar Terraform, utiliza un mecanismo apropiado al entorno,
como impersonación o Workload Identity Federation, evitando crear y distribuir claves privadas.
La arquitectura correcta no necesita un JSON secreto
Una estrategia madura de identidad en Google Cloud parte de una premisa sencilla: las credenciales estáticas deben ser la excepción, no el diseño por defecto.
Cuando combinas Service Accounts dedicadas, IAM de mínimo privilegio, impersonación, identidad adjunta y Workload Identity Federation, puedes construir plataformas mucho más fáciles de auditar, operar y proteger.
La pregunta arquitectónica deja de ser dónde guardar la clave y pasa a ser mucho más importante: qué identidad necesita cada workload, durante cuánto tiempo y con qué permisos exactos.
