Terraform: evidencia segura para emails de CI
Un pipeline de CI puede terminar en verde y aun así dejar un problema: nadie sabe qué dirección recibió el correo, qué job la creó ni cuándo debía desaparecer. Esto suele aparecer durante un incidente. El test de regist
Un pipeline de CI puede terminar en verde y aun así dejar un problema: nadie sabe qué dirección recibió el correo, qué job la creó ni cuándo debía desaparecer.
Esto suele aparecer durante un incidente. El test de registro falla, el equipo revisa los logs y encuentra que una bandeja temporal fue reutilizada por dos ejecuciones. El enlace de verificación parece correcto, pero pertenece a otro run. La infraestructura funcionó; la evidencia, no.
Para estos casos, una dirección de correo desechable (o throwaway email address) debe tratarse como un recurso temporal de CI, no como una cadena que se pega en una variable. Terraform puede ayudar a declarar su ciclo de vida, sus etiquetas y el límite de acceso. No resuelve la entrega del correo por sí solo, pero crea un contrato claro alrededor de ella.
El síntoma: CI verde, evidencia imposible de reconstruir
Un flujo de prueba tiene cuatro piezas: creación, envío, lectura y limpieza. Si cada una usa un identificador distinto, los fallos se convierten en adivinanzas.
Los síntomas más comunes son:
- Dos jobs leen mensajes de la misma bandeja.
- El log guarda el email, pero no el
run_idni el entorno. - Una prueba cancelada deja datos activos durante días.
En un sistema real, el nombre de una dirección no es suficiente. Necesitamos saber quién es el propietario temporal del recurso y cuánto tiempo puede vivir.
Qué debe declarar el recurso temporal
Antes de escribir Terraform, definí un contrato pequeño para cada ejecución:
-
run_id: identificador único del job y de sus reintentos. -
environment: por ejemplo,stagingopreview. -
owner: el workflow o servicio responsable de limpiarlo. -
expires_at: momento límite, incluso si el job se cancela. -
purpose: una descripción corta, comoemail-verification-e2e.
Las etiquetas permiten buscar recursos huérfanos. También facilitan responder una pregunta durante una guardia: “¿qué ejecución creó esta bandeja?”. Conviene que el run_id no contenga datos personales ni el contenido completo de un token.
Un patrón pequeño con Terraform
La implementación exacta depende del proveedor de correo, pero el patrón de infraestructura se parece a esto:
variable "ci_run_id" {
type = string
description = "Identificador único de la ejecución de CI"
}
variable "expires_at" {
type = string
description = "Fecha RFC3339 en la que el recurso deja de ser válido"
}
resource "example_test_inbox" "verification" {
name = "ci-${var.ci_run_id}"
labels = {
environment = "staging"
owner = "signup-e2e"
purpose = "email-verification-e2e"
expires_at = var.expires_at
}
}
El recurso anterior sólo es un ejemplo de contrato: el nombre del proveedor puede ser distinto. La creación debe ser idempotente: un reintento de lectura conserva el mismo run_id; un nuevo intento lógico tiene otro.
El secreto para crear o leer la bandeja debe llegar desde el almacén de secretos del runner. No lo pongas en tfvars, en el estado compartido ni en la salida de terraform plan. La seguridad aquí es aburrida a propósito: permisos mínimos, estado protegido y logs sin contenido de mensajes.
Seguridad y caducidad como parte del diseño
La caducidad no debería ser sólo una etiqueta decorativa. Hace falta una tarea que consulte expires_at y elimine recursos vencidos, también después de un job cancelado. Si el proveedor no soporta un TTL, un proceso de limpieza separado puede actuar como red de seguridad.
Usá dos límites distintos:
- Tiempo de vida del recurso: cuánto puede existir la bandeja.
- Tiempo de espera del test: cuánto espera el job un mensaje concreto.
Mezclarlos produce incidentes confusos. Una bandeja puede seguir activa mientras un test ya debería haber fallado. Y si el lector hace polling sin presupuesto, un problema de entrega termina ocupando todos los runners.
Para depurar un error de autenticación o de entrega, ayuda mantener una línea de tiempo con run_id, creación, envío, lectura, resultado y limpieza. El enfoque es parecido a depurar 401 intermitentes con contexto: un evento aislado dice poco; la secuencia completa revela el primer estado incorrecto.
También separaría los datos de prueba de las métricas de producto. Un email con formato raro, como tempail o temp gamil com, puede ser una entrada válida para probar validaciones; no debe convertirse en una excepción del sistema de limpieza. La cobertura de casos raros es buena, pero los nombres y las etiquetas deben seguir siendo predecibles.
Cómo investigar un fallo sin adivinar
Cuando CI reporta “no llegó el email”, revisá esto en orden:
- ¿El
run_iddel lector coincide con el de la creación? - ¿La aplicación aceptó el envío y tiene un identificador de mensaje?
- ¿El lector buscó el asunto o código correcto, sin datos de otro run?
- ¿El reloj del runner y el
expires_atestán alineados? - ¿La limpieza eliminó el recurso o dejó un estado parcial?
Si falla el segundo paso, no aumentes el polling. Si falla el primero, el problema es aislamiento. Si sólo falla la limpieza, el test puede estar verde pero queda una deuda de seguridad.
Este mismo criterio sirve para el onboarding: medir la activación sin perder el hilo del email exige distinguir entre “el mensaje fue enviado” y “el usuario completó la acción”. Son estados distintos, aunque el dashboard los muestre juntos.
Checklist operativo
- [ ] Cada job tiene un
run_idúnico y visible en los logs. - [ ] El recurso de email lleva entorno, propietario y caducidad.
- [ ] Los reintentos de lectura no crean otra bandeja.
- [ ] El secreto sólo está disponible para el paso que lo necesita.
- [ ] El estado de Terraform está protegido y no contiene mensajes.
- [ ] Un cleanup independiente elimina recursos vencidos.
- [ ] El test tiene un presupuesto de espera razonable.
- [ ] La evidencia permite reconstruir creación, envío, lectura y limpieza.
Preguntas frecuentes
¿Terraform debe leer el contenido del email?
No. Terraform declara y administra infraestructura; leer un código de verificación pertenece al test o a un pequeño adaptador. Mezclar ambos ciclos hace que un cambio de contenido parezca un cambio de infraestructura.
¿Qué pasa si el job se cancela?
La caducidad debe seguir activa aunque no corra el paso final. Usá TTL del proveedor y un limpiador periódico como respaldo.
¿Conviene compartir una bandeja para acelerar CI?
Sólo si el aislamiento está garantizado por contrato. En la práctica, una bandeja por run_id cuesta menos que investigar un falso positivo. Es facil ahorrar recursos y gastar mucho más en diagnóstico.
El objetivo no es crear recursos por costumbre. Cada email de prueba necesita dueño, razón y hora de salida. Así Terraform también forma parte de la evidencia operativa.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.