Saltar a contenido

Capítulo 34 — Secret Manager, variables de entorno y gestión segura de credenciales

Recursos visuales propuestos

Antes de desarrollar el capítulo conviene separar los recursos que ayudan a comprender decisiones de seguridad cotidianas de aquellos que muestran una arquitectura técnica con varios componentes y límites de confianza. La comparación entre código inseguro y código seguro, los ejemplos de variables de entorno, el flujo de acceso a un secreto, las buenas prácticas de gestión de credenciales y el checklist de seguridad deben presentarse como imágenes didácticas, porque buscan enseñar criterios prácticos y errores frecuentes de forma visual y rápida. En cambio, la arquitectura Secret Manager → Cloud Functions, el flujo de recuperación de credenciales, la integración con APIs externas y la arquitectura segura para producción deben representarse como diagramas SVG, ya que requieren modelar secretos, versiones, permisos IAM, despliegues, funciones enlazadas y consumo seguro de credenciales dentro del backend.[cite:1][cite:2]

Imágenes didácticas

  1. Comparación entre código inseguro y código seguro. Debe ser imagen didáctica porque el objetivo es contrastar prácticas de desarrollo, no infraestructura.
  2. Ejemplos de variables de entorno. Conviene como imagen didáctica para mostrar diferencias entre parámetros, .env y secretos.[cite:2]
  3. Flujo de acceso a un secreto. Funciona bien como imagen didáctica cuando se quiere enseñar la secuencia general desde el punto de vista del desarrollador.
  4. Buenas prácticas de gestión de credenciales. Debe ser imagen didáctica por su carácter pedagógico y de recordatorio operativo.
  5. Checklist de seguridad. Es imagen didáctica porque resume acciones para producción y auditoría.

Diagramas SVG

  1. Arquitectura Secret Manager → Cloud Functions. Debe ser SVG porque representa relación entre servicio de secretos, permisos, despliegue y función en ejecución.[cite:1][cite:2]
  2. Flujo de recuperación de credenciales. Debe ser SVG porque muestra acceso a secretos, versiones, runtime y uso contra APIs externas.[cite:1][cite:2]
  3. Integración con APIs externas. Debe ser SVG porque requiere mostrar sistemas como Stripe, OpenAI, AWS o SMTP y el punto en el que el backend recupera credenciales.
  4. Arquitectura segura para producción. Debe ser SVG porque incluye ambientes, CI/CD, GitHub Actions, Cloud Functions v2 y estrategia de rotación.

Objetivos de aprendizaje

Al finalizar este capítulo, el lector será capaz de:

  • Comprender qué es un secreto, por qué debe protegerse y qué vulnerabilidades aparecen cuando se expone en código fuente, repositorios o despliegues inseguros.
  • Explicar qué es Google Secret Manager, cómo funciona su modelo de secretos y versiones, y por qué es la opción recomendada para almacenar información sensible en entornos Firebase y Google Cloud.[cite:1]
  • Diferenciar correctamente entre parámetros, variables de entorno en archivos .env y secretos administrados por Secret Manager en Cloud Functions for Firebase.[cite:2]
  • Implementar ejemplos profesionales con Cloud Functions v2 usando defineSecret(), defineJsonSecret() y parámetros tipados del SDK de Functions.[cite:2]
  • Diseñar una estrategia de credenciales para desarrollo, pruebas y producción aplicada al proyecto oficial del libro.
  • Adoptar una perspectiva DevSecOps para rotación, auditoría, permisos mínimos, revocación y gestión del ciclo de vida de los secretos.[cite:1][cite:2]

Introducción

Las aplicaciones modernas viven conectadas a múltiples servicios externos. Un backend Firebase puede necesitar enviar correos por SMTP, cobrar mediante Stripe, generar texto con OpenAI o Gemini, enviar mensajes por Telegram, integrar almacenamiento secundario con AWS o verificar tokens emitidos por otra plataforma. Cada una de esas integraciones exige algún tipo de credencial: API key, token OAuth, secreto JWT, clave privada, certificado o password técnico.

El problema aparece cuando el equipo trata esas credenciales como si fueran simples valores de configuración. En etapas tempranas de un proyecto es común ver claves pegadas en el código, archivos JSON compartidos por chat, variables almacenadas sin control de acceso o secretos subidos a Git por “practicidad”. Esa comodidad inicial suele convertirse después en una fuente de riesgo operativo, deuda técnica y posibles incidentes de seguridad.

