tutoriales.com

Gestionando Secretos Sensibles en Terraform con HashiCorp Vault: Un Enfoque Seguro

Este tutorial te guiará a través de la integración de HashiCorp Vault con Terraform para la gestión segura de secretos. Exploraremos cómo configurar Vault, desplegarlo con Terraform y utilizarlo para inyectar credenciales dinámicas en tus recursos de infraestructura, mejorando significativamente la seguridad de tus despliegues en la nube.

Intermedio25 min de lectura5 views19 de marzo de 2026Reportar error

🚀 Introducción a la Gestión Segura de Secretos con Vault y Terraform

En el mundo de DevOps, la automatización y la infraestructura como código (IaC) son pilares fundamentales. Herramientas como Terraform nos permiten definir y provisionar infraestructuras complejas de manera repetible y eficiente. Sin embargo, un desafío persistente y crítico es la gestión segura de secretos: credenciales de bases de datos, claves API, certificados SSL y otros datos sensibles que son esenciales para el funcionamiento de nuestras aplicaciones e infraestructura.

Almacenar estos secretos directamente en el código de Terraform o en variables de entorno inseguras es una práctica de riesgo. Cualquier exposición podría tener consecuencias devastadoras. Aquí es donde HashiCorp Vault entra en juego como una solución robusta y confiable. Vault es una herramienta diseñada para almacenar, acceder y gestionar secretos de forma centralizada y segura, ofreciendo cifrado en tránsito y en reposo, auditoría detallada y control de acceso granular.

Este tutorial te proporcionará una guía completa para integrar Vault con Terraform. Aprenderás a desplegar una instancia básica de Vault y, lo que es más importante, a utilizarlo para gestionar y acceder a secretos dentro de tus configuraciones de Terraform, elevando el nivel de seguridad de tus operaciones de IaC.

¿Por qué Vault con Terraform? 🛡️

La combinación de Terraform y Vault crea un flujo de trabajo de infraestructura como código altamente seguro. Mientras Terraform se encarga de provisionar la infraestructura, Vault se encarga de proteger y distribuir los secretos necesarios para que esa infraestructura funcione correctamente. Esto nos permite:

  • Eliminar secretos del código fuente: Evita la exposición accidental en repositorios de código.
  • Auditoría completa: Registra todos los accesos a secretos, quién accedió, cuándo y desde dónde.
  • Cifrado de secretos: Protege los secretos en reposo y en tránsito.
  • Secretos dinámicos: Genera credenciales bajo demanda con tiempos de vida limitados, minimizando la superficie de ataque.
  • Control de acceso granular: Define políticas de acceso detalladas a los secretos.

🛠️ Requisitos Previos

Antes de sumergirnos en la configuración, asegúrate de tener las siguientes herramientas instaladas y configuradas en tu entorno:

  • Terraform: Versión 1.0.0 o superior. Puedes descargarlo desde la página oficial de HashiCorp.
  • HashiCorp Vault CLI: Es útil para interactuar con Vault directamente. También disponible en la página oficial de HashiCorp.
  • Docker (opcional pero recomendado): Para ejecutar una instancia local de Vault de forma sencilla para pruebas.
  • Cuenta AWS (o proveedor de nube similar): Para desplegar y probar la integración. Configuraremos el proveedor AWS en nuestros ejemplos.
💡 Consejo: Familiarízate con los conceptos básicos de Terraform (proveedores, recursos, variables, salidas) y una comprensión básica de Vault (conceptos de almacenamiento de secretos, políticas) te será de gran ayuda.

⚙️ Configuración Inicial de HashiCorp Vault (Local para Pruebas)

Para este tutorial, utilizaremos una instancia de Vault ejecutándose en modo de desarrollo con Docker. Esto nos permite una configuración rápida y un entorno aislado para experimentar.

Paso 1: Ejecutar Vault con Docker

Abre tu terminal y ejecuta el siguiente comando:

docker run -d --name vault-dev -p 8200:8200 -e 'VAULT_DEV_ROOT_TOKEN_ID=myroottoken' hashicorp/vault:latest

Este comando inicia un contenedor Docker con Vault, expone el puerto 8200 y establece un root token de desarrollo llamado myroottoken. En un entorno de producción, la configuración de Vault es considerablemente más compleja (inicialización, desprecintado, almacenamiento persistente, TLS, etc.).

