Logo GCP con Eduardo

GCP con Eduardo

Descarga el código de la lección

Inyecta Secretos en Cloud Run sin exponer credenciales | Google Secret Manager
✦ Guía Técnica & Arquitectura

Inyecta Secretos en Cloud Run sin exponer credenciales

Diseñar un microservicio seguro en Google Cloud no consiste simplemente en esconder una contraseña. La arquitectura correcta separa configuración, identidad y material secreto para que las credenciales de base de datos, API keys y tokens permanezcan fuera del código fuente, de las imágenes de contenedor y de los pipelines de CI/CD.

En esta guía de nivel Senior / Staff / Architect construiremos el patrón Cloud Run + Google Secret Manager + IAM + Terraform, analizaremos sus trade-offs y veremos por qué el verdadero control de seguridad está en quién puede leer cada secreto, no en ocultar una variable de entorno.

Lo que aprenderás

Diseñar el perímetro secreto
Separar secretos, configuración e identidad de ejecución.
Aplicar mínimo privilegio
Conceder acceso únicamente al secreto que necesita cada workload.
Desplegar con Terraform
Declarar Cloud Run, Secret Manager e IAM sin incrustar credenciales.
Evitar fugas en producción
Detectar estados Terraform, logs, imágenes y pipelines como superficies de riesgo.
Google Cloud Run Secret Manager IAM Terraform Docker Python CI/CD FinOps
01 · Modelo mental

Un secreto no es una variable de configuración normal

Una URL de una API pública puede formar parte de la configuración de una aplicación. Una contraseña de PostgreSQL, un token privado o una clave API no debería tratarse igual. Su ciclo de vida incluye creación, autorización, consumo, rotación, auditoría y revocación.

En Cloud Run, la identidad de ejecución del servicio es una pieza central del diseño: es esa identidad la que debe tener permiso para acceder al secreto. Google recomienda utilizar una cuenta de servicio administrada por el usuario con el conjunto mínimo de permisos necesario, en lugar de ampliar innecesariamente los permisos de la identidad predeterminada.

1

Secret Manager

Almacena el material sensible y permite controlar el acceso mediante IAM. El secreto debe vivir fuera del repositorio y de la imagen del contenedor.

2

Cloud Run

Ejecuta el workload con una identidad explícita. Cloud Run puede consumir secretos como variables de entorno o mediante volúmenes montados.

3

IAM

Define la frontera real de seguridad: qué principal puede acceder a qué secreto y a qué nivel de la jerarquía de recursos.

02 · Matriz de decisión

¿Dónde debe vivir el secreto?

El error arquitectónico más frecuente es confundir mecanismo de entrega con sistema de gestión de secretos. Una variable de entorno no es un gestor de secretos: es simplemente una superficie de exposición durante el ciclo de ejecución.

Patrón Seguridad Latencia Operación Coste Uso recomendado
Secret Manager → ENV Alta si IAM está correctamente restringido Muy baja durante el runtime tras la inicialización Baja Bajo Credenciales de DB, API keys, tokens y configuración sensible estable.
Secret Manager → volumen Alta Muy baja para el proceso consumidor Media Bajo Aplicaciones que esperan archivos o necesitan separar físicamente el contenido.
Secret embebido en imagen Crítica / mala práctica Muy baja Alta deuda de seguridad Bajo No recomendado. El secreto queda ligado al artefacto.
Secreto en repositorio Crítica / mala práctica Irrelevante Alta deuda de seguridad Bajo No recomendado. Git no es un sistema de gestión de secretos.
Secreto como texto en CI/CD Variable Baja Media / alta Variable Solo cuando el proveedor y el pipeline están diseñados para manejar secretos correctamente.
03 · Antipatrones

El error no es usar variables de entorno: es perder el control de su origen

⚠ Antipatrón: copiar el secreto dentro del pipeline

Un patrón aparentemente cómodo consiste en almacenar una contraseña como variable del sistema de CI/CD y ejecutar un comando que la inyecta directamente durante el despliegue.

