captainarkdotnet/content/post/2018-04-14-dns-zone-versioning.md

4.5 KiB

title date draft share
DNS zone versioning 2018-04-14T00:00:00+01:00 false false

I've been using PowerDNS with a SQL backend as a hidden master DNS server for a few years now.

I've been wanting to write a quick shell script to version my DNS zones for a while, and since I've finally taken the time to do so today, I figured I'd share it here.

The script uses PowerDNS API to list the configured zones. It then exports them to a file in an AXFR-like format, commits and finally pushes them on a git repository

Configuration

PowerDNS

For the script to work, we have to activate PowerDNS' API.

To do so, let's create a /etc/powerdns/pdns.d/api.conf file with the following content :

api=yes
api-key=mysupersecretapikey
webserver=yes
webserver-address=10.0.0.10
webserver-allow-from=10.0.0.0/8
webserver-port=8081

You should change mysupersecretapikey to an actual secret.

You should also adapt the webserver-address and webserver-allow-from to reflect your network configuration.

Once the file is created, we have to restart pdnsd :

systemctl restart pdns.service

N.B. : As with all my other articles, I'm assuming here you're running Debian. The path of the configuration file you have to create or edit might not be the same if you're running another distribution or if you've installed PowerDNS from source.

jq

jq is required for the script to work, so let's install it !

apt install jq

Git

We now have to create a git repository to host our zone files.

To do so, you can follow my previous tutorial on the subject if you want.

I've personnaly migrated my git repos to a self-hosted Gogs installation a while back.

If you don't care about your zones content being public (it already is, technically), you could create a GitHub repo for that use (or on any other available git hosting).

Once you've created your repo, you should clone it on the machine that will run the script. For me, the path to the repo will be /home/captainark/backup/dnsexport.

apt install git
mkdir ~/backup && cd ~/backup
git clone ssh://git@git.captainark.net/captainark/dnsexport.git

You should also create a ~/.gitconfig for the user that will run the script with the following parameters configured :

[user]
        email = captainark@captainark.net
        name = CaptainArk
[push]
        default = simple

Also, make sure your user can push to the remote server before running the script. The following should work :

cd ~/backup/dnsexport
echo '# DNSEXPORT' > README.md
git add README.md
git commit README.md -m 'adding README'
git push

Script

Once we've finished configuring PowerDNS and Git, we can run the script.

You can copy the following to ~/bin/dnsexport :

#!/bin/bash

ApiKey="mysupersecretapikey"
PdnsUrl="10.0.0.10:8081"
PdnsServerName="localhost"
PdnsZoneUrl="http://${PdnsUrl}/api/v1/servers/${PdnsServerName}/zones"
ZoneList=$(/usr/bin/curl -sH "X-API-Key: ${ApiKey}" ${PdnsZoneUrl} | jq -r '.[].id')
ExportFolder="/home/captainark/backup/dnsexport"

updateremote() {
  cd $ExportFolder
  git add db.${Zone%.}
  git commit -m "Automated commit due to modification on ${Zone%.} at $(date -Iseconds)"
  git push
  cd -
}

for Zone in ${ZoneList}; do
  ZoneFile="${ExportFolder}/db.${Zone%.}"
  CurrentShaSum=$(/usr/bin/sha256sum ${ZoneFile})
  /usr/bin/curl -o ${ZoneFile} -sH "X-API-Key: ${ApiKey}" ${PdnsZoneUrl}/${Zone}/export
  NewShaSum=$(/usr/bin/sha256sum ${ZoneFile})
  [[ ${NewShaSum%  *} != ${CurrentShaSum%  *} ]] && updateremote
done

It's nothing fancy, but it does the job.

You'll have to adapt the ApiKey, PdnsUrl and ExportFolder variables to your configuration.

Once that's done, let's fix the permissions on the script :

chmod 700 ~/bin/dnsexport

You should run the script manually once to make sure everything is working OK. If it is, you should see a new commit on the repo for each zone you have configured in PowerDNS.

Once the script has executed once without issue, you can schedule it regularly. I have it running every 10 minutes in my user's crontab :

crontab -e
# DNSEXPORT
*/10 * * * * /home/captainark/bin/dnsexport

Conclusion

That's all !

As always, if you've found this article useful, please feel free to make use of the comments section below !

Hopefully it won't take as long before I write another article here next time !