User Tools

Site Tools


howtos:create_records_from_template_file

Restore or Create Records from File

I made this script to be able to quickly populate a zone with a default set of records. I then turned into a complete restore function based on the backup script also provided here.

The Script

Basically you run the script with a backup file as a parameter. The file can be the backup dumped from the backup script or it can be handcrafted to fit a specific purpose, like a template.

Input File

The input file is formed like a csv file. First is the record type, and then depending on the type, different fields.

A,example.com,10.10.10.10,1,false,
A,chaos.example.com,10.10.10.10,1,false,
A,kaos.example.com,10.10.10.10,1,false,
A,mc1.example.com,10.10.10.10,1,false,
A,mc2.example.com,10.10.10.10,1,false,
CNAME,*.example.com,example.com,1,false,
SRV,_minecraft,_tcp,chaos.example.com,0,5,25562,mc1.example.com,1,false,
SRV,_minecraft,_tcp,kaos.example.com,0,5,25562,mc1.example.com,1,false,
SRV,_minecraft,_tcp,mc1.example.com,0,5,25564,mc1.example.com,1,false,
SRV,_minecraft,_tcp,mc2.example.com,0,5,25563,mc1.example.com,1,false,
TXT,example.com,v=spf1 ip4:172.17.4.5/32 ~all,1,false,
TXT,_dmarc.example.com,v=DMARC1; p=reject; rua=mailto:dmarc@example.com,1,false,
CAA,example.com,0,issue,letsencrypt.org,1,false,

Restore Script

The restore script take two API tokens, one for creating the zone records, and one for turning on the Certificate Transparency Monitoring feature. The two functions requires different authorization in Cloudflare. If you don't care about CT you can just disabled the function by setting the variable “ENABLE_CT=0”.

#!/bin/bash

# Set your Cloudflare API key
API_KEY="xxx"
CT_AUTH_TOKEN="xxx"
IFS=","
TOGGLE="true"
ENABLE_CT=1
USE_COMMENTS=1
DEBUG=1

