Daniel López Azaña

Tema

Social Media

Blog

GNU/Linux, Open Source, Cloud Computing, DevOps y más...

Cómo importar rápidamente todos los registros de una zona DNS de Route53 en Terraform

terraform-and-route53-logos

El comando terraform import nos permite importar en HashiCorp Terraform recursos que ya existían previamente en el proveedor con el que estemos trabajando, es este caso AWS. Sin embargo, sólo permite importar dichos registros uno por uno , con una ejecución de terraform import cada vez. Esto, aparte de ser tremendamente tedioso, en algunas situaciones se vuelve directamente impracticable. Este es el caso de los registros de una zona DNS de Route53. La tarea puede resultar inabarcable si tenemos varias zonas DNS, y cada una tiene decenas o cientos de registros. En este artículo te ofrezco un script en bash que te permitirá importar en Terraform todos los registros de una zona DNS de Route53 en cuestión de segundos o de pocos minutos.

Requisitos previos

Para poder llevar a cabo el procedimiento descrito en este artículo necesitarás tener instalada y configurada la herramienta aws cli de Amazon y la herramienta jq disponible en la mayoría de distribuciones de Linux.

Procedimiento

Puedes llevar a cabo la importación siguiendo estos sencillos pasos. Puedes saltarte los pasos 1 y 2 e ir directamente al 3 si ya tienes tu proyecto de Terraform correctamente configurado:

1.- Crea una nueva carpeta de proyecto de Terraform y configura el proveedor a través del siguiente fichero main.tf:

