Los que trabajamos con AWS hemos observado que no existe ninguna manera de hacer una copia de seguridad de las entradas dns de un dominio en route53.
Con lo que he hecho un pequeño script que importa en un fichero json las entradas dns y a la vez crea una plantilla en terraform para poder crearlas en caso de perder alguna.
Solo hay que configurar las variables de la zona hosteada, el dominio, la región de aws y la cuenta y asegurarse de tener instaladas las librerias de awscli y jq.
El script es el siguiente:
#!/bin/bash
# Define el ID de la zona alojada
HOSTED_ZONE_ID="<hosted_zone_id>"
ZONE_NAME="example.com"
AWS_REGION="<aws_region>"
AWS_ACCOUNT_ID="aws_account_id>"
# Archivo de salida
OUTPUT_FILE="route53.tf"
JSON_OUTPUT_FILE="route53.json"
# Crear o limpiar el archivo de salida JSON
echo "# Exportando registros DNS de Route53 a JSON" > $JSON_OUTPUT_FILE
# Listar todos los registros DNS en la zona y guardar en JSON
aws route53 list-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --output json > $JSON_OUTPUT_FILE
# Crear o limpiar el archivo de salida de Terraform
echo "# Route53 DNS records" > $OUTPUT_FILE
# Añadir el provider de AWS al inicio del archivo Terraform
cat <<EOL >> $OUTPUT_FILE
provider "aws" {
region = $AWS_REGION
allowed_account_ids = [$AWS_ACCOUNT_ID]
}
EOL
# Procesar el archivo JSON para generar el código Terraform
jq -c '.ResourceRecordSets[]' $JSON_OUTPUT_FILE | while read record; do
# Verificar si el registro tiene comillas dobles y crear una variable de control "quotes"
if [[ "$record" == *"\"\""* ]]; then
quotes="true"
# Quitar comillas dobles escapadas para el procesamiento
record=$(echo $record | sed 's/""/"/g')
else
quotes="false"
fi
# Procesar el registro con jq
NAME=$(echo $record | jq -r '.Name')
TYPE=$(echo $record | jq -r '.Type')
TTL=$(echo $record | jq -r '.TTL')
# Limpiar el nombre del recurso para que sea un nombre válido en Terraform
RESOURCE_NAME=$(echo "$NAME" | tr -cd '[:alnum:]_-')_${TYPE}
# Verificar si es un alias o un registro con ResourceRecords
IS_ALIAS=$(echo $record | jq -r 'has("AliasTarget")')
if [[ "$IS_ALIAS" == "true" ]]; then
# Es un registro alias
ALIAS_DNS=$(echo $record | jq -r '.AliasTarget.DNSName')
ALIAS_ZONE_ID=$(echo $record | jq -r '.AliasTarget.HostedZoneId')
EVALUATE_HEALTH=$(echo $record | jq -r '.AliasTarget.EvaluateTargetHealth')
# Añadir la plantilla de alias al archivo de salida
cat <<EOL >> $OUTPUT_FILE
resource "aws_route53_record" "${RESOURCE_NAME}" {
zone_id = "$HOSTED_ZONE_ID"
name = "$NAME"
type = "$TYPE"
alias {
name = "$ALIAS_DNS"
zone_id = "$ALIAS_ZONE_ID"
evaluate_target_health = $EVALUATE_HEALTH
}
}
EOL
else
# Procesar los registros no alias
VALUES=$(echo $record | jq -r '.ResourceRecords[].Value')
# Si es un registro de tipo A o CNAME (IP o dominio), rodearlo con comillas dobles
if [[ "$TYPE" == "A" || "$TYPE" == "CNAME" || "$TYPE" == "NS" || "$TYPE" == "SOA" ]]; then
VALUES=$(echo $VALUES | sed 's/[^"]\+/"&"/g')
fi
# Si tenía comillas dobles originalmente, volver a agregarlas
if [[ "$quotes" == "true" ]]; then
VALUES="\"\\\"$VALUES\\\"\""
fi
# Añadir la plantilla de registro normal al archivo de salida
cat <<EOL >> $OUTPUT_FILE
resource "aws_route53_record" "${RESOURCE_NAME}" {
zone_id = "$HOSTED_ZONE_ID"
name = "$NAME"
type = "$TYPE"
ttl = $TTL
records = [$VALUES]
}
EOL
fi
echo "Registro DNS añadido a route53.tf: $NAME ($TYPE)"
done