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

No hay comentarios

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!

 

Sobre el autor

Daniel López Azaña
Arquitecto de soluciones Cloud AWS & Linux Sysadmin Freelance

Emprendedor, generador de ideas y mente inquieta. Apasionado de las nuevas tecnologías, especialmente de los sistemas Linux y del software libre. Me gusta escribir además sobre actualidad tecnológica, Cloud Computing, AWSi, DevOps, DevSecOps, seguridad, desarrollo web y programación, SEO, ciencia, innovación, emprendimiento, etc.

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

Artículos relacionados

Deja una respuesta

Tu dirección de correo electrónico no será publicada.