Cybersecurity16 de mayo de 20269 min read

Gestión de secretos: deje de incrustar claves API en el código

Todos los post mortem de una brecha tienen el mismo capítulo: alguien encontró una credencial. Así se sacan los secretos estáticos de su código, sus imágenes y sus pipelines de una vez por todas.

Por Innovation T Team


Todos los post mortem de una brecha tienen un capítulo que se repite: alguien encontró una credencial. En un repositorio, en una capa de Docker, en un log de CI, en una captura de pantalla pegada en Slack. La gestión de secretos no es teatro de higiene. Es la diferencia entre un incidente contenido y un atacante con las llaves de su base de datos de producción.

Por qué los secretos incrustados nunca siguen siendo secretos

Un secreto commiteado en el código no es un secreto. Es una bomba de tiempo con visibilidad pública.

Estos son los lugares por donde se filtran de verdad:

  • El historial de git. Borrar la clave en un commit nuevo no sirve de nada. El blob antiguo sigue viviendo en el almacén de objetos, en cada clon, en cada fork y en las cachés de sus runners de CI. Un git log -p lo encuentra en segundos.
  • Las capas de la imagen Docker. Un COPY .env . seguido de RUN rm .env sigue empaquetando el secreto. Las capas son aditivas. Cualquiera con acceso de pull puede ejecutar docker history y extraerlo.
  • Los logs de CI. Un env | sort olvidado en un paso de depuración, un framework que imprime la configuración al arrancar, un runner de tests que vuelca el entorno cuando falla. Los logs se retienen, se reenvían y se indexan.
  • Los bundles del cliente. Los builds de frontend inyectan todo lo que lleve el prefijo de exposición pública. Vemos con frecuencia claves de servidor de Stripe o de Mercado Pago enviadas al navegador porque alguien renombró una variable para que el build pasara.
  • La sincronización con terceros. Plugins del editor, herramientas de respaldo y asistentes de programación con IA que indexan su espacio de trabajo indexarán también el .env sin pensarlo dos veces.

Los escáneres automáticos vigilan el flujo público de eventos de GitHub las veinticuatro horas. En nuestra experiencia, una clave de nube expuesta en un repositorio público recibe las primeras sondas en cuestión de minutos, no de días. Los mineros de criptomonedas en la factura de AWS suelen ser la forma en que los equipos se enteran.

El modelo de amenazas, sin rodeos

Ustedes se están defendiendo de tres cosas:

  1. Exfiltración: un atacante lee el secreto de algún lugar donde quedó escrito.
  2. Reutilización: un atacante que tiene el secreto lo usa, desde cualquier parte, mientras siga siendo válido.
  3. Radio de impacto: una sola credencial filtrada abre muchas más puertas de las que debería.

Cada control de esta guía ataca uno de esos tres frentes. El cifrado en reposo ataca la exfiltración. Los TTL cortos atacan la reutilización. Las credenciales acotadas por servicio atacan el radio de impacto. Si una herramienta no encaja claramente en uno de los tres, es decoración.

La escalera de madurez

No salte directamente a operar un clúster de Vault. Suba peldaño a peldaño, con intención.

Nivel 0: archivos .env fuera de git

El suelo, no la meta. Aceptable para un prototipo en solitario. Los secretos están en texto plano en cada portátil, no hay rastro de auditoría, no hay rotación, y dar de baja a un ingeniero consiste en confiar en que borre el archivo.

Nivel 1: el gestor de secretos de la plataforma

Use el almacén que su plataforma ya le da: AWS Secrets Manager o SSM Parameter Store, GCP Secret Manager, Azure Key Vault, o los secretos cifrados de Vercel, Fly.io o GitHub Actions. Los secretos quedan cifrados en reposo, se inyectan en tiempo de ejecución y el acceso se gobierna con IAM. Para la mayoría de los equipos de menos de 20 ingenieros, este nivel bien ejecutado supera a un Vault mal operado.

La disciplina clave en este nivel: la aplicación lee los secretos del entorno o del SDK al arrancar. Nunca los lee de un archivo dentro del repositorio.

Nivel 2: secretos centralizados con control de acceso y auditoría