Google Cloud Secret Manager existe precisamente para resolver este problema. La documentación oficial lo define como un servicio de gestión de secretos y credenciales que permite almacenar y administrar información sensible como API keys, usuarios, contraseñas y certificados. También explica que un secreto es un recurso global con metadatos, mientras que el valor real se guarda en versiones separadas del secreto.[cite:1]

En el ecosistema Firebase, la documentación actual de Cloud Functions recomienda dos grandes caminos para la configuración: configuración parametrizada, que es la opción preferida en la mayoría de escenarios, y variables de entorno basadas en archivos .env. Para información verdaderamente sensible, el mismo documento aclara que los .env no deben considerarse un medio seguro y que la integración con Cloud Secret Manager es la forma adecuada de almacenar secretos cifrados y exponerlos solo a las funciones que realmente los necesitan.[cite:2]

Este capítulo estudia con profundidad la diferencia entre configuración y secreto, cómo funciona Secret Manager internamente, cómo integrarlo con Cloud Functions v2, qué papel juegan los archivos .env, cómo administrar secretos por ambiente y cómo diseñar una estrategia segura para el proyecto transversal del libro, protegiendo credenciales SMTP, AWS, OpenAI, Gemini, Telegram, Stripe, JWT y otras integraciones externas.

Desarrollo completo

Introducción conceptual

¿Qué es un secreto?

Un secreto es cualquier dato cuyo valor debe permanecer confidencial porque permite acceder a un sistema, firmar información, autenticar una integración o modificar recursos con privilegios. En la práctica, un secreto no se define por su formato sino por su impacto. Una cadena aparentemente simple puede ser un secreto crítico si permite enviar correos, facturar cargos, consultar expedientes o invocar una API de pago.

Ejemplos típicos de secretos:

  • API keys con privilegios sensibles.
  • Tokens OAuth de acceso o refresh.
  • Secretos de firma JWT.
  • Claves privadas.
  • Certificados TLS o certificados cliente.
  • Credenciales SMTP.
  • Secretos de webhook.
  • Credenciales de terceros como Stripe, AWS, OpenAI, Gemini o Telegram.

¿Por qué proteger las credenciales?

Porque una credencial comprometida no solo afecta al código; afecta al negocio. Un atacante que obtiene la clave correcta puede enviar correos masivos, generar costos en APIs pagadas, leer datos, manipular integraciones o suplantar al sistema ante terceros. En un entorno productivo, la fuga de un secreto suele traducirse en una combinación de impacto técnico, económico, legal y reputacional.

Riesgos de almacenar claves en el código

Guardar claves en el repositorio crea una cadena de problemas:

  • Las credenciales quedan expuestas a cualquier colaborador con acceso al repositorio.
  • Pueden filtrarse por forks, backups, logs, capturas de pantalla o herramientas de análisis.
  • La rotación se vuelve costosa porque obliga a cambiar código, redeployar y revisar historial.
  • Los secretos pueden persistir incluso después de borrarlos del archivo, porque siguen viviendo en el historial de Git.

Principales vulnerabilidades

Entre las vulnerabilidades más habituales se encuentran:

  • secretos hardcodeados en el código fuente;
  • archivos .env subidos accidentalmente a Git;
  • reutilización del mismo secreto en dev, test y producción;
  • cuentas de servicio o API keys con permisos excesivos;
  • inexistencia de rotación periódica;
  • falta de trazabilidad sobre quién accedió o cambió un secreto;
  • uso de secretos en funciones que realmente no los necesitan.

Secret Manager

¿Qué es Google Secret Manager?

Google describe Secret Manager como un servicio de gestión de secretos y credenciales que permite almacenar y administrar datos sensibles como API keys, contraseñas, certificados y más.[cite:1] Es decir, no es una simple base de datos de strings, sino un componente de seguridad administrado, integrado con IAM, auditoría, cifrado, versionado y replicación.

Arquitectura

La arquitectura básica de Secret Manager distingue dos elementos: el secreto y sus versiones. Según la documentación oficial, el secreto es un recurso global que contiene metadatos como labels, anotaciones y permisos, mientras que cada versión almacena el valor real del secreto y se identifica por un ID o timestamp único.[cite:1]

