
Cloudflare is a popular service for managing DNS records, providing security features, and optimizing website performance. Automating DNS management tasks can save time and reduce the risk of human error. In this article, I will explore how to use PowerShell to automate Cloudflare DNS management tasks.
Cloudflare API
To interact with Cloudflare’s DNS management features, we will use the Cloudflare API. The API allows you to programmatically manage DNS records, zones, and other settings.
To get started, you need to create an API token in your Cloudflare account. Follow these steps: Create API token
Cloudflare ZoneId
To manage DNS records, you need to know the Zone ID of your domain. The Zone ID is not the name of your domain, but a unique identifier assigned by Cloudflare. You can find the Zone ID in the Cloudflare dashboard under the “Overview” tab - but we want to automate this via PowerShell.
1# Author: Benjamin Abt (https://benjamin-abt.com)
2# Script: cf-get-domain-zoneid.ps1
3# Purpose: Retrieves the Zone ID for a specified domain from Cloudflare using their API
4# Usage:
5# $zoneInfo = .\cf-get-domain-zoneid.ps1 -ApiToken "your-cloudflare-api-token" -DomainName "example.com" | ConvertFrom-Json
6# Write-Host "Domain: $($zoneInfo.Domain)"
7# Write-Host "Zone ID: $($zoneInfo.ZoneId)"
8
9param(
10 [Parameter(Mandatory = $true)]
11 [string]$ApiToken,
12
13 [Parameter(Mandatory = $true)]
14 [string]$DomainName
15)
16
17# Setup headers for Cloudflare API authentication
18$headers = @{
19 "Authorization" = "Bearer $ApiToken"
20 "Content-Type" = "application/json"
21}
22
23# Construct the API URL to query zones filtered by domain name
24$url = "https://api.cloudflare.com/client/v4/zones?name=$DomainName"
25
26# Send GET request to Cloudflare API
27$response = Invoke-RestMethod -Method Get -Uri $url -Headers $headers
28
29# Check if the request was successful and results were returned
30if ($response.success -and $response.result.Count -gt 0) {
31 # Create a custom object with domain and zone ID information
32 $data = [PSCustomObject]@{
33 Domain = $DomainName # Store the domain name
34 ZoneId = $response.result[0].id # Extract the zone ID from the response
35 }
36
37 # Return the data as a JSON object
38 return $data | ConvertTo-Json -Depth 2
39
40} else {
41 # Throw an error if the domain was not found
42 throw "Failed to retrieve Zone ID for domain '$DomainName'. Check if the domain exists in your Cloudflare account."
43}
To use the script, save it as cf-get-domain-zoneid.ps1 and run it with the following command:
1$zoneInfo = .\cf-get-domain-zoneid.ps1 -ApiToken "your-cloudflare-api-token" -DomainName "example.com" | ConvertFrom-Json
2Write-Host "Domain: $($zoneInfo.Domain)"
3Write-Host "Zone ID: $($zoneInfo.ZoneId)"
This will output the domain name and its corresponding Zone ID.
Cloudflare DNS Records
Once you have the Zone ID, you can manage DNS records for that domain. Below is a PowerShell script that demonstrates how to add and update using the Cloudflare API.
1# ---------------------------------------------------------------------------
2# Author: Benjamin Abt (https://benjamin-abt.com)
3# Script: cf-set-dns-entry.ps1
4# Description: Creates or updates DNS records in Cloudflare via the API.
5# This script can set CNAME or TXT records with specified TTL and proxy settings.
6# Usage:
7# .\cf-set-dns-entry.ps1 `
8# -ApiToken "CloudflareAPIToken123" `
9# -ZoneId "abc123def456" `
10# -Domain "example.com" `
11# -Subdomain "www" `
12# -RecordType "CNAME" `
13# -RecordContent "origin.myproxy.com" `
14# -Ttl "3600" `
15# -Proxied "true"
16# ---------------------------------------------------------------------------
17
18param(
19 [Parameter(Mandatory = $true)]
20 [string]$ApiToken, # Cloudflare API token with DNS edit permissions
21
22 [Parameter(Mandatory = $true)]
23 [string]$ZoneId, # Cloudflare Zone ID for the domain
24
25 [Parameter(Mandatory = $true)]
26 [string]$Domain, # Base domain name, e.g. "example.com"
27
28 [Parameter(Mandatory = $true)]
29 [string]$Subdomain, # Subdomain label, e.g. "_acme-challenge" or "www" (use empty string for apex domain)
30
31 [Parameter(Mandatory = $true)]
32 [ValidateSet("CNAME", "TXT")]
33 [string]$RecordType, # Type of DNS record to create/update
34
35 [Parameter(Mandatory = $true)]
36 [string]$RecordContent, # Value for the DNS record
37
38 [Parameter()]
39 [ValidatePattern("^\d+$|^(?i:auto)$")]
40 [string]$Ttl = "3600", # Time-to-live in seconds, or "auto" for Cloudflare default
41
42 [Parameter()]
43 [ValidateSet("true", "false")]
44 [string]$Proxied = "false" # Whether the record should be proxied through Cloudflare
45)
46
47# Construct the full record name based on subdomain and domain
48$RecordName = if ([string]::IsNullOrEmpty($Subdomain)) { $Domain } else { "$Subdomain.$Domain" }
49
50# Set up API request headers
51$headers = @{
52 "Authorization" = "Bearer $ApiToken"
53 "Content-Type" = "application/json"
54}
55
56# Convert TTL to proper format (1 is Cloudflare's "auto" TTL)
57$ttlValue = if ($Ttl.ToLower() -eq "auto") { 1 } else { [int]$Ttl }
58# Convert string "true"/"false" to boolean for JSON
59$proxiedValue = $Proxied.ToLower() -eq "true"
60
61# Build URL to check for existing records
62$recordListUrl = "https://api.cloudflare.com/client/v4/zones/$ZoneId/dns_records?type=$RecordType&name=$RecordName"
63
64# Query Cloudflare API to check if record already exists
65$response = Invoke-RestMethod -Method Get -Uri $recordListUrl -Headers $headers
66
67# Check if the API call was successful
68if (-not $response.success) {
69 throw "Error retrieving DNS records: $($response.errors[0].message)"
70}
71
72# Find an existing record that matches the name
73$existingRecord = $response.result | Where-Object { $_.name -eq $RecordName }
74
75# Prepare the request body for creating/updating the record
76$body = @{
77 type = $RecordType
78 name = $RecordName
79 content = $RecordContent
80 ttl = $ttlValue
81 proxied = $proxiedValue
82} | ConvertTo-Json -Depth 3
83
84# If the record exists, update it; otherwise, create a new record
85if ($existingRecord) {
86 Write-Host "Record exists. Updating..."
87 $updateUrl = "https://api.cloudflare.com/client/v4/zones/$ZoneId/dns_records/$($existingRecord.id)"
88 $updateResponse = Invoke-RestMethod -Method Put -Uri $updateUrl -Headers $headers -Body $body
89} else {
90 Write-Host "Record does not exist. Creating..."
91 $createUrl = "https://api.cloudflare.com/client/v4/zones/$ZoneId/dns_records"
92 $updateResponse = Invoke-RestMethod -Method Post -Uri $createUrl -Headers $headers -Body $body
93}
94
95# Check if the create/update operation was successful
96if ($updateResponse.success) {
97 Write-Host "$RecordType record successfully processed: $RecordName => $RecordContent"
98} else {
99 throw "Error updating/creating DNS record: $($updateResponse.errors[0].message)"
100}
To use the script, save it as cf-set-dns-entry.ps1 and run it with the following command:
1.\cf-set-dns-entry.ps1 `
2 -ApiToken "CloudflareAPIToken123" `
3 -ZoneId "abc123def456" `
4 -Domain "example.com" `
5 -Subdomain "www" `
6 -RecordType "CNAME" `
7 -RecordContent "origin.myproxy.com" `
8 -Ttl "3600" `
9 -Proxied "true"
This will create or update a CNAME record for the specified subdomain.
DevOps
In a DevOps context, automating DNS management with PowerShell can be integrated into CI/CD pipelines. For example, you can use the above scripts to automatically update DNS records when deploying new versions of your application or when changing infrastructure.
In my case, I can now use this script to update my DNS records for the SchwabenCode website. I can integrate it into my CI/CD pipeline to ensure that the DNS records are always up to date when I make changes to my infrastructure. This is especially necessary with the Azure Frontdoor, as it does not offer automatic certificate renewal for APEX domains, but only does this manually in combination with a re-validation of the domain (via TXT entries) - every 150 days.
Conclusion
Automating DNS management with PowerShell and the Cloudflare API is a powerful way to save time and reduce human error. With the scripts provided, you can easily create, update and manage DNS records. This automation can be integrated into DevOps pipelines to ensure your DNS records are always up to date.

Comments