provider "aws" {
    region = "eu-west-1"
    access_key = "XXXXXXXXXXXXXXXXXXXX"
    secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

2.- Inicia el nuevo proyecto de Terraform:

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.74.1...
- Installed hashicorp/aws v3.74.1 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

3.- Ejecuta el siguiente script:

Recuerda asignar previamente el valor adecuado para las variables zone_name , zone_id , y también la aws_profile si utilizas distintos perfiles en la herramienta aws cli para manejar distintas cuentas de AWS.

#! /bin/bash

# This script retrieves all DNS records from AWS Route53 DNS zone and imports all of them to Terraform

zone_name='example.com'
zone_id='XXXXXXXXXXXXXXXXXXXXX'
aws_profile='example_com'

# Get zone slug from zone name
zone_slug=$(echo ${zone_name} | tr '.' '-')

# Get DNS zone current data from AWS
zone="$(aws --profile=${aws_profile} route53 list-hosted-zones | jq '.HostedZones[] | select (.Id | contains("'${zone_id}'"))')"
# Another method to get DNS zone data searching by zone name instead of zone ID
#zone="$(aws --profile=${aws_profile} route53 list-hosted-zones | jq '.HostedZones[] | select (.Name=="'${zone_name}'.")')"
zone_comment="$(echo ${zone} | jq '.Comment')"
if [ "${zone_comment}" == 'null' ];then
    zone_comment="${zone_name} zone"
fi

# Write aws_route53_zone resource to terraform file
cat << EOF > dns-zone-${zone_name}.tf
resource "aws_route53_zone" "${zone_slug}" {
    name         = "${zone_name}"
    comment      = "${zone_comment}"
}
EOF

# Import DNS zone and records from file to terraform
terraform import "aws_route53_zone.${zone_slug}" "${zone_id}"

# Retrieve all regular records (not alias) from DNS zone and write them down to terraform file
IFS=$'\n'
for dns_record in $(aws --profile="${aws_profile}" route53 list-resource-record-sets --hosted-zone-id "${zone_id}" | jq -c '.ResourceRecordSets[] | select(has("AliasTarget") | not)');do
    name="$(echo ${dns_record} | jq -r '.Name')"
    type="$(echo ${dns_record} | jq -r '.Type')"
    name_slug="$(echo ${type}-${name} | sed -E 's/[\._\ ]+/-/g' | sed -E 's/(^-|-$)//g')"
    ttl="$(echo ${dns_record} | jq -r '.TTL')"
    records="$(echo ${dns_record} | jq -cr '.ResourceRecords' | jq '.[].Value' | sed 's/$/,/')"
    records="$(echo ${records} | sed 's/,$//')"

    cat << EOF >> dns-zone-${zone_name}.tf

resource "aws_route53_record" "${name_slug}" {
    zone_id = aws_route53_zone.${zone_slug}.zone_id
    name    = "${name}"
    type    = "${type}"
    ttl     = "${ttl}"
    records = [${records}]
}
EOF

    # Import DNS record to Terraform
    terraform import "aws_route53_record.${name_slug}" "${zone_id}_${name}_${type}"
done

# Retrieve all alias records from DNS zone and write them down to terraform file
IFS=$'\n'
for dns_record in $(aws --profile="${aws_profile}" route53 list-resource-record-sets --hosted-zone-id "${zone_id}" | jq -c '.ResourceRecordSets[] | select(has("AliasTarget"))');do
    name="$(echo ${dns_record} | jq -r '.Name')"
    type="$(echo ${dns_record} | jq -r '.Type')"
    name_slug="$(echo ${type}-${name} | sed -E 's/[\._\ ]+/-/g' | sed -E 's/(^-|-$)//g')"
    alias_name="$(echo ${dns_record} | jq -cr '.AliasTarget' | jq -r '.DNSName')"

    cat << EOF >> dns-zone-${zone_name}.tf

resource "aws_route53_record" "${name_slug}" {
    zone_id = aws_route53_zone.${zone_slug}.zone_id
    name    = "${name}"
    type    = "${type}"

    alias {
        name                   = "${alias_name}" 
        zone_id                = "${zone_id}"
        evaluate_target_health = true
    }
}
EOF

    # Import DNS record to Terraform
    terraform import "aws_route53_record.${name_slug}" "${zone_id}_${name}_${type}"
done

El script va generando en el directorio desde el que se ejecuta un fichero .tf con todos los registros DNS existentes en Route53, y al mismo tiempo los va importando en Terraform para a partir de que finalice poder empezar a gestionar estos recursos con Terraform. La ejecución del script tardará varios minutos dependiendo del número de registros que tenga la zona a importar, pero es un procesos totalmente desatendido que no requerirá ningún esfuerzo por tu parte. ¡Espero que te sea útil!

Daniel López Azaña

Sobre el autor

Daniel López Azaña

20+ Años de ExperienciaCertificado AWS & GCPEspecialista IA/LLM

Emprendedor tecnológico y arquitecto cloud con más de 20 años de experiencia transformando infraestructuras y automatizando procesos. Especialista en integración de IA/LLM, desarrollo con Rust y Python, y arquitectura AWS & GCP. Mente inquieta, generador de ideas y apasionado por la innovación tecnológica y la IA.

Artículos relacionados

Script para cambiar automáticamente todos los volúmenes gp2 a gp3 con aws-cli

Script para cambiar automáticamente todos los volúmenes gp2 a gp3 con aws-cli

El pasado diciembre Amazon anunció sus nuevos volúmenes EBS gp3, los cuales ofrecen mejores prestaciones y un ahorro en el coste del 20% respecto a los que se venían utilizando hasta ahora, los gp2. Pues bien, tras probar satisfactoriamente estos nuevos volúmenes en varios clientes, no puedo hacer otra cosa más que recomendar su utilización, pues son todo ventajas y en estos 2 meses y medio que han transcurrido desde el anuncio no he apreciado ningún problema ni efecto secundario.

16 de febrero de 2021
AWS security groups

Cómo actualizar automáticamente todos nuestros grupos de seguridad EC2 de AWS cuando nuestra IP dinámica cambia

Uno de los mayores fastidios cuando trabajamos con AWS y nuestra conexión a Internet tiene IP dinámica es que cuándo ésta cambia, automáticamente dejamos de tener acceso a todos los servidores y servicios que habíamos protegido mediante un grupo de seguridad EC2 cuyas reglas sólo permiten el tráfico a ciertas IP’s específicas en lugar de abrir las conexiones a todo el mundo (0.0.0.0/0).Ciertamente lo más sencillo es siempre indicar en el grupo de seguridad que permitimos el tráfico en un puerto a todo el mundo, de modo que aunque tengamos IP dinámica en nuestra conexión a Internet siempre podremos continuar accediendo aunque ésta cambie. Pero abrir el tráfico a un puerto a todo el mundo no es la forma correcta de proceder desde el punto de vista de la seguridad, pues entonces cualquier atacante podrá tener acceso a ese puerto sin restricciones, y eso no es lo que queremos.

12 de enero de 2021
Logo AWS EBS

Cómo ampliar el tamaño de un volumen EBS y de una partición ext4 en AWS

Cuando se nos llena completamente el sistema de ficheros de una partición ext4 alojada en un volumen EBS de Amazon Web Services y no podemos hacer nada por liberar espacio al no querer perder ninguno de los datos almacenados, el único remedio que nos queda es ampliar el volumen y hacer crecer la partición asociada hasta el 100% de su capacidad para disponer nuevamente de espacio libre de almacenamiento.Partimos en nuestro ejemplo de un volumen de 50 GB lleno al 100% que queremos ampliar a uno nuevo del doble de tamaño, 100 GB:

23 de mayo de 2017

Comentarios

Sé el primero en comentar

Enviar comentario