El problema es que ahora hay que auditar otra cadena completa: configuración del runner, logs, masking, comandos ejecutados, artefactos, debugging y permisos del pipeline.

El patrón más limpio es que Terraform declare la referencia al secreto y que la identidad de ejecución de Cloud Run sea quien tenga acceso al payload mediante IAM.


☠ Antipatrón FinOps + Security: permisos a nivel de proyecto sin necesidad

Conceder roles/secretmanager.secretAccessor a una cuenta de servicio sobre todo el proyecto puede funcionar técnicamente, pero rompe el principio de mínimo privilegio.

Si el workload solo necesita leer DB_PASSWORD, la autorización debería limitarse a ese secreto cuando el diseño lo permita. De esta forma, comprometer una aplicación no implica automáticamente comprometer todos los secretos accesibles en el proyecto.

04 · Implementación

Cloud Run + Secret Manager + Terraform

El patrón de referencia tiene cuatro piezas: secreto, versión del secreto, cuenta de servicio de Cloud Run y binding IAM que permite a esa cuenta acceder únicamente al secreto requerido.

Para variables de entorno, Cloud Run puede resolver el secreto antes de iniciar la instancia. Google recomienda fijar una versión concreta del secreto en lugar de depender de latest, especialmente cuando se busca reproducibilidad y control operacional.

main.tf · arquitectura de referencia
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 7.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

variable "project_id" {
  type        = string
  description = "Google Cloud project ID"
}

variable "region" {
  type        = string
  default     = "europe-west1"
}

# -------------------------------------------------------------------
# 1. Secret Manager
# -------------------------------------------------------------------

resource "google_secret_manager_secret" "db_password" {
  secret_id = "orders-db-password"

  replication {
    auto {}
  }
}

# En un entorno real, evita introducir valores productivos
# directamente en el código Terraform.
resource "google_secret_manager_secret_version" "db_password" {
  secret      = google_secret_manager_secret.db_password.name
  secret_data = var.db_password
}

variable "db_password" {
  type      = string
  sensitive = true
}

# -------------------------------------------------------------------
# 2. Identidad específica para Cloud Run
# -------------------------------------------------------------------

resource "google_service_account" "cloud_run" {
  account_id   = "orders-api-runtime"
  display_name = "Runtime identity for Orders API"
}

# -------------------------------------------------------------------
# 3. Mínimo privilegio: acceso únicamente al secreto necesario
# -------------------------------------------------------------------

resource "google_secret_manager_secret_iam_member" "db_password_accessor" {
  secret_id = google_secret_manager_secret.db_password.id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.cloud_run.email}"
}

# -------------------------------------------------------------------
# 4. Cloud Run
# -------------------------------------------------------------------

resource "google_cloud_run_v2_service" "orders_api" {
  name     = "orders-api"
  location = var.region

  template {
    service_account = google_service_account.cloud_run.email

    containers {
      image = "europe-west1-docker.pkg.dev/PROJECT_ID/apps/orders-api:1.0.0"

      env {
        name = "DB_PASSWORD"

        value_source {
          secret_key_ref {
            secret  = google_secret_manager_secret.db_password.id
            version = google_secret_manager_secret_version.db_password.version
          }
        }
      }

      env {
        name  = "APP_ENV"
        value = "production"
      }
    }
  }

  depends_on = [
    google_secret_manager_secret_iam_member.db_password_accessor
  ]
}

Nota de arquitectura: el ejemplo anterior demuestra el patrón completo, pero para producción conviene analizar cuidadosamente cómo se suministra var.db_password. Marcar una variable como sensitive evita exposiciones accidentales en ciertas salidas, pero no convierte automáticamente el estado de Terraform en un almacén de secretos seguro.

05 · Diseño de producción

La arquitectura correcta va más allá del Terraform

Identidad dedicada

