Gestionando Certificados TLS/SSL con Terraform y AWS Certificate Manager (ACM)
Este tutorial te guiará a través del proceso de aprovisionar y gestionar certificados TLS/SSL utilizando Terraform y AWS Certificate Manager (ACM). Cubriremos la creación de certificados, la validación de dominios y la integración con servicios como Load Balancers y CloudFront. Automatiza la seguridad de tus aplicaciones web.
🚀 Introducción a los Certificados TLS/SSL y ACM
En el mundo digital actual, la seguridad es primordial. Los certificados TLS/SSL son esenciales para establecer conexiones seguras entre los navegadores de los usuarios y tus aplicaciones web, protegiendo los datos en tránsito mediante cifrado. AWS Certificate Manager (ACM) simplifica la gestión de estos certificados, ofreciendo certificados públicos y privados de forma gratuita para usar con otros servicios de AWS.
Tradicionalmente, la gestión de certificados implica generar CSRs (Certificate Signing Requests), comprarlos de una CA (Certificate Authority), subirlos y renovarlos manualmente. Este proceso puede ser tedioso y propenso a errores. Con Terraform y ACM, podemos automatizar completamente el ciclo de vida de nuestros certificados, garantizando que nuestras aplicaciones siempre operen bajo HTTPS de manera eficiente y segura.
¿Por qué Terraform para ACM?
La infraestructura como código (IaC) con Terraform nos permite definir, versionar y desplegar nuestra infraestructura de certificados de manera declarativa. Esto aporta múltiples beneficios:
- Automatización: Elimina tareas manuales repetitivas.
- Consistencia: Asegura que los certificados se desplieguen de la misma manera en todos los entornos.
- Versionamiento: Permite rastrear cambios y revertir a versiones anteriores si es necesario.
- Colaboración: Facilita el trabajo en equipo en la gestión de la seguridad.
- Auditoría: Ofrece un registro claro de cómo se gestionan los certificados.
📋 Prerrequisitos
Antes de empezar, asegúrate de tener lo siguiente:
- Una cuenta de AWS activa con credenciales configuradas.
- Terraform instalado en tu máquina local (versión 0.13 o superior).
- Conocimientos básicos de AWS y Terraform.
- Un dominio registrado en Route 53 (o cualquier otro registrador de dominios si puedes gestionar sus registros DNS).
🛠️ Configuración Inicial de Terraform y AWS
Primero, necesitamos configurar nuestro archivo main.tf para indicar a Terraform que utilice el proveedor de AWS.
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.0.0"
}
provider "aws" {
region = "us-east-1"
}
variable "domain_name" {
description = "El nombre de dominio principal para el certificado."
type = string
}
variable "alternative_names" {
description = "Una lista de nombres de dominio alternativos (SANs)."
type = list(string)
default = []
}
variable "validation_method" {
description = "Método de validación del certificado (DNS o EMAIL)."
type = string
default = "DNS"
validation {
condition = contains(["DNS", "EMAIL"], var.validation_method)
error_message = "El método de validación debe ser 'DNS' o 'EMAIL'."
}
}
output "certificate_arn" {
description = "El ARN del certificado SSL/TLS emitido."
value = aws_acm_certificate.my_certificate.arn
}
output "certificate_status" {
description = "El estado actual del certificado."
value = aws_acm_certificate.my_certificate.status
}
Este main.tf establece el proveedor de AWS en la región us-east-1 (ACM es un servicio regional y muchos de sus usos, como con CloudFront, requieren que esté en us-east-1). Define variables para el nombre de dominio principal, nombres alternativos y el método de validación. También exporta el ARN y el estado del certificado.
🔑 Creación del Certificado ACM
El primer paso es solicitar el certificado a ACM. Añade el siguiente bloque de recursos a tu main.tf.
# Solicitar un certificado ACM
resource "aws_acm_certificate" "my_certificate" {
domain_name = var.domain_name
subject_alternative_names = var.alternative_names
validation_method = var.validation_method
lifecycle {
create_before_destroy = true
}
tags = {
Environment = "Production"
Project = "MyWebApp"
}
}
domain_name: El dominio principal para el cual solicitas el certificado (ej.example.com).subject_alternative_names: Una lista opcional de dominios adicionales (SANs) que el certificado cubrirá (ej.*.example.com,app.example.com).validation_method: Cómo se validará la propiedad del dominio.DNSes el método preferido para automatización con Terraform.lifecycle { create_before_destroy = true }: Esta es una configuración crucial. Asegura que Terraform cree un nuevo certificado antes de destruir el antiguo. Esto es vital para evitar interrupciones del servicio al renovar o reemplazar certificados.
🌐 Validación del Dominio con DNS
Para que ACM emita un certificado, debe verificar que eres el propietario o tienes control sobre el dominio para el que solicitas el certificado. El método de validación DNS es el más automatizable y robusto. Si tu dominio está gestionado en Route 53, Terraform puede crear automáticamente los registros DNS de validación.
Caso 1: Dominio en Route 53
Si tu dominio está en Route 53, puedes usar aws_route53_zone y aws_route53_record para crear los registros CNAME necesarios para la validación.
Primero, necesitamos obtener la zona de Route 53 para nuestro dominio.
# Data source para obtener la Hosted Zone de Route 53
data "aws_route53_zone" "selected_zone" {
name = "${var.domain_name}."
private_zone = false
}
Luego, creamos los registros CNAME de validación. ACM generará un registro CNAME por cada dominio/subdominio que deba ser validado.
# Creación de registros DNS para la validación de ACM
resource "aws_route53_record" "acm_validation" {
for_each = {
for dvo in aws_acm_certificate.my_certificate.domain_validation_options : dvo.domain_name => dvo
}
allow_overwrite = true
name = each.value.resource_record_name
type = each.value.resource_record_type
records = [each.value.resource_record_value]
ttl = 60
zone_id = data.aws_route53_zone.selected_zone.zone_id
}
El for_each itera sobre domain_validation_options que ACM proporciona. Cada opción contiene el resource_record_name (el nombre del CNAME), resource_record_type (CNAME) y resource_record_value (el valor al que apunta el CNAME).
Finalmente, necesitamos un recurso para esperar a que el certificado esté completamente validado y emitido.
# Esperar la validación del certificado
resource "aws_acm_certificate_validation" "certificate_validation" {
certificate_arn = aws_acm_certificate.my_certificate.arn
validation_record_fqdns = [for record in aws_route53_record.acm_validation : record.fqdn]
# Depende de los registros DNS para asegurar que se creen antes de la validación
depends_on = [
aws_route53_record.acm_validation
]
}
Este recurso aws_acm_certificate_validation esperará hasta que el estado del certificado sea ISSUED, lo que significa que la validación se ha completado con éxito y el certificado está listo para usar.
Caso 2: Dominio fuera de Route 53
Si tu dominio no está en Route 53, tendrás que crear los registros CNAME manualmente en el registrador DNS de tu dominio. Terraform solicitará el certificado y te proporcionará los detalles del registro CNAME, pero no podrá crearlos por ti.
El bloque aws_acm_certificate sigue siendo el mismo. Para obtener los valores CNAME necesarios, puedes usar un output o inspeccionar el estado de Terraform después de terraform apply:
output "cname_records_for_manual_validation" {
description = "Registros CNAME para configurar manualmente si el dominio no está en Route 53."
value = [
for dvo in aws_acm_certificate.my_certificate.domain_validation_options : {
name = dvo.resource_record_name
type = dvo.resource_record_type
value = dvo.resource_record_value
}
]
}
Una vez que hayas añadido estos registros CNAME en tu registrador DNS, ACM detectará los registros y validará el dominio automáticamente. No necesitarías el recurso aws_acm_certificate_validation en este caso, ya que Terraform no puede interactuar con un registrador DNS externo para confirmar la validación.
🔗 Integración del Certificado con Servicios AWS
Una vez que el certificado ha sido emitido, puedes asociarlo con varios servicios de AWS para habilitar HTTPS.
1. Con un Application Load Balancer (ALB)
La forma más común de usar certificados ACM es con un balanceador de carga (ALB/NLB) para terminar el TLS. Aquí tienes un ejemplo de cómo configurar un Listener HTTPS para un ALB.
# Ejemplo de integración con un Application Load Balancer
# Asume que ya tienes un ALB y Target Group definidos
resource "aws_lb" "example_lb" {
name = "my-example-alb"
internal = false
load_balancer_type = "application"
security_groups = ["sg-xxxxxxxx"]
subnets = ["subnet-xxxxxxxx", "subnet-yyyyyyyy"]
enable_deletion_protection = false
tags = {
Name = "MyExampleALB"
}
}
resource "aws_lb_target_group" "example_tg" {
name = "my-example-tg"
port = 80
protocol = "HTTP"
vpc_id = "vpc-xxxxxxxx"
}
resource "aws_lb_listener" "https_listener" {
load_balancer_arn = aws_lb.example_lb.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = aws_acm_certificate_validation.certificate_validation.certificate_arn # Usa el ARN del certificado validado
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.example_tg.arn
}
}
# (Opcional) Redireccionar HTTP a HTTPS
resource "aws_lb_listener" "http_listener" {
load_balancer_arn = aws_lb.example_lb.arn
port = 80
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
2. Con Amazon CloudFront
Para sitios web servidos globalmente, CloudFront es la elección ideal. Los certificados ACM asociados a distribuciones de CloudFront deben crearse en la región us-east-1 (N. Virginia). Ya hemos configurado nuestro provider y aws_acm_certificate para usar esta región.
# Ejemplo de integración con CloudFront Distribution
# Asume que ya tienes un bucket S3 para tu origen o un ALB como origen
resource "aws_s3_bucket" "origin_bucket" {
bucket = "my-cloudfront-origin-bucket-${random_string.suffix.result}"
tags = {
Name = "MyCloudFrontOriginBucket"
}
}
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
resource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = aws_s3_bucket.origin_bucket.bucket_regional_domain_name
origin_id = "S3-my-origin"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.default.cloudfront_access_identity_path
}
}
enabled = true
is_ipv6_enabled = true
comment = "My S3 CloudFront distribution"
default_root_object = "index.html"
aliases = [var.domain_name] # Aquí se asocia tu dominio personalizado
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-my-origin"
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
}
# Configuración SSL/TLS para CloudFront
viewer_certificate {
cloudfront_default_certificate = false
acm_certificate_arn = aws_acm_certificate_validation.certificate_validation.certificate_arn # ARN del certificado validado
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = "Production"
}
}
resource "aws_cloudfront_origin_access_identity" "default" {
comment = "OAI for S3 bucket"
}
# (Opcional) Crear un registro ALIAS en Route 53 para apuntar al CloudFront Distribution
resource "aws_route53_record" "domain_to_cloudfront" {
zone_id = data.aws_route53_zone.selected_zone.zone_id
name = var.domain_name
type = "A"
alias {
name = aws_cloudfront_distribution.s3_distribution.domain_name
zone_id = aws_cloudfront_distribution.s3_distribution.hosted_zone_id
evaluate_target_health = false
}
}
En la sección viewer_certificate de la distribución de CloudFront, especificamos acm_certificate_arn con el ARN de nuestro certificado validado. ssl_support_method = "sni-only" es el método más común y recomendado.
🔄 Renovación y Ciclo de Vida del Certificado
Una de las mayores ventajas de usar ACM es su capacidad de renovar automáticamente los certificados antes de que expiren. Esto es transparente para el usuario final y para Terraform, siempre y cuando la validación DNS se mantenga vigente. Si usaste la validación DNS con Route 53 y Terraform, los registros necesarios para la renovación se mantienen y ACM se encarga del resto.
El lifecycle { create_before_destroy = true } en el recurso aws_acm_certificate es fundamental para una renovación o reemplazo manual sin interrupciones. Cuando un certificado está a punto de expirar o necesitas reemplazarlo por cualquier motivo (por ejemplo, añadir un nuevo SAN), si modificas el recurso aws_acm_certificate en Terraform, éste solicitará un nuevo certificado y lo validará, y solo una vez que el nuevo certificado esté listo, Terraform lo asociará a los servicios dependientes y eliminará el certificado antiguo.
📊 Diagrama de Flujo del Proceso
Veamos un diagrama que ilustra el flujo de trabajo completo.
🗑️ Limpieza de Recursos
Para evitar cargos inesperados, es importante limpiar los recursos de AWS una vez que hayas terminado con este tutorial. Puedes hacerlo ejecutando:
terraform destroy
Este comando eliminará todos los recursos de AWS que Terraform ha creado.
✅ Conclusión
Hemos recorrido el proceso completo para gestionar certificados TLS/SSL con Terraform y AWS Certificate Manager. Desde la solicitud inicial del certificado y la automatización de la validación DNS con Route 53, hasta la integración con servicios clave como Application Load Balancers y CloudFront. Esta aproximación garantiza una gestión de certificados eficiente, segura y totalmente automatizada, eliminando la carga de las tareas manuales y reduciendo el riesgo de errores.
La infraestructura como código no es solo para servidores y redes; es una práctica fundamental para cada componente de tu arquitectura en la nube, incluida la seguridad y los certificados.
Tutoriales relacionados
- Gestionando Políticas de Servicio (SCP) en AWS Organizations con Terraform: Control Centralizado de Permisosintermediate20 min
- Gestionando Servidores sin Estado con Terraform y AWS Auto Scaling Groupsintermediate20 min
- Aprovisionando y Gestionando Redes de Contenido (CDN) con Terraform y AWS CloudFrontintermediate25 min
- Gestionando Bases de Datos Relacionales con Terraform y AWS RDS: Un Enfoque Declarativointermediate18 min
- Gestionando Contenedores con Terraform y Amazon ECS: Despliegue y Orquestación Escalableintermediate25 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!