The other day I spun up a free-tier e2-micro instance in GCP to play around with something and wanted the ability to access it by a common domain name internally and externally: gcloud.cthudson.com
. To address the external access, I created a script on the instance itself to hit the Cloudflare API and keep the dynamic IP up to date against the A record. Internally, I had to find a solution to keep my FreeIPA instance corresponding A record updated as well given it owns the cthudson.com
zone internally. So off I went to find a solution. I figured I’d post it here for in the event it is - or pieces of it are - helpful to someone else.
FreeIPA Automated Access Approach
In order to accomplish automatic updating of a FreeIPA DNS record, you will need to have proper access and privileges to do so. There are quite a few ways you could do this, but the one that seemed like the best fit to me was to create a service principal. That way, a script could use the associated Kerberos keytab for needed access.
Creating Service Principal
- From an FreeIPA client, grab a privileged kerberos ticket
# kinit admin
- Add a service prinicpal for DNS (I will use a ipa-joined host
itx1.cthudson.com
in this example)# ipa service-add dns/itx1.cthudson.com ------------------------------------------------------ Added service "dns/itx1.cthudson.com@CTHUDSON.COM" ------------------------------------------------------ Principal name: dns/itx1.cthudson.com@CTHUDSON.COM Principal alias: dns/itx1.cthudson.com@CTHUDSON.COM Managed by: itx1.cthudson.com
Privileges
In order for our keytab to have the correct permissions to update dns records, we need to create a role and associate it with the service principal.
Create a role for DNS Administration
# ipa role-add --desc="DNS Administration" "DNS Admin"
----------------------
Added role "DNS Admin"
----------------------
Role name: DNS Admin
Description: DNS Administration
Add the DNS Administrators privilege to our newly created role
# ipa role-add-privilege "DNS Admin" --privileges="DNS Administrators"
Role name: DNS Admin
Description: DNS Administration
Privileges: DNS Administrators
----------------------------
Number of privileges added 1
----------------------------
Associate DNS Admin role with our service principal
For some reason, I could not get this to work via ipa role-add-member "DNS Admin" --services dns/itx1.cthudson.com@CTHUDSON.COM
and added it via the FreeIPA webui instead, which did the trick. Just head over to the webui -> IPA Server tab -> Role-Based Access Control sub-tab -> Services sub-tab -> Add -> Select proper service principal from there. I will have to re-investigate this and update if I figure out what’s going on. It’s a weird one but in the end you should see something like:
# ipa role-show "DNS Admin"
Role name: DNS Admin
Description: DNS Administration
Privileges: DNS Administrators
Member services: dns/itx1.cthudson.com@CTHUDSON.COM
Pull the keytab
Next, we need to get the keytab and store it somewhere secure on the host that will be running our update script.
$ ipa-getkeytab -s idm1.cthudson.com -p dns/itx1.cthudson.com -k dnsadmin.keytab
Keytab successfully retrieved and stored in: dnsadmin.keytab
That’s all there is to getting the keytab. Make sure the permissions are 0600
for the user executing the update. ie:
-rw-------. 1 chris chris 180 Dec 16 12:13 dnsadmin.keytab
The Script
To wrap this post up, here is the ultimate script along with an explanation of what’s going on:
#!/bin/bash
/usr/bin/kinit -kt /home/chris/dns_scripts/dnsadmin.keytab dns/itx1.cthudson.com
IPA_IP=`/usr/bin/ipa dnsrecord-show cthudson.com gcloud --raw | grep record | sed s/"arecord: "// | xargs`
CLOUDFLARE_IP=`/usr/bin/dig @1.1.1.1 gcloud.cthudson.com +short`
if [[ "$IPA_IP" == "$CLOUDFLARE_IP" ]]; then
/usr/bin/logger "Cloudflare gcloud.cthudson.com IP address matched IPA record. No update necessary."
exit
else
/usr/bin/ipa dnsrecord-mod cthudson.com gcloud --a-rec=$CLOUDFLARE_IP
/usr/bin/logger "Cloudflare gcloud.cthudson.com IP address does not match IPA record. Updated IPA A record."
fi
- First, we
kinit
against the keytab we created to gain the proper permissions when using theipa
tools moving forward - We grab the current
gcloud.cthudson.com
IP address in FreeIPA and save it into theIPA_IP
variable - We query Cloudflare’s dns to get the current
gcloud.cthudson.com
IP address and save it into aCLOUDFLARE_IP
variable - With the
if
statement, we are comparing the two addresses. If the addresses match, no udpates occur and we output that note to the system log. If the addresses do not match (ourelse
in this case), we update the FreeIPA record via adnsrecord-mod
command and also notate the change in the system log.
Slap this script in cron to run however often you would like and there you have it! I run this every 10 minutes via the following in /etc/cron.d/dns
:
*/10 * * * * chris /home/chris/dns_scripts/gcloud_update_idm_dns.sh
Cheers!