No reutilices una única cuenta de servicio con acceso a decenas de secretos para todos los microservicios. Una identidad por workload o por dominio de confianza reduce el blast radius.

Mínimo privilegio

El rol roles/secretmanager.secretAccessor permite acceder al payload. Concederlo al nivel del secreto es preferible cuando el workload solo necesita un conjunto reducido de secretos.

Versionado explícito

Referenciar una versión concreta permite relacionar una revisión de Cloud Run con una versión conocida del secreto. Esto mejora rollback, reproducibilidad y troubleshooting.

Rotación sin acoplamiento

La aplicación no debería necesitar que el secreto aparezca en Git para poder desplegarse. Secret Manager debe ser la fuente de verdad del material secreto, mientras que Cloud Run recibe una referencia.

Logs sin secretos

Nunca registres variables sensibles para diagnosticar errores. Evita excepciones, dumps, trazas HTTP y mensajes de debug que puedan imprimir headers o credenciales.

Separación de responsabilidades

El equipo que despliega el servicio no tiene por qué ser el mismo principal que administra el contenido de todos los secretos. IAM permite construir fronteras operativas más precisas.

06 · ENV vs volumen

¿Variable de entorno o secreto montado como archivo?

Ambas estrategias son válidas. La elección debe depender del contrato de la aplicación y de cómo consume el secreto.

Criterio Variable de entorno Volumen de secretos
Integración Excelente para aplicaciones que leen configuración desde ENV. Excelente para software que espera un archivo.
Inicialización Cloud Run obtiene el secreto antes de iniciar la instancia. El proceso consume el contenido desde el volumen.
Uso típico DB_PASSWORD, API_TOKEN, JWT_SECRET. Certificados, claves o aplicaciones con configuración basada en archivos.
Consideración Evitar imprimir el entorno completo en logs o diagnósticos. Controlar cuidadosamente permisos y rutas de lectura.
07 · Aplicación

Consumir el secreto desde Python sin acoplarse a GCP

Una buena aplicación no debería conocer la implementación concreta del secreto. Desde el punto de vista del proceso, DB_PASSWORD es simplemente una configuración sensible proporcionada por el entorno de ejecución.

app/config.py
import os
from dataclasses import dataclass


@dataclass(frozen=True)
class Settings:
    database_url: str
    db_password: str
    environment: str


def load_settings() -> Settings:
    """
    Lee configuración inyectada por el entorno de ejecución.

    La aplicación no necesita llamar directamente a Secret Manager.
    Cloud Run resuelve el secreto antes de iniciar la instancia.
    """
    password = os.getenv("DB_PASSWORD")

    if not password:
        raise RuntimeError(
            "DB_PASSWORD is required but was not provided"
        )

    database_url = os.getenv(
        "DATABASE_URL",
        "postgresql://orders-db:5432/orders"
    )

    environment = os.getenv(
        "APP_ENV",
        "development"
    )

    return Settings(
        database_url=database_url,
        db_password=password,
        environment=environment,
    )


settings = load_settings()

Esta separación es importante: el código de negocio no necesita importar un SDK de Secret Manager únicamente para obtener una contraseña que Cloud Run ya puede proporcionar como parte de la configuración del proceso.

08 · Framework de implementación

Checklist para llevarlo a producción

  1. Clasifica el dato. Determina qué valores son secretos y cuáles son configuración pública.
  2. Crea el secreto. Utiliza Google Secret Manager como sistema de almacenamiento del material sensible.
  3. Define una identidad de runtime. Crea una cuenta de servicio dedicada para Cloud Run.
  4. Aplica IAM sobre el recurso más pequeño posible. Si el servicio necesita un único secreto, evita conceder acceso a todos los secretos del proyecto.
  5. Referencia el secreto desde Cloud Run. Usa variables de entorno o volúmenes según el contrato de la aplicación.
  6. Fija versiones. Usa una versión explícita cuando necesites reproducibilidad y control de rollbacks.
  7. Audita Terraform. Comprueba dónde puede aparecer material sensible, especialmente en el estado y en automatizaciones.
  8. Audita CI/CD. El pipeline debe poder desplegar referencias sin convertir el secreto en texto de logs o artefactos.
  9. Elimina secretos de logs. Revisa debugging, tracing, errores HTTP, dumps y métricas.
  10. Diseña rotación y revocación. Un secreto seguro también debe poder cambiarse y revocarse sin rediseñar el servicio.