Esta separación tiene una ventaja arquitectónica importante: el nombre y la identidad del secreto pueden mantenerse estables, mientras el valor rota por versiones. La aplicación puede seguir pidiendo el mismo secreto lógico, pero la organización conserva historial, rollback y control de ciclo de vida.

Funcionamiento interno

Internamente, el servicio ofrece varias garantías y capacidades que lo hacen adecuado para producción:

  • Cifrado en tránsito mediante TLS y cifrado en reposo por defecto con AES-256.[cite:1]
  • Posibilidad de usar claves administradas por el cliente mediante CMEK para requisitos más estrictos.[cite:1]
  • Control de acceso con IAM granular para separar quién crea, quién rota, quién lee y quién audita.[cite:1]
  • Replicación administrada para disponibilidad y recuperación ante desastres, ya sea automática o user-managed.[cite:1]

Versionado de secretos

La documentación oficial subraya que las versiones ayudan a administrar rollback, recuperación y auditoría.[cite:1] Este punto es crucial. En seguridad profesional, un secreto no debe verse como un dato fijo sino como un recurso vivo con cambios controlados.

El versionado permite:

  • cambiar el valor sin renombrar el secreto lógico;
  • volver atrás si una credencial nueva falla;
  • conservar trazabilidad histórica;
  • deshabilitar o destruir versiones que ya no deben usarse.[cite:1]

Rotación

Google destaca la rotación de secretos como mecanismo para reducir riesgo de acceso no autorizado y cumplir requisitos de seguridad o compliance.[cite:1] Rotar significa reemplazar periódicamente credenciales activas para limitar la ventana de exposición si una versión fue filtrada o permaneció demasiado tiempo vigente.

Auditoría

El servicio mantiene un historial que ayuda a rastrear cambios y accesos. La documentación recalca que el versionado mantiene un registro histórico de modificaciones, quién las realizó y cuándo, lo que ayuda tanto a auditoría como a detección de accesos no autorizados.[cite:1]

Permisos

Secret Manager se integra con IAM para gestionar permisos de forma granular. Google indica que se pueden separar responsabilidades de acceso, administración, auditoría y rotación.[cite:1] Ese detalle es fundamental en equipos medianos o grandes: no toda persona que despliega código debe leer todos los secretos, ni toda persona que administra secretos debe poder usar esos secretos desde cualquier workload.

Integración con Cloud Functions

La documentación de Cloud Functions para Firebase explica que los secretos pueden definirse como parámetros de tipo Secret mediante defineSecret() y que estos secretos deben ligarse explícitamente a las funciones que van a consumirlos.[cite:2] Esta es una de las mejores propiedades del modelo: un secreto no aparece automáticamente en todo el runtime; solo está disponible para las funciones que lo declaran.

Variables de entorno

¿Qué son?

Las variables de entorno son valores de configuración que el proceso de ejecución recibe en su entorno. En Cloud Functions para Firebase pueden cargarse desde archivos .env y luego leerse como process.env en Node.js o os.environ en Python.[cite:2]

Variables locales

La documentación explica que se puede crear un archivo .env dentro del directorio functions/ para cargar variables personalizadas durante despliegue y emulación local.[cite:2] Además, para desarrollo local puede usarse .env.local, que tiene precedencia sobre .env y sobre archivos específicos por proyecto.[cite:2]

Variables de producción

También se soportan archivos específicos por proyecto o alias, como .env.dev o .env.prod, lo que permite desplegar valores distintos según el proyecto Firebase activo.[cite:2]

Configuración mediante Firebase CLI

Cloud Functions v2 incorpora una configuración parametrizada muy relevante. Firebase la recomienda para la mayoría de escenarios porque ofrece parámetros tipados, validación en tiempo de despliegue y disponibilidad tanto en deploy como en runtime.[cite:2]

Esto significa que el equipo puede definir parámetros como enteros, strings o booleanos y dejar que la CLI bloquee el despliegue si falta un valor válido, reduciendo errores operativos.[cite:2]

Diferencias entre variables y secretos

La diferencia esencial es esta:

  • Variables de entorno / parámetros: útiles para configuración de aplicación, valores ajustables, flags, opciones por ambiente o parámetros no críticos.[cite:2]
  • Secretos: útiles para información confidencial que no debe vivir en archivos .env ni en repositorios y que requiere control estricto de acceso.[cite:1][cite:2]

