Mac OS X Server,  Mac Security

Programatically Manage DNS In macOS Server 5.2 On Sierra

DNS is DNS. And named is named. Except in OS X Server. Sometimes. The configuration files for the DNS services in macOS Server are stored in /Library/Server/named. This represents a faux root of named configuration data, similar to how that configuration data is stored in /var/named on most other platforms. Having the data in /Library/Server/ makes it more portable across systems. The current version of BIND is BIND 9.9.7-P3 (Extended Support Version).

Traditionally, you would edit this configuration data by simply editing the configuration files, and that’s absolutely still an option. In macOS Server 5.2 (for Sierra), a new command is available at /Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework called dnsconfig. The dnsconfig command appears simple at first. However, the options available are actually far more complicated than they initially appear. The verbs available include help (show help information), list (show the contents of configurations and zone files), add (create records and zones) and delete (remove records and zones).

To view data available in the service, use the list verb. Options available when using the list verb include –acl (show ACLs), –view (show BIND view data), –zone (show domains configured in the service), –rr (show resource records) and –rrtype (show types of resource records). For example, let’s say you have a domain called pretendco.lan and you would like to view information about that zone. You could use the dnsconfig command along with the list verb and then the –zone option and the domain name:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig list --zone=pretendco.lan

The output would show you information about the listed zone, usually including View data:

Views:
com.apple.ServerAdmin.DNS.public
Zones:
pretendco.lan
Options:
allow-transfer: none
allow-update: none 

To see a specific record, use the –rr option, followed by = and then the fqdn, so to see ecserver.pretendco.lan:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig list --rr=ecserver.pretendco.lan

By default views are enabled and a view called com.apple.ServerAdmin.DNS.public is created when the DNS server first starts up. You can create other views to control what different requests from different subnets see; however, even if you don’t create any views, you’ll need to add the –view option followed by the name of the view (–view=com.apple.ServerAdmin.DNS.public) to any records that you want to create. To create a record, use the add verb. You can add a view (–view), a zone (–zone) or a record (–rr). Let’s start by adding a record to the pretendco.lan from our previous example. In this case we’ll add an A record called www that points to the IP address of 192.168.210.201:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig add --view=com.apple.ServerAdmin.DNS.public --zone=pretendco.lan --rr=www A 192.168.210.201

You can add a zone, by providing the –view to add the zone to and not providing a –rr option. Let’s add krypted.lan:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig add --view=com.apple.ServerAdmin.DNS.public --zone=krypted.lan

Use the delete verb to remove the data just created:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig delete --view=com.apple.ServerAdmin.DNS.public --zone=krypted.lan

Or to delete that one www record earlier, just swap the add with a delete:

/Applications/Server.app/Contents/ServerRoot/System/Library/PrivateFrameworks/DNSManager.framework/dnsconfig delete --view=com.apple.ServerAdmin.DNS.public --zone=pretendco.lan --rr=www A 192.168.210.201

Exit codes would be “Zone krypted.lan removed.” and “Removed 1 resource record.” respectively for the two commands. You can also use the –option option when creating objects, along with the following options (each taken as a value followed by an =, with this information taken by the help page):

  • allow-transfer Takes one or more address match list entry. Address match list entries consist of any of these forms: IP addresses, Subnets or Keywords.
  • allow-recursion Takes one or more address match list entry.
  • allow-update Takes one or more address match list entry.
  • allow-query Takes one or more address match list entry.
  • allow-query-cache Takes one or more address match list entry.
  • forwarders Takes one or more IP addresses, e.g. 10.1.1.1
  • directory Takes a directory path
  • tkey-gssapi-credential Takes a kerberos service principal
  • tkey-domain Takes a kerberos realm
  • update-policy Takes one complete update-policy entry where you can grant or deny various matched objects and specify the dentity of the user/machine that is allowed/disallowed to update.. You can also identify match-type (Type of match to be used in evaulating the entry) and match-name (Name used to match) as well as rr-types (Resource record types that can be updated)

Overall, this command is one of the best I’ve seen for managing DNS in a long time. It shows a commitment to continuing to make the service better, when you add records or remove them you can instantly refresh the Server app and see the updates. It’s clear a lot of work went into this and it’s a great tool for when you’re imaging systems and want to create records back on a server or when you’re trying to script the creation of a bulk list of records (e.g. from a cached file from a downed host). It also makes working with Views as easy as I’ve seen it in most platforms and is overall a breeze to work with as compared to using the serveradmin command to populate objects so the GUI doesn’t break when you update records by hitting files directly.