DNSControl is a fantastic tool to manage DNS records, especially if there are multiple DNS zones being managed:
- DNS records in plain text files allowing them to be stored in a VCS of your choice
- Records are vendor agnostic; switch from one DNS provider to another without having to import/export records or put them in a certain format
- Make DNS changes part of a CI/CD pipeline
- Use functions, variables, macros; a subset of JavaScript features are available
There are many more advantages/features which I will not cover in this post. I also won’t go into basic configuration of DNSControl in this post. The documentation covers that pretty well and there are a variety of other posts that can help with the basics:
- Digital Ocean – How To Deploy and Manage Your DNS Using DNSControl on Debian 10
- Sven Luijten – Manage your DNS from GitHub with DNSControl
Contents
The Problem
When using Office 365, there is quite a few records which need to be set typically:
- Validation TXT record (at least initially to prove ownership of the domain)
- MX record
- DKIM CNAME records
- Skype for Business discovery SRV/CNAME records
- CNAME records for Azure AD device enrollment
- TXT record for SPF
- TXT record for DMARC
If using all of those features it quickly add up to 12 DNS records to add. Managing these manually (especially for a large number of domains) can be error prone at worst and time consuming at best.
The Solution: Office 365 Generator
Using DNSControl, all of the Office 365 records can be abstracted into a single function call in a DNS zone which is much more convenient: Office365()
The relevant files an example DNSControl configuration is available on GitHub here: dnscontrol-office365
File Structure
Rather than putting everything into a single dnsconfig.js
file, I like to split things up a bit. I am using the following file/directory structure:
.
.
├── creds.json
├── dnsconfig.json
├── domains
│ ├── example1.com.js
│ ├── example2.com.js
│ └── example3.com.js
├── functions
| ├── DKIMRecord.js
| ├── DMARCRecord.js
| ├── Office365.js
│ └── SPFRecord.js
├── records
│ └── Office365.js
└── vars
├── Office365.js
├── SPF.js
└── TTL.js
There are two domains being managed with DNSControl; example1.com and example2.com.
Main Configuration (dnsconfig.json)
The main dnsconfig.json
file needs to include the relevant files (DNS zones, functions, records and vars (variables). The order that the directories are included is important; the Office365 records rely on functions which rely on variables.
Variables (vars/)
I make use of two variable files; one to contain the default TTL that I use for all records (TTL.js) and the other containing common configuration for Office 365 (tenant name, MX record host name).
vars/TTL.js
The default TTL can be set to your preferred value. If required, you can also override this on a per-domain basis later.
vars/Office365.js
This file contains the tenant name and MX record hostname that will be built. For the purposes of this example the Office 365 tenant name is “example
“. MX records will be on the hostname “mail.protection.outlook.com
” with a priority of 0. If you have domains inside different tenants you may override the tenant name later if required.
vars/SPF.js
This file contains SPF record definitions. You can add common SPF record variables here for use in the domain configuration files.
Functions (functions/)
The main “Office365()
” function calls various smaller functions from functions/Office365.js
. As an example, to add the MX record the function “Office365MX()
” will be used.
A function has also been defined to add the SPF record and DMARC record. The DMARC record function assumes a strict SPF/DKIM alignment policy with reports by default being sent to dmarc-rua@$domain
and dmarc-ruf@$domain
.
Records (records/)
The main “Office365()
” function is defined in records/Office365.js
.
Usage/Examples
All functions are documented using JSDoc. If you need examples specific to your case check the relevant file and the comments should explain the variables.
Example domain configuration files are available in the domains directory.
The basic domain definition looks like this:
D( "example.com", // The domain name // Registrar and DNS providers REG_NAMECHEAP, // The registrar of the domain name DnsProvider(DNS_CLOUDFLARE), // The DNS provider that will be managed // Add Office 365 records // This will setup SPF, DKIM, DMARC, auto discovery, MX Office365( "example.com" // The domain name - This will be used to build records // { "...": "..." } // Optional parameters // { "...": "..." } // Optional features control ), // Custom DNS records A("@", "192.0.2.1", CF_PROXY_ON), AAAA("@", "2001:db8::1", CF_PROXY_ON), CNAME("www", "example.com.", CF_PROXY_ON) );