Managing DNS records in Cloudflare can be a tedious task, especially if you have multiple domains with several records. In this post, we will demonstrate how to leverage Cloudflare’s API to update multiple DNS records across different zones using cURL and a simple JSON configuration file.
Prepare Your Configuration File
The first step is to create a configuration file (for instance, config.json) that outlines the DNS zones and records you want to update. The structure of this JSON file is as follows:
{
"interface": "eth0",
"api_tok": "Your Cloudflare API Token",
"global_key": "Your Cloudflare Global API Key",
"auth_email": "Your Cloudflare Account Email",
"zones": [
{
"zone": "example.com",
"records": [
{ "record": "@", "type": "A" },
{ "record": "subdomain", "type": "A" }
]
}
]
}
In this configuration:
interfaceis the network interface used for internet access.api_tok,global_key, andauth_emailare your Cloudflare API credentials.zonesis an array of zones (domains), each with an array of DNS records that you want to update.
Using cURL to Call the Cloudflare API
With your configuration file prepared, you can now use cURL to call the Cloudflare API and update the DNS records.
Here’s a general example of how to use cURL with the Cloudflare API:
curl -X PUT "https://api.cloudflare.com/client/v4/zones/Zone_ID/dns_records/Record_ID" \
-H "Authorization: Bearer API_Token" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"Record_Name","content":"New_IP_Address","ttl":1,"proxied":false}'
To update multiple DNS records, you will have to loop through each zone and record defined in your JSON file, replacing Zone_ID, Record_ID, API_Token, Record_Name, and New_IP_Address with the appropriate values.
Keep in mind:
- To get your Zone ID and Record ID, you will need to use the List Zones and List DNS Records API methods, respectively.
- Make sure to replace
New_IP_Addresswith the actual new IP address you want to assign to the DNS record.
Using Python
The following script reads from a JSON configuration file and uses the Cloudflare API to update the DNS records.
import json
import requests
# Load the configuration file
with open('config.json', 'r') as file:
config = json.load(file)
headers = {
"Authorization": f'Bearer {config["api_tok"]}',
"Content-Type": "application/json"
}
# For each zone in the configuration file
for zone in config['zones']:
# Get the Zone ID
zone_id_resp = requests.get(f'https://api.cloudflare.com/client/v4/zones?name={zone["zone"]}', headers=headers)
zone_id = zone_id_resp.json()['result'][0]['id']
# For each record in the zone
for record in zone['records']:
# Get the Record ID
record_id_resp = requests.get(f'https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records?type={record["type"]}&name={record["record"]}', headers=headers)
record_id = record_id_resp.json()['result'][0]['id']
# Update the record
record_update_resp = requests.put(
f'https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}',
headers=headers,
json={
"type": record['type'],
"name": record['record'],
"content": "<New_IP_Address>",
"ttl": 1,
"proxied": False
}
)
print(f'Updated {record["record"]}.{zone["zone"]} with status {record_update_resp.status_code}')
Using bash
Creating a similar script in Bash that also leverages the jq command-line JSON processor will involve more manual parsing. Below is a rough script that demonstrates how to achieve the same functionality:
#!/bin/bash
config='config.json'
api_token=$(jq -r '.api_tok' "$config")
# Iterate over each zone
for zone in $(jq -c '.zones[]' "$config"); do
zone_name=$(echo "$zone" | jq -r '.zone')
# Get Zone ID
zone_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json" | jq -r '.result[0].id')
# Iterate over each record in the zone
for record in $(echo "$zone" | jq -c '.records[]'); do
record_type=$(echo "$record" | jq -r '.type')
record_name=$(echo "$record" | jq -r '.record')
# Get Record ID
record_id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?type=$record_type&name=$record_name" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json" | jq -r '.result[0].id')
# Update the record
update_status=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id" \
-H "Authorization: Bearer $api_token" \
-H "Content-Type: application/json" \
--data '{"type":"'$record_type'","name":"'$record_name'","content":"<New_IP_Address>","ttl":1,"proxied":false}' | jq -r '.success')
echo "Updated $record_name.$zone_name with status $update_status"
done
done
This Bash script follows similar steps to the Python script but uses curl to make the HTTP requests and jq to parse and manipulate the JSON data. It loads the configuration from config.json, then iterates over each zone and record, making API requests to get the necessary IDs and update each record. The new IP address is hard-coded as <New_IP_Address> and should be replaced with the actual IP address.
Note that the jq tool is incredibly powerful for working with JSON data in shell scripts, but its syntax can be a bit tricky if you’re not used to it. Also, error handling in Bash is more manual and can be a bit more complex compared to Python, so you might want to add more checks and error handling depending on your needs.
Buy Me a Coffee