Paso 2: Configurar la Variable de Entorno VAULT_ADDR

Para que el CLI de Vault (y Terraform) pueda comunicarse con tu instancia, necesitas establecer la variable de entorno VAULT_ADDR:

export VAULT_ADDR='http://127.0.0.1:8200'

Paso 3: Iniciar Sesión en Vault

Utiliza el root token para autenticarte en tu instancia de Vault:

vault login myroottoken

Deberías ver una salida indicando que la autenticación fue exitosa.

Ejecutar Docker run para Vault Exportar VAULT_ADDR vault login con token

🔐 Habilitar y Configurar un Motor de Secretos en Vault

Vault utiliza motores de secretos para gestionar diferentes tipos de secretos. Para almacenar secretos arbitrarios (como claves API estáticas), utilizaremos el motor de secretos kv (Key-Value).

Paso 1: Habilitar el Motor de Secretos KV

vault secrets enable kv-v2

Esto habilita una nueva instancia del motor KV en la ruta kv-v2/. Puedes usar kv a secas si prefieres la versión 1, pero kv-v2 ofrece características adicionales como versionado de secretos.

Paso 2: Escribir un Secreto de Ejemplo

Vamos a almacenar un secreto simple que luego leeremos con Terraform. Por ejemplo, una api_key para un servicio ficticio.

vault kv put kv-v2/my-app/config api_key='supersecretapikey123' db_user='admin_app' db_password='secure_db_password'

Esto guarda la api_key, db_user y db_password en la ruta kv-v2/my-app/config.

📌 Nota: En un escenario real, evitarías usar valores estáticos como 'supersecretapikey123'. Idealmente, usarías credenciales dinámicas generadas por Vault o rotarías estas claves con frecuencia.

Paso 3: Verificar el Secreto (Opcional)

Para asegurarte de que el secreto fue almacenado correctamente:

vault kv get kv-v2/my-app/config

Deberías ver una salida similar a esta:

==== Secret Data ==== 
Key            Value
---            -----
api_key        supersecretapikey123
db_password    secure_db_password
db_user        admin_app

📝 Creación de Políticas de Acceso en Vault

Para que Terraform (o cualquier otra aplicación) pueda leer secretos de Vault, necesita un token con los permisos adecuados. Estos permisos se definen mediante políticas de Vault.

Paso 1: Crear un Archivo de Política

Crea un archivo llamado terraform-policy.hcl con el siguiente contenido:

path "kv-v2/data/my-app/config" {
  capabilities = ["read"]
}

path "auth/token/create" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

Esta política concede permiso de solo lectura al secreto que acabamos de almacenar. La segunda ruta permite a la entidad que usa esta política crear tokens de corta duración si fuera necesario (aunque no lo usaremos directamente para la lectura simple en Terraform, es una buena práctica incluirla para un control de acceso más flexible).

Paso 2: Escribir la Política en Vault

vault policy write terraform-reader terraform-policy.hcl

Esto registra la política terraform-reader en Vault.

🤝 Integración de Vault con Terraform

Ahora viene la parte crucial: cómo hacer que Terraform hable con Vault y recupere nuestros secretos. Utilizaremos el proveedor de Vault para Terraform.

Crea un nuevo directorio para tu configuración de Terraform, por ejemplo, terraform-vault-integration, y dentro de él, crea los siguientes archivos.

Archivo: main.tf

# Proveedor de AWS (ejemplo)
provider "aws" {
  region = "us-east-1"
  # Se asume que las credenciales de AWS están configuradas externamente
  # (variables de entorno, ~/.aws/credentials, etc.)
}

# Configuración del proveedor de Vault
provider "vault" {
  address = var.vault_address
  token   = var.vault_token
}

# Leer el secreto de Vault
data "vault_generic_secret" "app_config" {
  path = "kv-v2/data/my-app/config"
}