Un único sistema de referencia para cada secreto en cada entorno. HashiCorp Vault, OpenBao (el fork de código abierto), Infisical o Doppler. Lo que se gana respecto al nivel 1:

  • Uniformidad: una sola API y un solo lenguaje de políticas para AWS, GCP, on premise y CI.
  • Auditoría: cada lectura queda registrada con identidad, ruta y marca de tiempo. Cuando una clave se filtra, el log de auditoría es lo que permite acotar el incidente. Es además la evidencia que le van a pedir en una auditoría del RGPD en España o de las leyes de protección de datos de México, Colombia o Argentina.
  • Políticas: el servicio de facturación puede leer billing/* y nada más, y eso se aplica de forma centralizada.

Nivel 3: credenciales dinámicas de corta duración

La meta final. No existe ningún secreto estático. Las credenciales se emiten bajo demanda, acotadas a una identidad, y caducan en minutos u horas. En este nivel, una credencial filtrada es una molestia, no una brecha.

Secretos dinámicos: elimine la credencial estática

El motor de secretos de base de datos de Vault es el ejemplo más claro del patrón. En lugar de un DB_PASSWORD compartido que vive en doce sitios, cada instancia del servicio solicita su propio usuario al arrancar:

vault write database/roles/app-readonly \
  db_name=postgres \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' \
    VALID UNTIL '{{expiration}}'; \
    GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl="1h" max_ttl="24h"

Cada lectura de database/creds/app-readonly crea un rol de Postgres nuevo que se autodestruye en una hora. Las propiedades que obtiene sin esfuerzo adicional:

  • Atribución. ¿Una consulta lenta de v-k8s-app-readonly-x7Hf? Sabe exactamente qué pod la emitió.
  • Revocación instantánea. Revoca el lease y la credencial muere ahora, no en el próximo despliegue.
  • Fugas sin valor. Una credencial capturada en una sesión de depuración caduca antes de que nadie pueda usarla.

El mismo patrón existe para credenciales de AWS STS, claves de cuentas de servicio de GCP, certificados SSH y PKI. La contrapartida es real: su base de datos debe tolerar la rotación constante de roles, los poolers de conexiones necesitan lógica de reautenticación y Vault se convierte en infraestructura de nivel cero. Lo que nos lleva a los modos de fallo.

El problema del secreto cero y otros modos de fallo

Los equipos adoptan un vault y luego tropiezan con las mismas cuatro piedras:

  • El secreto cero. La aplicación necesita una credencial para hablar con el vault. Si esa credencial es un token estático en una variable de entorno, el problema no se resolvió, se mudó de sitio. La solución es la identidad de plataforma: tokens de cuenta de servicio de Kubernetes, autenticación IAM de AWS, identidad de instancia de GCP. La carga de trabajo demuestra quién es con algo que la plataforma atestigua, no con algo que un humano pegó a mano.
  • El vault como punto único de fallo. Si Vault está caído y sus pods no pueden arrancar, ha convertido una herramienta de seguridad en un incidente de disponibilidad. Opérelo con alta disponibilidad real, cachee los leases en el cliente y fije TTL lo bastante largos para sobrevivir a un corte breve.
  • La regresión hacia el desorden. Los ingenieros con fechas de entrega encima copian secretos del vault de vuelta a archivos .env "de forma temporal". Haga que el camino sancionado sea el más fácil: integración por SDK, inyección con sidecar o archivos generados por plantilla en el despliegue.
  • Logs de auditoría que nadie lee. Un log de auditoría sin alertas es un artefacto de cumplimiento. Alerte sobre lecturas desde identidades inusuales, lecturas masivas y uso del token root.

CI/CD: deje de guardar claves de la nube en su pipeline

El CI es el lugar donde las credenciales estáticas van a que las roben. Una AWS_SECRET_ACCESS_KEY de larga duración en la configuración del pipeline es legible por cada mantenedor, cada action comprometida y cada dependencia con un script de postinstall.

La respuesta moderna es la federación OIDC. El proveedor de CI emite un token de identidad firmado y de corta duración por cada job, y su nube confía directamente en ese token. No existe ninguna clave almacenada que robar:

permissions:
  id-token: write
  contents: read
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/deploy-prod
      aws-region: eu-west-1

Acote la política de confianza de IAM a su organización, repositorio y rama exactos. Un job en main de su repositorio puede desplegar; un job en un fork no puede, y la garantía es criptográfica. GitHub Actions, GitLab CI y CircleCI lo soportan contra AWS, GCP y Azure. Si está construyendo la postura de seguridad de su pipeline de forma más amplia, nuestra guía de pipelines DevSecOps explica dónde encaja la gestión de secretos en la cadena completa.

Detecte las fugas antes de que lleguen a producción

Prevenir gana a responder, y las herramientas son gratuitas. Monte tres redes en capas:

1. Escaneo pre-commit. Gitleaks analiza un diff preparado en menos de un segundo:

repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.0
    hooks:
      - id: gitleaks

2. Protección en el push. El secret scanning de GitHub con push protection bloquea el push en el servidor cuando coincide con un patrón de credencial conocido. Actívelo en todos los repositorios, privados incluidos. GitLab tiene un equivalente.

3. Escaneo del historial y de artefactos. Ejecute TruffleHog o Gitleaks de forma programada sobre el historial completo de git, las imágenes de contenedores y los artefactos de build. Las detecciones verificadas (el escáner llama de verdad al proveedor para comprobar que la clave está viva) reducen drásticamente el ruido de falsos positivos.

Nada de esto sustituye a diseñar APIs y servicios con secretos bien acotados desde el principio. Nuestro artículo sobre buenas prácticas de seguridad en APIs profundiza en el alcance y la rotación de claves en la frontera de la API.

Cuando la clave se filtra igual: la primera hora

Asuma que va a pasar. El guion, en orden:

  1. Revoque primero, investigue después. En cuanto confirme la exposición, mate la credencial. No espere a una ventana de mantenimiento. El dolor de disponibilidad se recupera; los datos exfiltrados no.
  2. Emita el reemplazo. Genere la nueva credencial a través de su gestor de secretos, con un alcance más estrecho que la anterior. Este es el momento de arreglar esos permisos demasiado amplios que llevaba tiempo queriendo arreglar.
  3. Acote el daño. Extraiga los logs de auditoría de toda la ventana de exposición de la credencial, no solo desde el descubrimiento. En AWS eso significa consultas de CloudTrail por el ID de la clave de acceso. Busque IP desconocidas, regiones extrañas y llamadas API fuera de lo habitual.
  4. Purgue, pero dé la clave por quemada. Reescriba el historial con git filter-repo y haga force push, pero entienda que eso es limpieza, no remediación. Los clones y los forks todavía la tienen. La credencial está muerta de todos modos, para eso era el paso 1.
  5. Arregle el camino, no a la persona. El secreto acabó en el commit porque el camino seguro era más difícil que el inseguro. Añada el hook de pre-commit, conecte el gestor de secretos, cierre la brecha.

Si no tiene esto escrito y ensayado antes de necesitarlo, empiece por nuestro manual de respuesta a incidentes.

Un marco de decisión

Elija la herramienta según el equipo, no según la charla de conferencia:

  • En solitario o equipo mínimo, una sola nube: el gestor de secretos de su nube más OIDC en el CI. Una tarde de trabajo, la mayor parte del valor. Es el punto de partida sensato para casi cualquier startup del ecosistema latinoamericano o español.
  • Equipo en crecimiento, una o dos nubes, Kubernetes: gestores de secretos de la nube como backend, External Secrets Operator sincronizando hacia el clúster, push protection en todos los repositorios.
  • Multi nube, requisitos de cumplimiento, cargas 24/7: Vault u OpenBao con autenticación por identidad de plataforma, credenciales dinámicas para bases de datos y acceso a la nube, y alertas sobre el log de auditoría.
  • Sectores regulados u objetivos de alto valor: todo lo anterior, más TTL cortos como política, simulacros de fuga trimestrales y rotación de secretos verificada por automatización, no por un recordatorio en el calendario. Si opera bajo el RGPD o su equivalente local, aquí es donde el auditor va a mirar primero.

Elija el nivel que elija, hay tres reglas universales. Ningún secreto en git, jamás. Ningún secreto compartido entre dos servicios. Cada secreto debe tener un dueño, un alcance y una caducidad que alguien pueda recitar en voz alta.

Cómo puede ayudar Innovation T

Innovation T diseña y opera infraestructura de secretos para equipos de Europa y el norte de África: despliegues de Vault y OpenBao con alta disponibilidad real, federación OIDC para CI/CD, credenciales dinámicas de base de datos y detección de fugas integrada en el pipeline, no atornillada después de un incidente. Hemos migrado equipos que tenían claves incrustadas en el código sin una sola caída de producción, y dejamos runbooks que sus ingenieros usan de verdad.

Si sus archivos .env están a un portátil robado de convertirse en un informe de incidente, hablemos. Consulte nuestros servicios o contáctenos para una revisión de su postura de secretos.

#gestión de secretos#vault#claves API#devsecops

¿Listo para construir con Innovation T?

Ya se trate de seguridad, crecimiento o ingeniería, nuestro equipo puede ayudarte a lograrlo con calidad.