Firebase lo dice con claridad: los .env no deben considerarse un medio seguro para información sensible como credenciales de base de datos o API keys, especialmente si se suben a source control.[cite:2]

Información sensible

En un backend Firebase, los secretos más comunes incluyen:

API Keys

No todas las API keys son iguales. Algunas son públicas o limitadas por dominio y otras tienen privilegios efectivos sobre recursos costosos o sensibles. El criterio no es el nombre “API key”, sino el impacto real de la credencial.

Tokens OAuth

Permiten actuar frente a APIs externas con permisos delegados o de servicio. Deben tratarse como secretos de alto valor porque pueden abrir acceso a cuentas, calendarios, correo o recursos de terceros.

JWT Secrets

Se usan para firmar y verificar tokens. Si se filtran, un atacante podría fabricar tokens aparentemente válidos.

Claves privadas

Tienen sensibilidad crítica. Una clave privada expuesta compromete completamente la identidad asociada.

Certificados

Certificados cliente o materiales relacionados con TLS mutuo también deben protegerse como secreto.

Credenciales SMTP

Permiten envío de correo. Si se filtran, pueden producir abuso, spam, bloqueo de reputación o costos.

Credenciales AWS

Pueden abrir acceso a buckets, colas, funciones, logs o infraestructura adicional.

Credenciales OpenAI

Si se exponen, pueden generar costos elevados y abuso de consumo.

Credenciales Gemini

Deben tratarse igual que cualquier credencial de proveedor de IA: alta sensibilidad económica y reputacional.

Credenciales Telegram

El bot token equivale a control del bot. No debe vivir en código ni en repositorio.

Credenciales Stripe

Secret keys y webhook secrets son críticos. Exponerlos compromete pagos, conciliación y seguridad financiera.

Integración

Cloud Functions

La integración más directa y relevante para Firebase aparece en Cloud Functions v2. La documentación muestra dos enfoques complementarios.

Parámetros tipados

const { defineInt, defineString } = require('firebase-functions/params');

Se usan para configuración fuerte y validada.[cite:2]

Secretos ligados a funciones

const { defineSecret } = require('firebase-functions/params');
const stripeSecret = defineSecret('STRIPE_SECRET_KEY');

Y luego:

exports.processPayment = onRequest(
  { secrets: [stripeSecret] },
  (req, res) => {
    const key = stripeSecret.value();
    // ...
  }
);
[cite:2]

La gran ventaja es que solo la función processPayment ve ese secreto. Otra función que no lo declare recibirá undefined o su equivalente, como explica la documentación oficial.[cite:2]

Cloud Run

Aunque el enfoque del capítulo se centra en Firebase y Cloud Functions, el modelo conceptual es extrapolable a Cloud Run dentro del ecosistema Google Cloud: los secretos se vinculan al workload correcto en vez de quedar globalmente disponibles. Ese principio de diseño es el mismo que se debe conservar al crecer hacia arquitecturas híbridas.

Firebase CLI

Firebase CLI permite crear, actualizar, inspeccionar, destruir y limpiar secretos. La documentación enumera comandos como:

  • firebase functions:secrets:set SECRET_NAME
  • functions:secrets:access SECRET_NAME
  • functions:secrets:get SECRET_NAME
  • functions:secrets:destroy SECRET_NAME
  • functions:secrets:prune [cite:2]

GitHub Actions

En CI/CD, la regla profesional es evitar que el pipeline contenga credenciales duras o innecesarias. El pipeline debe autenticarse de forma segura y consumir secretos desde la plataforma adecuada, no duplicarlos por conveniencia en múltiples capas. Si el secreto es de runtime para Functions, debe vivir en Secret Manager y no en el repositorio.

CI/CD

La relación entre CI/CD y secretos exige separar al menos tres necesidades:

  1. Secretos del pipeline para autenticarse y desplegar.
  2. Variables de configuración por ambiente.
  3. Secretos de runtime consumidos por la aplicación ya desplegada.

Confundir estas tres capas suele crear desorden y sobreexposición.

Seguridad

Rotación periódica

Google recomienda la rotación automática o periódica para reducir el riesgo de secretos olvidados o expuestos y para cumplir con marcos de cumplimiento que exigen cambios regulares.[cite:1]

Revocación

Cuando una credencial se sospecha comprometida, el ciclo correcto no es “ocultarla mejor”, sino revocarla y emitir una nueva versión. El versionado de Secret Manager permite precisamente gestionar transición, rollback o destrucción de versiones antiguas.[cite:1]

Accesos mínimos

El principio central es mínimo privilegio: solo las personas, servicios y funciones que realmente necesitan un secreto deben poder usarlo. La documentación de Functions refuerza este patrón al exigir que los secretos se vinculen función por función.[cite:2]

Auditoría

Gracias a la integración con IAM y al historial de versiones, Secret Manager facilita revisar cambios, responsables y accesos relevantes.[cite:1]

Registro de cambios

Toda modificación sensible debería dejar trazabilidad técnica y operativa: nueva versión, motivo del cambio, fecha, función impactada y plan de rollback.

Gestión por ambientes

Firebase Functions soporta .env, .env.<project_ID> y .env.local, lo que ayuda a separar ambientes.[cite:2] Pero para secretos reales, la estrategia profesional es separar también los secretos de dev, test y prod, evitando reutilizar el mismo valor en todos los contextos.

Ejemplos paso a paso

Ejemplo 1: parámetro no sensible en Cloud Functions v2

Uso correcto para una configuración general:

const { onRequest } = require('firebase-functions/v2/https');
const { defineString } = require('firebase-functions/params');

const ENVIRONMENT = defineString('ENVIRONMENT', { default: 'dev' });

exports.info = onRequest((req, res) => {
  res.send(`Ambiente: ${ENVIRONMENT.value()}`);
});
[cite:2]

Aquí no se está protegiendo un secreto, sino una configuración operativa.

Ejemplo 2: secreto SMTP con defineSecret()

const { onRequest } = require('firebase-functions/v2/https');
const { defineSecret } = require('firebase-functions/params');

const SMTP_PASSWORD = defineSecret('SMTP_PASSWORD');

exports.sendMail = onRequest(
  { secrets: [SMTP_PASSWORD] },
  async (req, res) => {
    const password = SMTP_PASSWORD.value();
    // inicializar cliente SMTP con password
    res.send('Correo procesado');
  }
);
[cite:2]

Creación del secreto

firebase functions:secrets:set SMTP_PASSWORD
[cite:2]

Despliegue

firebase deploy --only functions
[cite:2]

Ejemplo 3: JSON secret para múltiples credenciales relacionadas

La documentación actual incorpora defineJsonSecret() para guardar varias configuraciones relacionadas como un único secreto JSON.[cite:2]

const { onRequest } = require('firebase-functions/v2/https');
const { defineJsonSecret } = require('firebase-functions/params');

const STRIPE_CONFIG = defineJsonSecret('STRIPE_CONFIG');

exports.createCheckout = onRequest(
  { secrets: [STRIPE_CONFIG] },
  async (req, res) => {
    const { apiKey, webhookSecret, accountId } = STRIPE_CONFIG.value();
    // usar apiKey, webhookSecret y accountId
    res.send('Checkout inicializado');
  }
);
[cite:2]

Esto puede ser útil para agrupar valores relacionados y aprovechar mejor el free tier de Secret Manager, tal como explica la documentación.[cite:2]

Ejemplo 4: uso de onInit() para inicialización segura

Firebase advierte que acceder a parámetros en alcance global durante deploy puede provocar fallos porque el código se inspecciona antes de disponer de valores efectivos. Para esos casos recomienda usar onInit().[cite:2]

const { onRequest } = require('firebase-functions/v2/https');
const { onInit } = require('firebase-functions/v2/core');
const { defineSecret } = require('firebase-functions/params');
const OpenAI = require('openai');

const OPENAI_API_KEY = defineSecret('OPENAI_API_KEY');
let openai;

onInit(() => {
  if (OPENAI_API_KEY.value()) {
    openai = new OpenAI({ apiKey: OPENAI_API_KEY.value() });
  }
});

exports.askAI = onRequest(
  { secrets: [OPENAI_API_KEY] },
  async (req, res) => {
    // usar cliente inicializado
    res.send('OK');
  }
);
[cite:2]

Ejemplo 5: .env para configuración no sensible por proyecto

# functions/.env
APP_NAME=Firebase Profesional
DEFAULT_REGION=us-central1
# functions/.env.prod
DEFAULT_REGION=us-east1

Firebase explica que el despliegue carga .env y el archivo específico del proyecto o alias activo, combinando valores según el target seleccionado.[cite:2]