09 · Decisión arquitectónica

El patrón que recomiendo para microservicios empresariales

Para un servicio Cloud Run estándar, mi arquitectura de referencia es:

Secret Manager

Fuente de verdad del material secreto, con versiones y políticas IAM.

Cloud Run Identity

Cuenta de servicio dedicada que recibe únicamente los permisos necesarios para ejecutar el workload.

Terraform

Describe infraestructura, IAM y referencias sin convertir el repositorio en un almacén de contraseñas.

Principio clave

El secreto debe viajar lo menos posible. El objetivo no es simplemente evitar que aparezca en Git. El objetivo es reducir el número de sistemas, identidades, artefactos, procesos y personas que pueden llegar a observar su valor.

10 · FAQ

Preguntas frecuentes sobre Secret Manager y Cloud Run

¿Cuál es la forma recomendada de pasar secretos a Cloud Run?

Una arquitectura habitual consiste en almacenar el secreto en Google Secret Manager, conceder a la identidad de ejecución de Cloud Run el rol roles/secretmanager.secretAccessor sobre el recurso necesario y referenciar el secreto desde Cloud Run como variable de entorno o volumen. La documentación oficial de Google contempla ambas modalidades.

¿Debo guardar contraseñas directamente en Terraform?

No es una buena práctica tratar el código Terraform como almacén de secretos. Incluso cuando una variable se marca como sensible, hay que analizar el ciclo de vida completo del valor y, especialmente, la gestión del estado de Terraform. La configuración declarativa debe separar referencias y metadatos de los valores secretos siempre que sea posible.

¿Qué permisos necesita la cuenta de servicio de Cloud Run?

Necesita permiso para acceder al payload del secreto utilizado por el servicio. El rol roles/secretmanager.secretAccessor permite acceder a los valores de las versiones de secretos. Para aplicar mínimo privilegio, es preferible concederlo al nivel más bajo compatible con la arquitectura.

Conclusión

Secretos seguros en GCP = identidad + IAM + ciclo de vida

La solución profesional para gestionar credenciales en Cloud Run no consiste en esconder una contraseña dentro de otra capa de configuración. Consiste en construir una cadena de confianza explícita: Secret Manager → IAM → identidad de Cloud Run → aplicación.

Terraform completa el modelo declarando la infraestructura y las relaciones entre recursos, pero no elimina la necesidad de gobernar el estado, los pipelines y las identidades que participan en el despliegue.

Cuando esta separación se mantiene, un microservicio puede cambiar de imagen, escalar horizontalmente y evolucionar su pipeline sin convertir las credenciales de producción en parte del artefacto de software.

Referencias técnicas oficiales:

Google Cloud Documentation · Cloud Run · Secret Manager · IAM.

La implementación descrita sigue el modelo documentado por Google para configurar secretos en Cloud Run y conceder a la identidad de ejecución el acceso mediante roles/secretmanager.secretAccessor.

Sobre el Autor: Eduardo Martínez Agrelo

AI & Data Architect

Eduardo Martínez Agrelo es AI & Data Architect, especializado en arquitectura de datos, inteligencia artificial, plataformas cloud y diseño de sistemas empresariales. Su enfoque combina decisiones arquitectónicas, automatización, seguridad, escalabilidad y eficiencia operativa para construir plataformas preparadas para producción.

© 2026 Eduardo Martínez Agrelo · AI & Data Architect

Cloud Run · Google Secret Manager · IAM · Terraform · Secure Cloud Architecture