# Read the input file line by line
while read line; do
  # Skip any lines that start with a # or is blank
  [[ $line =~ ^([[:space:]]*#|$) ]] && continue
  
  # Split the line into an array using tabs as the delimiter
 read -ra RECORD <<< "$line"
  
  # Look up the zone ID for the domain using Cloudflare's API
  if [ "${RECORD[0]}" = "A" ] || [ "${RECORD[0]}" = "TXT" ] || [ "${RECORD[0]}" = "CAA" ] || [ "${RECORD[0]}" = "CNAME" ]; then
    # For A, TXT, and CAA records, use the domain name itself (without the subdomain) to look up the zone ID
    DOMAIN=$(echo "${RECORD[1]}" | awk -F'.' '{print $(NF-1)"."$NF}')
    [[ $DEBUG -eq 1 ]] && echo "Domain extracted: $DOMAIN -  ${RECORD[@]}"
  elif [ "${RECORD[0]}" = "SRV" ];then
    DOMAIN="${RECORD[3]}"
    [[ $DEBUG -eq 1 ]] && echo "Domain extracted: $DOMAIN -  ${RECORD[@]}"
  
  else
    # For all other records, use the full domain name to look up the zone ID
    DOMAIN="${RECORD[1]}"
    [[ $DEBUG -eq 1 ]] && echo "Domain from file: $DOMAIN"
  fi
#echo name=${DOMAIN};sleep 10
  ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN}" \
             -H "Authorization: Bearer ${API_KEY}" \
             -H "Content-Type: application/json" | jq -r '.result[0].id')
  [[ $DEBUG -eq 1 ]] && echo "Zone ID: $ZONE_ID"
  
  # If the zone ID is not found, print an error and skip the record
  if [[ "$ZONE_ID" = "null" ]]; then
    echo "Error: Could not find zone ID for domain ${RECORD[1]}"
    continue
  fi
  
  # Insert comments in DNS records
  if [[ $USE_COMMENTS -eq 1 ]]; then
    last_element=${RECORD[-1]}
    echo "last: $last_element"
    # Check if the last element starts with "comment:"
    if [[ "$last_element" == comment:* ]]; then
      echo "comment: $last_element"
      # Extract the comment text by removing the "comment: " prefix
      comment_text=${last_element#comment:}
    fi
  else
    comment_text=""
    echo "lastx: $last_element"
  fi

  # Create the JSON data for the DNS record
  if [ "${RECORD[0]}" = "MX" ]; then
    # Create JSON for MX records with priority value
    JSON="{\"type\":\"${RECORD[0]}\",\"name\":\"${RECORD[1]}\",\"content\":\"${RECORD[2]}\",\"priority\":${RECORD[3]},\"ttl\":${RECORD[4]},\"proxied\":${RECORD[5]}}"
  elif [ "${RECORD[0]}" = "A" ] || [ "${RECORD[0]}" = "TXT" ]; then
    # Create JSON for A and TXT records
    JSON="{\"type\":\"${RECORD[0]}\",\"name\":\"${RECORD[1]}\",\"content\":\"${RECORD[2]}\",\"ttl\":${RECORD[3]},\"proxied\":${RECORD[4]}}"
  elif [ "${RECORD[0]}" = "CAA" ]; then
    # Create JSON for CAA records
    JSON="{\"type\":\"${RECORD[0]}\",\"name\":\"${RECORD[1]}\",\"data\":{\"flags\":${RECORD[2]},\"tag\":\"${RECORD[3]}\",\"value\":\"${RECORD[4]}\"},\"ttl\":${RECORD[5]},\"proxied\":${RECORD[6]}}"
  elif [ "${RECORD[0]}" = "SRV" ]; then
    # Create JSON for SRV records
    JSON="{\"type\":\"${RECORD[0]}\",\"comment\":\"$comment_text\",\"data\":{\"service\":\"${RECORD[1]}\",\"proto\":\"${RECORD[2]}\",\"name\":\"${RECORD[3]}\",\"priority\":${RECORD[4]},\"weight\":${RECORD[5]},\"port\":${RECORD[6]},\"target\":\"${RECORD[7]}\"}}"
  else
    # Create JSON for all other record types
    JSON="{\"type\":\"${RECORD[0]}\",\"name\":\"${RECORD[1]}\",\"content\":\"${RECORD[2]}\",\"ttl\":${RECORD[3]},\"proxied\":${RECORD[4]}}"
  fi
  [[ $DEBUG -eq 1 ]] && echo "JSON: $JSON"  

  # Make the API call using curl
  RESULT=$(curl -s -X POST -H "Authorization: Bearer ${API_KEY}" \
         -H "Content-Type: application/json" \
         -d "$JSON" \
         "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records")
  
  # Check if the API call was successful and print the result
  if echo "$RESULT" | jq -r '.success' | grep -q "true"; then
    echo "Record ${RECORD[1]} (${RECORD[0]}) successfully updated"
    [[ $DEBUG -eq 1 ]] && echo "Good result:" && echo "$RESULT"|jq
  else
    echo "Error updating record ${RECORD[1]} (${RECORD[0]}):"
    echo "$RESULT" | jq -r '.errors[0].message'
    [[ $DEBUG -eq 1 ]] && echo "Bad result:" && echo "$RESULT" | jq
  fi

  if [[ $ENABLE_CT -eq 1 ]]; then  
    # Enable Certificate Transparency Monitoring for the zone
    RESULT=$(curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/ct/alerting" \
         -H "Authorization: Bearer ${CT_AUTH_TOKEN}" \
         -H "Content-Type: application/json" \
         --data '{"enabled":'$TOGGLE'}')
  
    # Check if the API call was successful and print the result
    if echo "$RESULT" | jq -r '.success' | grep -q "true"; then
      echo "Certificate Transparency Monitoring successfully enabled for zone ${DOMAIN}"
      [[ $DEBUG -eq 1 ]] && echo "Good result:" && echo "$RESULT" | jq
    else
      echo "Error enabling Certificate Transparency Monitoring for zone ${DOMAIN}:"
      echo "$RESULT" | jq -r '.errors[0].message'
      [[ $DEBUG -eq 1 ]] && echo "Bad result:" && echo "$RESULT" | jq
    fi
  fi
  
done < "$1"
howtos/create_records_from_template_file.txt · Last modified: 08/04/2023 21:06 by domingo