Proyecto transversal: estrategia completa de secretos

El proyecto oficial del libro requiere proteger múltiples credenciales:

  • SMTP para envío de correos institucionales.
  • AWS para integraciones de almacenamiento o procesamiento complementario.
  • OpenAI para funciones de asistencia o análisis.
  • Gemini para capacidades generativas ligadas al ecosistema Google.
  • Telegram Bot Token para notificaciones.
  • Stripe para pagos y webhooks.
  • API keys externas para validaciones o catálogos.
  • JWT secret para integración de tokens internos o sistemas auxiliares.

Principios de diseño

  1. Ningún secreto sensible vive hardcodeado en el código fuente.
  2. Los secretos de runtime se administran con Secret Manager.[cite:1][cite:2]
  3. Las configuraciones no sensibles usan parámetros tipados o .env según convenga.[cite:2]
  4. Cada función recibe solo los secretos que necesita.[cite:2]
  5. Cada ambiente tiene secretos diferentes y aislados.
  6. Toda credencial tiene dueño operativo, política de rotación y procedimiento de revocación.

Clasificación para el proyecto

Desarrollo

  • .env.local para variables no sensibles de emulación y pruebas locales.[cite:2]
  • .secret.local para sobrescribir secretos en el emulador si el entorno no puede leer producción.[cite:2]
  • Secretos de pruebas o sandbox, nunca credenciales reales de producción.

Pruebas

  • Proyecto Firebase separado.
  • Secretos propios en Secret Manager.
  • Integraciones con cuentas de staging, cuentas demo o sandbox de proveedores.

Producción

  • Secretos reales en Secret Manager.
  • Rotación planificada.
  • Acceso mínimo por función y por equipo.
  • Auditoría y control estricto de cambios.[cite:1][cite:2]

Ejemplo de diseño por secreto

SMTP

  • SMTP_HOST: parámetro o .env si no es sensible.
  • SMTP_PORT: parámetro.
  • SMTP_USERNAME: según sensibilidad y modelo operativo; muchas veces secreto.
  • SMTP_PASSWORD: secreto en Secret Manager.

OpenAI

  • OPENAI_API_KEY: secreto.
  • OPENAI_MODEL_DEFAULT: parámetro.

Gemini

  • GEMINI_API_KEY: secreto.
  • GEMINI_REGION: parámetro.

Telegram

  • TELEGRAM_BOT_TOKEN: secreto.
  • TELEGRAM_CHAT_DEFAULT: parámetro o dato de negocio según contexto.

Stripe

  • STRIPE_SECRET_KEY: secreto.
  • STRIPE_WEBHOOK_SECRET: secreto.
  • STRIPE_PRICE_TABLE_VERSION: parámetro.

JWT interno

  • JWT_SIGNING_SECRET: secreto.
  • JWT_ISSUER: parámetro.
  • JWT_EXPIRATION_MINUTES: parámetro tipado.

Casos reales

Envío de correos

Un backend que envía correos necesita al menos usuario y password SMTP, o un token de proveedor transaccional. El error típico es dejar estos datos en .env versionado o en un archivo de ejemplo que termina siendo real. La solución profesional es parametrizar solo opciones no sensibles y guardar la credencial real como secreto enlazado a la función que envía correos.[cite:2]

Integración con OpenAI

El riesgo aquí es principalmente económico y operacional. Una API key filtrada puede generar consumo no autorizado. Además, si la función de IA escala, la combinación de cold starts y múltiples secretos puede impactar accesos facturados a Secret Manager, algo que la documentación menciona al explicar que las instancias leen los secretos enlazados en cada cold start.[cite:2]

Integración con AWS

Las credenciales AWS suelen tener una superficie de impacto amplia. Deben rotarse periódicamente y nunca compartirse entre ambientes.

Telegram

El token del bot otorga control operativo del canal. Debe administrarse como secreto de alta sensibilidad.

WhatsApp

Aunque la integración concreta puede variar por proveedor, el patrón es el mismo: tokens y secretos webhook deben salir del código y entrar a una plataforma segura de gestión.

Mercado Pago

Las secret keys de pago deben tratarse con el mismo nivel de protección que Stripe.

Stripe

Stripe combina varios secretos distintos: secret key, restricted key y webhook secret. No todos tienen el mismo alcance, por lo que conviene modelarlos por separado y no como una sola cadena global cuando el equipo y la arquitectura crecen.

Comparaciones técnicas

Variable de entorno vs secreto

Criterio Variable/Parámetro Secreto
Uso principal configuración general [cite:2] credencial sensible [cite:1][cite:2]
Fuente típica .env o parámetros [cite:2] Secret Manager [cite:1][cite:2]
Seguridad limitada si se versiona diseñada para confidencialidad
Control por función no necesariamente sí, mediante binding [cite:2]

.env vs Secret Manager

Criterio .env Secret Manager
Adecuado para secretos críticos No recomendado [cite:2] Sí [cite:1][cite:2]
Versionado informal/Git versiones de secreto [cite:1]
Auditoría pobre fuerte [cite:1]
IAM granular no sí [cite:1]
Rotación manual administrable y auditable [cite:1]

Secreto único vs JSON secret

Criterio Secret individual JSON secret
Granularidad alta media
Organización simple por valor útil para grupo relacionado [cite:2]
Free tier puede consumir más slots más eficiente para bloques relacionados [cite:2]
Riesgo de mezcla menor mayor si se sobrecarga

Hardcodeado vs administrado

Criterio Hardcodeado Secret Manager
Exposición muy alta reducida
Rotación costosa controlada por versiones [cite:1]
Auditoría casi nula integrada [cite:1]
Escalabilidad organizacional mala alta

Buenas prácticas

  • No subir nunca secretos a Git, aunque el repositorio sea privado.
  • Tratar .env como mecanismo de configuración, no como bóveda de credenciales críticas.[cite:2]
  • Usar Secret Manager para claves reales de producción.[cite:1][cite:2]
  • Enlazar cada secreto solo a las funciones que lo necesitan.[cite:2]
  • Usar parámetros tipados para configuración no sensible y validable en deploy.[cite:2]
  • Separar estrictamente secretos de desarrollo, pruebas y producción.
  • Rotar credenciales periódicamente y documentar el proceso.[cite:1]
  • Registrar responsable, proveedor, fecha de creación, fecha de última rotación y plan de revocación para cada secreto.
  • Usar onInit() cuando una inicialización global dependa de parámetros o secretos en Functions v2.[cite:2]
  • Revisar impacto económico de accesos a secretos cuando hay muchas instancias frías; Firebase indica que cada cold start lee los secretos enlazados y que Secret Manager cobra más allá del nivel gratuito mensual.[cite:2]
  • Eliminar versiones o secretos no usados con functions:secrets:prune o estrategias equivalentes de limpieza.[cite:2]

Errores comunes

  • Guardar claves API directamente en el código.
  • Subir .env con credenciales reales al repositorio.
  • Usar el mismo secreto para todos los ambientes.
  • Compartir una credencial entre múltiples integraciones sin separación de alcance.
  • Enlazar demasiados secretos a una misma función “por si acaso”.
  • Acceder a valores de parámetros en alcance global durante deploy y romper el despliegue.[cite:2]
  • Suponer que borrar una credencial del archivo elimina su rastro del historial de Git.
  • No redeployar funciones después de actualizar un secreto; Firebase indica que las funciones deben volver a desplegarse para recoger el valor nuevo.[cite:2]
  • Borrar un secreto todavía referenciado por funciones en producción, lo que puede causar fallos silenciosos.[cite:2]
  • No distinguir entre configuración operativa y credencial sensible.

Checklist para producción

Antes de publicar el backend en producción, revisar:

  • ¿Todos los secretos críticos viven en Secret Manager?[cite:1][cite:2]
  • ¿Las variables .env contienen solo configuración no sensible?[cite:2]
  • ¿Cada función está vinculada solo a los secretos que necesita?[cite:2]
  • ¿Existen secretos distintos para desarrollo, pruebas y producción?
  • ¿Cada secreto tiene política de rotación?
  • ¿Existe procedimiento documentado de revocación y rollback?[cite:1]
  • ¿Los permisos IAM siguen mínimo privilegio?[cite:1]
  • ¿Se auditan cambios y accesos relevantes?[cite:1]
  • ¿Se evitó por completo subir secretos a Git?
  • ¿Las funciones se redeployan tras cambiar secretos enlazados?[cite:2]
  • ¿Se han limpiado versiones o secretos no utilizados?[cite:2]
  • ¿Las integraciones de pago, mensajería y IA usan cuentas y claves separadas por ambiente?

