146 lines
4.5 KiB
Markdown
146 lines
4.5 KiB
Markdown
---
|
|
title: "DNS zone versioning"
|
|
date: 2018-04-14T00:00:00+01:00
|
|
draft: false
|
|
share: false
|
|
---
|
|
|
|
I've been using [PowerDNS](https://doc.powerdns.com/md/) 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](https://stedolan.github.io/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](https://www.captainark.net/2016/01/31/private-git-repo/) on the subject if you want.
|
|
|
|
I've personnaly migrated my git repos to a self-hosted [Gogs](https://gogs.io/) 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` :
|
|
|
|
```bash
|
|
#!/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 !
|