# Ejemplo de cómo usar los secretos en un recurso de AWS
resource "aws_instance" "web_server" {
  ami           = "ami-0abcdef1234567890" # ID de AMI de ejemplo, reemplaza con uno válido
  instance_type = "t2.micro"
  tags = {
    Name = "WebServer-with-Secrets"
  }

  # Inyectar secretos como variables de entorno en el user_data
  user_data = <EOF
#!/bin/bash
echo "API_KEY=${data.vault_generic_secret.app_config.data["api_key"]}" >> /etc/environment
echo "DB_USER=${data.vault_generic_secret.app_config.data["db_user"]}" >> /etc/environment
echo "DB_PASSWORD=${data.vault_generic_secret.app_config.data["db_password"]}" >> /etc/environment

systemctl restart my-application.service # Ejemplo de cómo usar en una aplicación
EOF
}

# Salida de ejemplo (no expongas secretos sensibles en las salidas en producción)
output "api_key_from_vault" {
  value     = data.vault_generic_secret.app_config.data["api_key"]
  sensitive = true # Marca la salida como sensible para que no se muestre en texto plano
}

output "instance_public_ip" {
  value = aws_instance.web_server.public_ip
}

Archivo: variables.tf

variable "vault_address" {
  description = "La dirección de tu instancia de Vault."
  type        = string
  default     = "http://127.0.0.1:8200"
}

variable "vault_token" {
  description = "El token de Vault con permisos para leer los secretos."
  type        = string
  sensitive   = true
}
⚠️ Advertencia: NUNCA hardcodees tokens de Vault o cualquier otro secreto sensible directamente en tus archivos `.tf`. Usa variables de entorno, archivos `.tfvars` ignorados por Git, o mejor aún, mecanismos de autenticación más robustos como la autenticación basada en roles (por ejemplo, AWS IAM en un entorno de producción). Para este tutorial usamos una variable `sensitive` para simplificar.

Explicación de los Componentes 📖

  • provider "vault": Define el proveedor de Vault. Necesita la address de tu instancia de Vault y un token de autenticación.
  • data "vault_generic_secret" "app_config": Este bloque data es el corazón de la integración. Le indica a Terraform que lea un secreto de Vault de la ruta especificada (kv-v2/data/my-app/config). Nota la diferencia en la ruta: kv-v2/data/... en el bloque data de Terraform versus kv-v2/... al escribir el secreto con el CLI de Vault. Esto es específico del motor kv-v2.
  • data.vault_generic_secret.app_config.data["api_key"]: Así es como accedes a los valores individuales del secreto. data es el atributo que contiene el mapa de todos los secretos almacenados en esa ruta.
  • user_data en aws_instance: Un ejemplo práctico de cómo inyectar estos secretos en una instancia EC2 al iniciarla, configurando variables de entorno para que la aplicación las lea.
  • sensitive = true en output: Aunque es mejor evitar exponer secretos en las salidas de Terraform, si es absolutamente necesario, marca la salida como sensitive para que Terraform la oculte en la consola.

🚀 Desplegando la Infraestructura con Secretos de Vault

Ahora que tenemos todo configurado, es hora de ejecutar Terraform.

Paso 1: Inicializar Terraform

Navega al directorio terraform-vault-integration y ejecuta:

terraform init

Esto descargará los proveedores de AWS y Vault.

Paso 2: Generar un Token de Vault para Terraform

En un entorno de producción, nunca usarías el root token para las operaciones de Terraform. En su lugar, generarías un token específico con la política terraform-reader que creamos. Asegúrate de que tu VAULT_ADDR esté configurado y estés autenticado como root.

vault token create -policy=terraform-reader -ttl=1h

Esta es la salida de ejemplo:

Key           Value
---           -----
token         s.xxxxxxxxxxxxxxxxxxxx # <-- Este es el token que necesitas
token_accessor y.xxxxxxxxxxxxxxxxxxxx
token_duration 1h0m0s
token_renewable true
token_policies ["default" "terraform-reader"]
identity_policies []
policies      [ "default", "terraform-reader" ]

Copia el valor del token (el que empieza con s.).

Paso 3: Planificar y Aplicar Terraform

Ahora, ejecuta el plan y aplica los cambios. Se te pedirá el vault_token.

terraform plan

Ingresa el token que generaste cuando se te solicite var.vault_token.

Verás la salida del plan, que debería mostrar la creación de la instancia EC2 y cómo los secretos serán inyectados (aunque los valores reales estarán ocultos debido a sensitive = true).

terraform apply

Confirma con yes para aplicar los cambios.

💡 Consejo: Para evitar ingresar el token manualmente cada vez, puedes pasarlo como una variable de entorno: `TF_VAR_vault_token='s.xxxxxxxxxxxxxxxxxxxx' terraform apply`.

Una vez que Terraform complete la aplicación, tu instancia EC2 estará en funcionamiento, y los secretos de Vault se habrán inyectado en su user_data durante el inicio.


🔄 Secretos Dinámicos con Vault (Concepto Avanzado)

La verdadera potencia de Vault reside en su capacidad para generar secretos dinámicos. En lugar de almacenar un secreto estático, Vault puede generar credenciales bajo demanda con tiempos de vida limitados (TTL). Esto es ideal para bases de datos, proveedores de nube, etc.

Por ejemplo, para una base de datos PostgreSQL, Vault podría generar un usuario y una contraseña temporales que solo sean válidos durante 5 minutos y se revoquen automáticamente después de ese tiempo.

Habilitar un Motor de Secretos de Base de Datos (Ejemplo)

vault secrets enable database
vault write database/config/postgresql plugin_name=postgresql-database-plugin connection_url="postgresql://{{username}}:{{password}}@localhost:5432/mydb"
vault write database/roles/my-app-role db_name=postgresql creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" default_ttl="1h" max_ttl="24h"

Luego, en Terraform, usarías data "vault_database_secret" "db_credentials" en lugar de vault_generic_secret para obtener credenciales dinámicas:

data "vault_database_secret" "db_credentials" {
  backend = "database"
  role    = "my-app-role"
}

resource "aws_instance" "app_server" {
  # ... (otros atributos)
  user_data = <EOF
#!/bin/bash
echo "DB_USERNAME=${data.vault_database_secret.db_credentials.username}" >> /etc/environment
echo "DB_PASSWORD=${data.vault_database_secret.db_credentials.password}" >> /etc/environment
EOF
}
🔥 Importante: La implementación de secretos dinámicos requiere una configuración más profunda de Vault y de la integración con la base de datos o servicio correspondiente. Es un paso vital para entornos de producción de alta seguridad.

✅ Limpieza de Recursos

Para evitar cargos inesperados en tu cuenta de AWS y limpiar tu entorno local:

Paso 1: Destruir la Infraestructura de Terraform

terraform destroy

Confirma con yes.

Paso 2: Detener y Eliminar el Contenedor de Vault

docker stop vault-dev
docker rm vault-dev

Paso 3: Eliminar la Variable de Entorno

unset VAULT_ADDR

📝 Resumen y Próximos Pasos

¡Felicidades! Has completado un tutorial exhaustivo sobre cómo integrar HashiCorp Vault con Terraform para gestionar secretos de forma segura. Hemos cubierto:

  • La importancia de la gestión segura de secretos en IaC.
  • La configuración de una instancia local de Vault.
  • La habilitación de un motor de secretos KV y el almacenamiento de datos.
  • La creación de políticas de acceso en Vault.
  • La integración de Terraform con el proveedor de Vault para leer secretos.
  • Un vistazo a los secretos dinámicos y su relevancia.

La gestión de secretos es un aspecto crítico de la seguridad en la nube. Al adoptar herramientas como Vault, puedes garantizar que tu infraestructura y aplicaciones permanezcan protegidas contra el acceso no autorizado a información sensible.

📌 Nota: Este tutorial utiliza una configuración de Vault en modo de desarrollo para simplificar. En producción, la configuración de Vault implica consideraciones adicionales como alta disponibilidad, almacenamiento persistente, TLS, integración con proveedores de autenticación (AWS IAM, Kubernetes, etc.) y unboxing automático.

Dónde Continuar Aprendiendo ✨

  • Documentación oficial de HashiCorp Vault: Profundiza en los motores de secretos y métodos de autenticación avanzados.
  • Autenticación en Vault: Explora métodos como AWS IAM, Kubernetes, LDAP, etc., para eliminar la necesidad de tokens estáticos.
  • Sellado automático (Auto-unseal): Aprende sobre las opciones para desprecintar automáticamente Vault en entornos de producción.
  • Integración con CI/CD: Cómo integrar la obtención de secretos de Vault en tus pipelines de entrega continua.

¡Mantén tus secretos seguros! 🔒

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!