Resumen

La gestión de credenciales seguras es una disciplina central del backend moderno. Un secreto no es simplemente un string especial, sino una pieza de confianza operativa cuyo compromiso puede traducirse en fuga de datos, consumo indebido de recursos, fraude, spam o pérdida de integridad del sistema.

Google Cloud Secret Manager ofrece una plataforma administrada para almacenar y gestionar secretos con cifrado, IAM granular, replicación, versionado, auditoría y rotación. La documentación oficial explica que un secreto es un recurso con metadatos y que el valor real vive en versiones, lo que facilita rollback, recuperación y control histórico de cambios.[cite:1]

En Firebase, Cloud Functions v2 distingue claramente entre configuración y secretos. La documentación actual recomienda configuración parametrizada para la mayoría de escenarios y aclara que los archivos .env no deben considerarse un medio seguro para credenciales sensibles. Para ese tipo de información, la integración con Secret Manager permite enlazar secretos a funciones concretas y exponerlos solo donde son necesarios.[cite:2]

Aplicado al proyecto oficial del libro, esto implica una arquitectura con parámetros para configuración no sensible, secretos administrados para SMTP, AWS, OpenAI, Gemini, Telegram, Stripe, JWT y otras integraciones, y separación estricta entre desarrollo, pruebas y producción. Esa combinación reduce riesgo, mejora mantenibilidad y prepara al sistema para crecer sin convertir la seguridad de credenciales en una fuente permanente de incidentes.

Conceptos clave

  • Secreto.
  • Credencial sensible.
  • Secret Manager.[cite:1]
  • Secret version.[cite:1]
  • IAM granular.[cite:1]
  • Rotación de secretos.[cite:1]
  • Auditoría.[cite:1]
  • Parámetros tipados en Functions v2.[cite:2]
  • .env.[cite:2]
  • .env.local.[cite:2]
  • .env.<project_ID>.[cite:2]
  • defineSecret().[cite:2]
  • defineJsonSecret().[cite:2]
  • onInit().[cite:2]
  • Mínimo privilegio.

Preguntas de repaso

  1. ¿Qué es un secreto y por qué no debe tratarse como una simple variable de configuración?
  2. ¿Qué riesgos aparecen cuando una credencial se almacena en el código fuente?
  3. ¿Cómo define Google Cloud la relación entre secreto y versión de secreto?[cite:1]
  4. ¿Qué ventajas aporta el versionado en Secret Manager?[cite:1]
  5. ¿Qué diferencia existe entre un parámetro tipado, una variable .env y un secreto?[cite:2]
  6. ¿Por qué Firebase no recomienda usar .env para credenciales críticas?[cite:2]
  7. ¿Qué significa que un secreto deba enlazarse explícitamente a una función?[cite:2]
  8. ¿Por qué conviene usar onInit() cuando la inicialización depende de secretos o parámetros?[cite:2]
  9. ¿Qué implicaciones operativas tiene cambiar el valor de un secreto en Functions?[cite:2]
  10. ¿Cómo debería organizar el proyecto oficial sus credenciales de desarrollo, pruebas y producción?

Ejercicios prácticos

  1. Clasifica una lista de valores del proyecto en tres grupos: parámetro, variable de entorno y secreto.
  2. Implementa una función v2 que use defineSecret() para enviar correos con SMTP.[cite:2]
  3. Diseña un JSON secret para Stripe que agrupe valores relacionados y justifica si conviene o no usarlo.[cite:2]
  4. Modela una estrategia de rotación trimestral para las credenciales de OpenAI, Gemini y Telegram.
  5. Diseña una política IAM mínima para que solo ciertas funciones accedan a secretos de pago.
  6. Propón una estructura de ambientes con .env.local, proyecto de pruebas y proyecto de producción.[cite:2]
  7. Reescribe una función insegura con claves hardcodeadas usando Secret Manager y bindings explícitos.
  8. Diseña un procedimiento de revocación de emergencia para una clave Stripe filtrada.
  9. Calcula los riesgos de costo si muchas funciones frías leen varios secretos enlazados y propone una optimización apoyada en la documentación de Firebase.[cite:2]
  10. Elabora una auditoría de seguridad de un repositorio que hoy contiene .env con credenciales reales.

Bibliografía y referencias oficiales