Using the cloudflare API
source link: https://willschenk.com/labnotes/2023/using_cloudflare_api/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
The goal here is to see how to add and update A
records on our
cloudflare managed domain using shell scripting. Eventually we'll
wire this, the hetzner command line client, and some mrsk inspired
scripts to get a machine up and running quickly.
First some basic unix tools to make it easier to manupulate json:
brew install jq jo
Get the Key
We'll need an API key, so lets go get that.
- Go to the api-tokens page in your profile.
Create a Token
- Select
Edit zone DNS
template - I'm limiting it to a specific zone.
- Copy and store the resulting token.
Test the token
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type:application/json" | jq
{
"result": {
"id": "726441c7a18f40e6ed5444a4635effd2",
"status": "active"
},
"success": true,
"errors": [],
"messages": [
{
"code": 10000,
"message": "This API Token is valid and active",
"type": null
}
]
}
Finding your zone identifier
I'm using willschenk.com
here but feel free to adjust.
export ZONE=willschenk.com
curl -X GET \
"https://api.cloudflare.com/client/v4/zones?name=${ZONE}&status=active" \
-H "Authorization: Bearer ${CF_TOKEN}" \
-H "Content-Type:application/json" | jq -r '{"result"}[] | .[0] | .id'
And in my case, we get:
7b3f2ff4b23ab88aa09326590263561b
Listing out your records
export ZONE_ID=7b3f2ff4b23ab88aa09326590263561b
curl -X GET \
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq -r '{"result"}[] | .[] | "| \(.id) | \(.type) | \(.name) | \(.content) |"'
Which yields something like:
7d2953… | CNAME | summarizer.willschenk.com | twilight-butterfly-9726.fly.dev |
e45be8… | CNAME | willschenk.com | wschenk.github.io |
31fb96… | CNAME | www.willschenk.com | wschenk.github.io |
f278db… | TXT | dev.willschenk.com | google-si… |
e35e0f… | TXT | willschenk.com | ALIAS for wschenk.github.io |
d93a74… | TXT | willschenk.com | google-si… |
Looking up a record
export ZONE_ID=7b3f2ff4b23ab88aa09326590263561b
export RECORD=apple.willschenk.com
curl -X GET \
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${RECORD} \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq -r '{"result"}[] | .[0] | .id'
And if you have a result, it will be something like:
425a21b7d74e958230f9f50d82adc836
Adding a record
export ZONE=willschenk.com
export ZONE_ID=7b3f2ff4b23ab88aa09326590263561b
export NAME=apple
export IP=65.108.63.49
jo type=A name=${NAME}.${ZONE} content=${IP} ttl=1 proxied=false | \
curl -X POST \
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records \
-d @- \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq
If the name is new, you'll see something like:
{
"result": {
"id": "3a7b82024e407dc58814b89fa5f45795",
"zone_id": "7b3f2ff4b23ab88aa09326590263561b",
"zone_name": "willschenk.com",
"name": "apple.willschenk.com",
"type": "A",
"content": "65.108.63.49",
"proxiable": true,
"proxied": false,
"ttl": 1,
"locked": false,
"meta": {
"auto_added": false,
"managed_by_apps": false,
"managed_by_argo_tunnel": false,
"source": "primary"
},
"comment": null,
"tags": [],
"created_on": "2023-06-20T17:20:39.753139Z",
"modified_on": "2023-06-20T17:20:39.753139Z"
},
"success": true,
"errors": [],
"messages": []
}
You'll get an error if something already exists, so lets wire it all together.
Updating or adding a record
export ZONE_ID=7b3f2ff4b23ab88aa09326590263561b
export RECORD=apple.willschenk.com
export IP=65.108.63.49
RECORD_ID=$(
curl -X GET \
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${RECORD} \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq -r '{"result"}[] | .[0] | .id')
if [[ $RECORD_ID == 'null' ]]; then
echo Creating ${RECORD}
jo type=A name=${RECORD} content=${IP} ttl=1 proxied=false | \
curl -X POST \
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records \
-d @- \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq
else
echo Updating $RECORD_ID
jo type=A name=${RECORD} content=${IP} ttl=1 proxied=false | \
curl -X PUT \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
-d @- \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${CF_TOKEN}" | \
jq
fi
This first checks to see if there's already an A
record, and if not it
created one. Otherwise, it updates it.
Either way it returns the latest info.
Creating apple.willschenk.com
{
"result": {
"id": "425a21b7d74e958230f9f50d82adc836",
"zone_id": "7b3f2ff4b23ab88aa09326590263561b",
"zone_name": "willschenk.com",
"name": "apple.willschenk.com",
"type": "A",
"content": "65.108.63.49",
"proxiable": true,
"proxied": false,
"ttl": 1,
"locked": false,
"meta": {
"auto_added": false,
"managed_by_apps": false,
"managed_by_argo_tunnel": false,
"source": "primary"
},
"comment": null,
"tags": [],
"created_on": "2023-06-20T17:30:53.819641Z",
"modified_on": "2023-06-20T17:30:53.819641Z"
},
"success": true,
"errors": [],
"messages": []
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK